Skip to content

Fonts

Overview

The SDK handles fonts via the M2ResourcesService (accessed from Evs.resourcesService).

Font resources are uploaded from the application to the glasses over BLE and bound to text drawables for rendering.

Font Format

Maverick AI uses SIF2 (System Independent Font 2) format for on-board text rendering. Standard font files (TTF, OTF, WOFF) must be converted to SIF2 before uploading.

Font Sources

Source Class Description
Stock M2FontResource.fontSmall / fontMedium Built into the glasses - no upload needed. 22 px and 44 px.
Hosted M2FontResourceUrl + M2FontUrlBuilder Ready-made SIF2 fonts hosted by Everysight, in several languages, weights and sizes. Downloaded on first use and cached on the phone.
URL M2FontResourceUrl Your own SIF2 font from any URL, with its .json metrics file next to it.
File M2FontResource A SIF2 font bundled with the application. Its .json metrics file is read from the same folder when present.
Bytes M2FontResource SIF2 font bytes (and optional JSON metrics) already in memory.
// Stock - no upload
text.setFont(M2FontResource.fontSmall)

// Bundled with the app (fonts/MyFont.24.sif2 + fonts/MyFont.24.json)
val bundled = M2FontResource("fonts/MyFont.24.sif2")

// In memory
val fromBytes = M2FontResource(sif2Bytes, jsonBytes)
// Stock - no upload
text.setFont(fontResource: M2FontResource.companion.fontSmall)

// Bundled with the app (fonts/MyFont.24.sif2 + fonts/MyFont.24.json)
let bundled = M2FontResource(nameWithExtension: "fonts/MyFont.24.sif2", cacheAcrossScreen: true, tag: nil)

Hosted Fonts

Everysight hosts ready-made fonts, so most apps never need to convert one. Pick a font with the M2FontUrlBuilder catalog - language, then family, then weight, then size - and load it with M2FontResourceUrl. Only combinations that exist can be written, so a wrong pick is a compile error, not a failed download.

Language Builder Sizes (px) With Latin glyphs (.withLatin)
English english 16 - 50 -
Western European (accented Latin) westEuropean 16 - 50 16 - 32
Eastern European eastEuropean 16 - 50 16 - 32
Russian / Bulgarian (Cyrillic) russian 16 - 50 16 - 32
Greek greek 16 - 50 16 - 32
Ukrainian ukrainian 16 - 40 16 - 32
  • Family: Roboto.
  • Weights: medium, bold (the default) and extraBold.
  • Sizes: even pixel heights only (size16, size18size50).
  • Quality: 2 bits per pixel.

Use .withLatin when the text mixes the language's own script with English, for example Greek words next to a Latin brand name.

Loading a Hosted Font

The font is downloaded on first use and cached on the phone under mav2sdk/fonts/, so later loads work offline. The callback gets an M2FontResourceUrl, which is an M2FontResource - pass it straight to setFont.

val selection = M2FontUrlBuilder.english.roboto.bold.size24

M2FontResourceUrl.from(selection) { font ->
    if (font.fontMetadata == null) return@from   // failed - see font.errorMessage
    title.setFont(font)
}

// Greek text with Latin glyphs, medium weight
val greek = M2FontUrlBuilder.greek.roboto.medium.withLatin.size24
let selection = M2FontUrlBuilder.shared.english.roboto.bold.size24

M2FontResourceUrl.companion.from(fontUrl: selection, forceRedownload: false, saveToAppCache: true) { font in
    if font.fontMetadata == nil { return }   // failed - see font.errorMessage
    title.setFont(fontResource: font)
}

font.fontMetadata is null when loading failed, and otherwise carries the font's metrics: maxHeight (use it for line height) and charWidth (every character the font contains, with its width).

Parameter Default Description
forceRedownload false Skip the phone cache and download again.
saveToAppCache true Keep the downloaded font on the phone for next time.

Clear the phone's font cache with Evs.appCacheService.deleteFontsCacheAsync().

Loading Your Own Font from a URL

Host a font you converted with font2sif2.py (below) and load it the same way. Put the .json file next to the .sif2 file, with the same name - the SDK derives its URL.

M2FontResourceUrl.from("https://example.com/fonts/MyFont.24.sif2") { font ->
    if (font.fontMetadata != null) title.setFont(font)
}
M2FontResourceUrl.companion.from(sif2Url: "https://example.com/fonts/MyFont.24.sif2",
                                 forceRedownload: false, saveToAppCache: true) { font in
    if font.fontMetadata != nil { title.setFont(fontResource: font) }
}

Limitations

Constraint Value
Maximum font data size 48 KB (per resource)
Maximum active font slots 24 (including 2 reserved for stock fonts)

Converting Fonts - font2sif2.py

The font2sif2.py tool converts standard fonts to SIF2 format. It can be found in the SDK repository.

Basic usage:

# Convert a TTF font at size 36, 2 bits per pixel
python3 font2sif2.py --path MyFont.ttf --size 36 --bpp 2

# Convert with larger size and higher quality
python3 font2sif2.py --path MyFont.otf --size 48 --bpp 4

# Convert specific character ranges (e.g. ASCII + extended Latin)
python3 font2sif2.py --path MyFont.ttf --size 28 --ranges 0x0020:0x00FF

Options:

Flag Default Description
--path (required) Input font file (TTF, OTF, WOFF)
--size 36 Pixel height
--bpp 2 Bits per pixel for glyph rendering (1, 2, 4, or 8)
--ranges 0x0020:0x007E Unicode character ranges to include (hex START:END)
--exclude - Hex character codes to exclude
--norender - Skip preview image generation

How it works:

  1. FreeType renders each glyph at the requested pixel size.
  2. Glyph bitmaps are quantized to the target BPP depth.
  3. All glyphs are packed into a single SIF2 binary file with a header, range metadata, character info table, and bitmap data.
  4. Optional RLE compression is applied to reduce size.

Output files:

  • <font>.<height>x<width>.<bpp>bpp.sif2 - the binary font file for the glasses
  • <font>.<height>x<width>.<bpp>bpp.json - metadata (character map, metrics)
  • <font>.<height>x<width>.<bpp>bpp.png - optional visual preview of all glyphs

Requirements: Python 3, numpy, freetype-py, Pillow.


See Also

  • Images - Display images on the glasses
  • Drawables - The drawable building blocks, and composing your own controls