@navaramap/font 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ Copyright (c) 2026 MapLibre contributors
2
+
3
+ This project is dual-licensed under either of
4
+
5
+ - Apache License, Version 2.0 (see LICENSE-APACHE)
6
+ - MIT license (see LICENSE-MIT)
7
+
8
+ at your option.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @navaramap/font
2
+
3
+ This is a font module for Navara for Web platform.
@@ -0,0 +1,556 @@
1
+ import { ConcurrencyManager } from '@navaramap/worker';
2
+ import { DataTexture } from 'three';
3
+
4
+ /**
5
+ * Pixel range over which a quality's atlas distance field ramps from
6
+ * "outside" to "inside" (i.e. the value covered by `d - 0.5` in the shader).
7
+ * Converts an outline-thickness expressed in pixels into a delta on the
8
+ * sampled distance value.
9
+ *
10
+ * SDF: `SDF_RADIUS` (35) in `crates/navara_wasm_font_worker/src/atlas.rs`.
11
+ * MSDF: `MSDF_RANGE_PX` (8) in `crates/navara_wasm_font_worker/src/msdf.rs`.
12
+ */
13
+ export declare const atlasRangePx: (highQuality: boolean) => number;
14
+
15
+ declare type BatchPrepareTextResult = {
16
+ results: {
17
+ text: string;
18
+ shapeResult: ShapeTextResult | null;
19
+ }[];
20
+ /** Snapshot of the SDF atlas, if any glyphs were added during the batch. */
21
+ atlas: FontAtlasData | null;
22
+ /** Snapshot of the COLRv1 color atlas (RGBA), if any color glyphs were added during the batch. */
23
+ colorAtlas: FontAtlasData | null;
24
+ /** The atlas key used for this batch (family name or font URL). */
25
+ atlasKey: string;
26
+ /** True if any glyph was evicted during this batch. The reused rects mean
27
+ * cached shape results for this atlas may be stale, so the FontManager bumps
28
+ * the atlas generation to force a re-shape on next use. Optional only so
29
+ * callers needn't construct it (the worker always sends it). */
30
+ evicted?: boolean;
31
+ };
32
+
33
+ /**
34
+ * Pixel size at which COLRv1 color glyphs are rasterized into the color atlas.
35
+ * Must match `COLOR_GLYPH_PX_SIZE` in `crates/navara_wasm_font_worker/src/color_raster.rs`.
36
+ */
37
+ export declare const COLOR_GLYPH_PX_SIZE = 64;
38
+
39
+ /** Create an RGBA color atlas DataTexture for COLRv1 glyphs.
40
+ * Pixel data is unpremultiplied sRGB; three.js linearizes on sample. */
41
+ export declare function createColorAtlasTexture(data: Uint8Array, width: number, height: number): DataTexture;
42
+
43
+ /** Create an SDF/MSDF distance-field atlas DataTexture.
44
+ *
45
+ * `channels`: 1 → R8 SDF (sampled as `.r`); 4 → RGBA8 MTSDF (three MSDF
46
+ * channels + true SDF in alpha, sampled as `median(.rgb)`). RGB8 isn't
47
+ * supported because three.js dropped `RGBFormat` in r137. */
48
+ export declare function createSdfAtlasTexture(data: Uint8Array, width: number, height: number, channels: number): DataTexture;
49
+
50
+ /** Filters selecting which `@font-face` blocks of a stylesheet to include. */
51
+ export declare type CssFontFaceFilter = {
52
+ /**
53
+ * Only include blocks whose `font-family` matches one of these names
54
+ * (quotes stripped, case-insensitive). Useful when a stylesheet declares
55
+ * several families and only some should become faces.
56
+ *
57
+ * When given as an array, it also sets face priority: faces are ordered by
58
+ * their family's position in the array (stable within a family). This
59
+ * matters for stylesheets like the Google Fonts CSS API that sort
60
+ * `@font-face` blocks alphabetically regardless of request order — face
61
+ * order decides which face wins for codepoints covered by several faces,
62
+ * and `faces[0]` is the fallback for uncovered codepoints.
63
+ */
64
+ fontFamily?: string | string[];
65
+ /** Only include blocks whose `font-weight` matches, e.g. `800` or `"100 900"`. */
66
+ fontWeight?: string | number;
67
+ /** Only include blocks whose `font-style` matches, e.g. `"normal"` or `"italic"`. */
68
+ fontStyle?: string;
69
+ };
70
+
71
+ export declare type FetchCssFontFamilyOptions = CssFontFaceFilter & {
72
+ /** Extra `fetch` options (e.g. credentials for a private font host). */
73
+ requestInit?: RequestInit;
74
+ };
75
+
76
+ /**
77
+ * Fetch one or more stylesheets and build a {@link FontFamily} from their
78
+ * `@font-face` rules — see {@link parseFontFamilyFromCss}. Only the CSS is
79
+ * downloaded here; font files stay lazily fetched per face as text needs
80
+ * them.
81
+ *
82
+ * Works directly with the Google Fonts CSS API, which declares one
83
+ * `@font-face` per script subset with `unicode-range` (CJK families are
84
+ * split into ~100 lazily-loaded slices):
85
+ *
86
+ * ```ts
87
+ * const family = await fetchFontFamilyFromCss(
88
+ * "labels",
89
+ * "https://fonts.googleapis.com/css2?family=Archivo:wght@800&family=Noto+Sans+JP:wght@800",
90
+ * );
91
+ * view.addFontFamily(family);
92
+ * ```
93
+ *
94
+ * When passing multiple URLs, face priority follows URL order, then block
95
+ * order within each stylesheet.
96
+ *
97
+ * @param family Family name to register the faces under.
98
+ * @param cssUrl Stylesheet URL(s) to fetch.
99
+ * @param options Optional block filters and fetch options.
100
+ */
101
+ export declare function fetchFontFamilyFromCss(family: string, cssUrl: string | string[], options?: FetchCssFontFamilyOptions): Promise<FontFamily>;
102
+
103
+ /** SDF/MSDF atlas texture data.
104
+ *
105
+ * `channels` selects the GPU texture format:
106
+ * - 1 → R8 (single-channel SDF, sampled as `.r`).
107
+ * - 4 → RGBA8. Either MTSDF (three MSDF channels + true SDF in alpha,
108
+ * sampled as `median(.rgb)` in the fragment shader) or the COLRv1 color
109
+ * atlas — distinguished by which atlas slot the data was placed in, not
110
+ * by `channels`.
111
+ *
112
+ * 3-channel MSDF (RGB8) isn't used: three.js dropped `RGBFormat` in r137,
113
+ * and the worker emits MTSDF (4 channels) for the high-quality path.
114
+ */
115
+ export declare type FontAtlasData = {
116
+ data: Uint8Array;
117
+ width: number;
118
+ height: number;
119
+ channels: number;
120
+ };
121
+
122
+ declare type FontFace_2 = {
123
+ unicodeRanges: UnicodeRange[];
124
+ url: string;
125
+ };
126
+ export { FontFace_2 as FontFace }
127
+
128
+ export declare type FontFamily = {
129
+ family: string;
130
+ faces: FontFace_2[];
131
+ };
132
+
133
+ /**
134
+ * Manages font loading, text shaping, and SDF atlas access.
135
+ *
136
+ * Delegates heavy computation (shaping, SDF rasterization, atlas packing)
137
+ * to a dedicated Web Worker via FontWorkerClient. GPU texture management
138
+ * (DataTexture creation/update) stays on the main thread.
139
+ */
140
+ export declare class FontManager {
141
+ private _workerUrl;
142
+ private _client;
143
+ private _clientPromise;
144
+ private _concurrencyManager;
145
+ /** Worker cache budget, delivered when the (lazy) client is created. */
146
+ private _fontBudgetBytes;
147
+ /** Tracks in-flight fetch promises to avoid duplicate requests. */
148
+ private _pending;
149
+ /** Tracks fonts that have been successfully loaded. */
150
+ private _loaded;
151
+ /** Cache shaped text results to avoid redundant worker calls (LRU-evicted). */
152
+ private _shapeCache;
153
+ /** Cache atlas data per font to avoid redundant copies. */
154
+ private _atlasCache;
155
+ /** Cache color atlas data per font (COLRv1 RGBA). */
156
+ private _colorAtlasCache;
157
+ /** Tracks whether the atlas cache is stale (new glyphs may have been rasterized). */
158
+ private _atlasDirty;
159
+ /** Tracks whether the color atlas cache is stale. */
160
+ private _colorAtlasDirty;
161
+ /** Shared GPU texture per font — all meshes using the same font share one DataTexture. */
162
+ private _textureCache;
163
+ /** Shared color atlas texture per atlas key (RGBA). */
164
+ private _colorTextureCache;
165
+ /** Tracks in-flight prepareText promises to deduplicate. */
166
+ private _preparePending;
167
+ /** Microtask batch queue: per-font list of texts awaiting worker dispatch. */
168
+ private _batchQueue;
169
+ /** Whether a microtask flush is already scheduled. */
170
+ private _batchScheduled;
171
+ private _refCount;
172
+ /** Registered font families, keyed by family name. */
173
+ private _families;
174
+ /** Real cmap coverage per font file URL, reported by the worker when the
175
+ * file is first loaded. Declared face ranges can differ from what the
176
+ * file contains (e.g. shared per-subset boilerplate in Google Fonts CSS
177
+ * claims codepoints the file lacks, which would shape as tofu), so
178
+ * registered faces pointing at the URL get their `unicodeRanges` replaced
179
+ * with these — once per file, never per shaped text. */
180
+ private _cmapRanges;
181
+ /** Maps font URL → atlas key (family name or URL for standalone fonts). */
182
+ private _atlasKeys;
183
+ /** Per-atlas generation counter. Bumped when the worker reports it evicted
184
+ * glyphs from an atlas; cached shape results carry the generation they were
185
+ * built under, so any from before the eviction are re-shaped on next use.
186
+ * Visible labels are *normally* unaffected — their glyphs are pinned and not
187
+ * evicted — but a large burst can evict a still-in-flight glyph before its
188
+ * retain lands; `onAtlasEvicted` lets consumers rebuild such stale meshes. */
189
+ private _atlasGeneration;
190
+ /** Eviction listeners keyed by resolved atlas key. Notified (coalesced on a
191
+ * microtask) after an eviction bumps an atlas's generation, so visible
192
+ * consumers can rebuild meshes whose baked metrics may now be stale. */
193
+ private _evictListeners;
194
+ /** Atlas keys with an eviction awaiting notification, plus its schedule flag. */
195
+ private _pendingEvictNotify;
196
+ private _evictNotifyScheduled;
197
+ /** Pending visible-label refcount increments per atlas key (one entry per
198
+ * occurrence), flushed to the worker on a microtask. */
199
+ private _retainQueue;
200
+ /** Pending visible-label refcount decrements per atlas key. */
201
+ private _releaseQueue;
202
+ /** Whether a retain/release flush is already scheduled. */
203
+ private _refFlushScheduled;
204
+ constructor(workerUrl: string | URL);
205
+ setConcurrencyManager(concurrencyManager: ConcurrencyManager): void;
206
+ /**
207
+ * Register a font family with multiple faces.
208
+ * No font files are loaded until text is prepared.
209
+ */
210
+ registerFontFamily(family: FontFamily): void;
211
+ /**
212
+ * Remove a registered font family. No font resources are unloaded here —
213
+ * each mesh that used this family tracks its loaded face URLs and unloads
214
+ * them individually on dispose.
215
+ */
216
+ unregisterFontFamily(familyName: string): void;
217
+ /** Check whether a font identifier is a registered family name. */
218
+ isFamily(fontIdentifier: string): boolean;
219
+ /**
220
+ * Split `text` into runs of consecutive characters that map to the same face.
221
+ * Each character picks the first face whose unicode ranges contain it,
222
+ * falling back to face 0. Spaces stick to the current run to avoid breaking
223
+ * up whitespace.
224
+ */
225
+ private _segmentTextByFace;
226
+ /** First face whose unicode ranges contain `codepoint`, or face 0. */
227
+ private _findFaceForCodepoint;
228
+ /** Replace the unicode ranges of every registered face pointing at
229
+ * `rawUrl` with the font file's real cmap coverage (see `_cmapRanges`). */
230
+ private _applyCmapRanges;
231
+ private _ensureClient;
232
+ /**
233
+ * Sets the worker-side cache budget (font data + atlas pixels). Must be
234
+ * called before the first font loads — the worker is created lazily and
235
+ * the budget is delivered with its init message.
236
+ */
237
+ setMemoryBudget(bytes: number | undefined): void;
238
+ /**
239
+ * Snapshot of the font worker's memory usage, or `undefined` while no
240
+ * worker has been spawned (no fonts in use = zero cost).
241
+ */
242
+ memoryStats(): Promise<FontWorkerMemoryStats | undefined>;
243
+ /**
244
+ * Load a font from a URL. Fetches the font file and sends it to the worker.
245
+ * Returns immediately if the font is already loaded. Deduplicates concurrent requests.
246
+ *
247
+ * `atlasKey`: optional shared atlas identifier (e.g. font family name).
248
+ * `highQuality`: which atlas raster path to use. Two materials referencing the
249
+ * same `url` but different `highQuality` values produce two independent
250
+ * (font, atlas) entries — both live side-by-side. The browser HTTP cache
251
+ * makes the second fetch effectively free.
252
+ */
253
+ loadFont(url: string, highQuality: boolean, atlasKey?: string): Promise<void>;
254
+ unloadFont(url: string, highQuality: boolean): Promise<void>;
255
+ /**
256
+ * Prepare text for rendering: shapes text and updates atlas in the worker.
257
+ * Must be called (and awaited) before shapeText() will return data for this text.
258
+ * Accepts either a font URL or a registered font family name.
259
+ *
260
+ * For font families, face URLs are loaded lazily — only the faces whose
261
+ * unicode ranges cover `text` are fetched. Pass a caller-owned `loadedFaces`
262
+ * Set to track which URLs were loaded; the caller must call unloadFont() for
263
+ * each URL in the set on dispose. Passing the same set across multiple calls
264
+ * ensures each face URL is loaded exactly once per caller.
265
+ *
266
+ * For standalone font URLs the font must already be loaded via loadFont().
267
+ */
268
+ prepareText(fontIdentifier: string, text: string, highQuality: boolean, loadedFaces?: Set<string>): Promise<void>;
269
+ /**
270
+ * Check if text has been prepared (sync).
271
+ * Accepts either a font URL or a registered font family name.
272
+ */
273
+ isTextPrepared(fontIdentifier: string, text: string, highQuality: boolean): boolean;
274
+ /**
275
+ * Get shaped text from cache. Returns undefined if not yet prepared.
276
+ * Call prepareText() first.
277
+ * Accepts either a font URL or a registered font family name.
278
+ */
279
+ shapeText(fontIdentifier: string, text: string, highQuality: boolean): ShapeTextResult | undefined;
280
+ /** Prepare text for a single standalone font (non-family path). */
281
+ private _prepareSingleFontText;
282
+ /** Prepare text for a font family: segment, shape per-face, stitch. */
283
+ private _prepareFamilyText;
284
+ /** Combine shaped results from multiple face segments into one result.
285
+ *
286
+ * All glyph advances/offsets and bearing values are normalized to the first
287
+ * segment's unitsPerEm so the consumer can apply a single scale factor.
288
+ */
289
+ private _stitchSegments;
290
+ /**
291
+ * Get the SDF atlas data for a loaded font from cache.
292
+ * Accepts either a font URL or a registered font family name.
293
+ * For families, the atlas is shared across all faces.
294
+ */
295
+ getAtlas(fontIdentifier: string, highQuality: boolean): FontAtlasData | undefined;
296
+ /**
297
+ * Shared GPU DataTexture for a font's atlas. Returns the same instance
298
+ * across callers and updates it in-place when the atlas grows. Accepts a
299
+ * font URL or a family name.
300
+ */
301
+ getAtlasTexture(fontIdentifier: string, highQuality: boolean): DataTexture | null;
302
+ /** Color atlas data for a loaded COLRv1 font. `undefined` for monochrome. */
303
+ getColorAtlas(fontIdentifier: string, highQuality: boolean): FontAtlasData | undefined;
304
+ /**
305
+ * Shared GPU DataTexture for a font's COLRv1 color atlas. `null` when no
306
+ * color glyphs have been rasterized under this key.
307
+ */
308
+ getColorAtlasTexture(fontIdentifier: string, highQuality: boolean): DataTexture | null;
309
+ /** Shared "get cached texture, create or refresh from atlas data" path.
310
+ * When the atlas grew, dispose() releases the GL handle so three.js
311
+ * reallocates at the new size on the next render instead of overflowing
312
+ * texSubImage2D. The DataTexture instance is preserved so existing meshes
313
+ * keep their refs. */
314
+ private _getOrUpdateTexture;
315
+ dispose(): void;
316
+ private _cacheKey;
317
+ /** Current generation of an atlas. Bumped whenever the atlas evicts glyphs;
318
+ * cached shape results stamped with an older generation are treated as
319
+ * stale (their metrics may point at reused rects) and re-shaped on next use. */
320
+ private _currentGen;
321
+ /** Whether `text` has a cached shape result that is still current for its
322
+ * atlas. A result from before the atlas last evicted is treated as not
323
+ * prepared, forcing a re-shape that re-rasterizes any evicted glyphs. */
324
+ private _isPreparedFresh;
325
+ /**
326
+ * Subscribe to evictions on the atlas backing `(fontIdentifier, highQuality)`.
327
+ * The listener fires (coalesced on a microtask) after the worker reports that
328
+ * atlas evicted glyphs — the cue for a visible consumer to rebuild any mesh
329
+ * whose baked atlas rects may now be stale. Returns an unsubscribe function.
330
+ */
331
+ onAtlasEvicted(fontIdentifier: string, highQuality: boolean, listener: () => void): () => void;
332
+ /** Queue an eviction notification for `atlasKey`, coalescing a burst of
333
+ * per-batch evictions into a single microtask-deferred fan-out. */
334
+ private _scheduleEvictNotify;
335
+ private _flushEvictNotify;
336
+ /**
337
+ * Add one visible-label reference to each glyph (composite keys) so the
338
+ * worker keeps them in the atlas while on screen. Call when a label using
339
+ * these glyphs becomes visible; balance with {@link releaseGlyphs}.
340
+ */
341
+ retainGlyphs(fontIdentifier: string, highQuality: boolean, keys: bigint[]): void;
342
+ /** Drop one visible-label reference from each glyph. Call when a label hides
343
+ * or is disposed. */
344
+ releaseGlyphs(fontIdentifier: string, highQuality: boolean, keys: bigint[]): void;
345
+ private _enqueueRef;
346
+ /** Send queued refcount changes to the worker. Retains are sent before
347
+ * releases so a glyph hidden and re-shown in the same tick never momentarily
348
+ * drops to zero. */
349
+ private _flushRefs;
350
+ /** Resolve a (font identifier, quality) pair to its qualified atlas key.
351
+ * Family names get a quality suffix and become their own atlas key; font
352
+ * URLs are looked up via `_atlasKeys` (already-qualified keys). */
353
+ private _resolveAtlasKey;
354
+ /** Fetch + worker-load a font for a single (url, quality) combination.
355
+ *
356
+ * `rawUrl` is the network URL (no `#q=...` fragment). `qUrl` and
357
+ * `qAtlasKey` are the qualified identifiers the worker will use as
358
+ * FontEntry / atlas keys. The worker side treats `qUrl` as opaque, so the
359
+ * same `rawUrl` can be loaded twice (once per quality) without collision.
360
+ */
361
+ private _fetchAndLoad;
362
+ private _flushBatch;
363
+ }
364
+
365
+ /**
366
+ * Main-thread client that communicates with the dedicated font Web Worker.
367
+ * Uses a request/response protocol with incrementing message IDs.
368
+ */
369
+ export declare class FontWorkerClient {
370
+ private _worker;
371
+ private _concurrencyManager;
372
+ private _nextId;
373
+ private _pending;
374
+ private _ready;
375
+ constructor(workerUrl: string | URL, concurrencyManager: ConcurrencyManager, options?: FontWorkerClientOptions);
376
+ /** Wait for the WASM module to be initialized in the worker. */
377
+ ready(): Promise<void>;
378
+ /** Load a font file into the worker's FontCache. Transfers the ArrayBuffer.
379
+ * `atlasKey`: optional shared atlas identifier (e.g. font family name).
380
+ * When provided, all fonts loaded with the same key share a single atlas.
381
+ * `highQuality`: whether to use the high-quality atlas raster path. The Rust side creates the
382
+ * atlas with this mode on the first load; subsequent loads under the same
383
+ * `atlasKey` are expected to reuse the same quality (the TS layer
384
+ * guarantees this by including the highQuality flag in both `url` and `atlasKey`).
385
+ *
386
+ * On success, `cmapRanges` holds the font's real cmap coverage as
387
+ * flattened `[from, to, ...]` inclusive codepoint ranges (empty when the
388
+ * face has no parsable unicode cmap — treat as unknown). */
389
+ loadFont(url: string, data: ArrayBuffer, atlasKey: string | undefined, highQuality: boolean): Promise<{
390
+ ok: boolean;
391
+ cmapRanges: Uint32Array | null;
392
+ }>;
393
+ unloadFont(url: string): Promise<{
394
+ ok: boolean;
395
+ }>;
396
+ /** Add one visible-label reference to each glyph (composite keys) under
397
+ * `atlasKey`. Fire-and-forget; the worker replies so `_pending` is cleared.
398
+ * Transfers the key buffer — the caller discards it after this call. */
399
+ retainGlyphs(atlasKey: string, keys: BigUint64Array): void;
400
+ /** Drop one visible-label reference from each glyph under `atlasKey`. */
401
+ releaseGlyphs(atlasKey: string, keys: BigUint64Array): void;
402
+ /** Shape multiple texts in one worker round-trip. */
403
+ prepareTextBatch(fontUrl: string, texts: string[]): Promise<BatchPrepareTextResult>;
404
+ /** Snapshot of the worker's WASM heap and font-cache memory usage. */
405
+ getMemoryStats(): Promise<FontWorkerMemoryStats>;
406
+ dispose(): void;
407
+ private _send;
408
+ }
409
+
410
+ declare type FontWorkerClientOptions = {
411
+ /** Memory budget for the worker's font caches (font data + atlas pixels).
412
+ * Caps further atlas growth; the WASM heap itself never shrinks. */
413
+ fontBudgetBytes?: number;
414
+ };
415
+
416
+ /** Snapshot of the font worker's WASM heap and font-cache memory usage. */
417
+ export declare type FontWorkerMemoryStats = {
418
+ /** Total WASM linear memory of the font worker (never shrinks). */
419
+ heapBytes: number;
420
+ fontCount: number;
421
+ atlasCount: number;
422
+ glyphCount: number;
423
+ /** Raw font file bytes held by the cache. */
424
+ fontBytes: number;
425
+ /** Monochrome (SDF/MSDF) atlas pixel bytes. */
426
+ atlasBytes: number;
427
+ /** COLRv1 color atlas pixel bytes. */
428
+ colorAtlasBytes: number;
429
+ /** Configured cache budget; undefined when unlimited. */
430
+ budgetBytes?: number;
431
+ };
432
+
433
+ /**
434
+ * Per-glyph character class used for line breaking during layout.
435
+ * Must match the `CHAR_CLASS_*` constants in
436
+ * `crates/navara_wasm_font_worker/src/shaping.rs`.
437
+ */
438
+ export declare const GlyphCharClass: {
439
+ readonly Normal: 0;
440
+ /** Breakable whitespace: a line may wrap here, dropping the glyph. */
441
+ readonly Whitespace: 1;
442
+ /** Synthetic hard-break marker (zero advance, no atlas entry). */
443
+ readonly Newline: 2;
444
+ /** CJK-style character: a line may break after this glyph. */
445
+ readonly Ideographic: 3;
446
+ };
447
+
448
+ /** Glyph metrics from either the SDF or the color atlas. */
449
+ export declare type GlyphMetrics = {
450
+ glyphId: number;
451
+ /** Unique font index within the atlas (distinguishes glyphs from different fonts). */
452
+ fontIndex: number;
453
+ /** Pre-computed composite key (font_index, glyph_id) from WASM. */
454
+ compositeKey: bigint;
455
+ atlasX: number;
456
+ atlasY: number;
457
+ atlasW: number;
458
+ atlasH: number;
459
+ bearingX: number;
460
+ bearingY: number;
461
+ /** True when this glyph lives in the COLRv1 color atlas (RGBA) rather than the SDF atlas (R8). */
462
+ isColor: boolean;
463
+ };
464
+
465
+ /**
466
+ * A Map with a maximum capacity that evicts the least-recently used entries.
467
+ *
468
+ * Both `get` and `set` refresh the entry's position, making it the most recent.
469
+ * When the map exceeds `maxSize`, the least-recently used entries are evicted.
470
+ */
471
+ export declare class LRUMap<K, V> {
472
+ private _map;
473
+ private _maxSize;
474
+ constructor(maxSize: number);
475
+ get size(): number;
476
+ has(key: K): boolean;
477
+ get(key: K): V | undefined;
478
+ set(key: K, value: V): void;
479
+ delete(key: K): boolean;
480
+ clear(): void;
481
+ }
482
+
483
+ export declare type ParseCssFontFamilyOptions = CssFontFaceFilter & {
484
+ /** Base URL used to resolve relative `src: url(...)` references. */
485
+ baseUrl?: string;
486
+ };
487
+
488
+ /**
489
+ * Parse a CSS `unicode-range` descriptor value (e.g. `"U+0-7F, U+131, U+4??"`)
490
+ * into inclusive codepoint ranges. Supports single codepoints (`U+26`),
491
+ * intervals (`U+0102-0103`) and wildcards (`U+4??`).
492
+ */
493
+ export declare function parseCssUnicodeRange(value: string): UnicodeRange[];
494
+
495
+ /**
496
+ * Build a {@link FontFamily} from CSS `@font-face` rules, so faces and their
497
+ * unicode ranges don't have to be written by hand. Each `@font-face` block
498
+ * becomes one face: its `src` URL and its `unicode-range` (faces stay
499
+ * lazily downloaded — a face is only fetched once text actually needs a
500
+ * codepoint in its ranges). Blocks without a `unicode-range` cover all
501
+ * codepoints.
502
+ *
503
+ * Face priority follows CSS semantics: later `@font-face` rules take
504
+ * precedence when their unicode-ranges overlap, so faces come out in
505
+ * reverse stylesheet order (use the `fontFamily` array to order families
506
+ * explicitly). The resulting first face doubles as the fallback for
507
+ * codepoints no face covers — same semantics as a hand-written
508
+ * {@link FontFamily}.
509
+ *
510
+ * @param family Family name to register the faces under.
511
+ * @param cssText Stylesheet text containing `@font-face` rules.
512
+ * @param options Optional block filters and a `baseUrl` for relative URLs.
513
+ */
514
+ export declare function parseFontFamilyFromCss(family: string, cssText: string, options?: ParseCssFontFamilyOptions): FontFamily;
515
+
516
+ /** A single shaped glyph with positioning info. */
517
+ export declare type ShapedGlyph = {
518
+ glyphId: number;
519
+ /** Unique font index within the atlas (distinguishes glyphs from different fonts). */
520
+ fontIndex: number;
521
+ /** Pre-computed composite key (font_index, glyph_id) from WASM. */
522
+ compositeKey: bigint;
523
+ xAdvance: number;
524
+ yAdvance: number;
525
+ xOffset: number;
526
+ yOffset: number;
527
+ /** One of `GlyphCharClass` (line-break info). */
528
+ charClass: number;
529
+ };
530
+
531
+ /** Result from shaping text: glyph positions + atlas metrics. */
532
+ export declare type ShapeTextResult = {
533
+ glyphs: ShapedGlyph[];
534
+ metrics: GlyphMetrics[];
535
+ /** Font units per em (needed for converting font-unit to pixel space) */
536
+ unitsPerEm: number;
537
+ /** Ascender in font units (hhea), for multi-line layout. */
538
+ ascender: number;
539
+ /** Descender in font units (hhea, negative below baseline). */
540
+ descender: number;
541
+ /** Extra line gap in font units (hhea). */
542
+ lineGap: number;
543
+ /** FontManager-internal: the atlas generation these metrics were built
544
+ * under. When the atlas evicts glyphs its generation bumps, marking older
545
+ * cached results stale so they are re-shaped on next use. Unset on results
546
+ * fresh from the worker; the FontManager stamps it when caching. */
547
+ _generation?: number;
548
+ };
549
+
550
+ /** Inclusive codepoint range covered by a font face. */
551
+ export declare type UnicodeRange = {
552
+ from: number;
553
+ to: number;
554
+ };
555
+
556
+ export { }