| name | font-measurement |
| description | Pixel-accurate font measurement for Even Realities G2 glasses — predict text layout dimensions matching the LVGL rendering engine. Use when sizing text containers precisely. |
| allowed-tools | ["Read","Grep","Glob","Bash","Write","Edit"] |
| argument-hint | ["measurement or layout sizing task"] |
even-pretext: Font Measurement Library
Pixel-accurate text measurement for Even Realities G2 smart glasses. Predicts exact layout dimensions matching the LVGL rendering engine in the glasses firmware.
Note: Results may be off for characters not present in the firmware fonts, since the firmware and this library may handle missing glyphs differently in some cases.
Installation
npm install @evenrealities/pretext
Display Constants
- Screen: 576 x 288 pixels
- Line height: 27px (fixed)
- List item height: 40px (fixed)
- List item horizontal padding: 12px per side
API
All functions are exported from @evenrealities/pretext.
getTextWidth(text: string): number
Returns single-line pixel width of a string (with kerning, no wrapping).
import { getTextWidth } from '@evenrealities/pretext';
const width = getTextWidth('Hello, world!');
measureTextWrap(text: string, maxWidth: number): MeasureTextResult
Measures multi-line text layout with word wrapping. maxWidth should be the inner content width — subtract padding and border before calling. The returned height is pure text height.
import { measureTextWrap } from '@evenrealities/pretext';
const result = measureTextWrap('The quick brown fox jumps over the lazy dog', 200);
const pad = 8, border = 2;
const m = measureTextWrap('Hello world', 300 - 2 * (pad + border));
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) |
Returns:
| Field | Type | Description |
|---|
lineCount | number | Number of lines after wrapping |
height | number | Total text height (lineCount * 27) |
lineWidths | number[] | Pixel width of each wrapped line |
pxTruncate(text: string, maxPx: number): string
Truncates a string to fit within a pixel budget, appending '...' if needed. Returns the original string unchanged when it already fits. Uses binary search and handles emoji/surrogate pairs correctly.
import { pxTruncate } from '@evenrealities/pretext';
const label = pxTruncate('Hello, world!', 50);
const fits = pxTruncate('Hi', 50);
Parameters:
| Parameter | Type | Description |
|---|
text | string | The string to truncate |
maxPx | number | Maximum width in pixels |
Returns: The original string if it fits, otherwise a truncated string ending with '...'.
Note: This function is single-line only. For multiline text, truncate each line individually.
getAdvW(cp: number): number
Returns raw advance width of a codepoint in 1/16px units (no kerning, no rounding). Useful for debugging or custom measurement logic.
Accounting for Padding and Borders
When a TextContainerProperty has paddingLength or borderWidth, the SDK's LVGL renderer subtracts these from the available text area inside the container. If you measure text against the full container width/height, the content will overflow and a scrollbar appears.
How padding and border affect the text area
Container (width × height)
┌─ border (borderWidth pixels) ─────────────────────┐
│ ┌─ padding (paddingLength pixels) ──────────────┐ │
│ │ │ │
│ │ Text renders here │ │
│ │ innerWidth = width - 2*padding - 2*border │ │
│ │ innerHeight = height - 2*padding - 2*border │ │
│ │ │ │
│ └────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────┘
Rules
paddingLength: N reduces text area by N pixels on all four sides
borderWidth: N reduces text area by N pixel on all four sides (border is drawn inside the container)
- Both stack: total inset =
paddingLength + borderWidth per side
- If neither is set, text renders at the full container width/height
Measuring text for a container with padding/border
import { measureTextWrap } from '@evenrealities/pretext';
const containerW = 560;
const containerH = 258;
const padding = 8;
const border = 1;
const inset = padding + border;
const innerW = containerW - 2 * inset;
const innerH = containerH - 2 * inset;
const maxLines = Math.floor(innerH / 27);
const m = measureTextWrap(text, innerW);
if (m.lineCount > maxLines) {
text = truncateToFitLines(text, innerW, maxLines);
}
Common mistake
const m = measureTextWrap(text, 560);
const m = measureTextWrap(text, 560 - 2 * (padding + border));
Common Patterns
Size a text container to fit its content
import { measureTextWrap } from '@evenrealities/pretext';
const containerWidth = 300;
const padding = 8;
const innerW = containerWidth - 2 * padding;
const result = measureTextWrap(myText, innerW);
const containerHeight = result.height + 2 * padding;
Truncate text to fit a container
import { pxTruncate } from '@evenrealities/pretext';
const label = pxTruncate(longText, containerWidth);
import { measureTextWrap } from '@evenrealities/pretext';
const { lineWidths } = measureTextWrap(longText, containerWidth);
Instructions
When using this library to size UI containers for Even Realities glasses:
- Always use this library to predict text dimensions before creating containers. Do not guess pixel sizes.
- Line height is 27px — multiply by line count for text container height.
- List items are 40px tall — multiply by item count and add
2 * padding for list container height.
- Max display is 576 x 288. Ensure containers fit within these bounds.
- When pairing with the glasses-ui skill, use
measureTextWrap results to set container width and height properties precisely.
- When a container has
paddingLength or borderWidth, subtract these from the container dimensions before measuring text. Failing to do so causes content overflow and a scrollbar. See "Accounting for Padding and Borders" above.
Task
$ARGUMENTS