ranger-compiler 3.5.1 → 3.5.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.
Files changed (338) hide show
  1. package/CHANGELOG.md +1064 -20
  2. package/LICENSE +3 -1
  3. package/README.md +123 -28
  4. package/dist/Lang.rgr +1188 -290
  5. package/dist/api.d.ts +2343 -879
  6. package/dist/api.js +79923 -56921
  7. package/dist/lib/JSON.rgr +102 -91
  8. package/dist/lib/Shell.rgr +4 -4
  9. package/dist/lib/apple/AppleToolchain.rgr +4 -4
  10. package/dist/lib/apple/README.md +5 -4
  11. package/dist/lib/apple/apple_test.rgr +1 -1
  12. package/dist/lib/core/README.md +1 -1
  13. package/dist/lib/evg/EVG.rgr +12 -0
  14. package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
  15. package/dist/lib/evg/EVGA11yTree.rgr +894 -0
  16. package/dist/lib/evg/EVGBox.rgr +267 -0
  17. package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
  18. package/dist/lib/evg/EVGCodepoint.rgr +316 -0
  19. package/dist/lib/evg/EVGColor.rgr +700 -0
  20. package/dist/lib/evg/EVGCommands.rgr +177 -0
  21. package/dist/lib/evg/EVGComponent.rgr +331 -0
  22. package/dist/lib/evg/EVGComponentTest.rgr +387 -0
  23. package/dist/lib/evg/EVGConnector.rgr +541 -0
  24. package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
  25. package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
  26. package/dist/lib/evg/EVGEasing.rgr +370 -0
  27. package/dist/lib/evg/EVGEffectTest.rgr +253 -0
  28. package/dist/lib/evg/EVGElement.rgr +4914 -0
  29. package/dist/lib/evg/EVGFixedTest.rgr +289 -0
  30. package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
  31. package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
  32. package/dist/lib/evg/EVGFling.rgr +244 -0
  33. package/dist/lib/evg/EVGFocus.rgr +400 -0
  34. package/dist/lib/evg/EVGFocusTest.rgr +399 -0
  35. package/dist/lib/evg/EVGGradient.rgr +322 -0
  36. package/dist/lib/evg/EVGGrapheme.rgr +190 -0
  37. package/dist/lib/evg/EVGGrid.rgr +975 -0
  38. package/dist/lib/evg/EVGHitTest.rgr +208 -0
  39. package/dist/lib/evg/EVGHoles.rgr +294 -0
  40. package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
  41. package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
  42. package/dist/lib/evg/EVGHostTree.rgr +834 -0
  43. package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
  44. package/dist/lib/evg/EVGImageDecode.rgr +117 -0
  45. package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
  46. package/dist/lib/evg/EVGInspect.rgr +883 -0
  47. package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
  48. package/dist/lib/evg/EVGJsonTest.rgr +535 -0
  49. package/dist/lib/evg/EVGLayout.rgr +4220 -0
  50. package/dist/lib/evg/EVGMeasure.rgr +1267 -0
  51. package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
  52. package/dist/lib/evg/EVGPatch.rgr +1721 -0
  53. package/dist/lib/evg/EVGPatchTest.rgr +692 -0
  54. package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
  55. package/dist/lib/evg/EVGReconcile.rgr +226 -0
  56. package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
  57. package/dist/lib/evg/EVGReject.rgr +126 -0
  58. package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
  59. package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
  60. package/dist/lib/evg/EVGRuler.rgr +232 -0
  61. package/dist/lib/evg/EVGRulerTest.rgr +172 -0
  62. package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
  63. package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
  64. package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
  65. package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
  66. package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
  67. package/dist/lib/evg/EVGText.rgr +105 -0
  68. package/dist/lib/evg/EVGTextEngine.rgr +536 -0
  69. package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
  70. package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
  71. package/dist/lib/evg/EVGToolbar.rgr +1369 -0
  72. package/dist/lib/evg/EVGTransition.rgr +728 -0
  73. package/dist/lib/evg/EVGTreeJson.rgr +721 -0
  74. package/dist/lib/evg/EVGUnit.rgr +554 -0
  75. package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
  76. package/dist/lib/evg/EvgApp.rgr +189 -0
  77. package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
  78. package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
  79. package/dist/lib/evg/EvgHost.rgr +451 -0
  80. package/dist/lib/evg/EvgTest.rgr +91 -0
  81. package/dist/lib/evg/EvgTraceColor.rgr +236 -0
  82. package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
  83. package/dist/lib/evg/EvgTraceFit.rgr +767 -0
  84. package/dist/lib/evg/EvgTracePath.rgr +435 -0
  85. package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
  86. package/dist/lib/evg/EvgViewport.rgr +313 -0
  87. package/dist/lib/evg/FxDemoDoc.rgr +185 -0
  88. package/dist/lib/evg/HOSTS.md +227 -0
  89. package/dist/lib/evg/ISSUES.md +835 -0
  90. package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
  91. package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
  92. package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
  93. package/dist/lib/evg/PLAN_EVG.md +518 -0
  94. package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
  95. package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
  96. package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
  97. package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
  98. package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
  99. package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
  100. package/dist/lib/evg/PathBuilder.rgr +333 -0
  101. package/dist/lib/evg/README.md +1236 -0
  102. package/dist/lib/evg/SPEC.md +1252 -0
  103. package/dist/lib/evg/SVGPathParser.rgr +1199 -0
  104. package/dist/lib/evg/SvgParser.rgr +1736 -0
  105. package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
  106. package/dist/lib/evg/VectorShapes.rgr +331 -0
  107. package/dist/lib/evg/VectorStroke.rgr +107 -0
  108. package/dist/lib/evg/VectorViewBox.rgr +380 -0
  109. package/dist/lib/evg/agent/README.md +290 -0
  110. package/dist/lib/evg/agent/evg_agent.rgr +899 -0
  111. package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
  112. package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
  113. package/dist/lib/evg/agent/fixtures/connector.css +63 -0
  114. package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
  115. package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
  116. package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
  117. package/dist/lib/evg/agent/fixtures/popover.css +99 -0
  118. package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
  119. package/dist/lib/evg/agent/roundtrip.sh +74 -0
  120. package/dist/lib/evg/agent/smoke.sh +230 -0
  121. package/dist/lib/evg/android/README.md +97 -0
  122. package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
  123. package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
  124. package/dist/lib/evg/android/androidstubs/App.kt +30 -0
  125. package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
  126. package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
  127. package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
  128. package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
  129. package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
  130. package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
  131. package/dist/lib/evg/android/androidstubs/View.kt +113 -0
  132. package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
  133. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
  134. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
  135. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
  136. package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
  137. package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
  138. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
  139. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
  140. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
  141. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
  142. package/dist/lib/evg/apple/README.md +128 -0
  143. package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
  144. package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
  145. package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
  146. package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
  147. package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
  148. package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
  149. package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
  150. package/dist/lib/evg/bench/README.md +64 -0
  151. package/dist/lib/evg/bench/layout-bench.mjs +316 -0
  152. package/dist/lib/evg/bench/layout-cases.mjs +510 -0
  153. package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
  154. package/dist/lib/evg/bin/.gitignore +17 -0
  155. package/dist/lib/evg/evg_test.rgr +313 -0
  156. package/dist/lib/evg/gl/README.md +198 -0
  157. package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
  158. package/dist/lib/evg/gl/blur-check.mjs +399 -0
  159. package/dist/lib/evg/gl/boxmodel.json +1 -0
  160. package/dist/lib/evg/gl/demo.html +46 -0
  161. package/dist/lib/evg/gl/effect-presets.css +285 -0
  162. package/dist/lib/evg/gl/effect-presets.js +63 -0
  163. package/dist/lib/evg/gl/effect-shots.mjs +135 -0
  164. package/dist/lib/evg/gl/evg-a11y.js +566 -0
  165. package/dist/lib/evg/gl/evg-binary.js +160 -0
  166. package/dist/lib/evg/gl/evg-engine.js +296 -0
  167. package/dist/lib/evg/gl/evg-fx.js +237 -0
  168. package/dist/lib/evg/gl/evg-gestures.js +209 -0
  169. package/dist/lib/evg/gl/evg-list.js +167 -0
  170. package/dist/lib/evg/gl/evg-measure.js +186 -0
  171. package/dist/lib/evg/gl/evg-textinput.js +303 -0
  172. package/dist/lib/evg/gl/evg-view.js +144 -0
  173. package/dist/lib/evg/gl/evg-webgl.js +3942 -0
  174. package/dist/lib/evg/gl/fx-check.mjs +998 -0
  175. package/dist/lib/evg/gl/fx-demo.html +166 -0
  176. package/dist/lib/evg/gl/fx-demo.js +2 -0
  177. package/dist/lib/evg/gl/fx-serve.mjs +47 -0
  178. package/dist/lib/evg/gl/gestures-check.mjs +189 -0
  179. package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
  180. package/dist/lib/evg/gl/measure-check.mjs +135 -0
  181. package/dist/lib/evg/gl/rotation-check.mjs +207 -0
  182. package/dist/lib/evg/gl/shift-check.mjs +113 -0
  183. package/dist/lib/evg/gl/stroke-check.mjs +168 -0
  184. package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
  185. package/dist/lib/evg/gl/view-check.mjs +343 -0
  186. package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
  187. package/dist/lib/evg/html/evg-dom.js +318 -0
  188. package/dist/lib/evg/html/evg-html.js +600 -0
  189. package/dist/lib/evg/inspect/README.md +415 -0
  190. package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
  191. package/dist/lib/evg/inspect/evg-inspect.js +947 -0
  192. package/dist/lib/evg/inspect/shots/css.png +0 -0
  193. package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
  194. package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
  195. package/dist/lib/evg/inspect/shots/state.png +0 -0
  196. package/dist/lib/evg/inspect/shots.mjs +226 -0
  197. package/dist/lib/evg/oracle/css-blur.json +576 -0
  198. package/dist/lib/evg/oracle/css-box.json +157 -0
  199. package/dist/lib/evg/oracle/css-timing.json +709 -0
  200. package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
  201. package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
  202. package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
  203. package/dist/lib/evg/original/EVGColor.clj +310 -0
  204. package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
  205. package/dist/lib/evg/original/SVGPath.rgr +627 -0
  206. package/dist/lib/evg/original/Vec2.crgr +103 -0
  207. package/dist/lib/evg/ranger.json +9 -0
  208. package/dist/lib/evg/showcase/README.md +246 -0
  209. package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
  210. package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
  211. package/dist/lib/evg/showcase/build.mjs +651 -0
  212. package/dist/lib/evg/showcase/pages/album.tsx +30 -0
  213. package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
  214. package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
  215. package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
  216. package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
  217. package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
  218. package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
  219. package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
  220. package/dist/lib/evg/showcase/pages/more.tsx +332 -0
  221. package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
  222. package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
  223. package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
  224. package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
  225. package/dist/lib/evg/showcase/pages/units.tsx +35 -0
  226. package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
  227. package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
  228. package/dist/lib/evg/showcase/pages/views.tsx +223 -0
  229. package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
  230. package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
  231. package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
  232. package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
  233. package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
  234. package/dist/lib/evg/showcase/themes/more-default.css +128 -0
  235. package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
  236. package/dist/lib/evg/showcase/themes/showcase.css +508 -0
  237. package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
  238. package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
  239. package/dist/lib/evg/showcase/themes/views-default.css +15 -0
  240. package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
  241. package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
  242. package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
  243. package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
  244. package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
  245. package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
  246. package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
  247. package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
  248. package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
  249. package/dist/lib/evg/web/responsive/README.md +97 -0
  250. package/dist/lib/evg/web/responsive/build.mjs +90 -0
  251. package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
  252. package/dist/lib/evg/web/responsive/index.html +177 -0
  253. package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
  254. package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
  255. package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
  256. package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
  257. package/dist/lib/evg/web/tools/minify.mjs +60 -0
  258. package/dist/lib/evg/web/tracer/build.mjs +87 -0
  259. package/dist/lib/evg/web/tracer/index.html +2805 -0
  260. package/dist/lib/evg/web/tracer/sample.png +0 -0
  261. package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
  262. package/dist/lib/evgr/Cargo.lock +21 -0
  263. package/dist/lib/evgr/Cargo.toml +19 -0
  264. package/dist/lib/evgr/README.md +140 -0
  265. package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
  266. package/dist/lib/evgr/bench/compare.mjs +252 -0
  267. package/dist/lib/evgr/bench/speed.mjs +277 -0
  268. package/dist/lib/evgr/bin/.gitignore +3 -0
  269. package/dist/lib/evgr/src/bin/bench.rs +106 -0
  270. package/dist/lib/evgr/src/bin/smoke.rs +13 -0
  271. package/dist/lib/evgr/src/grid.rs +730 -0
  272. package/dist/lib/evgr/src/lib.rs +1003 -0
  273. package/dist/lib/evgr/src/style.rs +468 -0
  274. package/dist/lib/evgr/src/text.rs +83 -0
  275. package/dist/lib/image/BitReader.rgr +171 -0
  276. package/dist/lib/image/Buffer.rgr +173 -0
  277. package/dist/lib/image/DCT.rgr +283 -0
  278. package/dist/lib/image/Deflate.rgr +339 -0
  279. package/dist/lib/image/HuffmanDecoder.rgr +181 -0
  280. package/dist/lib/image/ImageBuffer.rgr +706 -0
  281. package/dist/lib/image/JPEGDecoder.rgr +808 -0
  282. package/dist/lib/image/PNGDecoder.rgr +544 -0
  283. package/dist/lib/image/PNGEncoder.rgr +388 -0
  284. package/dist/lib/image/PPMImage.rgr +224 -0
  285. package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
  286. package/dist/lib/image/README.md +33 -0
  287. package/dist/lib/image/RasterBuffer.rgr +294 -0
  288. package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
  289. package/dist/lib/image/WebPDecoder.rgr +433 -0
  290. package/dist/lib/image/WebPLossless.rgr +1035 -0
  291. package/dist/lib/image/WebPLossy.rgr +1929 -0
  292. package/dist/lib/image/ranger.json +9 -0
  293. package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
  294. package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
  295. package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
  296. package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
  297. package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
  298. package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
  299. package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
  300. package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
  301. package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
  302. package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
  303. package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
  304. package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
  305. package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
  306. package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
  307. package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
  308. package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
  309. package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
  310. package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
  311. package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
  312. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
  313. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
  314. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
  315. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
  316. package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
  317. package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
  318. package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
  319. package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
  320. package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
  321. package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
  322. package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
  323. package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
  324. package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
  325. package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
  326. package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
  327. package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
  328. package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
  329. package/dist/lib/image/tests/run_webp_tests.sh +39 -0
  330. package/dist/lib/rust/RsJson.rgr +468 -0
  331. package/dist/lib/rust/RsPrelude.rgr +1663 -0
  332. package/dist/lib/shell_test.rgr +7 -7
  333. package/dist/lib/stdlib.rgr +21 -5
  334. package/dist/lib/zip/ranger.json +6 -0
  335. package/dist/rgrc.js +87318 -67610
  336. package/package.json +1010 -1040
  337. package/dist/README.md +0 -117
  338. package/dist/package.json +0 -47
