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.umd.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
|
*/
|
|
@@ -3267,6 +3267,8 @@
|
|
|
3267
3267
|
static { this.patternCache = new Map(); }
|
|
3268
3268
|
static { this.hbInitPromise = null; }
|
|
3269
3269
|
static { this.fontCache = new Map(); }
|
|
3270
|
+
static { this.fontLoadPromises = new Map(); }
|
|
3271
|
+
static { this.fontRefCounts = new Map(); }
|
|
3270
3272
|
static { this.fontCacheMemoryBytes = 0; }
|
|
3271
3273
|
static { this.maxFontCacheMemoryBytes = Infinity; }
|
|
3272
3274
|
static { this.fontIdCounter = 0; }
|
|
@@ -3311,9 +3313,9 @@
|
|
|
3311
3313
|
if (!Text.hbInitPromise) {
|
|
3312
3314
|
Text.hbInitPromise = HarfBuzzLoader.getHarfBuzz();
|
|
3313
3315
|
}
|
|
3314
|
-
const loadedFont = await Text.resolveFont(options);
|
|
3316
|
+
const { loadedFont, fontKey } = await Text.resolveFont(options);
|
|
3315
3317
|
const text = new Text();
|
|
3316
|
-
text.setLoadedFont(loadedFont);
|
|
3318
|
+
text.setLoadedFont(loadedFont, fontKey);
|
|
3317
3319
|
const result = await text.createLayout(options);
|
|
3318
3320
|
const update = async (newOptions) => {
|
|
3319
3321
|
const mergedOptions = { ...options };
|
|
@@ -3326,8 +3328,8 @@
|
|
|
3326
3328
|
if (newOptions.font !== undefined ||
|
|
3327
3329
|
newOptions.fontVariations !== undefined ||
|
|
3328
3330
|
newOptions.fontFeatures !== undefined) {
|
|
3329
|
-
const newLoadedFont = await Text.resolveFont(mergedOptions);
|
|
3330
|
-
text.setLoadedFont(newLoadedFont);
|
|
3331
|
+
const { loadedFont: newLoadedFont, fontKey: newFontKey } = await Text.resolveFont(mergedOptions);
|
|
3332
|
+
text.setLoadedFont(newLoadedFont, newFontKey);
|
|
3331
3333
|
text.resetHelpers();
|
|
3332
3334
|
}
|
|
3333
3335
|
options = mergedOptions;
|
|
@@ -3348,6 +3350,22 @@
|
|
|
3348
3350
|
dispose: () => text.destroy()
|
|
3349
3351
|
};
|
|
3350
3352
|
}
|
|
3353
|
+
static retainFont(fontKey) {
|
|
3354
|
+
Text.fontRefCounts.set(fontKey, (Text.fontRefCounts.get(fontKey) ?? 0) + 1);
|
|
3355
|
+
}
|
|
3356
|
+
static releaseFont(fontKey, loadedFont) {
|
|
3357
|
+
const nextCount = (Text.fontRefCounts.get(fontKey) ?? 0) - 1;
|
|
3358
|
+
if (nextCount > 0) {
|
|
3359
|
+
Text.fontRefCounts.set(fontKey, nextCount);
|
|
3360
|
+
return;
|
|
3361
|
+
}
|
|
3362
|
+
Text.fontRefCounts.delete(fontKey);
|
|
3363
|
+
// Cached fonts stay alive while present in the cache. If a font has been
|
|
3364
|
+
// evicted, destroy it once the last live handle releases it.
|
|
3365
|
+
if (!Text.fontCache.has(fontKey)) {
|
|
3366
|
+
FontLoader.destroyFont(loadedFont);
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3351
3369
|
static async resolveFont(options) {
|
|
3352
3370
|
const baseFontKey = typeof options.font === 'string'
|
|
3353
3371
|
? options.font
|
|
@@ -3361,9 +3379,17 @@
|
|
|
3361
3379
|
}
|
|
3362
3380
|
let loadedFont = Text.fontCache.get(fontKey);
|
|
3363
3381
|
if (!loadedFont) {
|
|
3364
|
-
|
|
3382
|
+
let loadPromise = Text.fontLoadPromises.get(fontKey);
|
|
3383
|
+
if (!loadPromise) {
|
|
3384
|
+
loadPromise = Text.loadAndCacheFont(fontKey, options.font, options.fontVariations, options.fontFeatures).finally(() => {
|
|
3385
|
+
Text.fontLoadPromises.delete(fontKey);
|
|
3386
|
+
});
|
|
3387
|
+
Text.fontLoadPromises.set(fontKey, loadPromise);
|
|
3388
|
+
}
|
|
3389
|
+
loadedFont = await loadPromise;
|
|
3365
3390
|
}
|
|
3366
|
-
|
|
3391
|
+
Text.retainFont(fontKey);
|
|
3392
|
+
return { loadedFont, fontKey };
|
|
3367
3393
|
}
|
|
3368
3394
|
static async loadAndCacheFont(fontKey, font, fontVariations, fontFeatures) {
|
|
3369
3395
|
const tempText = new Text();
|
|
@@ -3395,8 +3421,12 @@
|
|
|
3395
3421
|
const firstKey = Text.fontCache.keys().next().value;
|
|
3396
3422
|
if (firstKey === undefined)
|
|
3397
3423
|
break;
|
|
3424
|
+
const font = Text.fontCache.get(firstKey);
|
|
3398
3425
|
Text.trackFontCacheRemove(firstKey);
|
|
3399
3426
|
Text.fontCache.delete(firstKey);
|
|
3427
|
+
if ((Text.fontRefCounts.get(firstKey) ?? 0) <= 0 && font) {
|
|
3428
|
+
FontLoader.destroyFont(font);
|
|
3429
|
+
}
|
|
3400
3430
|
}
|
|
3401
3431
|
}
|
|
3402
3432
|
static generateFontContentHash(buffer) {
|
|
@@ -3418,8 +3448,12 @@
|
|
|
3418
3448
|
return `c${++Text.fontIdCounter}`;
|
|
3419
3449
|
}
|
|
3420
3450
|
}
|
|
3421
|
-
setLoadedFont(loadedFont) {
|
|
3451
|
+
setLoadedFont(loadedFont, fontKey) {
|
|
3452
|
+
if (this.loadedFont && this.loadedFont !== loadedFont) {
|
|
3453
|
+
this.releaseCurrentFont();
|
|
3454
|
+
}
|
|
3422
3455
|
this.loadedFont = loadedFont;
|
|
3456
|
+
this.currentFontCacheKey = fontKey;
|
|
3423
3457
|
const contentHash = Text.generateFontContentHash(loadedFont._buffer);
|
|
3424
3458
|
this.currentFontId = `font_${contentHash}`;
|
|
3425
3459
|
if (loadedFont.fontVariations) {
|
|
@@ -3429,6 +3463,29 @@
|
|
|
3429
3463
|
this.currentFontId += `_feat_${Text.stableStringify(loadedFont.fontFeatures)}`;
|
|
3430
3464
|
}
|
|
3431
3465
|
}
|
|
3466
|
+
releaseCurrentFont() {
|
|
3467
|
+
if (!this.loadedFont)
|
|
3468
|
+
return;
|
|
3469
|
+
const currentFont = this.loadedFont;
|
|
3470
|
+
const currentFontKey = this.currentFontCacheKey;
|
|
3471
|
+
try {
|
|
3472
|
+
if (currentFontKey) {
|
|
3473
|
+
Text.releaseFont(currentFontKey, currentFont);
|
|
3474
|
+
}
|
|
3475
|
+
else {
|
|
3476
|
+
FontLoader.destroyFont(currentFont);
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
catch (error) {
|
|
3480
|
+
logger.warn('Error destroying HarfBuzz objects:', error);
|
|
3481
|
+
}
|
|
3482
|
+
finally {
|
|
3483
|
+
this.loadedFont = undefined;
|
|
3484
|
+
this.currentFontCacheKey = undefined;
|
|
3485
|
+
this.textLayout = undefined;
|
|
3486
|
+
this.textShaper = undefined;
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3432
3489
|
async loadFont(fontSrc, fontVariations, fontFeatures) {
|
|
3433
3490
|
perfLogger.start('Text.loadFont', {
|
|
3434
3491
|
fontSrc: typeof fontSrc === 'string' ? fontSrc : `buffer(${fontSrc.byteLength})`
|
|
@@ -3648,18 +3705,7 @@
|
|
|
3648
3705
|
if (!this.loadedFont) {
|
|
3649
3706
|
return;
|
|
3650
3707
|
}
|
|
3651
|
-
|
|
3652
|
-
try {
|
|
3653
|
-
FontLoader.destroyFont(currentFont);
|
|
3654
|
-
}
|
|
3655
|
-
catch (error) {
|
|
3656
|
-
logger.warn('Error destroying HarfBuzz objects:', error);
|
|
3657
|
-
}
|
|
3658
|
-
finally {
|
|
3659
|
-
this.loadedFont = undefined;
|
|
3660
|
-
this.textLayout = undefined;
|
|
3661
|
-
this.textShaper = undefined;
|
|
3662
|
-
}
|
|
3708
|
+
this.releaseCurrentFont();
|
|
3663
3709
|
}
|
|
3664
3710
|
};
|
|
3665
3711
|
|
|
@@ -6378,7 +6424,8 @@
|
|
|
6378
6424
|
getCacheSize: () => meshPipeline.getCacheSize(),
|
|
6379
6425
|
clearCache: () => meshPipeline.clearCache(),
|
|
6380
6426
|
measureTextWidth: (text, letterSpacing) => layoutHandle.measureTextWidth(text, letterSpacing),
|
|
6381
|
-
update
|
|
6427
|
+
update,
|
|
6428
|
+
dispose: () => layoutHandle.dispose()
|
|
6382
6429
|
};
|
|
6383
6430
|
}
|
|
6384
6431
|
class Text {
|