three-text 0.4.8 → 0.4.9

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.
Files changed (41) hide show
  1. package/README.md +6 -6
  2. package/dist/core/Text.d.ts +56 -0
  3. package/dist/core/cache/GlyphContourCollector.d.ts +38 -0
  4. package/dist/core/cache/GlyphGeometryBuilder.d.ts +60 -0
  5. package/dist/core/cache/sharedCaches.d.ts +15 -0
  6. package/dist/core/font/FontLoader.d.ts +9 -0
  7. package/dist/core/font/FontMetadata.d.ts +32 -0
  8. package/dist/core/font/TableDirectory.d.ts +7 -0
  9. package/dist/core/font/WoffConverter.d.ts +9 -0
  10. package/dist/core/font/constants.d.ts +14 -0
  11. package/dist/core/geometry/BoundaryClusterer.d.ts +8 -0
  12. package/dist/core/geometry/Extruder.d.ts +10 -0
  13. package/dist/core/geometry/PathOptimizer.d.ts +21 -0
  14. package/dist/core/geometry/Polygonizer.d.ts +56 -0
  15. package/dist/core/geometry/Tessellator.d.ts +14 -0
  16. package/dist/core/layout/LineBreak.d.ts +95 -0
  17. package/dist/core/layout/TextLayout.d.ts +59 -0
  18. package/dist/core/layout/TextRangeQuery.d.ts +11 -0
  19. package/dist/core/layout/constants.d.ts +7 -0
  20. package/dist/core/shaping/DrawCallbacks.d.ts +19 -0
  21. package/dist/core/shaping/HarfBuzzLoader.d.ts +6 -0
  22. package/dist/core/shaping/TextMeasurer.d.ts +5 -0
  23. package/dist/core/shaping/TextShaper.d.ts +35 -0
  24. package/dist/core/shaping/fontFeatures.d.ts +3 -0
  25. package/dist/core/types.d.ts +354 -0
  26. package/dist/hyphenation/HyphenationPatternLoader.d.ts +2 -0
  27. package/dist/hyphenation/index.d.ts +7 -0
  28. package/dist/hyphenation/types.d.ts +6 -0
  29. package/dist/index.cjs +3 -4
  30. package/dist/index.js +3 -4
  31. package/dist/index.min.cjs +2 -2
  32. package/dist/index.min.js +2 -2
  33. package/dist/index.umd.js +63 -16
  34. package/dist/index.umd.min.js +552 -550
  35. package/dist/utils/Cache.d.ts +14 -0
  36. package/dist/utils/Logger.d.ts +8 -0
  37. package/dist/utils/MinHeap.d.ts +14 -0
  38. package/dist/utils/PerformanceLogger.d.ts +20 -0
  39. package/dist/utils/loadBinary.d.ts +1 -0
  40. package/dist/utils/vectors.d.ts +75 -0
  41. package/package.json +3 -2
