three-text 0.5.1 → 0.6.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_THIRD_PARTY +15 -0
- package/README.md +80 -50
- package/dist/index.cjs +66 -20
- package/dist/index.d.ts +8 -0
- package/dist/index.js +66 -20
- package/dist/index.min.cjs +310 -307
- package/dist/index.min.js +265 -262
- package/dist/index.umd.js +68 -21
- package/dist/index.umd.min.js +268 -265
- package/dist/three/index.cjs +2 -1
- package/dist/three/index.d.ts +1 -0
- package/dist/three/index.js +2 -1
- package/dist/three/react.cjs +35 -17
- package/dist/three/react.d.ts +8 -0
- package/dist/three/react.js +35 -17
- package/dist/types/core/Text.d.ts +6 -0
- package/dist/types/core/types.d.ts +2 -33
- package/dist/types/three/index.d.ts +1 -0
- package/dist/types/vector/core/index.d.ts +28 -0
- package/dist/types/vector/index.d.ts +17 -12
- package/dist/types/vector/react.d.ts +3 -4
- package/dist/types/vector/slug/SlugPacker.d.ts +2 -0
- package/dist/types/vector/slug/curveUtils.d.ts +6 -0
- package/dist/types/vector/slug/index.d.ts +8 -0
- package/dist/types/vector/slug/shaderStrings.d.ts +4 -0
- package/dist/types/vector/slug/slugGLSL.d.ts +21 -0
- package/dist/types/vector/slug/slugTSL.d.ts +13 -0
- package/dist/types/vector/slug/types.d.ts +30 -0
- package/dist/types/vector/slug/unpackVertices.d.ts +11 -0
- package/dist/types/vector/webgl/index.d.ts +7 -3
- package/dist/types/vector/webgpu/index.d.ts +4 -4
- package/dist/vector/all.cjs +21 -0
- package/dist/vector/all.d.ts +134 -0
- package/dist/vector/all.js +2 -0
- package/dist/vector/core/index.cjs +856 -0
- package/dist/vector/core/index.d.ts +63 -0
- package/dist/vector/core/index.js +854 -0
- package/dist/vector/core.cjs +5489 -0
- package/dist/vector/core.d.ts +402 -0
- package/dist/vector/core.js +5486 -0
- package/dist/vector/index.cjs +5 -1305
- package/dist/vector/index.d.ts +41 -67
- package/dist/vector/index.js +3 -1306
- package/dist/vector/index2.cjs +287 -0
- package/dist/vector/index2.js +264 -0
- package/dist/vector/loopBlinnTSL.d.ts +69 -0
- package/dist/vector/react.cjs +54 -40
- package/dist/vector/react.d.ts +11 -2
- package/dist/vector/react.js +55 -41
- package/dist/vector/slugTSL.cjs +252 -0
- package/dist/vector/slugTSL.js +231 -0
- package/dist/vector/webgl/index.cjs +131 -201
- package/dist/vector/webgl/index.d.ts +19 -44
- package/dist/vector/webgl/index.js +131 -201
- package/dist/vector/webgpu/index.cjs +100 -283
- package/dist/vector/webgpu/index.d.ts +16 -45
- package/dist/vector/webgpu/index.js +100 -283
- package/package.json +6 -1
- package/dist/types/vector/GlyphVectorGeometryBuilder.d.ts +0 -26
- package/dist/types/vector/LoopBlinnGeometry.d.ts +0 -68
- package/dist/types/vector/loopBlinnTSL.d.ts +0 -11
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @license
|
|
3
|
-
* three-text v0.
|
|
3
|
+
* three-text v0.6.0
|
|
4
4
|
* Copyright © 2025-2026 Jeremy Tribby, Countertype LLC
|
|
5
5
|
* SPDX-License-Identifier: MIT
|
|
6
6
|
*/
|
|
@@ -3260,6 +3260,8 @@ class Text {
|
|
|
3260
3260
|
static { this.patternCache = new Map(); }
|
|
3261
3261
|
static { this.hbInitPromise = null; }
|
|
3262
3262
|
static { this.fontCache = new Map(); }
|
|
3263
|
+
static { this.fontLoadPromises = new Map(); }
|
|
3264
|
+
static { this.fontRefCounts = new Map(); }
|
|
3263
3265
|
static { this.fontCacheMemoryBytes = 0; }
|
|
3264
3266
|
static { this.maxFontCacheMemoryBytes = Infinity; }
|
|
3265
3267
|
static { this.fontIdCounter = 0; }
|
|
@@ -3304,9 +3306,9 @@ class Text {
|
|
|
3304
3306
|
if (!Text.hbInitPromise) {
|
|
3305
3307
|
Text.hbInitPromise = HarfBuzzLoader.getHarfBuzz();
|
|
3306
3308
|
}
|
|
3307
|
-
const loadedFont = await Text.resolveFont(options);
|
|
3309
|
+
const { loadedFont, fontKey } = await Text.resolveFont(options);
|
|
3308
3310
|
const text = new Text();
|
|
3309
|
-
text.setLoadedFont(loadedFont);
|
|
3311
|
+
text.setLoadedFont(loadedFont, fontKey);
|
|
3310
3312
|
const result = await text.createLayout(options);
|
|
3311
3313
|
const update = async (newOptions) => {
|
|
3312
3314
|
const mergedOptions = { ...options };
|
|
@@ -3319,8 +3321,8 @@ class Text {
|
|
|
3319
3321
|
if (newOptions.font !== undefined ||
|
|
3320
3322
|
newOptions.fontVariations !== undefined ||
|
|
3321
3323
|
newOptions.fontFeatures !== undefined) {
|
|
3322
|
-
const newLoadedFont = await Text.resolveFont(mergedOptions);
|
|
3323
|
-
text.setLoadedFont(newLoadedFont);
|
|
3324
|
+
const { loadedFont: newLoadedFont, fontKey: newFontKey } = await Text.resolveFont(mergedOptions);
|
|
3325
|
+
text.setLoadedFont(newLoadedFont, newFontKey);
|
|
3324
3326
|
text.resetHelpers();
|
|
3325
3327
|
}
|
|
3326
3328
|
options = mergedOptions;
|
|
@@ -3341,6 +3343,22 @@ class Text {
|
|
|
3341
3343
|
dispose: () => text.destroy()
|
|
3342
3344
|
};
|
|
3343
3345
|
}
|
|
3346
|
+
static retainFont(fontKey) {
|
|
3347
|
+
Text.fontRefCounts.set(fontKey, (Text.fontRefCounts.get(fontKey) ?? 0) + 1);
|
|
3348
|
+
}
|
|
3349
|
+
static releaseFont(fontKey, loadedFont) {
|
|
3350
|
+
const nextCount = (Text.fontRefCounts.get(fontKey) ?? 0) - 1;
|
|
3351
|
+
if (nextCount > 0) {
|
|
3352
|
+
Text.fontRefCounts.set(fontKey, nextCount);
|
|
3353
|
+
return;
|
|
3354
|
+
}
|
|
3355
|
+
Text.fontRefCounts.delete(fontKey);
|
|
3356
|
+
// Cached fonts stay alive while present in the cache. If a font has been
|
|
3357
|
+
// evicted, destroy it once the last live handle releases it.
|
|
3358
|
+
if (!Text.fontCache.has(fontKey)) {
|
|
3359
|
+
FontLoader.destroyFont(loadedFont);
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3344
3362
|
static async resolveFont(options) {
|
|
3345
3363
|
const baseFontKey = typeof options.font === 'string'
|
|
3346
3364
|
? options.font
|
|
@@ -3354,9 +3372,17 @@ class Text {
|
|
|
3354
3372
|
}
|
|
3355
3373
|
let loadedFont = Text.fontCache.get(fontKey);
|
|
3356
3374
|
if (!loadedFont) {
|
|
3357
|
-
|
|
3375
|
+
let loadPromise = Text.fontLoadPromises.get(fontKey);
|
|
3376
|
+
if (!loadPromise) {
|
|
3377
|
+
loadPromise = Text.loadAndCacheFont(fontKey, options.font, options.fontVariations, options.fontFeatures).finally(() => {
|
|
3378
|
+
Text.fontLoadPromises.delete(fontKey);
|
|
3379
|
+
});
|
|
3380
|
+
Text.fontLoadPromises.set(fontKey, loadPromise);
|
|
3381
|
+
}
|
|
3382
|
+
loadedFont = await loadPromise;
|
|
3358
3383
|
}
|
|
3359
|
-
|
|
3384
|
+
Text.retainFont(fontKey);
|
|
3385
|
+
return { loadedFont, fontKey };
|
|
3360
3386
|
}
|
|
3361
3387
|
static async loadAndCacheFont(fontKey, font, fontVariations, fontFeatures) {
|
|
3362
3388
|
const tempText = new Text();
|
|
@@ -3388,8 +3414,12 @@ class Text {
|
|
|
3388
3414
|
const firstKey = Text.fontCache.keys().next().value;
|
|
3389
3415
|
if (firstKey === undefined)
|
|
3390
3416
|
break;
|
|
3417
|
+
const font = Text.fontCache.get(firstKey);
|
|
3391
3418
|
Text.trackFontCacheRemove(firstKey);
|
|
3392
3419
|
Text.fontCache.delete(firstKey);
|
|
3420
|
+
if ((Text.fontRefCounts.get(firstKey) ?? 0) <= 0 && font) {
|
|
3421
|
+
FontLoader.destroyFont(font);
|
|
3422
|
+
}
|
|
3393
3423
|
}
|
|
3394
3424
|
}
|
|
3395
3425
|
static generateFontContentHash(buffer) {
|
|
@@ -3411,8 +3441,12 @@ class Text {
|
|
|
3411
3441
|
return `c${++Text.fontIdCounter}`;
|
|
3412
3442
|
}
|
|
3413
3443
|
}
|
|
3414
|
-
setLoadedFont(loadedFont) {
|
|
3444
|
+
setLoadedFont(loadedFont, fontKey) {
|
|
3445
|
+
if (this.loadedFont && this.loadedFont !== loadedFont) {
|
|
3446
|
+
this.releaseCurrentFont();
|
|
3447
|
+
}
|
|
3415
3448
|
this.loadedFont = loadedFont;
|
|
3449
|
+
this.currentFontCacheKey = fontKey;
|
|
3416
3450
|
const contentHash = Text.generateFontContentHash(loadedFont._buffer);
|
|
3417
3451
|
this.currentFontId = `font_${contentHash}`;
|
|
3418
3452
|
if (loadedFont.fontVariations) {
|
|
@@ -3422,6 +3456,29 @@ class Text {
|
|
|
3422
3456
|
this.currentFontId += `_feat_${Text.stableStringify(loadedFont.fontFeatures)}`;
|
|
3423
3457
|
}
|
|
3424
3458
|
}
|
|
3459
|
+
releaseCurrentFont() {
|
|
3460
|
+
if (!this.loadedFont)
|
|
3461
|
+
return;
|
|
3462
|
+
const currentFont = this.loadedFont;
|
|
3463
|
+
const currentFontKey = this.currentFontCacheKey;
|
|
3464
|
+
try {
|
|
3465
|
+
if (currentFontKey) {
|
|
3466
|
+
Text.releaseFont(currentFontKey, currentFont);
|
|
3467
|
+
}
|
|
3468
|
+
else {
|
|
3469
|
+
FontLoader.destroyFont(currentFont);
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
catch (error) {
|
|
3473
|
+
logger.warn('Error destroying HarfBuzz objects:', error);
|
|
3474
|
+
}
|
|
3475
|
+
finally {
|
|
3476
|
+
this.loadedFont = undefined;
|
|
3477
|
+
this.currentFontCacheKey = undefined;
|
|
3478
|
+
this.textLayout = undefined;
|
|
3479
|
+
this.textShaper = undefined;
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3425
3482
|
async loadFont(fontSrc, fontVariations, fontFeatures) {
|
|
3426
3483
|
perfLogger.start('Text.loadFont', {
|
|
3427
3484
|
fontSrc: typeof fontSrc === 'string' ? fontSrc : `buffer(${fontSrc.byteLength})`
|
|
@@ -3641,18 +3698,7 @@ class Text {
|
|
|
3641
3698
|
if (!this.loadedFont) {
|
|
3642
3699
|
return;
|
|
3643
3700
|
}
|
|
3644
|
-
|
|
3645
|
-
try {
|
|
3646
|
-
FontLoader.destroyFont(currentFont);
|
|
3647
|
-
}
|
|
3648
|
-
catch (error) {
|
|
3649
|
-
logger.warn('Error destroying HarfBuzz objects:', error);
|
|
3650
|
-
}
|
|
3651
|
-
finally {
|
|
3652
|
-
this.loadedFont = undefined;
|
|
3653
|
-
this.textLayout = undefined;
|
|
3654
|
-
this.textShaper = undefined;
|
|
3655
|
-
}
|
|
3701
|
+
this.releaseCurrentFont();
|
|
3656
3702
|
}
|
|
3657
3703
|
}
|
|
3658
3704
|
|