@weasel-js/renderer 0.0.0-stage → 1.10.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/dist/mesh.d.ts ADDED
@@ -0,0 +1,241 @@
1
+ import { PaintUnits, ColorSpace, Paint, GradStop } from '@weasel-js/paint';
2
+ import { c as PaintDrawKind } from './paintKinds-BmPAT51k.js';
3
+ import '@weasel-js/registry';
4
+ import '@weasel-js/geom';
5
+
6
+ /**
7
+ * Coons and tensor-product patch surfaces — PDF's shading types 6 and 7, as
8
+ * pure geometry.
9
+ *
10
+ * A patch is a curved quadrilateral: four cubic Bézier edges and a color at
11
+ * each corner. A Coons patch reads its interior off the boundary alone; a
12
+ * tensor patch adds four interior control points that pull it around.
13
+ */
14
+ /** A point in the patch's own space. */
15
+ interface MeshPoint {
16
+ x: number;
17
+ y: number;
18
+ }
19
+ /**
20
+ * One patch.
21
+ *
22
+ * `points` walks the boundary: corner 0, the two control points of the edge
23
+ * leaving it, corner 1, its two, and so on — twelve points, ending with the
24
+ * two controls that return to corner 0. A tensor patch appends its four
25
+ * interior points, in the order `(1,1)`, `(1,2)`, `(2,2)`, `(2,1)` of the
26
+ * bicubic control net, which is PDF's own order. Twelve points is a Coons
27
+ * patch and sixteen is a tensor patch.
28
+ *
29
+ * `colors` are the corner colors in the same walk order.
30
+ */
31
+ interface MeshPatch<TColor = string> {
32
+ points: readonly MeshPoint[];
33
+ colors: readonly [TColor, TColor, TColor, TColor];
34
+ }
35
+ /** Corner `i` of the boundary walk. */
36
+ declare function patchCorner(patch: MeshPatch<unknown>, i: number): MeshPoint;
37
+ /** `true` when the patch carries the four interior points a tensor patch adds. */
38
+ declare function isTensorPatch(patch: MeshPatch<unknown>): boolean;
39
+ /** A patch is twelve boundary points, or sixteen with the interior. Anything
40
+ * else cannot be evaluated, and saying so here beats painting nonsense. */
41
+ declare function isValidPatch(patch: MeshPatch<unknown>): boolean;
42
+ /**
43
+ * The patch surface at `(u, v)`, both in `0..1`.
44
+ *
45
+ * `u` runs along the edge leaving corner 0 and `v` along the edge leaving
46
+ * corner 1, so `(0,0)` is corner 0, `(1,0)` corner 1, `(1,1)` corner 2 and
47
+ * `(0,1)` corner 3 — the same walk `colors` is in.
48
+ */
49
+ declare function evalPatch(patch: MeshPatch<unknown>, u: number, v: number): MeshPoint;
50
+ /**
51
+ * The four corner weights at `(u, v)` — bilinear, in the corner walk order.
52
+ */
53
+ declare function cornerWeights(u: number, v: number): [number, number, number, number];
54
+ /** Axis-aligned bounds of a patch, sampled on a grid: control points alone
55
+ * bound a Bézier but not tightly. */
56
+ declare function patchBounds(patch: MeshPatch<unknown>, steps?: number): {
57
+ x: number;
58
+ y: number;
59
+ width: number;
60
+ height: number;
61
+ };
62
+
63
+ /**
64
+ * The `mesh-gradient` paint kind — PDF's shading types 6 and 7 as a registered
65
+ * paint: a set of curved quadrilateral patches, each with a color at every
66
+ * corner.
67
+ *
68
+ * It uses only the slots `registerPaintKind` gives a consumer, so whatever it
69
+ * can do, a consumer's own kind can do too.
70
+ */
71
+
72
+ /**
73
+ * A mesh gradient paint.
74
+ *
75
+ * `patches` are in the space `units` names, the same way a gradient's
76
+ * geometry is — under `'bounds'` every point is a fraction of the painted
77
+ * node's box, which is what lets the paint survive a resize.
78
+ *
79
+ * `interpolate` is the space corner colors blend through, matching the three
80
+ * gradients.
81
+ */
82
+ interface MeshGradientPaint {
83
+ kind: 'mesh-gradient';
84
+ patches: MeshPatch[];
85
+ units?: PaintUnits;
86
+ interpolate?: ColorSpace;
87
+ opacity?: number;
88
+ }
89
+ /** The kind's id, as `Paint['fill']` carries it. */
90
+ declare const MESH_GRADIENT_KIND = "mesh-gradient";
91
+ /** A mesh paint, narrowed. */
92
+ declare function isMeshGradientPaint(fill: Paint | null | undefined): fill is Paint & MeshGradientPaint;
93
+ /** A one-patch square covering the unit box, its four corners four readings of
94
+ * `color` — a mesh seeded from a solid has to show *something* curved, or
95
+ * switching kind looks like nothing happened. */
96
+ declare function seedMeshPatch(color: string): MeshGradientPaint;
97
+ /**
98
+ * A stop list as a mesh: one full-height band per gap between neighboring
99
+ * stops, colored left to right. The bands blend exactly the way the ramp
100
+ * does, so a horizontal gradient survives the switch unchanged. A zero-width
101
+ * gap is a hard break and gets no band.
102
+ */
103
+ declare function meshFromStops(stops: readonly GradStop[]): MeshGradientPaint;
104
+ /**
105
+ * A mesh read as a stop list: every patch's top edge — corner 0 to corner 1 —
106
+ * placed by its `x` across the mesh's horizontal extent. The inverse of
107
+ * `meshFromStops`, and for any other mesh the ramp across its top.
108
+ */
109
+ declare function meshStops(mesh: MeshGradientPaint): GradStop[];
110
+ /** The kind's draw half, shader program included. Core adds the editor's
111
+ * slots and registers the whole entry. */
112
+ declare const meshDrawKind: PaintDrawKind;
113
+ /**
114
+ * The `<defs>` entry for a mesh paint, in weasel's own namespace.
115
+ *
116
+ * Not SVG's abandoned `<meshgradient>`: that vocabulary only reaches Coons
117
+ * patches, shares patch edges implicitly — a reader that gets the sharing
118
+ * wrong tears the surface rather than failing outright — and has exactly one
119
+ * implementation in the world. Ours writes every patch's points in full.
120
+ * `@weasel-js/svg` puts the paint fallback color beside the reference, so a
121
+ * foreign renderer paints flat instead of nothing.
122
+ */
123
+ declare function meshGradientXml(id: string, mesh: MeshGradientPaint): string;
124
+
125
+ /**
126
+ * A mesh paint baked into one RGBA bitmap: each patch is subdivided into small
127
+ * quads and rasterized forward, once per paint, into a texture the shader then
128
+ * samples. Inverting a bicubic per fragment would be Newton iteration.
129
+ *
130
+ * The bitmap is straight (non-premultiplied) RGBA; the fragment shader
131
+ * premultiplies.
132
+ */
133
+
134
+ /** Texels on a side of a bake when the caller names no size. The renderer
135
+ * sizes each bake from how large the paint draws — see `meshBakeSize`. */
136
+ declare const MESH_BAKE_SIZE = 256;
137
+ /** The box a bake covers, in the paint's own space. */
138
+ interface MeshBox {
139
+ x: number;
140
+ y: number;
141
+ width: number;
142
+ height: number;
143
+ }
144
+ /** The bitmap `bakeMesh` produces, and the paint-space box it covers. */
145
+ interface BakedMesh {
146
+ /** `size` × `size` texels, straight RGBA. */
147
+ pixels: Uint8ClampedArray;
148
+ /** Texels on a side; `MESH_BAKE_SIZE` unless the caller asked otherwise. */
149
+ size: number;
150
+ /** Where the bitmap sits in paint space, which is what the shader maps a
151
+ * fragment through. */
152
+ box: MeshBox;
153
+ }
154
+ /** The union of every patch's bounds, or `null` when nothing is drawable. */
155
+ declare function meshBounds(patches: readonly MeshPatch[]): MeshBox | null;
156
+ /**
157
+ * Rasterize `patches` into a square bitmap covering their union, or `null`
158
+ * when no patch is drawable.
159
+ */
160
+ declare function bakeMesh(patches: readonly MeshPatch[], space?: ColorSpace, size?: number): BakedMesh | null;
161
+
162
+ /**
163
+ * How large a mesh bake is, and the bounded cache the bakes live in.
164
+ *
165
+ * A gradient's ramp is one-dimensional, so 256 texels cover it at any size. A
166
+ * mesh's bake is two-dimensional and is stretched over whatever the paint
167
+ * covers, so a fixed size shows its texels once the paint draws large. The
168
+ * bake is sized from the device pixels it covers instead, in power-of-two
169
+ * buckets so a zoom inside one bucket reuses the bake it already has.
170
+ */
171
+ /** The smallest bake: below this a texture costs more in bookkeeping than in
172
+ * bytes. */
173
+ declare const MESH_BAKE_MIN = 32;
174
+ /** The largest bake, whatever the context allows: 16 MiB of RGBA, and a bake
175
+ * that already takes a noticeable moment on the CPU. */
176
+ declare const MESH_BAKE_MAX = 2048;
177
+ /**
178
+ * The bake side for a paint drawn `devicePx` device pixels across, on a
179
+ * context accepting `maxTextureSize`: the next power of two at or above it,
180
+ * clamped to `[MESH_BAKE_MIN, MESH_BAKE_MAX]` and to the context. A size that
181
+ * cannot be measured gets `MESH_BAKE_SIZE`.
182
+ */
183
+ declare function meshBakeSize(devicePx: number, maxTextureSize: number): number;
184
+
185
+ /**
186
+ * The draggable points of a mesh paint, as pure geometry — what an on-canvas
187
+ * editor lists, and what moving one of them does to the paint.
188
+ *
189
+ * Nothing here knows a frame: the handles are in whatever space the mesh's
190
+ * points are, so a caller resolves a `'bounds'` mesh onto its box first
191
+ * (`fillInPoseFrame`) and normalizes the result back (`fillToBoundsFrame`).
192
+ */
193
+
194
+ /** What a handle moves: a patch corner, one of the two controls of an edge,
195
+ * or one of a tensor patch's four interior points. */
196
+ type MeshHandleKind = 'corner' | 'control' | 'interior';
197
+ /** One stored point: `patches[patch].points[index]`. */
198
+ interface MeshPointRef {
199
+ patch: number;
200
+ index: number;
201
+ }
202
+ /**
203
+ * One draggable point.
204
+ *
205
+ * Patches store their points in full rather than sharing edges, so two
206
+ * patches that meet each carry a copy of the corner and controls they meet
207
+ * at. Those copies are one handle, with a `ref` per copy — dragging one of
208
+ * them alone would tear the surface open along the seam.
209
+ */
210
+ interface MeshHandle {
211
+ /** Stable while the handle moves: its first ref, as `"patch:index"`. */
212
+ id: string;
213
+ kind: MeshHandleKind;
214
+ at: MeshPoint;
215
+ refs: readonly MeshPointRef[];
216
+ }
217
+ /**
218
+ * Every draggable point of `mesh`, in walk order: each patch's corners and
219
+ * edge controls, then a tensor patch's interior. Coincident points of one
220
+ * kind merge into one handle. A patch that cannot be evaluated has none.
221
+ */
222
+ declare function meshHandles(mesh: MeshGradientPaint): MeshHandle[];
223
+ /**
224
+ * `mesh` with `handle` moved to `to`. A corner carries its edge controls
225
+ * and interior neighbor along by the same offset, the way a path editor's
226
+ * anchor carries its handles; a control or interior point moves alone.
227
+ * Returns a new paint; `mesh` is not modified.
228
+ */
229
+ declare function moveMeshHandle(mesh: MeshGradientPaint, handle: MeshHandle, to: MeshPoint): MeshGradientPaint;
230
+ /** The lines an editor draws under the handles, as control polygons. */
231
+ interface MeshGuides {
232
+ /** Every patch edge as its four cubic control points, from the corner it
233
+ * leaves to the corner it reaches. */
234
+ edges: [MeshPoint, MeshPoint, MeshPoint, MeshPoint][];
235
+ /** Corner to each point it carries — an edge control or interior point. */
236
+ arms: [MeshPoint, MeshPoint][];
237
+ }
238
+ /** The guides for `mesh`'s valid patches. Shared edges appear once per patch. */
239
+ declare function meshGuides(mesh: MeshGradientPaint): MeshGuides;
240
+
241
+ export { type BakedMesh, MESH_BAKE_MAX, MESH_BAKE_MIN, MESH_BAKE_SIZE, MESH_GRADIENT_KIND, type MeshBox, type MeshGradientPaint, type MeshGuides, type MeshHandle, type MeshHandleKind, type MeshPatch, type MeshPoint, type MeshPointRef, bakeMesh, cornerWeights, evalPatch, isMeshGradientPaint, isTensorPatch, isValidPatch, meshBakeSize, meshBounds, meshDrawKind, meshFromStops, meshGradientXml, meshGuides, meshHandles, meshStops, moveMeshHandle, patchBounds, patchCorner, seedMeshPatch };