@@ -0,0 +1,3 @@
1
+ export declare function convertFontFeaturesToString(features?: {
2
+ [tag: string]: boolean | number;
3
+ }): string | undefined;
@@ -0,0 +1,354 @@
1
+ import type { HyphenationTrieNode } from '../hyphenation';
2
+ import type { CacheStats } from '../utils/Cache';
3
+ import type { Vec2, Vec3, BoundingBox } from '../utils/vectors';
4
+ export type { HyphenationTrieNode };
5
+ export interface Path {
6
+ points: Vec2[];
7
+ glyphIndex: number;
8
+ bounds?: {
9
+ minX: number;
10
+ minY: number;
11
+ maxX: number;
12
+ maxY: number;
13
+ };
14
+ }
15
+ export interface HarfBuzzGlyph {
16
+ g: number;
17
+ cl: number;
18
+ ax: number;
19
+ ay: number;
20
+ dx: number;
21
+ dy: number;
22
+ x?: number;
23
+ y?: number;
24
+ lineIndex: number;
25
+ absoluteTextIndex: number;
26
+ }
27
+ export interface GlyphCluster {
28
+ text: string;
29
+ glyphs: HarfBuzzGlyph[];
30
+ position: Vec3;
31
+ }
32
+ export interface GlyphContours {
33
+ glyphId: number;
34
+ paths: Path[];
35
+ bounds: {
36
+ min: {
37
+ x: number;
38
+ y: number;
39
+ };
40
+ max: {
41
+ x: number;
42
+ y: number;
43
+ };
44
+ };
45
+ }
46
+ export type TextAlign = 'left' | 'center' | 'right' | 'justify';
47
+ export type TextDirection = 'ltr' | 'rtl';
48
+ export interface LineInfo {
49
+ text: string;
50
+ originalStart: number;
51
+ originalEnd: number;
52
+ xOffset: number;
53
+ adjustmentRatio?: number;
54
+ isLastLine?: boolean;
55
+ naturalWidth?: number;
56
+ endedWithHyphen?: boolean;
57
+ }
58
+ export interface LoadedFont {
59
+ hb: HarfBuzzAPI;
60
+ fontBlob: HarfBuzzBlob;
61
+ face: HarfBuzzFace;
62
+ font: HarfBuzzFont;
63
+ module: HarfBuzzModule;
64
+ upem: number;
65
+ metrics: ExtractedMetrics;
66
+ fontVariations?: {
67
+ [key: string]: number;
68
+ };
69
+ fontFeatures?: {
70
+ [tag: string]: boolean | number;
71
+ };
72
+ isVariable?: boolean;
73
+ variationAxes?: {
74
+ [key: string]: VariationAxis;
75
+ };
76
+ availableFeatures?: string[];
77
+ featureNames?: {
78
+ [tag: string]: string;
79
+ };
80
+ _buffer?: ArrayBuffer;
81
+ }
82
+ export interface HarfBuzzModule {
83
+ addFunction: (func: Function, signature: string) => number;
84
+ exports: any;
85
+ removeFunction: (ptr: number) => void;
86
+ }
87
+ export interface VariationAxis {
88
+ min: number;
89
+ default: number;
90
+ max: number;
91
+ name?: string;
92
+ }
93
+ export interface HarfBuzzAPI {
94
+ createBlob: (data: Uint8Array) => HarfBuzzBlob;
95
+ createFace: (blob: HarfBuzzBlob, index: number) => HarfBuzzFace;
96
+ createFont: (face: HarfBuzzFace) => HarfBuzzFont;
97
+ createBuffer: () => HarfBuzzBuffer;
98
+ shape: (font: HarfBuzzFont, buffer: HarfBuzzBuffer, features?: string) => void;
99
+ }
100
+ export interface HarfBuzzBlob {
101
+ destroy: () => void;
102
+ }
103
+ export interface HarfBuzzFace {
104
+ destroy: () => void;
105
+ getAxisInfos: () => {
106
+ [tag: string]: VariationAxis;
107
+ };
108
+ }
109
+ export interface HarfBuzzFont {
110
+ ptr: number;
111
+ destroy: () => void;
112
+ setScale: (xScale: number, yScale: number) => void;
113
+ setVariations: (variations: {
114
+ [key: string]: number;
115
+ }) => void;
116
+ }
117
+ export interface HarfBuzzBuffer {
118
+ addText: (text: string) => void;
119
+ guessSegmentProperties: () => void;
120
+ setDirection: (direction: string) => void;
121
+ json: (font: HarfBuzzFont) => any[];
122
+ destroy: () => void;
123
+ }
124
+ export interface HarfBuzzInstance {
125
+ hb: HarfBuzzAPI;
126
+ module: HarfBuzzModule;
127
+ }
128
+ export interface ExtractedMetrics {
129
+ isCFF: boolean;
130
+ unitsPerEm: number;
131
+ hheaAscender: number | null;
132
+ hheaDescender: number | null;
133
+ hheaLineGap: number | null;
134
+ typoAscender: number | null;
135
+ typoDescender: number | null;
136
+ typoLineGap: number | null;
137
+ winAscent: number | null;
138
+ winDescent: number | null;
139
+ axisNames: {
140
+ [tag: string]: string;
141
+ } | null;
142
+ }
143
+ export interface VerticalMetrics {
144
+ ascender: number;
145
+ descender: number;
146
+ lineGap: number;
147
+ }
148
+ export interface FontMetrics {
149
+ ascender: number;
150
+ descender: number;
151
+ lineGap: number;
152
+ unitsPerEm: number;
153
+ naturalLineHeight: number;
154
+ }
155
+ export interface ProcessedPath {
156
+ outer: Path;
157
+ holes: Path[];
158
+ }
159
+ export interface Triangles {
160
+ vertices: number[];
161
+ indices: number[];
162
+ }
163
+ export interface ProcessedGeometry {
164
+ triangles: Triangles;
165
+ contours: number[][];
166
+ contoursAreBoundary?: boolean;
167
+ }
168
+ export interface GlyphData {
169
+ geometry: ProcessedGeometry;
170
+ vertices: Float32Array;
171
+ normals: Float32Array;
172
+ indices: Uint32Array;
173
+ bounds: {
174
+ min: {
175
+ x: number;
176
+ y: number;
177
+ z: number;
178
+ };
179
+ max: {
180
+ x: number;
181
+ y: number;
182
+ z: number;
183
+ };
184
+ };
185
+ useCount: number;
186
+ }
187
+ export interface PathInfo {
188
+ start: number;
189
+ count: number;
190
+ }
191
+ export interface GlyphGeometryInfo {
192
+ textIndex: number;
193
+ lineIndex: number;
194
+ vertexStart: number;
195
+ vertexCount: number;
196
+ bounds: {
197
+ min: {
198
+ x: number;
199
+ y: number;
200
+ z: number;
201
+ };
202
+ max: {
203
+ x: number;
204
+ y: number;
205
+ z: number;
206
+ };
207
+ };
208
+ paths?: PathInfo[];
209
+ }
210
+ export interface TextRange {
211
+ start: number;
212
+ end: number;
213
+ originalText: string;
214
+ bounds: {
215
+ min: {
216
+ x: number;
217
+ y: number;
218
+ z: number;
219
+ };
220
+ max: {
221
+ x: number;
222
+ y: number;
223
+ z: number;
224
+ };
225
+ }[];
226
+ glyphs: GlyphGeometryInfo[];
227
+ lineIndices: number[];
228
+ }
229
+ export interface TextQueryOptions {
230
+ byText?: string[];
231
+ byCharRange?: {
232
+ start: number;
233
+ end: number;
234
+ }[];
235
+ }
236
+ export interface TextGeometryInfo {
237
+ vertices: Float32Array;
238
+ normals: Float32Array;
239
+ indices: Uint32Array;
240
+ colors?: Float32Array;
241
+ glyphAttributes?: {
242
+ glyphCenter: Float32Array;
243
+ glyphIndex: Float32Array;
244
+ glyphLineIndex: Float32Array;
245
+ glyphProgress: Float32Array;
246
+ glyphBaselineY: Float32Array;
247
+ };
248
+ glyphs: GlyphGeometryInfo[];
249
+ planeBounds: BoundingBox;
250
+ stats: {
251
+ trianglesGenerated: number;
252
+ verticesGenerated: number;
253
+ pointsRemovedByVisvalingam: number;
254
+ originalPointCount: number;
255
+ } & Partial<CacheStats & {
256
+ hitRate: number;
257
+ memoryUsageMB: number;
258
+ }>;
259
+ query(options: TextQueryOptions): TextRange[];
260
+ coloredRanges?: ColoredRange[];
261
+ }
262
+ export interface TextHandle extends TextGeometryInfo {
263
+ getLoadedFont(): LoadedFont | undefined;
264
+ getCacheSize(): number;
265
+ clearCache(): void;
266
+ measureTextWidth(text: string, letterSpacing?: number): number;
267
+ update(options: Partial<TextOptions>): Promise<TextHandle>;
268
+ }
269
+ export interface ColorByRange {
270
+ start: number;
271
+ end: number;
272
+ color: [number, number, number];
273
+ }
274
+ export interface ColorOptions {
275
+ default?: [number, number, number];
276
+ byText?: {
277
+ [text: string]: [number, number, number];
278
+ };
279
+ byCharRange?: ColorByRange[];
280
+ }
281
+ export interface ColoredRange {
282
+ start: number;
283
+ end: number;
284
+ originalText: string;
285
+ color: [number, number, number];
286
+ bounds: {
287
+ min: {
288
+ x: number;
289
+ y: number;
290
+ z: number;
291
+ };
292
+ max: {
293
+ x: number;
294
+ y: number;
295
+ z: number;
296
+ };
297
+ }[];
298
+ glyphs: GlyphGeometryInfo[];
299
+ lineIndices: number[];
300
+ }
301
+ export interface TextOptions {
302
+ text: string;
303
+ font: string | ArrayBuffer;
304
+ size?: number;
305
+ depth?: number;
306
+ lineHeight?: number;
307
+ letterSpacing?: number;
308
+ perGlyphAttributes?: boolean;
309
+ fontVariations?: {
310
+ [key: string]: number;
311
+ };
312
+ fontFeatures?: {
313
+ [tag: string]: boolean | number;
314
+ };
315
+ maxTextLength?: number;
316
+ removeOverlaps?: boolean;
317
+ curveSteps?: number;
318
+ curveFidelity?: CurveFidelityConfig;
319
+ geometryOptimization?: GeometryOptimizationOptions;
320
+ layout?: LayoutOptions;
321
+ color?: [number, number, number] | ColorOptions;
322
+ }
323
+ export interface HyphenationPatternsMap {
324
+ [language: string]: HyphenationTrieNode;
325
+ }
326
+ export interface CurveFidelityConfig {
327
+ distanceTolerance?: number;
328
+ angleTolerance?: number;
329
+ }
330
+ export interface GeometryOptimizationOptions {
331
+ enabled?: boolean;
332
+ areaThreshold?: number;
333
+ }
334
+ export interface LayoutOptions {
335
+ width?: number;
336
+ align?: TextAlign;
337
+ direction?: TextDirection;
338
+ respectExistingBreaks?: boolean;
339
+ hyphenate?: boolean;
340
+ language?: string;
341
+ patternsPath?: string;
342
+ tolerance?: number;
343
+ pretolerance?: number;
344
+ emergencyStretch?: number;
345
+ autoEmergencyStretch?: number;
346
+ hyphenationPatterns?: HyphenationPatternsMap;
347
+ lefthyphenmin?: number;
348
+ righthyphenmin?: number;
349
+ linepenalty?: number;
350
+ adjdemerits?: number;
351
+ hyphenpenalty?: number;
352
+ exhyphenpenalty?: number;
353
+ doublehyphendemerits?: number;
354
+ }
@@ -0,0 +1,2 @@
1
+ import { HyphenationTrieNode } from './types';
2
+ export declare function loadPattern(language: string, patternsPath?: string): Promise<HyphenationTrieNode>;
@@ -0,0 +1,7 @@
1
+ export interface HyphenationTrieNode {
2
+ patterns: number[] | null;
3
+ children: {
4
+ [char: string]: HyphenationTrieNode;
5
+ };
6
+ }
7
+ export { loadPattern } from './HyphenationPatternLoader';
@@ -0,0 +1,6 @@
1
+ export interface HyphenationTrieNode {
2
+ patterns: number[] | null;
3
+ children: {
4
+ [key: string]: HyphenationTrieNode;
5
+ };
6
+ }
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * three-text v0.4.8
2
+ * three-text v0.4.9
3
3
  * Copyright (C) 2025 Countertype LLC
