@swf2es/render 0.0.0-stage → 0.1.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.
Files changed (143) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +17 -2
  3. package/dist/commands.d.ts +67 -0
  4. package/dist/commands.d.ts.map +1 -0
  5. package/dist/commands.js +93 -0
  6. package/dist/commands.js.map +1 -0
  7. package/dist/filter-plan.d.ts +110 -0
  8. package/dist/filter-plan.d.ts.map +1 -0
  9. package/dist/filter-plan.js +480 -0
  10. package/dist/filter-plan.js.map +1 -0
  11. package/dist/filter-shaders.d.ts +63 -0
  12. package/dist/filter-shaders.d.ts.map +1 -0
  13. package/dist/filter-shaders.js +350 -0
  14. package/dist/filter-shaders.js.map +1 -0
  15. package/dist/filters.d.ts +107 -0
  16. package/dist/filters.d.ts.map +1 -0
  17. package/dist/filters.js +187 -0
  18. package/dist/filters.js.map +1 -0
  19. package/dist/geometry.d.ts +83 -0
  20. package/dist/geometry.d.ts.map +1 -0
  21. package/dist/geometry.js +93 -0
  22. package/dist/geometry.js.map +1 -0
  23. package/dist/index.d.ts +11 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +13 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/keeps.d.ts +17 -0
  28. package/dist/keeps.d.ts.map +1 -0
  29. package/dist/keeps.js +17 -0
  30. package/dist/keeps.js.map +1 -0
  31. package/dist/kernel-shaders.d.ts +74 -0
  32. package/dist/kernel-shaders.d.ts.map +1 -0
  33. package/dist/kernel-shaders.js +323 -0
  34. package/dist/kernel-shaders.js.map +1 -0
  35. package/dist/measure.d.ts +56 -0
  36. package/dist/measure.d.ts.map +1 -0
  37. package/dist/measure.js +287 -0
  38. package/dist/measure.js.map +1 -0
  39. package/dist/plan.d.ts +14 -0
  40. package/dist/plan.d.ts.map +1 -0
  41. package/dist/plan.js +247 -0
  42. package/dist/plan.js.map +1 -0
  43. package/dist/registry.d.ts +49 -0
  44. package/dist/registry.d.ts.map +1 -0
  45. package/dist/registry.js +87 -0
  46. package/dist/registry.js.map +1 -0
  47. package/dist/rows.d.ts +39 -0
  48. package/dist/rows.d.ts.map +1 -0
  49. package/dist/rows.js +60 -0
  50. package/dist/rows.js.map +1 -0
  51. package/dist/scene.d.ts +179 -0
  52. package/dist/scene.d.ts.map +1 -0
  53. package/dist/scene.js +265 -0
  54. package/dist/scene.js.map +1 -0
  55. package/dist/shelves.d.ts +23 -0
  56. package/dist/shelves.d.ts.map +1 -0
  57. package/dist/shelves.js +63 -0
  58. package/dist/shelves.js.map +1 -0
  59. package/dist/textures.d.ts +72 -0
  60. package/dist/textures.d.ts.map +1 -0
  61. package/dist/textures.js +160 -0
  62. package/dist/textures.js.map +1 -0
  63. package/dist/webgl/atlas.d.ts +63 -0
  64. package/dist/webgl/atlas.d.ts.map +1 -0
  65. package/dist/webgl/atlas.js +328 -0
  66. package/dist/webgl/atlas.js.map +1 -0
  67. package/dist/webgl/backend.d.ts +141 -0
  68. package/dist/webgl/backend.d.ts.map +1 -0
  69. package/dist/webgl/backend.js +659 -0
  70. package/dist/webgl/backend.js.map +1 -0
  71. package/dist/webgl/composite.d.ts +101 -0
  72. package/dist/webgl/composite.d.ts.map +1 -0
  73. package/dist/webgl/composite.js +293 -0
  74. package/dist/webgl/composite.js.map +1 -0
  75. package/dist/webgl/draws.d.ts +213 -0
  76. package/dist/webgl/draws.d.ts.map +1 -0
  77. package/dist/webgl/draws.js +714 -0
  78. package/dist/webgl/draws.js.map +1 -0
  79. package/dist/webgl/filters.d.ts +107 -0
  80. package/dist/webgl/filters.d.ts.map +1 -0
  81. package/dist/webgl/filters.js +351 -0
  82. package/dist/webgl/filters.js.map +1 -0
  83. package/dist/webgl/gpu-textures.d.ts +44 -0
  84. package/dist/webgl/gpu-textures.d.ts.map +1 -0
  85. package/dist/webgl/gpu-textures.js +178 -0
  86. package/dist/webgl/gpu-textures.js.map +1 -0
  87. package/dist/webgl/holds.d.ts +97 -0
  88. package/dist/webgl/holds.d.ts.map +1 -0
  89. package/dist/webgl/holds.js +453 -0
  90. package/dist/webgl/holds.js.map +1 -0
  91. package/dist/webgl/index.d.ts +2 -0
  92. package/dist/webgl/index.d.ts.map +1 -0
  93. package/dist/webgl/index.js +4 -0
  94. package/dist/webgl/index.js.map +1 -0
  95. package/dist/webgl/kernels.d.ts +64 -0
  96. package/dist/webgl/kernels.d.ts.map +1 -0
  97. package/dist/webgl/kernels.js +160 -0
  98. package/dist/webgl/kernels.js.map +1 -0
  99. package/dist/webgl/pool.d.ts +71 -0
  100. package/dist/webgl/pool.d.ts.map +1 -0
  101. package/dist/webgl/pool.js +192 -0
  102. package/dist/webgl/pool.js.map +1 -0
  103. package/dist/webgl/programs.d.ts +130 -0
  104. package/dist/webgl/programs.d.ts.map +1 -0
  105. package/dist/webgl/programs.js +582 -0
  106. package/dist/webgl/programs.js.map +1 -0
  107. package/dist/webgl/stage.d.ts +67 -0
  108. package/dist/webgl/stage.d.ts.map +1 -0
  109. package/dist/webgl/stage.js +173 -0
  110. package/dist/webgl/stage.js.map +1 -0
  111. package/dist/webgl/targets.d.ts +172 -0
  112. package/dist/webgl/targets.d.ts.map +1 -0
  113. package/dist/webgl/targets.js +323 -0
  114. package/dist/webgl/targets.js.map +1 -0
  115. package/package.json +35 -3
  116. package/src/commands.ts +98 -0
  117. package/src/filter-plan.ts +755 -0
  118. package/src/filter-shaders.ts +360 -0
  119. package/src/filters.ts +220 -0
  120. package/src/geometry.ts +143 -0
  121. package/src/index.ts +87 -0
  122. package/src/keeps.ts +21 -0
  123. package/src/kernel-shaders.ts +375 -0
  124. package/src/measure.ts +400 -0
  125. package/src/plan.ts +331 -0
  126. package/src/registry.ts +105 -0
  127. package/src/rows.ts +93 -0
  128. package/src/scene.ts +297 -0
  129. package/src/shelves.ts +70 -0
  130. package/src/textures.ts +198 -0
  131. package/src/webgl/atlas.ts +370 -0
  132. package/src/webgl/backend.ts +973 -0
  133. package/src/webgl/composite.ts +372 -0
  134. package/src/webgl/draws.ts +902 -0
  135. package/src/webgl/filters.ts +502 -0
  136. package/src/webgl/gpu-textures.ts +253 -0
  137. package/src/webgl/holds.ts +624 -0
  138. package/src/webgl/index.ts +3 -0
  139. package/src/webgl/kernels.ts +205 -0
  140. package/src/webgl/pool.ts +245 -0
  141. package/src/webgl/programs.ts +620 -0
  142. package/src/webgl/stage.ts +214 -0
  143. package/src/webgl/targets.ts +464 -0