@@ -0,0 +1,431 @@
1
+ # Surface effects: declared on an element, drawn by a plugin
2
+
3
+ `evg-surface-effect: ripple` shipped as one effect, over one surface, driven by
4
+ hand. This is what it became, why, and what is still missing.
5
+
6
+ ## What it was
7
+
8
+ ```
9
+ EVGElement surfaceEffect + fourteen evg-ripple-* fields + three drop arrays
10
+ EVGDisplayList readEffect: the FIRST element that names one wins, whole page
11
+ evg-webgl.js one hard-wired program, one fullscreen post-pass
12
+ the application pushes drops, ages them, retires them, stamps them on the root
13
+ ```
14
+
15
+ Three things follow from that shape, and all three were the reason to change it:
16
+
17
+ * **Which element has it is not a question the document can answer.** The
18
+ property is read off the first element that carries it and applied to the
19
+ whole surface. A card cannot ripple; a page can.
20
+ * **What starts it is in the app's code.** `gallery/ui/demo/main.js` calls
21
+ `dashboard.ripple(ev.offsetX, ev.offsetY)` on every `pointerdown`, anywhere on
22
+ the canvas, and `DashboardDemo.rgr` keeps three arrays and four methods to
23
+ hold the result. None of that is about a dashboard.
24
+ * **A second effect cannot exist.** Its parameters would have to be fields on
25
+ `EVGElement` — every element in every document carrying a starfield's density
26
+ — and its shader would have to be another branch in the painter.
27
+
28
+ ## What it is now
29
+
30
+ Three properties, and a box the layout already knew:
31
+
32
+ ```css
33
+ .hero-sky {
34
+ evg-surface-effect: starfield; /* WHAT runs — a name, nothing more */
35
+ evg-effect-on: always; /* WHAT starts it: press drag hover always */
36
+ evg-fx-density: 1.6; /* PARAMETERS the engine never reads */
37
+ evg-fx-hue: 228;
38
+ }
39
+
40
+ .pool {
41
+ evg-surface-effect: ripple;
42
+ evg-effect-on: press drag; /* and nothing else on the page reacts */
43
+ evg-ripple-speed: 240; /* the ripple's own properties still work */
44
+ }
45
+ ```
46
+
47
+ WHERE is the element's own border box. That is the whole of the idea: the
48
+ layout has already worked out where every box is, so an effect that names an
49
+ element needs no geometry of its own, and it moves, wraps and reflows with the
50
+ element for free.
51
+
52
+ ### The path
53
+
54
+ ```
55
+ EVGElement surfaceEffect, effectTrigger, fxNames/fxValues (CSS)
56
+ EVGLayout paintHasEffect — does this subtree carry one at all
57
+ EVGDisplayList collectEffects → one instance per element:
58
+ id, kind, trigger, box, radius, parameters
59
+ and `efx` on the rectangle where the element paints
60
+ JSON / evg-list "effects": [...] on the envelope, "efx" on the command
61
+ evg-fx.js the driver: pointer → events, per instance, aged per frame
62
+ evg-webgl.js the registry: name → { layer, params, GLSL }, and the passes
63
+ ```
64
+
65
+ Nothing between the stylesheet and the painter knows what an effect *is*.
66
+ `starfield` is a string, `density` is a number under a name, and the first
67
+ thing that attaches meaning to either is the plugin.
68
+
69
+ ### Sources, backdrops and filters
70
+
71
+ A plugin declares which it is, and the difference decides when it is drawn:
72
+
73
+ | | drawn | reads | example |
74
+ | --- | --- | --- | --- |
75
+ | `source` | in paint order, at the element's own background | nothing | `starfield`, `plasma-wave`, `ambient-light`, `smoke` |
76
+ | `backdrop` | in paint order, at the same point | the surface so far | `liquid-glass`, `raindrop` |
77
+ | `filter` | after the frame, over the box's region | the finished surface | `ripple` |
78
+
79
+ A source is under the element's content, which is what makes a starfield a
80
+ background rather than a sticker over the text. A filter runs when there are
81
+ pixels to bend, which is why it can distort text, charts and images it knows
82
+ nothing about. A backdrop is the third case and the one `backdrop-filter:
83
+ blur()` has always been: it reads what is *behind* the element and nothing in
84
+ front of it, so a pane of glass refracts the page and leaves its own label
85
+ sharp. It costs one copy of the canvas and one full-screen pass per instance
86
+ per frame — the copy is `copyTexSubImage2D` into a kept texture, and the pass
87
+ writes back what is outside the box unchanged.
88
+
89
+ All three get the same things without asking: `uBox`, `uRadius`, `uRes`,
90
+ `uTime`, and `uEvents[]` with `uEventCount`, plus `fxBoxDistance(p)` — the
91
+ element's rounded box as a signed distance, which is what lets a plugin shape
92
+ itself to a box it has never been told the size of. All three write one
93
+ function:
94
+
95
+ ```glsl
96
+ vec4 fxColor(vec2 p, vec2 local) // p in page pixels, y down
97
+ ```
98
+
99
+ The box mask — rounded corners included — is applied in the shared `main`, so
100
+ a plugin **cannot** paint outside the element that declared it. That is checked
101
+ against pixels, not asserted: `lib/evg/gl/fx-check.mjs`.
102
+
103
+ ### Liquid glass, as an example of what the layer buys
104
+
105
+ Frosted glass has been one declaration for years and reads as a fogged sheet
106
+ rather than an object. What is missing from it is refraction: a real pane is
107
+ thicker in the middle than at its edge, so the edge is a curved surface, and
108
+ light through a curve bends. `liquid-glass` is that band — the page behind
109
+ dragged toward the rim, compressed, split slightly into colour, with a
110
+ specular arc inset from the very edge so it reads as a bevel rather than as a
111
+ border somebody drew.
112
+
113
+ It needs nothing of its own to know the shape: the bend follows
114
+ `fxBoxDistance`, the rounded-box signed distance the preamble hands every
115
+ plugin, and its gradient is the surface normal. So the pane is a lens at
116
+ whatever size the flex row gave it and whatever `border-radius` the sheet
117
+ asked for, and `thickness`, `strength`, `power`, `disperse`, `shine`, `angle`
118
+ and `tint` are the seven numbers that shape it — every parameter of every
119
+ effect is listed below.
120
+
121
+ **The sweep** is the second half of it: a bar of light crossing the pane,
122
+ `evg-fx-sweep` and its five siblings. Two of those decide whether it reads as
123
+ a shine or as a line somebody drew:
124
+
125
+ * `sweep-rim` weights the bar toward the bevel. Real glass catches a moving
126
+ light at its EDGES, where the surface is turned; the flat middle only
127
+ flashes as the light goes by. At 1 the middle is left exactly as it was.
128
+ * `sweep-duty` is the fraction of each cycle the pass takes. The rest of the
129
+ cycle the bar is parked off the pane, so the pane is clean glass most of the
130
+ time and the glint is an event.
131
+
132
+ Both are checked against pixels: a rim-weighted bar leaves the flat middle
133
+ byte-for-byte unchanged, and between passes nothing on the pane is brighter
134
+ than the pane without a sweep at all.
135
+
136
+ ### The quieter four
137
+
138
+ A starfield and a pane of glass are both loud: they are the effect, and the
139
+ page is arranged around them. Four more are the other kind — a background you
140
+ can put text on and still read it.
141
+
142
+ * **`plasma-wave`** (source). Ribbons of light drifting across the box: a few
143
+ sine paths through a value-noise field, each one drawn as a thin core with a
144
+ wide glow, plus a `sheet` of colour behind them and sub-cell `grain` motes in
145
+ it.
146
+ * **`raindrop`** (backdrop). One drop per cell of a hash grid, mostly small and
147
+ a few large, each a sphere's lens over what is behind: strongest bend at the
148
+ rim and none in the middle, so the page stays legible through the centre and
149
+ smears at the edge, with a transmitted crescent, a small specular dot and a
150
+ darkened rim. It is the ripple's opposite number: a ripple is a lens that travels and dies,
151
+ a drop is a lens that stays.
152
+ * **`ambient-light`** (source). A slow wash — two-tone fbm, desaturated by
153
+ `sat` — with a handful of bokeh discs floating through it. Nothing in it is
154
+ sharp, which is the point: it is the background under a dashboard, not the
155
+ subject.
156
+
157
+ * **`smoke`** (source). A bank of smoke rising through the box: fbm evaluated
158
+ at a point two other fbms have already moved — a DOMAIN WARP, which is the
159
+ cheapest way to get a turbulent flow out of a function that has none. One
160
+ warp gives the billows, the second gives the tendrils that come off their
161
+ edges. What it has to clear rises with height, so the floor is full and the
162
+ top is single wisps in the black; `height` is how far up that goes, and at 3
163
+ or more it is a cloud filling the box instead. The light is the field
164
+ compared with itself one step toward `angle`: where the smoke is thinning
165
+ that way the step is lower and the pixel is a lit face, where it is
166
+ thickening the pixel is in shadow — a gradient, which is what gives a cloud
167
+ its volume.
168
+
169
+ They take their box from the layout like the others, and each is in
170
+ `effect-presets.css` two or three times, with different numbers.
171
+
172
+ ### Every parameter
173
+
174
+ `evg-fx-<name>: <number>` — and nothing else takes one. A name left out takes
175
+ the default below; a name the plugin does not know reaches the shader and is
176
+ ignored. This list IS the registry in `evg-webgl.js` — `surfaceEffect(name).params`
177
+ is the same object, and `fx-check` holds this table to it: a parameter added to
178
+ a plugin and not written down here fails a check, and so does a default changed
179
+ in one place and not the other.
180
+
181
+ Values are clamped where a shader needs them to be, so one outside the range is
182
+ not an error, it just stops changing anything: `sweep-duty` is held to 0.02…1
183
+ and `sweep-rim` to 0…1, which is why `sweep-duty: 1.1` behaves as 1 (the bar
184
+ never leaves the pane) and `sweep-rim: 0.004` as 0 (the bar is as bright across
185
+ the flat middle as it is at the bevel).
186
+
187
+ **`ripple`** (filter) — rings from a press or a drag.
188
+
189
+ | | default | |
190
+ | --- | --- | --- |
191
+ | `speed` | 220 | how fast a ring travels, px/s |
192
+ | `width` | 28 | the ring's thickness, px |
193
+ | `strength` | 7 | how far the surface is displaced |
194
+ | `decay` | 1.8 | how quickly a drop dies |
195
+ | `highlight` | 0.08 | brightening along the crest |
196
+ | `rings` | 3 | rings per drop |
197
+ | `stagger` | 0.09 | the delay between them |
198
+ | `falloff` | 0.62 | how much dimmer each following ring is |
199
+ | `shine` / `gloss` / `bump` | 0.45 / 120 / 70 | the specular lift on the wave |
200
+ | `lightX` / `lightY` / `lightZ` | -0.45 / -0.65 / 0.62 | where that light is |
201
+
202
+ **`starfield`** (source) — stars and dust.
203
+
204
+ | | default | |
205
+ | --- | --- | --- |
206
+ | `density` | 1 | stars per cell; the grid follows it |
207
+ | `speed` | 6 | drift, px/s |
208
+ | `angle` | 200 | the direction of that drift, degrees |
209
+ | `twinkle` | 1 | how much a star's brightness wanders |
210
+ | `glow` | 1 | the halo around one |
211
+ | `nebula` | 0.6 | how much dust there is |
212
+ | `hue` / `hue2` | 225 / 300 | the two ends of the cloud's colour |
213
+ | `seed` | 1 | a different sky at the same settings |
214
+
215
+ **`liquid-glass`** (backdrop) — refraction at the rim, and a light crossing it.
216
+
217
+ | | default | |
218
+ | --- | --- | --- |
219
+ | `thickness` | 24 | how far in from the edge the pane is curved, px |
220
+ | `strength` | 32 | how far the bend drags what is behind it |
221
+ | `power` | 2.2 | how sharply that falls off toward the middle |
222
+ | `disperse` | 0.07 | how far the colour channels are split |
223
+ | `shine` | 0.6 | the specular arc inset from the edge |
224
+ | `angle` | -60 | where its light comes from, degrees |
225
+ | `tint` | 0.05 | a flat lift over the pane |
226
+ | `sweep` | 0 | the bar's brightness — 0 is no sweep at all |
227
+ | `sweep-angle` | -62 | the direction it crosses in, degrees |
228
+ | `sweep-width` | 0.06 | the bar's width, as a fraction of the pane |
229
+ | `sweep-speed` | 0 | passes per second; 0 parks it at `sweep-at` |
230
+ | `sweep-at` | 0.5 | where it is parked, 0…1 across the pane |
231
+ | `sweep-edge` | 2.2 | extra brightness where it meets the bevel |
232
+ | `sweep-rim` | 0.55 | how much it keeps to the bevel; 1 leaves the flat middle alone |
233
+ | `sweep-duty` | 0.35 | the fraction of each cycle the pass takes; the rest of it the bar is off the pane |
234
+
235
+ **`plasma-wave`** (source) — ribbons of light.
236
+
237
+ | | default | |
238
+ | --- | --- | --- |
239
+ | `ribbons` | 5 | how many, 1…8 |
240
+ | `speed` | 0.35 | how fast they travel |
241
+ | `amp` | 0.22 | how far they swing, as a fraction of the height |
242
+ | `freq` | 1.7 | how many waves across the box |
243
+ | `width` | 2.2 | the bright core's thickness, px |
244
+ | `glow` | 26 | the halo around a ribbon, px |
245
+ | `sheet` | 0.16 | the wide colour behind them; 0 is ribbons on black |
246
+ | `hue` / `hue2` | 225 / 285 | the two ends of their colour |
247
+ | `grain` | 0.35 | the motes in the sheet |
248
+ | `seed` | 1 | a different set of paths |
249
+
250
+ **`raindrop`** (backdrop) — drops on the pane.
251
+
252
+ | | default | |
253
+ | --- | --- | --- |
254
+ | `density` | 1 | how close the drops are; cells are `46 / density` px apart |
255
+ | `size` | 0.5 | how big a drop is within its cell |
256
+ | `refract` | 14 | how far it bends what is behind it, px |
257
+ | `shine` | 0.85 | the transmitted crescent and the specular dot |
258
+ | `angle` | -55 | where the light is, degrees |
259
+ | `rim` | 0.55 | how dark the drop's edge is |
260
+ | `speed` | 0 | how fast the field drifts down; 0 is still |
261
+ | `seed` | 1 | a different scatter |
262
+
263
+ **`smoke`** (source) — a bank of it rising through the box.
264
+
265
+ | | default | |
266
+ | --- | --- | --- |
267
+ | `density` | 1.2 | how much of the field shows as smoke |
268
+ | `rise` | 0.05 | how fast it climbs |
269
+ | `wind` | 0 | sideways drift |
270
+ | `swirl` | 2.6 | how hard the warp curls it; 0 is clouds of plain noise |
271
+ | `scale` | 190 | the size of a billow, px |
272
+ | `detail` | 5 | octaves, 1…6 — the last two are the tendrils and most of the cost |
273
+ | `height` | 0.9 | how far up the box it reaches; 3 or more fills it |
274
+ | `softness` | 0.55 | how gradually an edge gives out |
275
+ | `shade` | 0.6 | how much the light sculpts it; 0 is flat grey |
276
+ | `angle` | -60 | where that light is, degrees |
277
+ | `hue` | 205 | the colour it is lit by |
278
+ | `tint` | 0.1 | how much of that colour it takes |
279
+ | `seed` | 1 | a different roll of it |
280
+
281
+ **`ambient-light`** (source) — a slow wash.
282
+
283
+ | | default | |
284
+ | --- | --- | --- |
285
+ | `hue` / `hue2` | 190 / 268 | the two ends of the wash |
286
+ | `sat` | 0.5 | how far from grey those are |
287
+ | `tilt` | 25 | the direction the wash runs, degrees |
288
+ | `depth` | 0.5 | how bright it is overall |
289
+ | `orbs` | 7 | the bokeh discs in it, 0…10 |
290
+ | `size` | 0.55 | how big one is, against the shorter side |
291
+ | `softness` | 1.6 | how far its edge is blurred |
292
+ | `speed` | 0.06 | how fast they drift |
293
+ | `glow` | 0.45 | how bright they are |
294
+ | `seed` | 1 | a different arrangement |
295
+
296
+ ### Presets
297
+
298
+ `lib/evg/gl/effect-presets.css` is fourteen blocks of ordinary CSS, one
299
+ element's worth each: five skies, two plasma fields, two rains, two washes and
300
+ three of smoke. They exist to
301
+ be pasted — into the live editor under the gallery's effects demo, or into a
302
+ stylesheet — and nothing but numbers comes with them.
303
+
304
+ ```
305
+ npm run evg:fx:shots every preset, one picture
306
+ npm run evg:fx:shots -- out.png --only raindrop --tile 520x300
307
+ ```
308
+
309
+ The gallery's effects demo has them in its rail: picking one types the block
310
+ into the live stylesheet under the canvas, and which element it lands on is the
311
+ plugin's layer — a source effect is the sky, a backdrop effect is the pane over
312
+ it, because a backdrop draws what is behind an element and an opaque sky would
313
+ paint over it.
314
+
315
+ The file is read twice and written once: `effect-shots.mjs` paints it, and
316
+ `fx-check.mjs` parses it with the ENGINE's own `EVGStyleSheet` and compares
317
+ every declaration against what the picture used — so a preset the cascade
318
+ refuses fails a check instead of quietly drawing the plugin's defaults. The
319
+ pixel half then renders all eleven on a page of their own size and holds each
320
+ to changing its tile against the same tile with the effect off. The tiles under
321
+ a backdrop preset carry a mock page — a headline bar and three lines — because
322
+ a lens over a flat colour is invisible by construction.
323
+
324
+ ### Registering one
325
+
326
+ ```js
327
+ import { registerSurfaceEffect } from "./evg-webgl.js";
328
+
329
+ registerSurfaceEffect({
330
+ name: "scanlines",
331
+ layer: "filter",
332
+ params: { period: 4, depth: 0.15 },
333
+ frag: `vec4 fxColor(vec2 p, vec2 local) {
334
+ float k = 1.0 - p_depth * step(0.5, fract(p.y / p_period));
335
+ return vec4(texture(uSrc, vUV).rgb * k, 1.0);
336
+ }`,
337
+ });
338
+ ```
339
+
340
+ and then `evg-surface-effect: scanlines; evg-fx-period: 3` in any stylesheet.
341
+ No engine change, no display list change, no painter change.
342
+
343
+ ### The driver
344
+
345
+ `lib/evg/gl/evg-fx.js` is the part that turns a pointer into events:
346
+
347
+ ```js
348
+ const fx = createEffectDriver();
349
+ attachEffectPointer(canvas, fx, schedule);
350
+ // per frame:
351
+ fx.tick(dtMs, doc.list); // ages events, stamps the clock on each instance
352
+ frame.draw();
353
+ ```
354
+
355
+ It hit-tests the boxes the display list carries, topmost first, and gives the
356
+ event to the instance whose trigger list mentions what happened. An element
357
+ with no `evg-effect-on` is not adopted: that is an effect the application
358
+ drives, which is exactly the old behaviour and still works.
359
+
360
+ `fx.busy()` is false when nothing is in flight and no effect says `always`, so
361
+ a page stops drawing when the water stills.
362
+
363
+ ### Switching one off
364
+
365
+ `inst.off = true` on an instance, and the painter skips the run, the filter is
366
+ not live, nothing is compiled or copied, and the driver stops giving it events
367
+ or reporting it busy. The frame is **not** rebuilt: not one buffer is
368
+ re-uploaded to stop drawing one shader. `fx-demo.html` puts a switch on each
369
+ effect the document declares and remembers the choice per browser.
370
+
371
+ ### The trap under a backdrop effect
372
+
373
+ A backdrop reads the surface mid-frame, and the one surface it may never read
374
+ is the canvas. A WebGL2 context asked for `antialias: true` — the default, and
375
+ what every page here asks for — has a MULTISAMPLED default framebuffer, and
376
+ copying out of one is `INVALID_OPERATION`: the copy leaves the texture black
377
+ and the pass writes that black over everything painted before the element. So
378
+ a frame with a live backdrop in it is rendered into the offscreen target and
379
+ presented at the end.
380
+
381
+ This shipped broken for an afternoon and every check passed, because the checks
382
+ rendered with `preserveDrawingBuffer: true`, which on this driver hands out a
383
+ single-sampled buffer. `fx-check.mjs` now asks for the attributes a page asks
384
+ for and reads the pixels back through a 2-D canvas, which is what a screenshot
385
+ does — and it fails three ways if the routing is removed.
386
+
387
+ ## What this deliberately did not touch
388
+
389
+ * **`list.effect`, the whole-surface effect, is untouched** — its own field on
390
+ the list, its own program in the painter, its own drops from the application.
391
+ `landing/`, `gallery/ui/demo` and their gates draw exactly what they drew
392
+ before. The two coexist: the whole-surface pass runs first, then the
393
+ element-scoped filters.
394
+ * The ripple's math is **not** duplicated. `RIPPLE_CORE` is one string; the
395
+ whole-surface program and the plugin are two entry points into it.
396
+
397
+ ## What is still missing
398
+
399
+ * **The binary list** (`toBinary` / `evg-binary.js`) does not carry effects, so
400
+ an app served through `evg-engine.js` in a Worker loses them. The JSON and the
401
+ in-process object path (`evg-list.js`) both carry them. Adding it means a
402
+ field in the command record and the instances in the envelope.
403
+ * **Scroll.** An effect's box is recorded pre-shift. Inside a scrolling layer
404
+ the painter is handed the layer's shift and applies it, but the driver
405
+ hit-tests the unshifted box — so an effect on a scrolled element takes its
406
+ press in the wrong place. The fix is for the driver to be told the shifts,
407
+ which is the same list the painter already gets.
408
+ * **Id selectors.** `EVGStyleSheet` matches classes, not `#id`, so an effect is
409
+ styled by class and named by id. That is a stylesheet limitation rather than
410
+ an effect one.
411
+ * **A page that declares an element-scoped effect still emits the legacy
412
+ `effect` block** as well, with no drops in it, because `readEffect` predates
413
+ all of this and nothing should change under the pages that rely on it. It is
414
+ inert: the painter skips a whole-surface pass with no drops.
415
+ * **Other painters.** SoftCanvas, PDF and SVG draw the page and drop the
416
+ effect, which is the right failure — `evg-html.js` now reports which kinds it
417
+ dropped. A Skia/AGSL host could implement the same plugin ABI; see
418
+ `PLAN_NATIVE_HOSTS.md`.
419
+ * **WebGPU.** The plugin declaration is a name, a parameter list and a shader
420
+ string. Nothing in the display list or in a stylesheet says GLSL, so the same
421
+ registry with WGSL bodies would need no change above the painter.
422
+
423
+ ## Running it
424
+
425
+ ```
426
+ npm run evg:fx:test the document side: CSS → instances, without a GPU
427
+ npm run evg:fx:check the pixels: scoped, layered, moving, and not leaking
428
+ npm run evg:fx:doc rebuild the demo document from lib/evg/FxDemoDoc.rgr
429
+ npm run evg:fx:demo serve it — http://localhost:8099/fx-demo.html
430
+ npm run evg:fx:shots paint every preset in effect-presets.css
431
+ ```