4
4
  *
5
5
  * This program is free software: you can redistribute it and/or modify
@@ -2005,7 +2005,7 @@ class WoffConverter {
2005
2005
  }
2006
2006
  if (!woff2Decoder) {
2007
2007
  throw new Error('WOFF2 fonts require enabling the decoder. Add to your code:\n' +
2008
- " import { woff2Decode } from 'woff2-decode';\n" +
2008
+ " import { woff2Decode } from 'woff-lib/woff2/decode';\n" +
2009
2009
  ' Text.enableWoff2(woff2Decode);');
2010
2010
  }
2011
2011
  const decoded = await woff2Decoder(woff2Buffer);
@@ -5602,8 +5602,7 @@ class Text {
5602
5602
  static { this.fontCacheMemoryBytes = 0; }
5603
5603
  static { this.maxFontCacheMemoryBytes = Infinity; }
5604
5604
  static { this.fontIdCounter = 0; }
5605
- // Enable WOFF2 font support (adds ~45KB to bundle if imported)
5606
- // Usage: import { woff2Decode } from 'woff2-decode'; Text.enableWoff2(woff2Decode);
5605
+ // Enable WOFF2 font support
5607
5606
  static enableWoff2(decoder) {
5608
5607
  setWoff2Decoder(decoder);
5609
5608
  }
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * three-text v0.4.8
2
+ * three-text v0.4.9
3
3
  * Copyright (C) 2025 Countertype LLC
4
4
  *
5
5
  * This program is free software: you can redistribute it and/or modify
@@ -2002,7 +2002,7 @@ class WoffConverter {
2002
2002
  }
2003
2003
  if (!woff2Decoder) {
2004
2004
  throw new Error('WOFF2 fonts require enabling the decoder. Add to your code:\n' +
2005
- " import { woff2Decode } from 'woff2-decode';\n" +
2005
+ " import { woff2Decode } from 'woff-lib/woff2/decode';\n" +
2006
2006
  ' Text.enableWoff2(woff2Decode);');
2007
2007
  }
2008
2008
  const decoded = await woff2Decoder(woff2Buffer);
@@ -5599,8 +5599,7 @@ class Text {
5599
5599
  static { this.fontCacheMemoryBytes = 0; }
5600
5600
  static { this.maxFontCacheMemoryBytes = Infinity; }
5601
5601
  static { this.fontIdCounter = 0; }
5602
- // Enable WOFF2 font support (adds ~45KB to bundle if imported)
5603
- // Usage: import { woff2Decode } from 'woff2-decode'; Text.enableWoff2(woff2Decode);
5602
+ // Enable WOFF2 font support
5604
5603
  static enableWoff2(decoder) {
5605
5604
  setWoff2Decoder(decoder);
5606
5605
  }
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * three-text v0.4.8
2
+ * three-text v0.4.9
3
3
  * Copyright (C) 2025 Countertype LLC
4
4
  *
5
5
  * This program is free software: you can redistribute it and/or modify
@@ -307,7 +307,7 @@ if(n.byteLength!==t.Be)throw Error(`Decompression failed: expected ${t.Be} bytes
307
307
  return new Uint8Array(n)}))
308
308
  for(let t=0;s>t;t++){const e=l[t],i=12+16*t
309
309
  a.setUint32(i,e.tag),a.setUint32(i+4,e.t),a.setUint32(i+8,c),a.setUint32(i+12,e.Be),o.set(u[t],c),c+=e.Be,c+=(4-e.Be%4)%4}return o.buffer.slice(0,c)}static async Ne(t){if(new DataView(t).getUint32(0)!==C)throw Error("Not a valid WOFF2 font")
310
- if(!V)throw Error("WOFF2 fonts require enabling the decoder. Add to your code:\n import { woff2Decode } from 'woff2-decode';\n Text.enableWoff2(woff2Decode);")
310
+ if(!V)throw Error("WOFF2 fonts require enabling the decoder. Add to your code:\n import { woff2Decode } from 'woff-lib/woff2/decode';\n Text.enableWoff2(woff2Decode);")
311
311
  return(await V(t)).buffer}static async Ue(t){const e=new ReadableStream({start(e){e.enqueue(t),e.close()}}).pipeThrough(new DecompressionStream("deflate"))
312
312
  return new Response(e).arrayBuffer()}}class Y{constructor(t){this.$e=t}async Pe(t,e){if(!t||12>t.byteLength)throw Error("Invalid font buffer: too small to be a valid font file")
313
313
  const i=q.ke(t)
package/dist/index.min.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * three-text v0.4.8
2
+ * three-text v0.4.9
3
3
  * Copyright (C) 2025 Countertype LLC
4
4
  *
5
5
  * This program is free software: you can redistribute it and/or modify
@@ -306,7 +306,7 @@ if(n.byteLength!==t.Be)throw Error(`Decompression failed: expected ${t.Be} bytes
306
306
  return new Uint8Array(n)}))