@@ -0,0 +1,323 @@
1
+ // Pixel Bender kernels where Flash draws with them, as fragment shaders
2
+ // around a kernel's GLSL (the player's scene/pixel-bender-glsl.ts, which
3
+ // defines `vec4 pbKernel(vec2 outCoord)` and calls `pbNearest<t>` and
4
+ // `pbLinear<t>` for each texture `t` it samples). What is here is how
5
+ // each use reads its images and writes what the kernel gives, as adl
6
+ // does (docs/architecture/bitmaps.md, "Pixel Bender"): an image read as
7
+ // its premultiplied bytes times the float nearest 1/255, linearly in
8
+ // 256ths with each step's byte cut down; floats as they are, linearly in
9
+ // the same 256ths; as the CPU interpreter reads them. GLSL ES 3, each a
10
+ // whole fragment shader.
11
+ /** A byte's float as adl samples one: times the float nearest 1/255, not divided. */
12
+ const BYTE = "0.003921568859368563";
13
+ /** Each fragment shader's first lines, so that one is the whole source a program cache keys by. */
14
+ const HEADER = "#version 300 es\nprecision highp float;\n";
15
+ /** The most images a kernel's program binds besides its layer's: one with more is not drawn. */
16
+ export const KERNEL_IMAGES = 8;
17
+ /** Whether `images` bind no more textures of their own than a program takes (KERNEL_IMAGES). */
18
+ export function kernelImagesFit(images) {
19
+ let own = 0;
20
+ for (let k = 0; k < images.length; k++) {
21
+ if (!images[k].layer) {
22
+ own++;
23
+ }
24
+ }
25
+ return own <= KERNEL_IMAGES;
26
+ }
27
+ /**
28
+ * Precision, as ints default to mediump in a fragment shader; a texel
29
+ * coordinate as a texel's index, NaN as 0 and far past the edges kept in
30
+ * int's range; a texel's bytes from 0 to 255, read exactly from the 8-bit
31
+ * texture; and a kernel's output as adl writes it into a bitmap: clamped,
32
+ * NaN as 0, rounded to a byte a half to the even, each colour at most its
33
+ * alpha.
34
+ */
35
+ const PRELUDE = `precision highp int;
36
+ precision highp sampler2D;
37
+ ivec2 pbFloor(vec2 x) {
38
+ x = mix(x, vec2(0.0), isnan(x));
39
+ return ivec2(clamp(floor(x), -1.0e9, 1.0e9));
40
+ }
41
+ vec4 pbBytes(vec4 v) {
42
+ return floor(v * 255.0 + 0.5);
43
+ }
44
+ vec4 pbOutput(vec4 c) {
45
+ c = mix(vec4(0.0), min(c, 1.0), greaterThan(c, vec4(0.0)));
46
+ c = roundEven(c * 255.0) / 255.0;
47
+ return vec4(min(c.rgb, c.a), c.a);
48
+ }
49
+ `;
50
+ /**
51
+ * Image `t`'s sampling from `pbTexel<t>`, its texel at an index (bytes from
52
+ * 0 to 255, or floats), at the texel coordinates `at` gives for a kernel's.
53
+ */
54
+ function sampling(t, at, float) {
55
+ if (float) {
56
+ // The interpreter's floats: their texels as they are, linearly in 256ths, nothing cut.
57
+ return `vec4 pbNearest${t}(vec2 p) {
58
+ return pbTexel${t}(pbFloor(${at}));
59
+ }
60
+ vec4 pbLinear${t}(vec2 p) {
61
+ vec2 f = ${at} - 0.5;
62
+ vec2 below = floor(f);
63
+ vec2 w = floor((f - below) * 256.0 + 0.5) / 256.0;
64
+ w = mix(w, vec2(0.0), isnan(w));
65
+ ivec2 a = pbFloor(below);
66
+ vec4 row0 = pbTexel${t}(a) * (1.0 - w.x) + pbTexel${t}(a + ivec2(1, 0)) * w.x;
67
+ vec4 row1 = pbTexel${t}(a + ivec2(0, 1)) * (1.0 - w.x) + pbTexel${t}(a + 1) * w.x;
68
+ return row0 * (1.0 - w.y) + row1 * w.y;
69
+ }
70
+ `;
71
+ }
72
+ return `vec4 pbNearest${t}(vec2 p) {
73
+ return pbTexel${t}(pbFloor(${at})) * ${BYTE};
74
+ }
75
+ vec4 pbLinear${t}(vec2 p) {
76
+ vec2 f = ${at} - 0.5;
77
+ vec2 below = floor(f);
78
+ vec2 w = floor((f - below) * 256.0 + 0.5);
79
+ w = mix(w, vec2(0.0), isnan(w));
80
+ ivec2 a = pbFloor(below);
81
+ vec4 row0 = floor((pbTexel${t}(a) * (256.0 - w.x) + pbTexel${t}(a + ivec2(1, 0)) * w.x) / 256.0);
82
+ vec4 row1 = floor((pbTexel${t}(a + ivec2(0, 1)) * (256.0 - w.x) + pbTexel${t}(a + 1) * w.x) / 256.0);
83
+ return floor((row0 * (256.0 - w.y) + row1 * w.y) / 256.0) * ${BYTE};
84
+ }
85
+ `;
86
+ }
87
+ /**
88
+ * Image `t`, a texture of its own (`pbImage<t>`), clamped to its edges as
89
+ * adl clamps a kernel's input: its sampler, its texels and its sampling, in
90
+ * its own pixels.
91
+ */
92
+ function ownImage(t, float) {
93
+ const texel = `texelFetch(pbImage${t}, clamp(at, ivec2(0), size - 1), 0)`;
94
+ return `uniform sampler2D pbImage${t};
95
+ vec4 pbTexel${t}(ivec2 at) {
96
+ ivec2 size = textureSize(pbImage${t}, 0);
97
+ return ${float ? texel : `pbBytes(${texel})`};
98
+ }
99
+ ${sampling(t, "p", float)}`;
100
+ }
101
+ /**
102
+ * The kernel's GLSL with what every use puts round it: PRELUDE, then each
103
+ * image, by `layerTexel` for the layer's, its texel at an index, and
104
+ * ownImage for the others; `layerAt` takes a kernel's coordinate to the
105
+ * layer's texels.
106
+ */
107
+ export function withImages(kernel, images, layerTexel, layerAt) {
108
+ const parts = [PRELUDE];
109
+ for (const { texture: t, layer, float, back } of images) {
110
+ parts.push(layer
111
+ ? `${layerTexel(t, back ?? false)}\n${sampling(t, layerAt, false)}`
112
+ : ownImage(t, float));
113
+ }
114
+ parts.push(kernel);
115
+ return parts.join("\n");
116
+ }
117
+ /** The most kernels whose shaders a use keeps made (madeOnce), emptied when more come. */
118
+ const MADE = 64;
119
+ /** A kernel's shader for its images, made once: a frame asks for it again on each of its uses. */
120
+ export function madeOnce(made, kernel, images, make) {
121
+ let key = "";
122
+ for (let k = 0; k < images.length; k++) {
123
+ const i = images[k];
124
+ key += `${i.texture}${i.layer ? (i.back ? "B" : "L") : ""}${i.float ? "F" : ""},`;
125
+ }
126
+ let byImages = made.get(kernel);
127
+ if (!byImages) {
128
+ if (made.size >= MADE) {
129
+ made.clear();
130
+ }
131
+ byImages = new Map();
132
+ made.set(kernel, byImages);
133
+ }
134
+ let source = byImages.get(key);
135
+ if (source === undefined) {
136
+ source = make();
137
+ byImages.set(key, source);
138
+ }
139
+ return source;
140
+ }
141
+ const madeFilters = new Map();
142
+ /**
143
+ * A ShaderFilter's pass (filter-plan.ts, KERNEL_PASS), run as the
144
+ * filters' other passes are (webgl/filters.ts): the kernel's output over
145
+ * the input's frame, `outCoord` its pixel's centre in stage pixels from
146
+ * the corner of the bitmap the filter reads, `uKernelAt.xy` texels in from
147
+ * the frame's, which starts at `uOutputAt` in the target drawn into, at
148
+ * `uKernelAt.z` texels a stage pixel. The layer's image is the input
149
+ * (uTexture, within uTextureRect), transparent past the frame,
150
+ * `uKernelFrame` texels, as adl reads a filter's source; the others clamp
151
+ * to their edges. The output is as adl writes it (pbOutput), and
152
+ * transparent outside `uKernelRegion`, that bitmap grown by the filter's
153
+ * extensions, in stage pixels.
154
+ */
155
+ export function filterKernel(kernel, images) {
156
+ return madeOnce(madeFilters, kernel, images, () => filterSource(kernel, images));
157
+ }
158
+ function filterSource(kernel, images) {
159
+ const layer = (t) => `vec4 pbTexel${t}(ivec2 at) {
160
+ if (any(lessThan(at, ivec2(0))) || any(greaterThanEqual(at, ivec2(uKernelFrame)))) {
161
+ return vec4(0.0);
162
+ }
163
+ return pbBytes(texelFetch(uTexture, ivec2(uTextureRect.xy) + at, 0));
164
+ }`;
165
+ return `${HEADER}in vec2 vTextureCoord;
166
+ out vec4 finalColor;
167
+ uniform sampler2D uTexture;
168
+ uniform highp vec4 uInputPixel;
169
+ uniform vec4 uTextureRect;
170
+ uniform vec3 uKernelAt;
171
+ uniform vec2 uKernelFrame;
172
+ uniform vec4 uKernelRegion;
173
+ uniform vec2 uOutputAt;
174
+ ${withImages(kernel, images, layer, "p * uKernelAt.z + uKernelAt.xy")}
175
+ void main(void) {
176
+ // From the fragment's centre, exact, where an interpolated coordinate is a hair off a half.
177
+ vec2 outCoord = (gl_FragCoord.xy - uOutputAt - uKernelAt.xy) / uKernelAt.z;
178
+ if (any(lessThan(outCoord, uKernelRegion.xy)) || any(greaterThanEqual(outCoord, uKernelRegion.zw))) {
179
+ finalColor = vec4(0.0);
180
+ return;
181
+ }
182
+ finalColor = pbOutput(pbKernel(outCoord));
183
+ }
184
+ `;
185
+ }
186
+ const madeBlends = new Map();
187
+ /**
188
+ * A blend shader's composite (webgl/composite.ts), drawn as the composite
189
+ * program is (programs.ts, compositeFragment), its uniforms the same: as
190
+ * adl runs one, a pixel at a time, each where the layer covers anything
191
+ * and nothing where it does not, or over its whole rectangle (uWhole),
192
+ * the kernel's coordinate (0.5, 0.5) and its first two inputs that pixel
193
+ * of what is below and of the layer, coloured, whatever coordinate it
194
+ * samples them at; its result in place of what was below, as adl writes
195
+ * it (pbOutput). `rows` is the colour transform's reading of uRows
196
+ * (programs.ts, LAYER_COLOR).
197
+ */
198
+ export function blendKernel(kernel, images, rows) {
199
+ return madeOnce(madeBlends, kernel, images, () => blendSource(kernel, images, rows));
200
+ }
201
+ function blendSource(kernel, images, rows) {
202
+ const pixel = (t, back) => `vec4 pbTexel${t}(ivec2 at) {
203
+ return pbBytes(${back ? "pbBack" : "pbFront"});
204
+ }`;
205
+ return `${HEADER}uniform sampler2D uLayer;
206
+ uniform sampler2D uBack;
207
+ uniform highp sampler2D uRows;
208
+ uniform int uRow;
209
+ uniform ivec2 uOffset;
210
+ uniform bool uFlip;
211
+ uniform ivec2 uBackOffset;
212
+ uniform bool uWhole;
213
+ out vec4 finalColor;
214
+ vec4 pbFront;
215
+ vec4 pbBack;
216
+ ${withImages(kernel, images, pixel, "p")}
217
+ void main(void) {
218
+ ivec2 frag = ivec2(gl_FragCoord.xy);
219
+ ivec2 at = ivec2(frag.x - uOffset.x, uFlip ? uOffset.y - frag.y : frag.y - uOffset.y);
220
+ vec4 front = texelFetch(uLayer, at, 0);
221
+ ${rows}
222
+ pbBack = texelFetch(uBack, frag - uBackOffset, 0);
223
+ if (!uWhole && pbBytes(front).a == 0.0) {
224
+ finalColor = pbBack;
225
+ return;
226
+ }
227
+ pbFront = front;
228
+ finalColor = pbOutput(pbKernel(vec2(0.5)));
229
+ }
230
+ `;
231
+ }
232
+ /**
233
+ * The layer shrunk to a texel a stage pixel for a kernel run once a pixel
234
+ * (filter-plan.ts): each output texel the mean of the `uDown.x` by
235
+ * `uDown.x` texels of the pixel it stands for, the grid from `uDown.yz`
236
+ * texels past the input's corner, which may be less than 0; the texels of
237
+ * a pixel past the frame, `uKernelFrame`, left out of the mean.
238
+ */
239
+ export const PIXELS_DOWN = `${HEADER}precision highp int;
240
+ in vec2 vTextureCoord;
241
+ out vec4 finalColor;
242
+ uniform sampler2D uTexture;
243
+ uniform vec4 uTextureRect;
244
+ uniform vec3 uDown;
245
+ uniform vec2 uKernelFrame;
246
+ uniform vec2 uOutputAt;
247
+ void main(void) {
248
+ int n = int(uDown.x);
249
+ ivec2 from = ivec2(gl_FragCoord.xy - uOutputAt) * n + ivec2(uDown.yz);
250
+ ivec2 frame = ivec2(uKernelFrame);
251
+ vec4 sum = vec4(0.0);
252
+ float count = 0.0;
253
+ for (int j = 0; j < 16; j++) {
254
+ if (j >= n) { break; }
255
+ for (int i = 0; i < 16; i++) {
256
+ if (i >= n) { break; }
257
+ ivec2 at = from + ivec2(i, j);
258
+ if (all(greaterThanEqual(at, ivec2(0))) && all(lessThan(at, frame))) {
259
+ sum += texelFetch(uTexture, ivec2(uTextureRect.xy) + at, 0);
260
+ count += 1.0;
261
+ }
262
+ }
263
+ }
264
+ finalColor = count > 0.0 ? sum / count : vec4(0.0);
265
+ }
266
+ `;
267
+ /**
268
+ * A kernel's output, run a texel a stage pixel, drawn back over the
269
+ * layer's frame: each texel its pixel's, the grid as PIXELS_DOWN had it.
270
+ */
271
+ export const PIXELS_BACK = `${HEADER}precision highp int;
272
+ in vec2 vTextureCoord;
273
+ out vec4 finalColor;
274
+ uniform sampler2D uTexture;
275
+ uniform vec4 uTextureRect;
276
+ uniform vec3 uDown;
277
+ uniform vec2 uOutputAt;
278
+ void main(void) {
279
+ ivec2 at = (ivec2(gl_FragCoord.xy - uOutputAt) - ivec2(uDown.yz)) / int(uDown.x);
280
+ at = clamp(at, ivec2(0), ivec2(uTextureRect.zw) - 1);
281
+ finalColor = texelFetch(uTexture, ivec2(uTextureRect.xy) + at, 0);
282
+ }
283
+ `;
284
+ const madeFills = new Map();
285
+ /**
286
+ * A shader fill's program, after the mesh's vertex shader (programs.ts,
287
+ * meshVertex), which carries the kernel's coordinates in vUVT with a depth
288
+ * of 1: the kernel run once a pixel of Flash's, at its centre (uFrag as the
289
+ * mesh's has it), its images clamped to their edges; its colours left
290
+ * past its alpha, as adl composites them, but under a colour transform,
291
+ * which takes them straight.
292
+ */
293
+ export function fillKernel(kernel, images) {
294
+ return madeOnce(madeFills, kernel, images, () => fillSource(kernel, images));
295
+ }
296
+ function fillSource(kernel, images) {
297
+ return `${HEADER}in vec3 vUVT;
298
+ flat in vec4 vMul;
299
+ flat in vec4 vAdd;
300
+ uniform vec4 uFrag;
301
+ out vec4 finalColor;
302
+ ${withImages(kernel, images, () => "", "p")}
303
+ void main(void) {
304
+ float pixel = uFrag.w;
305
+ vec2 f = vec2(gl_FragCoord.x + uFrag.x, uFrag.y + uFrag.z * gl_FragCoord.y);
306
+ vec2 centre = (floor(f / pixel) + 0.5) * pixel;
307
+ vec3 at = vUVT + dFdx(vUVT) * (centre.x - f.x) + dFdy(vUVT) * ((centre.y - f.y) * uFrag.z);
308
+ vec4 c = pbKernel(at.xy / at.z);
309
+ c = mix(vec4(0.0), min(c, 1.0), greaterThan(c, vec4(0.0)));
310
+ if (vMul == vec4(1.0) && vAdd == vec4(0.0)) {
311
+ finalColor = c;
312
+ return;
313
+ }
314
+ if (c.a == 0.0) {
315
+ finalColor = vec4(0.0);
316
+ return;
317
+ }
318
+ vec4 s = clamp(vec4(c.rgb / c.a, c.a) * vMul + vAdd, 0.0, 1.0);
319
+ finalColor = vec4(s.rgb * s.a, s.a);
320
+ }
321
+ `;
322
+ }
323
+ //# sourceMappingURL=kernel-shaders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kernel-shaders.js","sourceRoot":"","sources":["../src/kernel-shaders.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import type { Geometries } from "./geometry.js";
2
+ import { type Rows } from "./rows.js";
3
+ import { type SceneList } from "./scene.js";
4
+ /**
5
+ * What measuring a frame's layers needs of its target: its size in pixels,
6
+ * its pixels a stage pixel, and its pixels a unit of its own (resolution),
7
+ * which a filtered layer is padded in.
8
+ */
9
+ export interface MeasureTarget {
10
+ width: number;
11
+ height: number;
12
+ scale: number;
13
+ resolution: number;
14
+ }
15
+ /**
16
+ * Each layer's rectangle of the target (SceneList.layerRect), from what is
17
+ * drawn in it: its draws' geometries placed by their rows, a mask's own
18
+ * draws apart, what a mask clips cut to that mask's draws as it pops, and
19
+ * the rectangles of the layers in it; out to whole pixels and a pixel more
20
+ * each way, cut to the target. An alpha mask's layer is no part of the
21
+ * unfiltered layer it ends, which it cuts to its own rectangle instead, as
22
+ * nothing of that layer shows past it. What is drawn is what is measured,
23
+ * so a layer covers its draws however they came to be where they are. A
24
+ * filtered layer is measured as PixiJS's filter system measures it, which
25
+ * the filters' exactness rules were found with: cut to the target, out to
26
+ * whole pixels, then padded, not cut again; where nothing is drawn in it,
27
+ * it draws nothing.
28
+ */
29
+ export declare function measureLayers(scene: SceneList, rows: Rows, geometries: Geometries, target: MeasureTarget): void;
30
+ /**
31
+ * The rectangle a filtered layer padded by `pad` units covers, from its
32
+ * area (least x and y, greatest x and y in target pixels, from `area[at]`)
33
+ * as PixiJS's filter system has it (FilterSystem's _calculateFilterArea): in
34
+ * units, the area cut to the target, out to whole pixels at the
35
+ * resolution, or to whole stage pixels as `whole` says (SceneList.wholes),
36
+ * padded; nothing where it has no size then; its edges snapped to the
37
+ * pixels they lie on. Into `out` from `to`: x, y, width, height, of no
38
+ * size for nothing. A whole layer's object, uncut, goes into `objects` at
39
+ * `to` too (SceneList.objects).
40
+ */
41
+ export declare function filteredRect(area: ArrayLike<number>, at: number, pad: number, target: MeasureTarget, out: Int32Array, to: number, whole?: number, objects?: Float64Array | null): void;
42
+ /**
43
+ * Flash's bitmap of an object of bounds x0, y0 to x1, y1 in stage pixels:
44
+ * the bounds out to twips, then antialiased (WHOLE_SMOOTH) the pixels its
45
+ * edges touch and one more right and down where an edge lies on one,
46
+ * aliased (WHOLE_ALIASED) those whose centres it covers.
47
+ */
48
+ export declare function wholeBitmap(x0: number, y0: number, x1: number, y1: number, whole: number): number[];
49
+ /**
50
+ * The area of the target the draws from entry `from` on cover, at `scale`
51
+ * target pixels a stage pixel, masks' own draws apart and nothing cut by
52
+ * the masks: into `out`, its least x and y, then its greatest, in target
53
+ * pixels; nothing drawn leaves the least past the greatest.
54
+ */
55
+ export declare function drawnArea(scene: SceneList, rows: Rows, geometries: Geometries, from: number, scale: number, out: number[]): void;
56
+ //# sourceMappingURL=measure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../src/measure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAUL,KAAK,SAAS,EAEf,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,aAAa,GACpB,IAAI,CAqIN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EACvB,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,UAAU,EACf,EAAE,EAAE,MAAM,EACV,KAAK,SAAW,EAChB,OAAO,GAAE,YAAY,GAAG,IAAW,GAClC,IAAI,CA2DN;AAKD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,MAAM,EAAE,CAkBV;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EAAE,GACZ,IAAI,CAoBN"}
@@ -0,0 +1,287 @@
1
+ import { ROW_FLOATS } from "./rows.js";
2
+ import { ALPHA_MASK, DRAW, KEPT, LAYER_BEGIN, LAYER_END, MASK_BEGIN, MASK_POP, MASK_USE, NO_WHOLE, WHOLE_ALIASED, } from "./scene.js";
3
+ /** A hair, which keeps a padded edge on the pixel it lies on at any resolution. */
4
+ const TEXEL_SNAP = 1e-6;
5
+ // Scratch stacks, four numbers an open area: least x and y, greatest x and y, in target pixels.
6
+ const areas = [];
7
+ const clips = [];
8
+ const open = [];
9
+ // Each open layer's cut, four numbers as an area's: an alpha mask's rectangle in it (ALPHA_MASK).
10
+ const cuts = [];
11
+ /**
12
+ * Each layer's rectangle of the target (SceneList.layerRect), from what is
13
+ * drawn in it: its draws' geometries placed by their rows, a mask's own
14
+ * draws apart, what a mask clips cut to that mask's draws as it pops, and
15
+ * the rectangles of the layers in it; out to whole pixels and a pixel more
16
+ * each way, cut to the target. An alpha mask's layer is no part of the
17
+ * unfiltered layer it ends, which it cuts to its own rectangle instead, as
18
+ * nothing of that layer shows past it. What is drawn is what is measured,
19
+ * so a layer covers its draws however they came to be where they are. A
20
+ * filtered layer is measured as PixiJS's filter system measures it, which
21
+ * the filters' exactness rules were found with: cut to the target, out to
22
+ * whole pixels, then padded, not cut again; where nothing is drawn in it,
23
+ * it draws nothing.
24
+ */
25
+ export function measureLayers(scene, rows, geometries, target) {
26
+ if (scene.layerCount === 0) {
27
+ return;
28
+ }
29
+ areas.length = 0;
30
+ clips.length = 0;
31
+ open.length = 0;
32
+ cuts.length = 0;
33
+ pushEmpty(areas);
34
+ const k = target.scale;
35
+ const box = geometries.box;
36
+ const m = rows.data;
37
+ for (let i = 0; i < scene.length; i++) {
38
+ switch (scene.kind[i]) {
39
+ case DRAW:
40
+ placeDraw(scene, i, box, m, k, areas);
41
+ break;
42
+ case MASK_BEGIN:
43
+ // The mask's own draws, measured apart.
44
+ pushEmpty(areas);
45
+ break;
46
+ case LAYER_BEGIN:
47
+ open.push(scene.geometry[i]);
48
+ pushEmpty(areas);
49
+ cuts.push(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
50
+ break;
51
+ case MASK_USE:
52
+ // The mask's draws clip what follows, measured apart till it pops.
53
+ moveTop(areas, clips);
54
+ pushEmpty(areas);
55
+ break;
56
+ case MASK_POP: {
57
+ const n = areas.length;
58
+ const c = clips.length;
59
+ const left = Math.max(areas[n - 4], clips[c - 4]);
60
+ const top = Math.max(areas[n - 3], clips[c - 3]);
61
+ const right = Math.min(areas[n - 2], clips[c - 2]);
62
+ const bottom = Math.min(areas[n - 1], clips[c - 1]);
63
+ areas.length = n - 4;
64
+ clips.length = c - 4;
65
+ if (right > left && bottom > top) {
66
+ unionTop(left, top, right, bottom);
67
+ }
68
+ break;
69
+ }
70
+ case LAYER_END: {
71
+ const n = areas.length;
72
+ const layer = open.pop();
73
+ const pad = scene.pads[layer];
74
+ const c = cuts.length - 4;
75
+ if (pad < 0) {
76
+ const left = Math.max(0, Math.floor(areas[n - 4]) - 1, cuts[c]);
77
+ const top = Math.max(0, Math.floor(areas[n - 3]) - 1, cuts[c + 1]);
78
+ const right = Math.min(target.width, Math.ceil(areas[n - 2]) + 1, cuts[c + 2]);
79
+ const bottom = Math.min(target.height, Math.ceil(areas[n - 1]) + 1, cuts[c + 3]);
80
+ areas.length = n - 4;
81
+ cuts.length = c;
82
+ if (scene.geometry[i] === ALPHA_MASK) {
83
+ // Not taken into the layer it ends, which it cuts to its rectangle: to nothing, where it
84
+ // has none.
85
+ if (right > left && bottom > top) {
86
+ scene.layerRect(layer, left, top, right - left, bottom - top);
87
+ }
88
+ const p = c - 4;
89
+ if (p >= 0) {
90
+ cuts[p] = Math.max(cuts[p], left);
91
+ cuts[p + 1] = Math.max(cuts[p + 1], top);
92
+ cuts[p + 2] = Math.min(cuts[p + 2], right);
93
+ cuts[p + 3] = Math.min(cuts[p + 3], bottom);
94
+ }
95
+ break;
96
+ }
97
+ if (right > left && bottom > top) {
98
+ scene.layerRect(layer, left, top, right - left, bottom - top);
99
+ unionTop(left, top, right, bottom);
100
+ }
101
+ break;
102
+ }
103
+ // The view puts no alpha mask straight in a filtered layer, which would run its filters on
104
+ // what the mask left (cuts).
105
+ cuts.length = c;
106
+ const kept = scene.areas;
107
+ for (let k = 0; k < 4; k++) {
108
+ kept[layer * 4 + k] = areas[n - 4 + k];
109
+ }
110
+ filteredRect(scene.areas, layer * 4, pad, target, scene.layers, layer * 4, scene.wholes[layer], scene.objects);
111
+ areas.length = n - 4;
112
+ const r = scene.layers;
113
+ const at = layer * 4;
114
+ if (r[at + 2] > 0) {
115
+ unionTop(r[at], r[at + 1], r[at] + r[at + 2], r[at + 1] + r[at + 3]);
116
+ }
117
+ break;
118
+ }
119
+ case KEPT: {
120
+ // A kept output covers its rectangle, which its owner placed.
121
+ const r = scene.layers;
122
+ const at = scene.geometry[i] * 4;
123
+ if (r[at + 2] > 0 && r[at + 3] > 0) {
124
+ unionTop(r[at], r[at + 1], r[at] + r[at + 2], r[at + 1] + r[at + 3]);
125
+ }
126
+ break;
127
+ }
128
+ }
129
+ }
130
+ }
131
+ /**
132
+ * The rectangle a filtered layer padded by `pad` units covers, from its
133
+ * area (least x and y, greatest x and y in target pixels, from `area[at]`)
134
+ * as PixiJS's filter system has it (FilterSystem's _calculateFilterArea): in
135
+ * units, the area cut to the target, out to whole pixels at the
136
+ * resolution, or to whole stage pixels as `whole` says (SceneList.wholes),
137
+ * padded; nothing where it has no size then; its edges snapped to the
138
+ * pixels they lie on. Into `out` from `to`: x, y, width, height, of no
139
+ * size for nothing. A whole layer's object, uncut, goes into `objects` at
140
+ * `to` too (SceneList.objects).
141
+ */
142
+ export function filteredRect(area, at, pad, target, out, to, whole = NO_WHOLE, objects = null) {
143
+ const res = target.resolution;
144
+ let x0 = area[at] / res;
145
+ let y0 = area[at + 1] / res;
146
+ let x1 = area[at + 2] / res;
147
+ let y1 = area[at + 3] / res;
148
+ out[to] = 0;
149
+ out[to + 1] = 0;
150
+ out[to + 2] = 0;
151
+ out[to + 3] = 0;
152
+ if (!(x1 > x0 && y1 > y0)) {
153
+ return;
154
+ }
155
+ if (whole !== NO_WHOLE) {
156
+ // Flash's bitmap of the object, of whole stage pixels, whatever the stage's scale; cut to the
157
+ // target only after.
158
+ const k = target.scale;
159
+ const object = wholeBitmap(area[at] / k, area[at + 1] / k, area[at + 2] / k, area[at + 3] / k, whole);
160
+ const ox0 = object[0] * k;
161
+ const oy0 = object[1] * k;
162
+ const ox1 = object[2] * k;
163
+ const oy1 = object[3] * k;
164
+ if (objects) {
165
+ objects[to] = ox0;
166
+ objects[to + 1] = oy0;
167
+ objects[to + 2] = ox1 - ox0;
168
+ objects[to + 3] = oy1 - oy0;
169
+ }
170
+ x0 = Math.max(ox0, 0) / res - pad;
171
+ y0 = Math.max(oy0, 0) / res - pad;
172
+ x1 = Math.min(ox1, target.width) / res + pad;
173
+ y1 = Math.min(oy1, target.height) / res + pad;
174
+ }
175
+ else {
176
+ // Each edge moved in alone, as Bounds.fitBounds does: an area off the target turns inside out,
177
+ // and its padding may yet give it a size.
178
+ x0 = Math.floor(Math.max(x0, 0) * res) / res - pad;
179
+ y0 = Math.floor(Math.max(y0, 0) * res) / res - pad;
180
+ x1 = Math.ceil(Math.min(x1, target.width / res) * res) / res + pad;
181
+ y1 = Math.ceil(Math.min(y1, target.height / res) * res) / res + pad;
182
+ }
183
+ if (!(x1 - x0 > 0 && y1 - y0 > 0)) {
184
+ return;
185
+ }
186
+ const left = Math.floor(x0 * res + TEXEL_SNAP);
187
+ const top = Math.floor(y0 * res + TEXEL_SNAP);
188
+ out[to] = left;
189
+ out[to + 1] = top;
190
+ out[to + 2] = Math.ceil(x1 * res - TEXEL_SNAP) - left;
191
+ out[to + 3] = Math.ceil(y1 * res - TEXEL_SNAP) - top;
192
+ }
193
+ /** What wholeBitmap gives, read before it is asked again. */
194
+ const bitmap = [0, 0, 0, 0];
195
+ /**
196
+ * Flash's bitmap of an object of bounds x0, y0 to x1, y1 in stage pixels:
197
+ * the bounds out to twips, then antialiased (WHOLE_SMOOTH) the pixels its
198
+ * edges touch and one more right and down where an edge lies on one,
199
+ * aliased (WHOLE_ALIASED) those whose centres it covers.
200
+ */
201
+ export function wholeBitmap(x0, y0, x1, y1, whole) {
202
+ x0 = Math.floor(x0 * 20 + TEXEL_SNAP) / 20;
203
+ y0 = Math.floor(y0 * 20 + TEXEL_SNAP) / 20;
204
+ x1 = Math.ceil(x1 * 20 - TEXEL_SNAP) / 20;
205
+ y1 = Math.ceil(y1 * 20 - TEXEL_SNAP) / 20;
206
+ if (whole === WHOLE_ALIASED) {
207
+ bitmap[0] = Math.ceil(x0 - 0.5);
208
+ bitmap[1] = Math.ceil(y0 - 0.5);
209
+ bitmap[2] = Math.ceil(x1 - 0.5);
210
+ bitmap[3] = Math.ceil(y1 - 0.5);
211
+ }
212
+ else {
213
+ bitmap[0] = Math.floor(x0);
214
+ bitmap[1] = Math.floor(y0);
215
+ bitmap[2] = Math.floor(x1) + 1;
216
+ bitmap[3] = Math.floor(y1) + 1;
217
+ }
218
+ return bitmap;
219
+ }
220
+ /**
221
+ * The area of the target the draws from entry `from` on cover, at `scale`
222
+ * target pixels a stage pixel, masks' own draws apart and nothing cut by
223
+ * the masks: into `out`, its least x and y, then its greatest, in target
224
+ * pixels; nothing drawn leaves the least past the greatest.
225
+ */
226
+ export function drawnArea(scene, rows, geometries, from, scale, out) {
227
+ out.length = 0;
228
+ pushEmpty(out);
229
+ let defining = 0;
230
+ for (let i = from; i < scene.length; i++) {
231
+ switch (scene.kind[i]) {
232
+ case DRAW:
233
+ if (defining === 0) {
234
+ placeDraw(scene, i, geometries.box, rows.data, scale, out);
235
+ }
236
+ break;
237
+ case MASK_BEGIN:
238
+ defining++;
239
+ break;
240
+ case MASK_USE:
241
+ defining--;
242
+ break;
243
+ }
244
+ }
245
+ }
246
+ /** Entry `i`'s geometry box placed by its row at `k` target pixels a stage pixel, taken into the area atop `stack`. */
247
+ function placeDraw(scene, i, box, m, k, stack) {
248
+ const g = scene.geometry[i] * 4;
249
+ const x0 = box[g];
250
+ const y0 = box[g + 1];
251
+ const x1 = box[g + 2];
252
+ const y1 = box[g + 3];
253
+ if (!(x1 >= x0 && y1 >= y0)) {
254
+ return;
255
+ }
256
+ const r = scene.row[i] * ROW_FLOATS;
257
+ const a = m[r] * k;
258
+ const b = m[r + 1] * k;
259
+ const c = m[r + 2] * k;
260
+ const d = m[r + 3] * k;
261
+ const tx = m[r + 4] * k;
262
+ const ty = m[r + 5] * k;
263
+ // The box's corners placed: each of the least and greatest a coordinate takes, by sign.
264
+ const n = stack.length;
265
+ stack[n - 4] = Math.min(stack[n - 4], tx + Math.min(a * x0, a * x1) + Math.min(c * y0, c * y1));
266
+ stack[n - 3] = Math.min(stack[n - 3], ty + Math.min(b * x0, b * x1) + Math.min(d * y0, d * y1));
267
+ stack[n - 2] = Math.max(stack[n - 2], tx + Math.max(a * x0, a * x1) + Math.max(c * y0, c * y1));
268
+ stack[n - 1] = Math.max(stack[n - 1], ty + Math.max(b * x0, b * x1) + Math.max(d * y0, d * y1));
269
+ }
270
+ function pushEmpty(stack) {
271
+ stack.push(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);
272
+ }
273
+ /** The top area of `from` moved onto `to`. */
274
+ function moveTop(from, to) {
275
+ const n = from.length;
276
+ to.push(from[n - 4], from[n - 3], from[n - 2], from[n - 1]);
277
+ from.length = n - 4;
278
+ }
279
+ /** The open area on top grown to take in the rectangle. */
280
+ function unionTop(left, top, right, bottom) {
281
+ const n = areas.length;
282
+ areas[n - 4] = Math.min(areas[n - 4], left);
283
+ areas[n - 3] = Math.min(areas[n - 3], top);
284
+ areas[n - 2] = Math.max(areas[n - 2], right);
285
+ areas[n - 1] = Math.max(areas[n - 1], bottom);
286
+ }
287
+ //# sourceMappingURL=measure.js.map