three-text 0.2.6 → 0.2.8
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/README.md +33 -13
- package/dist/index.cjs +533 -83
- package/dist/index.d.ts +2 -1
- package/dist/index.js +533 -83
- package/dist/index.min.cjs +2 -2
- package/dist/index.min.js +2 -2
- package/dist/index.umd.js +533 -83
- package/dist/index.umd.min.js +2 -2
- package/dist/three/react.d.ts +2 -1
- package/dist/types/core/cache/GlyphGeometryBuilder.d.ts +1 -0
- package/dist/types/core/layout/LineBreak.d.ts +9 -2
- package/dist/types/core/shaping/TextShaper.d.ts +1 -0
- package/dist/types/core/types.d.ts +2 -1
- package/dist/types/utils/LRUCache.d.ts +38 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ A high fidelity 3D font renderer and text layout engine for the web
|
|
|
15
15
|
> [!CAUTION]
|
|
16
16
|
> three-text is an alpha release and the API may break rapidly. This warning will last at least through the end of 2025. If API stability is important to you, consider pinning your version. Community feedback is encouraged; please open an issue if you have any suggestions or feedback, thank you
|
|
17
17
|
|
|
18
|
-
**three-text** renders and formats text from TTF, OTF, and WOFF font files as 3D geometry. It uses [TeX](https://en.wikipedia.org/wiki/TeX)-based parameters for breaking text into paragraphs across multiple lines, and turns font outlines into 3D shapes on the fly
|
|
18
|
+
**three-text** renders and formats text from TTF, OTF, and WOFF font files as 3D geometry. It uses [TeX](https://en.wikipedia.org/wiki/TeX)-based parameters for breaking text into paragraphs across multiple lines, and turns font outlines into 3D shapes on the fly. Glyph geometry is cached for low CPU overhead, especially in languages with lots of repeating glyphs. Variable fonts are supported as static instances at a given axis coordinate
|
|
19
19
|
|
|
20
20
|
The library has a framework-agnostic core that returns raw vertex data, with lightweight adapters for [Three.js](https://threejs.org), [React Three Fiber](https://docs.pmnd.rs/react-three-fiber), [p5.js](https://p5js.org), [WebGL](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API), and [WebGPU](https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API)
|
|
21
21
|
|
|
@@ -243,7 +243,7 @@ Existing solutions take different approaches:
|
|
|
243
243
|
- **three-bmfont-text** is a 2D approach for Three.js, using pre-rendered bitmap fonts with SDF support. Texture atlases are generated at specific sizes, and artifacts are apparent up close
|
|
244
244
|
- **troika-three-text** uses MSDF, which improves quality, and like three-text, it is built on HarfBuzz, which provides substantial language coverage, but is ultimately a 2D technique in image space. For flat text that does not need formatting or extrusion, and where artifacts are acceptable up close, troika works well
|
|
245
245
|
|
|
246
|
-
three-text generates true 3D geometry from font files via HarfBuzz. It is sharper at close distances than bitmap approaches when flat, and produces real mesh data that can be used with any rendering system. The library caches
|
|
246
|
+
three-text generates true 3D geometry from font files via HarfBuzz. It is sharper at close distances than bitmap approaches when flat, and produces real mesh data that can be used with any rendering system. The library caches glyph geometry, so a paragraph of 1000 words might only require 50 unique glyphs to be processed. This makes it well-suited to longer texts. In addition to performance considerations, three-text provides control over typesetting and paragraph justification via TeX-based parameters
|
|
247
247
|
|
|
248
248
|
## Library structure
|
|
249
249
|
|
|
@@ -298,7 +298,7 @@ Hyphenation uses patterns derived from the Tex hyphenation project, converted in
|
|
|
298
298
|
|
|
299
299
|
### Geometry generation and optimization
|
|
300
300
|
|
|
301
|
-
|
|
301
|
+
The geometry pipeline runs once per unique glyph (or glyph cluster), with intermediate results cached to avoid redundant work:
|
|
302
302
|
|
|
303
303
|
1. **Path collection**: HarfBuzz callbacks provide low level drawing operations
|
|
304
304
|
2. **Curve polygonization**: Uses Anti-Grain Geometry's recursive subdivision to convert bezier curves into polygons, concentrating points where curvature is high
|
|
@@ -315,7 +315,7 @@ The multi-stage geometry approach (curve polygonization followed by cleanup, the
|
|
|
315
315
|
|
|
316
316
|
The library uses a hybrid caching strategy to maximize performance while ensuring visual correctness
|
|
317
317
|
|
|
318
|
-
By default, it operates with glyph-level cache. The geometry for each unique character (`a`, `b`, `c`...) is generated only once and stored for reuse
|
|
318
|
+
By default, it operates with glyph-level cache. The geometry for each unique character (`a`, `b`, `c`...) is generated only once and stored for reuse, avoiding redundant computation
|
|
319
319
|
|
|
320
320
|
For text with tight tracking, connected scripts, or complex kerning pairs, individual glyphs can overlap. When an overlap within a word is found, the entire word is treated as a single unit and escalated to a word-level cache. All of its glyphs are tessellated together to correctly resolve the overlaps, and the resulting geometry for the word is cached
|
|
321
321
|
|
|
@@ -395,7 +395,8 @@ The Knuth-Plass algorithm provides extensive control over line breaking quality:
|
|
|
395
395
|
- **tolerance** (800): Maximum badness for the second pass with hyphenation
|
|
396
396
|
- **emergencyStretch** (0): Additional stretchability for difficult paragraphs
|
|
397
397
|
- **autoEmergencyStretch** (0.1): Emergency stretch as percentage of line width (e.g., 0.1 = 10%). Defaults to 10% for non-hyphenated text
|
|
398
|
-
- **
|
|
398
|
+
- **disableShortLineDetection** (false): Disable automatic prevention of short lines
|
|
399
|
+
- **shortLineThreshold** (0.5): Width ratio threshold for short line detection (0.0 to 1.0)
|
|
399
400
|
|
|
400
401
|
#### Advanced parameters
|
|
401
402
|
|
|
@@ -416,9 +417,9 @@ The Knuth-Plass algorithm provides extensive control over line breaking quality:
|
|
|
416
417
|
|
|
417
418
|
Lower penalty/tolerance values produce tighter spacing but may fail to find acceptable breaks for challenging text
|
|
418
419
|
|
|
419
|
-
####
|
|
420
|
+
#### Short line detection
|
|
420
421
|
|
|
421
|
-
By default, the library detects and prevents short
|
|
422
|
+
By default, the library detects and prevents short lines (lines occupying less than 50% of the target width on non-final lines) by iteratively applying emergency stretch. This can be customized or disabled:
|
|
422
423
|
|
|
423
424
|
```javascript
|
|
424
425
|
const text = await Text.create({
|
|
@@ -426,7 +427,9 @@ const text = await Text.create({
|
|
|
426
427
|
font: '/fonts/Font.ttf',
|
|
427
428
|
layout: {
|
|
428
429
|
width: 1000,
|
|
429
|
-
|
|
430
|
+
shortLineThreshold: 0.6, // Only flag lines < 60% width (more lenient)
|
|
431
|
+
// Or disable entirely:
|
|
432
|
+
// disableShortLineDetection: true,
|
|
430
433
|
},
|
|
431
434
|
});
|
|
432
435
|
```
|
|
@@ -754,9 +757,9 @@ interface LayoutOptions {
|
|
|
754
757
|
pretolerance?: number; // Maximum badness for first pass (default: 100)
|
|
755
758
|
emergencyStretch?: number; // Additional stretchability for difficult paragraphs
|
|
756
759
|
autoEmergencyStretch?: number; // Emergency stretch as percentage of line width (defaults to 10% for non-hyphenated)
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
//
|
|
760
|
+
disableShortLineDetection?: boolean; // Disable automatic short line prevention (default: false)
|
|
761
|
+
shortLineThreshold?: number; // Width ratio threshold for short line detection (default: 0.5)
|
|
762
|
+
lefthyphenmin?: number; // Minimum characters before hyphen (default: 2)
|
|
760
763
|
righthyphenmin?: number; // Minimum characters after hyphen (default: 4)
|
|
761
764
|
linepenalty?: number; // Base penalty per line (default: 10)
|
|
762
765
|
adjdemerits?: number; // Penalty for incompatible fitness classes (default: 10000)
|
|
@@ -940,9 +943,9 @@ While `three-text` runs on all modern browsers, performance varies significantly
|
|
|
940
943
|
|
|
941
944
|
**Chrome** provides the best experience
|
|
942
945
|
|
|
943
|
-
**Firefox** also delivers great performance but may exhibit less responsive mouse interactions
|
|
946
|
+
**Firefox** also delivers great performance but may exhibit less responsive mouse interactions
|
|
944
947
|
|
|
945
|
-
**Safari** for macOS shows reduced performance, which is likely due to the platform's conservative resource management
|
|
948
|
+
**Safari** for macOS shows reduced performance, which is likely due to the platform's conservative resource management; 120FPS is not acheivable
|
|
946
949
|
|
|
947
950
|
The library was also tested on a Brightsign 223HD, which took a long time to generate the initial geometry but seemed fine after that
|
|
948
951
|
|
|
@@ -958,6 +961,23 @@ npm test -- --coverage # Coverage report
|
|
|
958
961
|
|
|
959
962
|
Tests use mocked HarfBuzz and tessellation libraries for fast execution without requiring WASM files
|
|
960
963
|
|
|
964
|
+
### Benchmarking
|
|
965
|
+
|
|
966
|
+
For performance of the real pipeline using HarfBuzz, including shaping, layout, tessellation, extrusion, there is a dedicated benchmark:
|
|
967
|
+
|
|
968
|
+
```bash
|
|
969
|
+
npm run benchmark
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
This runs a Node/Vitest scenario that:
|
|
973
|
+
|
|
974
|
+
- initializes HarfBuzz from `hb.wasm` via `Text.setHarfBuzzBuffer`
|
|
975
|
+
- loads Nimbus Sans and tests the example paragraph from the demos
|
|
976
|
+
- performs a small number of cold runs followed by warm runs of `Text.create()` with justification and hyphenation enabled
|
|
977
|
+
- prints a per-stage timing table (font load, line breaking, polygonization, tessellation, extrusion, and overall geometry creation)
|
|
978
|
+
|
|
979
|
+
Use this to compare changes locally; it is meant as a sanity check on real work rather than a reliable micro-benchmark
|
|
980
|
+
|
|
961
981
|
## Build system
|
|
962
982
|
|
|
963
983
|
### Development
|