three-text 0.3.5 → 0.4.1
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 +31 -39
- package/dist/index.cjs +237 -119
- package/dist/index.d.ts +1 -3
- package/dist/index.js +237 -119
- package/dist/index.min.cjs +410 -396
- package/dist/index.min.js +400 -386
- package/dist/index.umd.js +237 -119
- package/dist/index.umd.min.js +486 -472
- package/dist/three/react.d.ts +1 -3
- package/dist/types/core/cache/GlyphContourCollector.d.ts +1 -0
- package/dist/types/core/cache/GlyphGeometryBuilder.d.ts +2 -0
- package/dist/types/core/geometry/PathOptimizer.d.ts +0 -4
- package/dist/types/core/geometry/Polygonizer.d.ts +5 -0
- package/dist/types/core/types.d.ts +1 -3
- package/dist/webgpu/index.cjs +15 -5
- package/dist/webgpu/index.js +15 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ High fidelity 3D mesh font geometry and text layout engine for the web
|
|
|
13
13
|
## Overview
|
|
14
14
|
|
|
15
15
|
> [!CAUTION]
|
|
16
|
-
> three-text is an alpha release and the API may break rapidly. This warning will last
|
|
16
|
+
> three-text is an alpha release and the API may break rapidly. This warning will likely last until the end of March 2026. 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
18
|
**three-text** is a 3D mesh font geometry and text layout library for the web. It supports TTF, OTF, and WOFF font files. For layout, it uses [TeX](https://en.wikipedia.org/wiki/TeX)-based parameters for breaking text into paragraphs across multiple lines and supports CJK and RTL scripts. three-text caches the geometries it generates for low CPU overhead in languages with lots of repeating glyphs. Variable fonts are supported as static instances at a given axis coordinate, and can be animated by re-drawing each frame with new coordinates
|
|
19
19
|
|
|
@@ -248,10 +248,10 @@ three-text generates high-fidelity 3D mesh geometry from font files. Unlike text
|
|
|
248
248
|
Existing solutions take different approaches:
|
|
249
249
|
|
|
250
250
|
- **Three.js native TextGeometry** uses fonts converted by facetype.js to JSON format. It creates 3D text by extruding flat 2D character outlines. While this produces true 3D geometry with depth, there is no support for real fonts or OpenType features needed for many of the world's scripts
|
|
251
|
-
- **three-bmfont-text**
|
|
252
|
-
- **troika-three-text**
|
|
251
|
+
- **three-bmfont-text** renders from pre-generated SDF atlas textures. Atlases are built offline at fixed sizes
|
|
252
|
+
- **troika-three-text** generates SDF glyphs at runtime from font files via HarfBuzz. More flexible than bmfont, but still a 2D image-space technique with artifacts up close
|
|
253
253
|
|
|
254
|
-
three-text generates true 3D geometry from font files via HarfBuzz. It is sharper at close distances than bitmap approaches
|
|
254
|
+
three-text generates true 3D geometry from font files via HarfBuzz. It is sharper at close distances than bitmap approaches, and produces 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. three-text also provides control over typesetting and paragraph justification via TeX-based parameters
|
|
255
255
|
|
|
256
256
|
## Library structure
|
|
257
257
|
|
|
@@ -309,15 +309,14 @@ Hyphenation uses patterns derived from the Tex hyphenation project, converted in
|
|
|
309
309
|
The geometry pipeline runs once per unique glyph (or glyph cluster), with intermediate results cached to avoid redundant work:
|
|
310
310
|
|
|
311
311
|
1. **Path collection**: HarfBuzz callbacks provide low level drawing operations
|
|
312
|
-
2. **Curve polygonization**:
|
|
312
|
+
2. **Curve polygonization**: Flattens bezier curves into line segments, placing more points where curves are tight
|
|
313
313
|
3. **Geometry optimization**:
|
|
314
|
-
- **Visvalingam-Whyatt simplification**: removes vertices that
|
|
315
|
-
- **Colinear point removal**: eliminates redundant points that lie on straight lines within angle tolerances
|
|
314
|
+
- **Visvalingam-Whyatt simplification**: removes vertices that form tiny triangles with their neighbors, smoothing out subtle bumps while preserving sharp corners
|
|
316
315
|
4. **Overlap removal**: removes self-intersections and resolves overlapping paths between glyphs, preserving correct winding rules for triangulation
|
|
317
316
|
5. **Triangulation**: converts cleaned 2D shapes into triangles using libtess2 with non-zero winding rule
|
|
318
317
|
6. **Mesh construction**: generates 2D or 3D geometry with front faces and optional depth/extrusion (back faces and side walls)
|
|
319
318
|
|
|
320
|
-
The multi-stage geometry approach (curve polygonization followed by cleanup, then triangulation)
|
|
319
|
+
The multi-stage geometry approach (curve polygonization followed by cleanup, then triangulation) reduces triangle counts and removes overlaps in variable fonts
|
|
321
320
|
|
|
322
321
|
#### Glyph caching
|
|
323
322
|
|
|
@@ -340,54 +339,49 @@ When `depth` is 0, the library generates single-sided geometry, reducing triangl
|
|
|
340
339
|
|
|
341
340
|
### Curve fidelity
|
|
342
341
|
|
|
343
|
-
|
|
342
|
+
Font outlines are bezier curves, but screens render curves flattened into many line segments. The library uses one of two modes:
|
|
344
343
|
|
|
345
|
-
-
|
|
346
|
-
- `angleTolerance`: The maximum angle in radians between segments at a join. This helps preserve sharp corners. Default is `0.2`
|
|
344
|
+
**Adaptive (default)** - The algorithm splits each curve at its midpoint, checks if the resulting line segment is close enough to the true curve, and recurses until it is. Tight curves get more segments; gentle curves get fewer. Two tolerances control when to stop subdividing:
|
|
347
345
|
|
|
348
|
-
|
|
346
|
+
- `distanceTolerance`: how far the line segment can stray from the true curve, in font units. Lower values trace the curve more faithfully (default: `0.5`)
|
|
347
|
+
- `angleTolerance`: the maximum angle between adjacent segments, in radians. Smaller values preserve sharp corners better (default: `0.2`)
|
|
348
|
+
|
|
349
|
+
**Fixed-step** - Divides each curve into exactly `curveSteps` segments, regardless of curvature. Simpler and predictable. Overrides adaptive mode when set
|
|
349
350
|
|
|
350
351
|
```javascript
|
|
352
|
+
// Adaptive (default)
|
|
351
353
|
const text = await Text.create({
|
|
352
|
-
text: 'Sample
|
|
354
|
+
text: 'Sample',
|
|
353
355
|
font: '/fonts/Font.ttf',
|
|
354
|
-
curveFidelity: {
|
|
356
|
+
curveFidelity: {
|
|
355
357
|
distanceTolerance: 0.2,
|
|
356
|
-
angleTolerance: 0.1
|
|
358
|
+
angleTolerance: 0.1
|
|
357
359
|
},
|
|
358
360
|
});
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
### Geometry optimization
|
|
362
|
-
|
|
363
|
-
`three-text` uses a line simplification algorithm after creating lines to reduce the complexity of the shapes as well, which can be combined with `curveFidelity` for different types of control. It is enabled by default:
|
|
364
361
|
|
|
365
|
-
|
|
366
|
-
```javascript
|
|
367
|
-
// Default optimization (automatic)
|
|
362
|
+
// Fixed-step: 8 segments per curve
|
|
368
363
|
const text = await Text.create({
|
|
369
|
-
text: 'Sample
|
|
364
|
+
text: 'Sample',
|
|
370
365
|
font: '/fonts/Font.ttf',
|
|
366
|
+
curveSteps: 8,
|
|
371
367
|
});
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Geometry optimization
|
|
371
|
+
|
|
372
|
+
After curve polygonization, the library applies Visvalingam-Whyatt simplification. Unlike curve flattening, which operates on each bezier independently, V-W sees the complete assembled path. The algorithm looks at each vertex and the triangle it forms with its two neighbors. Vertices that form tiny triangles - nearly collinear with their neighbors - are removed first. The process repeats until no triangle is smaller than `areaThreshold`, measured in square font units. Sharp corners form large triangles, so they survive; subtle bumps form small ones and get smoothed out:
|
|
372
373
|
|
|
373
|
-
// Custom optimization settings
|
|
374
374
|
```javascript
|
|
375
375
|
const text = await Text.create({
|
|
376
376
|
text: 'Sample text',
|
|
377
377
|
font: '/fonts/Font.ttf',
|
|
378
378
|
geometryOptimization: {
|
|
379
|
-
areaThreshold: 1.0,
|
|
380
|
-
colinearThreshold: 0.0087, // Default: ~0.5° in radians
|
|
381
|
-
minSegmentLength: 10, // Default: 10 font units
|
|
379
|
+
areaThreshold: 1.0, // remove triangles < 1 font unit²
|
|
382
380
|
},
|
|
383
381
|
});
|
|
384
382
|
```
|
|
385
383
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
**Colinear point removal** eliminates redundant vertices that lie on straight lines within the specified angle tolerance
|
|
389
|
-
|
|
390
|
-
The default settings provide a significant reduction while maintaining high visual quality, but won't be perfect for every font. Adjust thresholds based on your quality requirements, performance constraints, and testing
|
|
384
|
+
Defaults work well for most fonts. Adjust thresholds based on quality requirements and testing
|
|
391
385
|
|
|
392
386
|
### Line breaking parameters
|
|
393
387
|
|
|
@@ -740,6 +734,7 @@ interface TextOptions {
|
|
|
740
734
|
removeOverlaps?: boolean; // Override default overlap removal (auto-enabled for VF only)
|
|
741
735
|
perGlyphAttributes?: boolean; // Keep per-glyph identity and add per-glyph shader attributes
|
|
742
736
|
color?: [number, number, number] | ColorOptions; // Text coloring (simple or complex)
|
|
737
|
+
curveSteps?: number; // Fixed segments per curve; overrides curveFidelity when set
|
|
743
738
|
curveFidelity?: CurveFidelityConfig;
|
|
744
739
|
geometryOptimization?: GeometryOptimizationOptions;
|
|
745
740
|
layout?: LayoutOptions;
|
|
@@ -796,12 +791,10 @@ interface CurveFidelityConfig {
|
|
|
796
791
|
|
|
797
792
|
```typescript
|
|
798
793
|
interface GeometryOptimizationOptions {
|
|
799
|
-
enabled?: boolean;
|
|
800
|
-
areaThreshold?: number; // Min triangle area
|
|
801
|
-
colinearThreshold?: number; // Max angle for colinear removal in radians (default: 0.0087)
|
|
802
|
-
minSegmentLength?: number; // Min segment length in font units (default: 10)
|
|
794
|
+
enabled?: boolean; // Enable optimization (default: true)
|
|
795
|
+
areaThreshold?: number; // Min triangle area in font units² (default: 1.0)
|
|
803
796
|
}
|
|
804
|
-
|
|
797
|
+
```
|
|
805
798
|
|
|
806
799
|
#### TextGeometryInfo (Core)
|
|
807
800
|
|
|
@@ -827,7 +820,6 @@ interface TextGeometryInfo {
|
|
|
827
820
|
trianglesGenerated: number;
|
|
828
821
|
verticesGenerated: number;
|
|
829
822
|
pointsRemovedByVisvalingam: number;
|
|
830
|
-
pointsRemovedByColinear: number;
|
|
831
823
|
originalPointCount: number;
|
|
832
824
|
};
|
|
833
825
|
query(options: TextQueryOptions): TextRange[];
|