textpour 0.1.1 → 0.1.2
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 +54 -19
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,16 +3,18 @@
|
|
|
3
3
|
A render-agnostic **text-geometry kernel** on top of
|
|
4
4
|
[`@chenglou/pretext`](https://github.com/chenglou/pretext).
|
|
5
5
|
|
|
6
|
-
- **Shape-flow
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
never poke outside tight curves.
|
|
6
|
+
- **Shape-flow — the reusable core.** Turn any 2D region — circles, ellipses, polygons, boolean
|
|
7
|
+
unions/intersections/**holes**, SVG paths, glyph outlines, raster alpha masks — into the per-row
|
|
8
|
+
spans Pretext fills, threading one cursor across the *several disjoint spans* a single row can have
|
|
9
|
+
(around a hole, through a glyph's counters). This shape→spans geometry is the part worth a library.
|
|
10
|
+
(CSS `shape-inside` never shipped; this does it.)
|
|
12
11
|
- **Cursor ↔ point mapping**: map pixel positions to exact grapheme positions and back, for
|
|
13
12
|
caret/hit-testing in custom-rendered text.
|
|
14
|
-
- **
|
|
15
|
-
|
|
13
|
+
- **Conveniences over the line breaker** (nice-to-haves, *not* the moat): justification, soft-
|
|
14
|
+
hyphenation, balanced lines, auto-fit, conservative band sampling — pragmatic implementations over
|
|
15
|
+
the *published* `@chenglou/pretext@0.0.1`; Pretext's fuller API does several of these natively.
|
|
16
|
+
- **Pluggable paint**: the kernel computes geometry; `Renderer`s paint it. Canvas2D today; an
|
|
17
|
+
HTML-in-Canvas adapter (high-fidelity, accessible, 3D-surface paint) is stubbed for later.
|
|
16
18
|
|
|
17
19
|
The design bet is the **plan/paint split**: Pretext plans cheaply every frame (no DOM reflow); an
|
|
18
20
|
expensive high-fidelity backend paints only when the plan changes.
|
|
@@ -24,6 +26,12 @@ prepared pass reused on every frame:
|
|
|
24
26
|
|
|
25
27
|

|
|
26
28
|
|
|
29
|
+
A gallery of practical demos lives in `demo/` — serve over http (`npm run build` first) and open
|
|
30
|
+
**`demo/gallery.html`**. Start with **Anatomy**, which runs raw Pretext and textpour *side by side*:
|
|
31
|
+
identical pixels for a circle (just inline the loop), and the spans function ballooning into a
|
|
32
|
+
rasterizer for a glyph (reuse the library). The rest — Islands, Letterform, Ghostwriter, Reflow,
|
|
33
|
+
Touchpoint — isolate one capability each, with a "textpour vs raw Pretext" code panel on every page.
|
|
34
|
+
|
|
27
35
|
## Why not just Pretext?
|
|
28
36
|
|
|
29
37
|
Pretext is the line-breaking and measurement engine — a very good one. It breaks lines at a width
|
|
@@ -53,7 +61,18 @@ balanced-lines are pragmatic implementations over that minimal surface — when
|
|
|
53
61
|
richer API (Knuth–Plass justify, real hyphenation, `walkLineRanges`), textpour will defer to those
|
|
54
62
|
and keep only the geometry it uniquely contributes.
|
|
55
63
|
|
|
56
|
-
In one line: **Pretext breaks the lines; textpour decides the shape those lines fill.**
|
|
64
|
+
In one line: **Pretext breaks the lines; textpour decides the shape those lines fill.** The flow loop
|
|
65
|
+
on top is ~12 lines you could inline — what textpour actually packages is `region.spansAt(y)` for
|
|
66
|
+
shapes Pretext has no concept of. A convenience kernel, not a new capability. (See the **Anatomy**
|
|
67
|
+
demo for the side-by-side proof.)
|
|
68
|
+
|
|
69
|
+
## What this is (and isn't)
|
|
70
|
+
|
|
71
|
+
A **hobby + learning project** — as much an excuse to learn the npm release loop (publish, semver,
|
|
72
|
+
CI-on-tag) as a library. It's a thin geometry layer **on top of** Pretext, **not** a replacement for
|
|
73
|
+
or competitor to it: Pretext does the hard part (shaping, line-breaking, measurement); textpour just
|
|
74
|
+
turns shapes into spans. Treat it as a niche convenience, not infrastructure — fun if you're pouring
|
|
75
|
+
text into odd shapes, but don't build anything load-bearing on it.
|
|
57
76
|
|
|
58
77
|
## Quickstart
|
|
59
78
|
|
|
@@ -63,7 +82,7 @@ npm test # builds, runs the pure-logic test suite (56 specs)
|
|
|
63
82
|
npm run build # emits dist/
|
|
64
83
|
# demo (needs a browser + http):
|
|
65
84
|
npx http-server . # or any static server
|
|
66
|
-
# open /demo/
|
|
85
|
+
# open /demo/gallery.html
|
|
67
86
|
```
|
|
68
87
|
|
|
69
88
|
## Status
|
|
@@ -80,17 +99,33 @@ flagship "shaped CSS text on a 3D surface" demo (Phase 3).
|
|
|
80
99
|
- **SPEC.md** — the full design, API reference, and the relationship to Pretext + HTML-in-Canvas.
|
|
81
100
|
- **ROADMAP.md** — phased tasks with acceptance + kill criteria.
|
|
82
101
|
|
|
83
|
-
## Example
|
|
102
|
+
## Example — Pretext vs textpour
|
|
103
|
+
|
|
104
|
+
Pour text into a column with a hole, both ways — the contrast every demo shows ([live](demo/gallery.html)):
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
// raw Pretext: you write the loop AND the geometry
|
|
108
|
+
let cur = { segmentIndex: 0, graphemeIndex: 0 };
|
|
109
|
+
const spansAt = (yc) => { // column minus the hole's chord
|
|
110
|
+
const h = 90 * 90 - (yc - 200) ** 2;
|
|
111
|
+
return h <= 0 ? [[0, 600]] : [[0, 300 - Math.sqrt(h)], [300 + Math.sqrt(h), 600]];
|
|
112
|
+
};
|
|
113
|
+
for (let y = 0; y + 26 <= 400; y += 26)
|
|
114
|
+
for (const [x0, x1] of spansAt(y + 13)) {
|
|
115
|
+
const line = layoutNextLine(prepared, cur, x1 - x0); // one cursor across the gap
|
|
116
|
+
if (!line) break;
|
|
117
|
+
ctx.fillText(line.text, x0, y + 20); cur = line.end;
|
|
118
|
+
}
|
|
119
|
+
```
|
|
84
120
|
|
|
85
121
|
```ts
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
const result = shapeFlow(source, region, { lineHeight: 24, ascent: 18 });
|
|
91
|
-
|
|
92
|
-
new Canvas2DRenderer('17px Georgia', { color: '#1a1a1a' }).render(result, ctx);
|
|
93
|
-
// result.overflow / result.endCursor drive auto-fit and multi-region pagination
|
|
122
|
+
// textpour: describe the shape, pour
|
|
123
|
+
const region = subtract(rect(0, 0, 600, 400), circle(300, 200, 90));
|
|
124
|
+
const result = shapeFlow(source, region, { lineHeight: 26, ascent: 20, multiSpan: 'fill' });
|
|
125
|
+
renderer.render(result, ctx);
|
|
94
126
|
```
|
|
95
127
|
|
|
128
|
+
Same output. The loop is glue; **`region` is the part textpour gives you** — and it scales to glyphs,
|
|
129
|
+
masks, and booleans without touching `spansAt`. [Anatomy](demo/anatomy.html) runs both, pixel-for-pixel.
|
|
130
|
+
|
|
96
131
|
MIT.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "textpour",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Hobby/learning project: a small geometry layer on top of @chenglou/pretext — turn any 2D shape (holes, glyphs, image masks) into the per-row spans it fills, plus cursor<->point mapping. Not a Pretext replacement.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/src/index.js",
|
|
7
7
|
"types": "./dist/src/index.d.ts",
|