@viewscript/renderer 0.1.0-202605140639
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/ast/types.d.ts +403 -0
- package/dist/ast/types.js +33 -0
- package/dist/compiler/chunk-splitter.d.ts +98 -0
- package/dist/compiler/chunk-splitter.js +361 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +17 -0
- package/dist/rasterizer/__tests__/error-distribution.test.d.ts +7 -0
- package/dist/rasterizer/__tests__/error-distribution.test.js +322 -0
- package/dist/rasterizer/canvas-mapper.d.ts +280 -0
- package/dist/rasterizer/canvas-mapper.js +414 -0
- package/dist/rasterizer/error-distribution.d.ts +143 -0
- package/dist/rasterizer/error-distribution.js +231 -0
- package/dist/rasterizer/gradient-mapper.d.ts +223 -0
- package/dist/rasterizer/gradient-mapper.js +352 -0
- package/dist/rasterizer/topology-rounding.d.ts +151 -0
- package/dist/rasterizer/topology-rounding.js +347 -0
- package/dist/runtime/__tests__/event-backpressure.test.d.ts +10 -0
- package/dist/runtime/__tests__/event-backpressure.test.js +190 -0
- package/dist/runtime/event-backpressure.d.ts +393 -0
- package/dist/runtime/event-backpressure.js +458 -0
- package/dist/runtime/render-loop.d.ts +277 -0
- package/dist/runtime/render-loop.js +435 -0
- package/dist/runtime/wasm-resource-manager.d.ts +122 -0
- package/dist/runtime/wasm-resource-manager.js +253 -0
- package/dist/runtime/wgpu-renderer-adapter.d.ts +168 -0
- package/dist/runtime/wgpu-renderer-adapter.js +230 -0
- package/dist/semantic/__tests__/semantic-translator.test.d.ts +4 -0
- package/dist/semantic/__tests__/semantic-translator.test.js +203 -0
- package/dist/semantic/semantic-translator.d.ts +229 -0
- package/dist/semantic/semantic-translator.js +398 -0
- package/package.json +28 -0
- package/playwright-report/data/0bafe4e0863f0e244bba68a838f73241f8f2efaa.md +226 -0
- package/playwright-report/data/9281aca8abfb06c6cecb35d5ddd13d61f8c752d8.md +226 -0
- package/playwright-report/index.html +90 -0
- package/playwright.config.ts +160 -0
- package/screenshot-chrome.png +0 -0
- package/screenshots/visual-demo-verification.png +0 -0
- package/screenshots/visual-demo.png +0 -0
- package/src/ast/types.ts +473 -0
- package/src/compiler/chunk-splitter.ts +534 -0
- package/src/index.ts +62 -0
- package/src/rasterizer/__tests__/error-distribution.test.ts +382 -0
- package/src/rasterizer/canvas-mapper.ts +677 -0
- package/src/rasterizer/error-distribution.ts +344 -0
- package/src/rasterizer/gradient-mapper.ts +563 -0
- package/src/rasterizer/topology-rounding.ts +499 -0
- package/src/runtime/__tests__/event-backpressure.test.ts +254 -0
- package/src/runtime/event-backpressure.ts +622 -0
- package/src/runtime/render-loop.ts +660 -0
- package/src/runtime/wasm-resource-manager.ts +349 -0
- package/src/runtime/wgpu-renderer-adapter.ts +318 -0
- package/src/semantic/__tests__/semantic-translator.test.ts +263 -0
- package/src/semantic/semantic-translator.ts +637 -0
- package/test-results/.last-run.json +4 -0
- package/tests/e2e/async-race.spec.ts +612 -0
- package/tests/e2e/bilayer-sync.spec.ts +405 -0
- package/tests/e2e/failures/.gitkeep +0 -0
- package/tests/e2e/fullstack.spec.ts +681 -0
- package/tests/e2e/g1-continuity.spec.ts +703 -0
- package/tests/e2e/golden/.gitkeep +0 -0
- package/tests/e2e/golden/conic-color-wheel.raw +0 -0
- package/tests/e2e/golden/conic-color-wheel.sha256 +1 -0
- package/tests/e2e/golden/conic-rotated.raw +0 -0
- package/tests/e2e/golden/conic-rotated.sha256 +1 -0
- package/tests/e2e/golden/linear-45deg.raw +0 -0
- package/tests/e2e/golden/linear-45deg.sha256 +1 -0
- package/tests/e2e/golden/linear-horizontal.raw +0 -0
- package/tests/e2e/golden/linear-horizontal.sha256 +1 -0
- package/tests/e2e/golden/linear-multi-stop.raw +0 -0
- package/tests/e2e/golden/linear-multi-stop.sha256 +1 -0
- package/tests/e2e/golden/radial-circle-center.raw +0 -0
- package/tests/e2e/golden/radial-circle-center.sha256 +1 -0
- package/tests/e2e/golden/radial-offset.raw +0 -0
- package/tests/e2e/golden/radial-offset.sha256 +1 -0
- package/tests/e2e/golden/tile-mirror.raw +0 -0
- package/tests/e2e/golden/tile-mirror.sha256 +1 -0
- package/tests/e2e/golden/tile-repeat.raw +0 -0
- package/tests/e2e/golden/tile-repeat.sha256 +1 -0
- package/tests/e2e/gradient-animation.spec.ts +606 -0
- package/tests/e2e/memory-stability.spec.ts +396 -0
- package/tests/e2e/path-topology.spec.ts +674 -0
- package/tests/e2e/performance-profile.spec.ts +501 -0
- package/tests/e2e/screenshot.spec.ts +60 -0
- package/tests/e2e/test-harness.html +1005 -0
- package/tests/e2e/text-layout.spec.ts +451 -0
- package/tests/e2e/visual-demo.html +340 -0
- package/tests/e2e/visual-regression.spec.ts +335 -0
- package/tsconfig.json +12 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Instructions
|
|
2
|
+
|
|
3
|
+
- Following Playwright test failed.
|
|
4
|
+
- Explain why, be concise, respect Playwright best practices.
|
|
5
|
+
- Provide a snippet of code with the fix, if possible.
|
|
6
|
+
|
|
7
|
+
# Test info
|
|
8
|
+
|
|
9
|
+
- Name: gradient-animation.spec.ts >> Gradient Rendering: Conic (Sweep) Gradients >> renders rotated conic gradient
|
|
10
|
+
- Location: tests/e2e/gradient-animation.spec.ts:254:3
|
|
11
|
+
|
|
12
|
+
# Error details
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
Error: expect(received).toBeGreaterThan(expected)
|
|
16
|
+
|
|
17
|
+
Expected: > 255
|
|
18
|
+
Received: 1
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
# Test source
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
167 | css: 'radial-gradient(circle at center, white, black)',
|
|
25
|
+
168 | bounds: { x: 0, y: 0, width: 100, height: 100 },
|
|
26
|
+
169 | });
|
|
27
|
+
170 |
|
|
28
|
+
171 | // Center should be white, corners should be dark
|
|
29
|
+
172 | const center = getPixelColor(pixelBuffer, 100, 100, 50, 50);
|
|
30
|
+
173 | const corner = getPixelColor(pixelBuffer, 100, 100, 5, 5);
|
|
31
|
+
174 |
|
|
32
|
+
175 | expect(center.r).toBeGreaterThan(200);
|
|
33
|
+
176 | expect(center.g).toBeGreaterThan(200);
|
|
34
|
+
177 | expect(center.b).toBeGreaterThan(200);
|
|
35
|
+
178 |
|
|
36
|
+
179 | expect(corner.r).toBeLessThan(100);
|
|
37
|
+
180 | expect(corner.g).toBeLessThan(100);
|
|
38
|
+
181 | expect(corner.b).toBeLessThan(100);
|
|
39
|
+
182 |
|
|
40
|
+
183 | await compareGolden(pixelBuffer, 'radial-circle-center');
|
|
41
|
+
184 | });
|
|
42
|
+
185 |
|
|
43
|
+
186 | /**
|
|
44
|
+
187 | * Test: Offset focal point radial gradient
|
|
45
|
+
188 | *
|
|
46
|
+
189 | * CSS: radial-gradient(circle at 25% 25%, red, blue)
|
|
47
|
+
190 | * Expected: Gradient center offset to top-left quadrant
|
|
48
|
+
191 | */
|
|
49
|
+
192 | test('renders offset radial gradient', async ({ page }) => {
|
|
50
|
+
193 | await setupDeterministicRenderer(page);
|
|
51
|
+
194 |
|
|
52
|
+
195 | const pixelBuffer = await renderGradient(page, {
|
|
53
|
+
196 | type: 'radial-gradient',
|
|
54
|
+
197 | css: 'radial-gradient(circle at 25% 25%, red, blue)',
|
|
55
|
+
198 | bounds: { x: 0, y: 0, width: 100, height: 100 },
|
|
56
|
+
199 | });
|
|
57
|
+
200 |
|
|
58
|
+
201 | // Point at 25%, 25% should be red (center of gradient)
|
|
59
|
+
202 | const focalPoint = getPixelColor(pixelBuffer, 100, 100, 25, 25);
|
|
60
|
+
203 |
|
|
61
|
+
204 | expect(focalPoint.r).toBeGreaterThan(200);
|
|
62
|
+
205 | expect(focalPoint.b).toBeLessThan(100);
|
|
63
|
+
206 |
|
|
64
|
+
207 | await compareGolden(pixelBuffer, 'radial-offset');
|
|
65
|
+
208 | });
|
|
66
|
+
209 | });
|
|
67
|
+
210 |
|
|
68
|
+
211 | // =============================================================================
|
|
69
|
+
212 | // Conic Gradient Tests
|
|
70
|
+
213 | // =============================================================================
|
|
71
|
+
214 |
|
|
72
|
+
215 | test.describe('Gradient Rendering: Conic (Sweep) Gradients', () => {
|
|
73
|
+
216 | test.beforeAll(async () => {
|
|
74
|
+
217 | ensureDirectories();
|
|
75
|
+
218 | });
|
|
76
|
+
219 |
|
|
77
|
+
220 | /**
|
|
78
|
+
221 | * Test: Color wheel conic gradient
|
|
79
|
+
222 | *
|
|
80
|
+
223 | * CSS: conic-gradient(from 0deg, red, yellow, lime, cyan, blue, magenta, red)
|
|
81
|
+
224 | * Expected: Full color wheel around center
|
|
82
|
+
225 | */
|
|
83
|
+
226 | test('renders color wheel conic gradient', async ({ page }) => {
|
|
84
|
+
227 | await setupDeterministicRenderer(page);
|
|
85
|
+
228 |
|
|
86
|
+
229 | const pixelBuffer = await renderGradient(page, {
|
|
87
|
+
230 | type: 'conic-gradient',
|
|
88
|
+
231 | css: 'conic-gradient(from 0deg, red, yellow, lime, cyan, blue, magenta, red)',
|
|
89
|
+
232 | bounds: { x: 0, y: 0, width: 100, height: 100 },
|
|
90
|
+
233 | });
|
|
91
|
+
234 |
|
|
92
|
+
235 | // Sample at 0deg (right), 90deg (bottom), 180deg (left), 270deg (top)
|
|
93
|
+
236 | // relative to center (50, 50)
|
|
94
|
+
237 | const right = getPixelColor(pixelBuffer, 100, 100, 95, 50); // 0deg - red
|
|
95
|
+
238 | const bottom = getPixelColor(pixelBuffer, 100, 100, 50, 95); // 90deg - between yellow and lime
|
|
96
|
+
239 | const left = getPixelColor(pixelBuffer, 100, 100, 5, 50); // 180deg - cyan
|
|
97
|
+
240 | const top = getPixelColor(pixelBuffer, 100, 100, 50, 5); // 270deg - blue/magenta
|
|
98
|
+
241 |
|
|
99
|
+
242 | // Right edge (0deg) should be red
|
|
100
|
+
243 | expect(right.r).toBeGreaterThan(150);
|
|
101
|
+
244 |
|
|
102
|
+
245 | await compareGolden(pixelBuffer, 'conic-color-wheel');
|
|
103
|
+
246 | });
|
|
104
|
+
247 |
|
|
105
|
+
248 | /**
|
|
106
|
+
249 | * Test: Rotated conic gradient
|
|
107
|
+
250 | *
|
|
108
|
+
251 | * CSS: conic-gradient(from 90deg at center, red, blue)
|
|
109
|
+
252 | * Expected: Gradient starts from bottom instead of right
|
|
110
|
+
253 | */
|
|
111
|
+
254 | test('renders rotated conic gradient', async ({ page }) => {
|
|
112
|
+
255 | await setupDeterministicRenderer(page);
|
|
113
|
+
256 |
|
|
114
|
+
257 | const pixelBuffer = await renderGradient(page, {
|
|
115
|
+
258 | type: 'conic-gradient',
|
|
116
|
+
259 | css: 'conic-gradient(from 90deg at center, red, blue)',
|
|
117
|
+
260 | bounds: { x: 0, y: 0, width: 100, height: 100 },
|
|
118
|
+
261 | });
|
|
119
|
+
262 |
|
|
120
|
+
263 | // With 90deg rotation, red should be at bottom, blue at top
|
|
121
|
+
264 | const bottom = getPixelColor(pixelBuffer, 100, 100, 50, 95);
|
|
122
|
+
265 | const top = getPixelColor(pixelBuffer, 100, 100, 50, 5);
|
|
123
|
+
266 |
|
|
124
|
+
> 267 | expect(bottom.r).toBeGreaterThan(bottom.b); // More red at bottom
|
|
125
|
+
| ^ Error: expect(received).toBeGreaterThan(expected)
|
|
126
|
+
268 | expect(top.b).toBeGreaterThan(top.r); // More blue at top
|
|
127
|
+
269 |
|
|
128
|
+
270 | await compareGolden(pixelBuffer, 'conic-rotated');
|
|
129
|
+
271 | });
|
|
130
|
+
272 | });
|
|
131
|
+
273 |
|
|
132
|
+
274 | // =============================================================================
|
|
133
|
+
275 | // T-Vector Animation Tests
|
|
134
|
+
276 | // =============================================================================
|
|
135
|
+
277 |
|
|
136
|
+
278 | test.describe('Gradient Animation: T-Vector Binding', () => {
|
|
137
|
+
279 | test.beforeAll(async () => {
|
|
138
|
+
280 | ensureDirectories();
|
|
139
|
+
281 | });
|
|
140
|
+
282 |
|
|
141
|
+
283 | /**
|
|
142
|
+
284 | * Test: Animated gradient angle
|
|
143
|
+
285 | *
|
|
144
|
+
286 | * T-vector controls the gradient angle: as T increases, angle rotates.
|
|
145
|
+
287 | * This validates that P-dimension constraints properly propagate to GPU.
|
|
146
|
+
288 | */
|
|
147
|
+
289 | test('animates gradient angle via T-vector', async ({ page }) => {
|
|
148
|
+
290 | await setupDeterministicRenderer(page);
|
|
149
|
+
291 |
|
|
150
|
+
292 | // Frame 1: T=0, angle=0deg
|
|
151
|
+
293 | const frame1 = await renderAnimatedGradient(page, {
|
|
152
|
+
294 | type: 'linear-gradient',
|
|
153
|
+
295 | baseAngle: 0,
|
|
154
|
+
296 | tValue: 0,
|
|
155
|
+
297 | anglePerT: 90, // 90 degrees per T unit
|
|
156
|
+
298 | colors: ['red', 'blue'],
|
|
157
|
+
299 | bounds: { x: 0, y: 0, width: 100, height: 100 },
|
|
158
|
+
300 | });
|
|
159
|
+
301 |
|
|
160
|
+
302 | // Frame 2: T=1, angle=90deg
|
|
161
|
+
303 | const frame2 = await renderAnimatedGradient(page, {
|
|
162
|
+
304 | type: 'linear-gradient',
|
|
163
|
+
305 | baseAngle: 0,
|
|
164
|
+
306 | tValue: 1,
|
|
165
|
+
307 | anglePerT: 90,
|
|
166
|
+
308 | colors: ['red', 'blue'],
|
|
167
|
+
309 | bounds: { x: 0, y: 0, width: 100, height: 100 },
|
|
168
|
+
310 | });
|
|
169
|
+
311 |
|
|
170
|
+
312 | // Frame 1 should be horizontal (red on left)
|
|
171
|
+
313 | const f1Left = getPixelColor(frame1, 100, 100, 10, 50);
|
|
172
|
+
314 | expect(f1Left.r).toBeGreaterThan(f1Left.b);
|
|
173
|
+
315 |
|
|
174
|
+
316 | // Frame 2 should be vertical (red on top)
|
|
175
|
+
317 | const f2Top = getPixelColor(frame2, 100, 100, 50, 10);
|
|
176
|
+
318 | expect(f2Top.r).toBeGreaterThan(f2Top.b);
|
|
177
|
+
319 |
|
|
178
|
+
320 | // Frames should be different
|
|
179
|
+
321 | const hash1 = computeHash(frame1);
|
|
180
|
+
322 | const hash2 = computeHash(frame2);
|
|
181
|
+
323 | expect(hash1).not.toBe(hash2);
|
|
182
|
+
324 | });
|
|
183
|
+
325 |
|
|
184
|
+
326 | /**
|
|
185
|
+
327 | * Test: Animated color stop positions
|
|
186
|
+
328 | *
|
|
187
|
+
329 | * T-vector controls color stop positions for dynamic effects.
|
|
188
|
+
330 | */
|
|
189
|
+
331 | test('animates color stop positions via T-vector', async ({ page }) => {
|
|
190
|
+
332 | await setupDeterministicRenderer(page);
|
|
191
|
+
333 |
|
|
192
|
+
334 | // Frame 1: First stop at 30%
|
|
193
|
+
335 | const frame1 = await renderAnimatedGradient(page, {
|
|
194
|
+
336 | type: 'linear-gradient',
|
|
195
|
+
337 | baseAngle: 90, // Top to bottom
|
|
196
|
+
338 | tValue: 0.3,
|
|
197
|
+
339 | colors: ['red', 'blue'],
|
|
198
|
+
340 | stopPositions: [{ base: 0, tFactor: 1 }, { base: 1, tFactor: 0 }],
|
|
199
|
+
341 | bounds: { x: 0, y: 0, width: 100, height: 100 },
|
|
200
|
+
342 | });
|
|
201
|
+
343 |
|
|
202
|
+
344 | // Frame 2: First stop at 70%
|
|
203
|
+
345 | const frame2 = await renderAnimatedGradient(page, {
|
|
204
|
+
346 | type: 'linear-gradient',
|
|
205
|
+
347 | baseAngle: 90,
|
|
206
|
+
348 | tValue: 0.7,
|
|
207
|
+
349 | colors: ['red', 'blue'],
|
|
208
|
+
350 | stopPositions: [{ base: 0, tFactor: 1 }, { base: 1, tFactor: 0 }],
|
|
209
|
+
351 | bounds: { x: 0, y: 0, width: 100, height: 100 },
|
|
210
|
+
352 | });
|
|
211
|
+
353 |
|
|
212
|
+
354 | // In frame 1, red extends further (to ~30% from top)
|
|
213
|
+
355 | // In frame 2, red extends much further (to ~70% from top)
|
|
214
|
+
356 | const f1Mid = getPixelColor(frame1, 100, 100, 50, 50);
|
|
215
|
+
357 | const f2Mid = getPixelColor(frame2, 100, 100, 50, 50);
|
|
216
|
+
358 |
|
|
217
|
+
359 | // Frame 2 middle should have more red than frame 1 middle
|
|
218
|
+
360 | expect(f2Mid.r).toBeGreaterThan(f1Mid.r);
|
|
219
|
+
361 | });
|
|
220
|
+
362 | });
|
|
221
|
+
363 |
|
|
222
|
+
364 | // =============================================================================
|
|
223
|
+
365 | // Tile Mode Tests
|
|
224
|
+
366 | // =============================================================================
|
|
225
|
+
367 |
|
|
226
|
+
```
|