Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
f094501
feat: establish portable raster technique boundary
thejustinwalsh Aug 7, 2026
df5b230
docs: fix integration subpath topology summary
thejustinwalsh Aug 7, 2026
0746d42
feat: add portable MTSDF technique
thejustinwalsh Aug 7, 2026
7b0892d
feat: add portable Bitmap and Slug techniques
thejustinwalsh Aug 7, 2026
c2970be
feat: implement target-v1 text integrations
thejustinwalsh Aug 7, 2026
6981ae4
feat(text): resolve Three raster programs by technique identity
thejustinwalsh Aug 7, 2026
75d3038
feat(text): export the Bitmap strike selector from the technique
thejustinwalsh Aug 7, 2026
719cf66
feat(text): report retained GPU bytes from Three targets
thejustinwalsh Aug 7, 2026
5749d03
fix(text): correct R3F error reporting, demand rendering, and React f…
thejustinwalsh Aug 7, 2026
69029ae
docs: record the Three program registry and R3F corrections
thejustinwalsh Aug 7, 2026
2fe3603
feat(text): forward load cancellation and registry through the Three …
thejustinwalsh Aug 7, 2026
6a30f7d
feat(text): export the canonical Bitmap, MTSDF, and Slug TSL shaders
thejustinwalsh Aug 7, 2026
96e010e
feat(benchmarks): load font assets once through the target-v1 FontLoader
thejustinwalsh Aug 7, 2026
c20436c
fix(text): resolve composed spans by nesting, inheritance, and replac…
thejustinwalsh Aug 7, 2026
25471d6
chore(benchmarks): record the core size cost of the span fixes
thejustinwalsh Aug 7, 2026
e22fd5f
feat(text): publish the MTSDF glyph record stride
thejustinwalsh Aug 7, 2026
11f76e1
refactor(benchmarks): migrate the MTSDF lane to target-v1
thejustinwalsh Aug 7, 2026
7d65bae
feat(benchmarks): migrate the shaping and React targets to target-v1
thejustinwalsh Aug 7, 2026
6f23bc5
fix(text): accept a paragraph-wide font feature on empty text
thejustinwalsh Aug 7, 2026
6474705
refactor(benchmarks): read the Bitmap raster key from the target-v1 t…
thejustinwalsh Aug 7, 2026
b966658
fix(text): sample Slug em space in the quad's own direction
thejustinwalsh Aug 7, 2026
d80bc3e
feat(benchmarks): render the Slug lane through target-v1
thejustinwalsh Aug 7, 2026
96a4606
docs: record the Slug em-space fix and the Bitmap snapping gap
thejustinwalsh Aug 7, 2026
2d4dfb9
fix(text): reproduce the Bitmap atlas rows and pixel grid in the Thre…
thejustinwalsh Aug 7, 2026
80d345a
chore(benchmarks): record the size cost of the empty-feature fix
thejustinwalsh Aug 7, 2026
e2848cd
test(benchmarks): raise the reviewed Bitmap brotli ceiling for snappe…
thejustinwalsh Aug 7, 2026
0d20504
feat(benchmarks): move the live technique scenes to target-v1
thejustinwalsh Aug 7, 2026
3326485
refactor(benchmarks): migrate the comparison workloads to target-v1
thejustinwalsh Aug 7, 2026
6b5dc2c
docs: regenerate package digests after the benchmark migration
thejustinwalsh Aug 7, 2026
501242e
docs: scope professional typography into milestone 11
thejustinwalsh Aug 7, 2026
914181e
refactor(text): resolve one span cascade for shaping and paint
thejustinwalsh Aug 7, 2026
d66cf56
feat(benchmarks): exercise composed text spans end to end
thejustinwalsh Aug 7, 2026
04d09c0
test(benchmarks): record nested span paint inheriting its enclosing span
thejustinwalsh Aug 7, 2026
701b491
test(benchmarks): raise size ceilings for the span cascade and pixel …
thejustinwalsh Aug 7, 2026
6c9252d
docs: record Three material authority as unresolved follow-up work
thejustinwalsh Aug 7, 2026
8eddd08
docs(roadmap): close milestone 11 items 11.1 through 11.7
thejustinwalsh Aug 7, 2026
fe6fa01
feat!: delete the merged-v0 surface
thejustinwalsh Aug 7, 2026
e90f34b
docs: require technique-paired integration subpaths
thejustinwalsh Aug 7, 2026
cb0af7b
test(text): pin decoded page bytes apart from the padded binding
thejustinwalsh Aug 7, 2026
3a75a97
chore(benchmarks): re-derive size baselines after deleting merged v0
thejustinwalsh Aug 7, 2026
e7bdeb2
feat(benchmarks): commit live text updates in the caller's turn
thejustinwalsh Aug 7, 2026
453485f
test(benchmarks): measure live update latency from the presented canvas
thejustinwalsh Aug 7, 2026
312ebe9
docs(benchmarks): record the synchronous live update contract
thejustinwalsh Aug 7, 2026
b6e2a4c
docs: refresh the benchmarks digest after the synchronous update path
thejustinwalsh Aug 7, 2026
2bd45c5
fix(benchmarks): type the latency probe against the scripts project
thejustinwalsh Aug 7, 2026
b9ab059
fix(benchmarks): match glyph identity across a size change
thejustinwalsh Aug 7, 2026
0e0aa14
perf(text): reuse the shaped run when only its scale changed
thejustinwalsh Aug 7, 2026
d011f9e
perf(text): retain the cluster index buffers across preparations
thejustinwalsh Aug 8, 2026
24d0c8b
feat(text)!: pair each technique with its Three program in its own su…
thejustinwalsh Aug 8, 2026
71ac0cc
style(text): format the technique-paired subpath modules
thejustinwalsh Aug 8, 2026
8f969dd
perf(text): measure layout cost by phase and by invalidation class
thejustinwalsh Aug 8, 2026
2d267ec
perf(text): reuse preparation across updates instead of rebuilding it
thejustinwalsh Aug 8, 2026
073b4a8
perf(text): position glyphs into typed arrays without a per-glyph copy
thejustinwalsh Aug 8, 2026
ecdd6eb
perf(text): separate boundary reshaping from fragment building
thejustinwalsh Aug 8, 2026
e71db4f
docs: record layout tiering and how its evidence is measured
thejustinwalsh Aug 8, 2026
de7f551
build: raise the browser-core size allowance for layout tiering
thejustinwalsh Aug 8, 2026
3b43e59
perf(text): analyse text without allocating per grapheme
thejustinwalsh Aug 8, 2026
65b5cb1
fix(text): ignore the ellipsis runs when resolving font fallback
thejustinwalsh Aug 8, 2026
35b57b1
perf(text): measure clusters into parallel typed arrays
thejustinwalsh Aug 8, 2026
2c3829b
perf(text): build line fragments in place
thejustinwalsh Aug 8, 2026
1e9f7ae
perf(text): gather shaped cluster advances by text offset
thejustinwalsh Aug 8, 2026
9f602a2
perf(text): batch glyph instances without a per-glyph key string
thejustinwalsh Aug 8, 2026
0e14967
perf(text): carry uniform glyph attribution as one value
thejustinwalsh Aug 8, 2026
8cb8e64
perf(text): reuse glyph instance inputs across updates
thejustinwalsh Aug 8, 2026
56229fc
docs(text): record the pooled glyph input lifetime
thejustinwalsh Aug 8, 2026
5425ace
perf(text): drop the dead script-extension helper and refresh evidence
thejustinwalsh Aug 8, 2026
b19c45a
perf(text): lay out from the retained shape instead of reshaping boun…
thejustinwalsh Aug 8, 2026
dbdcc3f
test(benchmarks): assert no reshape crossings and report what drifted
thejustinwalsh Aug 8, 2026
fac880b
refactor: remove the layout profiler and debounce at the controls
thejustinwalsh Aug 8, 2026
629166a
fix(benchmarks): debounce the control, not the path an animation shares
thejustinwalsh Aug 8, 2026
ad729d3
refactor(text)!: name the distance-field subpaths msdf
thejustinwalsh Aug 8, 2026
486001b
docs: record the reshape removal, the rename, and its safety rule
thejustinwalsh Aug 8, 2026
dd80786
fix: satisfy lint and format after the reshape removal and the rename
thejustinwalsh Aug 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "dev",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["run", "dev"],
"port": 5173
}
]
}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ engine integrations below are implemented and pass their portability gates.
## Render text with React Three Fiber