307
307
  for(let t=0;s>t;t++){const e=l[t],i=12+16*t
308
308
  a.setUint32(i,e.tag),a.setUint32(i+4,e.t),a.setUint32(i+8,c),a.setUint32(i+12,e.Be),o.set(u[t],c),c+=e.Be,c+=(4-e.Be%4)%4}return o.buffer.slice(0,c)}static async Ue(t){if(new DataView(t).getUint32(0)!==C)throw Error("Not a valid WOFF2 font")
309
- if(!V)throw Error("WOFF2 fonts require enabling the decoder. Add to your code:\n import { woff2Decode } from 'woff2-decode';\n Text.enableWoff2(woff2Decode);")
309
+ if(!V)throw Error("WOFF2 fonts require enabling the decoder. Add to your code:\n import { woff2Decode } from 'woff-lib/woff2/decode';\n Text.enableWoff2(woff2Decode);")
310
310
  return(await V(t)).buffer}static async Ne(t){const e=new ReadableStream({start(e){e.enqueue(t),e.close()}}).pipeThrough(new DecompressionStream("deflate"))
311
311
  return new Response(e).arrayBuffer()}}class Y{constructor(t){this.$e=t}async Pe(t,e){if(!t||12>t.byteLength)throw Error("Invalid font buffer: too small to be a valid font file")
312
312
  const i=q.ke(t)
package/dist/index.umd.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * three-text v0.4.8
2
+ * three-text v0.4.9
3
3
  * Copyright (C) 2025 Countertype LLC
4
4
  *
5
5
  * This program is free software: you can redistribute it and/or modify
@@ -12,10 +12,10 @@
12
12
  * This software includes third-party code - see LICENSE_THIRD_PARTY for details.
13
13
  */
14
14
  (function (global, factory) {
15
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
16
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
17
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ThreeText = {}));
18
- })(this, (function (exports) {
15
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three')) :
16
+ typeof define === 'function' && define.amd ? define(['exports', 'three'], factory) :
17
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ThreeText = {}, global.THREE));
18
+ })(this, (function (exports, three) {
19
19
  // Cached flag check at module load time for zero-cost logging
20
20
  const isLogEnabled = (() => {
21
21
  if (typeof window !== 'undefined' && window.THREE_TEXT_LOG) {
@@ -2007,7 +2007,7 @@
2007
2007
  }
2008
2008
  if (!woff2Decoder) {
2009
2009
  throw new Error('WOFF2 fonts require enabling the decoder. Add to your code:\n' +
2010
- " import { woff2Decode } from 'woff2-decode';\n" +
2010
+ " import { woff2Decode } from 'woff-lib/woff2/decode';\n" +
2011
2011
  ' Text.enableWoff2(woff2Decode);');
2012
2012
  }
2013
2013
  const decoded = await woff2Decoder(woff2Buffer);
@@ -2434,9 +2434,6 @@
2434
2434
  return `${fontId}_${glyphId}_${roundedDepth}_${removeOverlaps}`;
2435
2435
  }
2436
2436
  const globalGlyphCache = new Cache();
2437
- function createGlyphCache() {
2438
- return new Cache();
2439
- }
2440
2437
  const globalContourCache = new Cache();
2441
2438
  const globalWordCache = new Cache();
2442
2439
  const globalClusteringCache = new Cache();
@@ -5599,15 +5596,14 @@
5599
5596
 
5600
5597
  const DEFAULT_MAX_TEXT_LENGTH = 100000;
5601
5598
  const DEFAULT_FONT_SIZE = 72;
5602
- class Text {
5599
+ let Text$1 = class Text {
5603
5600
  static { this.patternCache = new Map(); }
5604
5601
  static { this.hbInitPromise = null; }
5605
5602
  static { this.fontCache = new Map(); }
5606
5603
  static { this.fontCacheMemoryBytes = 0; }
5607
5604
  static { this.maxFontCacheMemoryBytes = Infinity; }
5608
5605
  static { this.fontIdCounter = 0; }
5609
- // Enable WOFF2 font support (adds ~45KB to bundle if imported)
5610
- // Usage: import { woff2Decode } from 'woff2-decode'; Text.enableWoff2(woff2Decode);
5606
+ // Enable WOFF2 font support
5611
5607
  static enableWoff2(decoder) {
5612
5608
  setWoff2Decoder(decoder);
5613
5609
  }
@@ -6348,12 +6344,63 @@
6348
6344
  this.textShaper = undefined;
6349
6345
  }
6350
6346
  }
6347
+ };
6348
+
6349
+ // Three.js adapter - wraps core text processing and returns BufferGeometry
6350
+ // This is a thin convenience layer for Three.js users
6351
+ function convertToThree(result) {
6352
+ // Create BufferGeometry from raw arrays
6353
+ const geometry = new three.BufferGeometry();
6354
+ geometry.setAttribute('position', new three.Float32BufferAttribute(result.vertices, 3));
6355
+ geometry.setAttribute('normal', new three.Float32BufferAttribute(result.normals, 3));
6356
+ geometry.setIndex(new three.Uint32BufferAttribute(result.indices, 1));
6357
+ // Add optional color attribute (only if provided)
6358
+ if (result.colors) {
6359
+ geometry.setAttribute('color', new three.Float32BufferAttribute(result.colors, 3));
6360
+ }
6361
+ if (result.glyphAttributes) {
6362
+ geometry.setAttribute('glyphCenter', new three.Float32BufferAttribute(result.glyphAttributes.glyphCenter, 3));
6363
+ geometry.setAttribute('glyphIndex', new three.Float32BufferAttribute(result.glyphAttributes.glyphIndex, 1));
6364
+ geometry.setAttribute('glyphLineIndex', new three.Float32BufferAttribute(result.glyphAttributes.glyphLineIndex, 1));
6365
+ geometry.setAttribute('glyphProgress', new three.Float32BufferAttribute(result.glyphAttributes.glyphProgress, 1));
6366
+ geometry.setAttribute('glyphBaselineY', new three.Float32BufferAttribute(result.glyphAttributes.glyphBaselineY, 1));
6367
+ }
6368
+ geometry.computeBoundingBox();
6369
+ // Return Three.js specific interface with utility methods
6370
+ return {
6371
+ geometry,
6372
+ glyphs: result.glyphs,
6373
+ planeBounds: result.planeBounds,
6374
+ stats: result.stats,
6375
+ query: result.query,
6376
+ coloredRanges: result.coloredRanges,
6377
+ // Pass through utility methods from core
6378
+ getLoadedFont: result.getLoadedFont,
6379
+ getCacheSize: result.getCacheSize,
6380
+ clearCache: result.clearCache,
6381
+ measureTextWidth: result.measureTextWidth,
6382
+ update: async (newOptions) => {
6383
+ const newCoreResult = await result.update(newOptions);
6384
+ return convertToThree(newCoreResult);
6385
+ }
6386
+ };
6387
+ }
6388
+ class Text {
6389
+ // Delegate static methods to core
6390
+ static { this.setHarfBuzzPath = Text$1.setHarfBuzzPath; }
6391
+ static { this.setHarfBuzzBuffer = Text$1.setHarfBuzzBuffer; }
6392
+ static { this.init = Text$1.init; }
6393
+ static { this.registerPattern = Text$1.registerPattern; }
6394
+ static { this.preloadPatterns = Text$1.preloadPatterns; }
6395
+ static { this.setMaxFontCacheMemoryMB = Text$1.setMaxFontCacheMemoryMB; }
6396
+ static { this.enableWoff2 = Text$1.enableWoff2; }
6397
+ // Main API - wraps core result in BufferGeometry
6398
+ static async create(options) {
6399
+ const coreResult = await Text$1.create(options);
6400
+ return convertToThree(coreResult);
6401
+ }
6351
6402
  }
6352
6403
 
6353
- exports.DEFAULT_CURVE_FIDELITY = DEFAULT_CURVE_FIDELITY;
6354
- exports.FontMetadataExtractor = FontMetadataExtractor;
6355
6404
  exports.Text = Text;
6356
- exports.createGlyphCache = createGlyphCache;
6357
- exports.globalGlyphCache = globalGlyphCache;
6358
6405
 
6359
6406
  }));