@evenrealities/pretext
v0.1.4
Published
Pixel-accurate font measurement library for Even Realities G2 glasses
Downloads
895
Readme
@evenrealities/pretext
Pixel-accurate font measurement library for Even Realities G2 smart glasses (EvenHub specifically). Predicts exact text layout dimensions matching the LVGL rendering engine used in the glasses firmware, so you can size UI containers precisely without guesswork. Inspired by pretext.
Note: Measurements have been manually compared and verified against the actual glasses rendering for most cases, but edge cases may exist where predictions differ from the firmware output. In particular, results may be off for characters that are not present in the firmware fonts, since the firmware and this library may handle missing glyphs differently in some cases.
Features
- Text measurement — multi-line layout prediction with word wrapping
- Kerning — per-character pair adjustments using the firmware's exact formula
- Wide character support — Latin, Cyrillic, Greek, CJK (Chinese, Japanese, Korean), Bopomofo
Installation
npm install @evenrealities/pretextAPI
getTextWidth(text: string): number
Returns the single-line pixel width of a string, with kerning applied.
import { getTextWidth } from '@evenrealities/pretext';
const width = getTextWidth('Hello, world!');
// => 79 (pixels)measureTextWrap(text: string, maxWidth: number): MeasureTextResult
Measures multi-line text layout within the given pixel width. Handles word wrapping at spaces and hyphens, CJK boundary breaks, explicit newlines, and hard breaks when no break opportunity exists.
maxWidth should be the inner content width — if your container has padding or borders, subtract them before calling. The returned height is pure text height; add your own padding/border to get the final container size.
import { measureTextWrap } from '@evenrealities/pretext';
const result = measureTextWrap('The quick brown fox jumps over the lazy dog', 200);
// => {
// lineCount: 2,
// height: 54, // lineCount * 27 (line height)
// lineWidths: [192, 96]
// }
// With padding + border:
const pad = 8, border = 2;
const inner = 300 - 2 * (pad + border); // 280px available for text
const m = measureTextWrap('Hello world', inner);
const containerHeight = m.height + 2 * (pad + border);Parameters:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| text | string | — | The string to measure |
| maxWidth | number | — | Available width for text in pixels (subtract padding/border first) |
Return type:
| Field | Type | Description |
|-------|------|-------------|
| lineCount | number | Number of lines after wrapping |
| height | number | Total text height in pixels (lineCount * 27) |
| lineWidths | number[] | Pixel width of each line |
pxTruncate(text: string, maxPx: number): string
Truncates a string to fit within a pixel budget, appending '...' if needed. Returns the original string if it already fits. Uses binary search for efficient fitting and is codepoint-aware (won't break surrogate pairs like emoji).
import { pxTruncate } from '@evenrealities/pretext';
const truncated = pxTruncate('Hello, world!', 50);
// => 'Hell...'getAdvW(cp: number): number
Returns the raw advance width of a codepoint in 1/16px units (no kerning, no rounding). Follows the font fallback chain: evenroster -> evenroster_crylgrek -> cn. Primarily useful for debugging or building custom measurement logic.
Display Reference
The G2 glasses have a 576 x 288 pixel display rendered by LVGL with a fixed line height of 27px.
How It Works
The library embeds extracted font metrics from the LVGL C font files used in the G2 firmware. It replicates the firmware's text shaping pipeline:
- Glyph lookup — resolves each codepoint through a three-font fallback chain (Latin -> Cyrillic/Greek -> CJK)
- Kerning — applies pair adjustments using the firmware formula:
(kern_value * kern_scale) >> 4 - Per-glyph rounding — each advance width is rounded to pixels individually (
(adv + kern + 8) >> 4), matching LVGL's behavior exactly - Line breaking — breaks at spaces, hyphens, and CJK boundaries, with hard breaks as fallback
Note: if the firmware font metrics change, this library must be updated to match.
Changelog
0.1.4
- add Emoji font
0.1.3
- Breaking: Removed
containerPaddingparameter frommeasureTextWrap. The function now measures pure text — callers should subtract padding/border frommaxWidthbefore calling and add it back to the returnedheight. This avoids the inconsistency where padding was handled internally but border width was not. - Breaking: Removed
measureList. Its logic was trivial (item count × 40px, plus basic width comparisons) and callers can replicate it inline withgetTextWidth.
0.1.2
- Initial public release with
getTextWidth,measureTextWrap,pxTruncate,measureList, andgetAdvW.