```tsx
import { Text, TextGroup, useFont } from '@pmndrs/text-r3f';
import { Text, TextGroup, useFont } from '@pmndrs/text/r3f';
import { mtsdf } from '@pmndrs/text/raster/mtsdf';

function Labels() {
Expand All @@ -28,7 +28,7 @@ function Labels() {
## Render text with Three.js

```ts
import { FontLoader, Text, TextGroup } from '@pmndrs/text-three';
import { FontLoader, Text, TextGroup } from '@pmndrs/text/three';
import { mtsdf } from '@pmndrs/text/raster/mtsdf';

const loader = new FontLoader();
Expand All @@ -49,7 +49,7 @@ Both integrations load fonts explicitly and add one same-technique text batch to

```ts
import { createFontStack } from '@pmndrs/text';
import { FontLoader, Text, TextGroup, span, txt, type SpanStyle } from '@pmndrs/text-three';
import { FontLoader, Text, TextGroup, span, txt, type SpanStyle } from '@pmndrs/text/three';
import { mtsdf } from '@pmndrs/text/raster/mtsdf';

const loader = new FontLoader();
Expand Down
43 changes: 13 additions & 30 deletions apps/benchmarks/scripts/measure-package-sizes.mts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ interface BundleResult {

const root = fileURLToPath(new URL('..', import.meta.url));
const diagnosticModuleFragments = ['/packages/text/dist/internal/raster-baker-profile.js'];
const diagnosticCodeFragments = ['createProfiledDirectRasterBakerFromInstance', 'profiled MTSDF baker'];
const diagnosticCodeFragments = ['createProfiledDirectRasterBakerFromInstance', 'profiled MSDF baker'];

function isTextPeerDependency(id: string): boolean {
return id === 'three' || id.startsWith('three/') || id === 'react' || id.startsWith('@react-three/fiber');
Expand Down Expand Up @@ -253,7 +253,7 @@ async function measureWasm(id: string, label: string, source: URL): Promise<Meas
};
}

async function measureAdmittedMtsdfGenerator(): Promise<MeasuredEntry> {
async function measureAdmittedMsdfGenerator(): Promise<MeasuredEntry> {
const evidence = JSON.parse(
await readFile(
new URL('../../../packages/text/rust/mtsdf-admission/evidence/simd-v0.json', import.meta.url),
Expand Down Expand Up @@ -281,11 +281,11 @@ async function measureAdmittedMtsdfGenerator(): Promise<MeasuredEntry> {
scalar.gzipBytes === undefined ||
scalar.brotliBytes === undefined
) {
throw new Error('admitted scalar MTSDF generator size evidence is incomplete');
throw new Error('admitted scalar MSDF generator size evidence is incomplete');
}
return {
id: 'mtsdf-generator-wasm',
label: 'MTSDF admitted generator kernel',
label: 'MSDF admitted generator kernel',
status: 'measured',
format: 'wasm',
sha256: scalar.optimizedSha256,
Expand All @@ -309,10 +309,11 @@ const entries: SizeEntry[] = [
excludedInitial: [
'/packages/text/dist/runtime-bake.js',
'/packages/text/dist/runtime-bake-worker.js',
'/packages/text/dist/react.js',
'/packages/text/dist/raster/bitmap.js',
'/packages/text/dist/r3f.js',
'/packages/text/dist/three.js',
'/packages/text/dist/raster/bitmap-technique.js',
'/packages/text/dist/raster/msdf.js',
'/packages/text/dist/raster/slug.js',
'/packages/text/dist/raster/slug-technique.js',
'/packages/text/dist/bakers/msdf.js',
'/packages/text/dist/node/',
'/packages/font-baker/dist/index.js',
Expand Down Expand Up @@ -360,32 +361,14 @@ const entries: SizeEntry[] = [
false,
true,
true,
{
expectedDynamic: [],
excludedInitial: [
'/packages/text/dist/raster/slug.js',
'/packages/text/dist/internal/slug-shaders/',
'/packages/text/dist/bakers/slug.js',
'/packages/text/dist/runtime-bakers/slug',
],
},
),
await measureJavaScript(
'mtsdf-runtime-js',
'MTSDF runtime JS graph',
'MSDF runtime JS graph',
new URL('../size-entries/mtsdf-runtime.ts', import.meta.url),
false,
true,
true,
{
expectedDynamic: [],
excludedInitial: [
'/packages/text/dist/raster/slug.js',
'/packages/text/dist/internal/slug-shaders/',
'/packages/text/dist/bakers/slug.js',
'/packages/text/dist/runtime-bakers/slug',
],
},
),
await measureJavaScript(
'slug-runtime-js',
Expand All @@ -412,18 +395,18 @@ const entries: SizeEntry[] = [
),
await measureJavaScript(
'mtsdf-generator-js',
'MTSDF generator host JS',
'MSDF generator host JS',
new URL('../size-entries/mtsdf-generator.ts', import.meta.url),
),
await measureAdmittedMtsdfGenerator(),
await measureAdmittedMsdfGenerator(),
await measureWasm(
'mtsdf-baker-wasm',
'MTSDF fixed baker Wasm',
'MSDF fixed baker Wasm',
new URL('../../../packages/text/dist/mtsdf_baker.wasm', import.meta.url),
),
await measureJavaScript(
'mtsdf-baker-js',
'MTSDF fixed baker host JS',
'MSDF fixed baker host JS',
new URL('../size-entries/mtsdf-baker.ts', import.meta.url),
false,
true,
Expand Down
4 changes: 4 additions & 0 deletions apps/benchmarks/scripts/run-headless.mts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ const conformanceCases: readonly BenchmarkCase[] = [
targetId: 'advanced-shaping-conformance',
scenarioId: 'advanced-shaping-conformance',
},
{
targetId: 'rich-text-spans-conformance',
scenarioId: 'rich-text-spans-conformance',
},
];

const readinessTimeoutMs = 30_000;
Expand Down
Loading