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,370 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EVGEasing — CSS timing functions
5
+ ; ==============================================================================
6
+ ;
7
+ ; A transition needs two numbers from the clock: how far through it is, and how
8
+ ; far along it therefore LOOKS. Those are not the same number, and the gap
9
+ ; between them is most of why a browser's motion feels different from a
10
+ ; hand-rolled `t += dt` one.
11
+ ;
12
+ ; input progress elapsed / duration. Linear, always.
13
+ ; output progress what the timing function makes of it. This is what the
14
+ ; value is actually interpolated by.
15
+ ;
16
+ ; Two families, which is all CSS has:
17
+ ;
18
+ ; cubic-bezier(x1 y1 x2 y2) a curve from (0,0) to (1,1) with two control
19
+ ; points. `ease`, `ease-in`, `ease-out` and
20
+ ; `ease-in-out` are named instances of it, and so
21
+ ; is `linear`.
22
+ ; steps(n start|end) n discrete jumps.
23
+ ;
24
+ ; The awkward part is that the curve is parametric — both x and y are functions
25
+ ; of a parameter that is NOT the input progress — so the output cannot be read
26
+ ; off directly. Given x, the parameter has to be solved for first. Newton–
27
+ ; Raphson converges in a handful of iterations over almost the whole range, and
28
+ ; where it does not (a control point outside [0,1] can flatten the derivative)
29
+ ; bisection finishes the job. This is the method every engine uses, and matching
30
+ ; it is the difference between 5e-6 of the browser and 1e-2 of it.
31
+ ;
32
+ ; The control points for the four keywords, and every number this file is
33
+ ; checked against, are CAPTURED rather than quoted: `oracle/css-timing.json`
34
+ ; holds samples taken off a real `Animation` at thirteen input progresses.
35
+ ; `EVGTimingTest.rgr` is those samples.
36
+ ; ==============================================================================
37
+
38
+ class EVGEasing {
39
+
40
+ ; 0 = cubic-bezier, 1 = steps
41
+ def kind:int 0
42
+ def x1:double 0.0
43
+ def y1:double 0.0
44
+ def x2:double 1.0
45
+ def y2:double 1.0
46
+ def stepCount:int 1
47
+ ; `steps(n, start)` jumps at the beginning of each interval, so it leaves
48
+ ; zero immediately; `end` holds zero until the first boundary.
49
+ def jumpStart:boolean false
50
+ ; False when `parse` was handed something it did not understand. The caller
51
+ ; reports it: a timing function silently downgraded to linear is a bug you
52
+ ; find by squinting at motion.
53
+ def ok:boolean true
54
+
55
+ Constructor () {
56
+ }
57
+
58
+ sfn cubic:EVGEasing (x1:double y1:double x2:double y2:double) {
59
+ def e (new EVGEasing())
60
+ e.kind = 0
61
+ e.x1 = x1
62
+ e.y1 = y1
63
+ e.x2 = x2
64
+ e.y2 = y2
65
+ return e
66
+ }
67
+
68
+ sfn linear:EVGEasing () {
69
+ return (EVGEasing.cubic(0.0 0.0 1.0 1.0))
70
+ }
71
+
72
+ sfn steps:EVGEasing (count:int atStart:boolean) {
73
+ def e (new EVGEasing())
74
+ e.kind = 1
75
+ e.stepCount = count
76
+ if (count < 1) {
77
+ e.stepCount = 1
78
+ }
79
+ e.jumpStart = atStart
80
+ return e
81
+ }
82
+
83
+ ; --- parsing ----------------------------------------------------------------
84
+
85
+ ; The four keywords are cubic-beziers with the control points CSS names.
86
+ ; `ease` is not symmetric — it leaves fast and arrives slowly — which is why
87
+ ; it is the default and why a linear default feels mechanical beside it.
88
+ sfn parse:EVGEasing (text:string) {
89
+ def t:string (trim text)
90
+ if ((strlen t) == 0) {
91
+ return (EVGEasing.linear())
92
+ }
93
+ if (t == "linear") { return (EVGEasing.cubic(0.0 0.0 1.0 1.0)) }
94
+ if (t == "ease") { return (EVGEasing.cubic(0.25 0.1 0.25 1.0)) }
95
+ if (t == "ease-in") { return (EVGEasing.cubic(0.42 0.0 1.0 1.0)) }
96
+ if (t == "ease-out") { return (EVGEasing.cubic(0.0 0.0 0.58 1.0)) }
97
+ if (t == "ease-in-out") { return (EVGEasing.cubic(0.42 0.0 0.58 1.0)) }
98
+ ; `step-start` and `step-end` are the one-step shorthands.
99
+ if (t == "step-start") { return (EVGEasing.steps(1 true)) }
100
+ if (t == "step-end") { return (EVGEasing.steps(1 false)) }
101
+
102
+ def args:string (EVGEasing.argsOf(t "cubic-bezier"))
103
+ if ((strlen args) > 0) {
104
+ def nums:[double] (EVGEasing.numbers(args))
105
+ if ((array_length nums) == 4) {
106
+ ; x has to stay inside [0,1] — the curve is a function of the
107
+ ; input progress and a control point outside that range would
108
+ ; make it fold back on itself. y is free, and a y outside [0,1]
109
+ ; is the overshoot that makes a bounce.
110
+ def cx1:double (EVGEasing.clamp01((itemAt nums 0)))
111
+ def cx2:double (EVGEasing.clamp01((itemAt nums 2)))
112
+ return (EVGEasing.cubic(cx1 (itemAt nums 1) cx2 (itemAt nums 3)))
113
+ }
114
+ def bad:EVGEasing (EVGEasing.linear())
115
+ bad.ok = false
116
+ return bad
117
+ }
118
+
119
+ def sargs:string (EVGEasing.argsOf(t "steps"))
120
+ if ((strlen sargs) > 0) {
121
+ def parts:[string] (EVGEasing.splitTop(sargs 44))
122
+ def countTxt:string (trim (itemAt parts 0))
123
+ def n@(optional):double (to_double countTxt)
124
+ if n {
125
+ def atStart:boolean false
126
+ if ((array_length parts) > 1) {
127
+ def word:string (trim (itemAt parts 1))
128
+ if ((word == "start") || (word == "jump-start")) {
129
+ atStart = true
130
+ }
131
+ }
132
+ return (EVGEasing.steps((to_int (unwrap n)) atStart))
133
+ }
134
+ }
135
+
136
+ def unknown:EVGEasing (EVGEasing.linear())
137
+ unknown.ok = false
138
+ return unknown
139
+ }
140
+
141
+ ; Does this token look like a timing function at all? The transition
142
+ ; shorthand is order-tolerant about everything except its two times, so
143
+ ; telling a function from a duration is how the parts get sorted.
144
+ sfn looksLikeFunction:boolean (text:string) {
145
+ def t:string (trim text)
146
+ if (t == "linear") { return true }
147
+ if (t == "ease") { return true }
148
+ if (t == "ease-in") { return true }
149
+ if (t == "ease-out") { return true }
150
+ if (t == "ease-in-out") { return true }
151
+ if (t == "step-start") { return true }
152
+ if (t == "step-end") { return true }
153
+ if ((strlen (EVGEasing.argsOf(t "cubic-bezier"))) > 0) { return true }
154
+ if ((strlen (EVGEasing.argsOf(t "steps"))) > 0) { return true }
155
+ ; Anything else shaped like a call is an ATTEMPTED timing function, and
156
+ ; claiming it here is deliberate: `spring(1, 2)` then reaches `parse`,
157
+ ; which reports it. Refusing to recognise it instead makes the shorthand
158
+ ; parser mistake it for a property name and drop it in silence, and the
159
+ ; author gets linear motion with nothing anywhere saying why. No CSS
160
+ ; property name contains parentheses, so there is nothing to lose.
161
+ def n:int (strlen t)
162
+ if (n > 2) {
163
+ if ((charAt t (n - 1)) == 41) {
164
+ def i:int 0
165
+ while (i < n) {
166
+ if ((charAt t i) == 40) {
167
+ return true
168
+ }
169
+ i = (i + 1)
170
+ }
171
+ }
172
+ }
173
+ return false
174
+ }
175
+
176
+ ; The inside of `name( ... )`, or "" when `t` is not that call.
177
+ sfn argsOf:string (t:string name:string) {
178
+ def nl:int (strlen name)
179
+ def tl:int (strlen t)
180
+ if (tl < (nl + 3)) {
181
+ return ""
182
+ }
183
+ if ((substring t 0 nl) != name) {
184
+ return ""
185
+ }
186
+ if ((charAt t nl) != 40) {
187
+ return ""
188
+ }
189
+ if ((charAt t (tl - 1)) != 41) {
190
+ return ""
191
+ }
192
+ return (substring t (nl + 1) (tl - 1))
193
+ }
194
+
195
+ sfn numbers:[double] (s:string) {
196
+ def out:[double]
197
+ def parts:[string] (EVGEasing.splitTop(s 44))
198
+ def i:int 0
199
+ while (i < (array_length parts)) {
200
+ def v@(optional):double (to_double (trim (itemAt parts i)))
201
+ if v {
202
+ push out (unwrap v)
203
+ }
204
+ i = (i + 1)
205
+ }
206
+ return out
207
+ }
208
+
209
+ ; Split on `ch`, but only OUTSIDE parentheses. `cubic-bezier(0.25, 0.1,
210
+ ; 0.25, 1)` inside a comma-separated transition list is why: splitting the
211
+ ; list on every comma tears the function into four meaningless fragments,
212
+ ; and the failure is silent because each fragment still parses as something.
213
+ sfn splitTop:[string] (s:string ch:int) {
214
+ def out:[string]
215
+ def depth:int 0
216
+ def start:int 0
217
+ def i:int 0
218
+ def n:int (strlen s)
219
+ while (i < n) {
220
+ def c:int (charAt s i)
221
+ if (c == 40) { depth = (depth + 1) }
222
+ if (c == 41) { depth = (depth - 1) }
223
+ if ((c == ch) && (depth == 0)) {
224
+ push out (substring s start i)
225
+ start = (i + 1)
226
+ }
227
+ i = (i + 1)
228
+ }
229
+ push out (substring s start n)
230
+ return out
231
+ }
232
+
233
+ ; Whitespace-separated words, outside parentheses for the same reason:
234
+ ; `steps(4, end)` is ONE word of the shorthand and has a space in it.
235
+ sfn splitWordsTop:[string] (s:string) {
236
+ def out:[string]
237
+ def depth:int 0
238
+ def start:int 0
239
+ def i:int 0
240
+ def n:int (strlen s)
241
+ while (i < n) {
242
+ def c:int (charAt s i)
243
+ if (c == 40) { depth = (depth + 1) }
244
+ if (c == 41) { depth = (depth - 1) }
245
+ def isSpace:boolean (((c == 32) || (c == 9)) || (c == 10))
246
+ if (isSpace && (depth == 0)) {
247
+ if (i > start) {
248
+ push out (substring s start i)
249
+ }
250
+ start = (i + 1)
251
+ }
252
+ i = (i + 1)
253
+ }
254
+ if (n > start) {
255
+ push out (substring s start n)
256
+ }
257
+ return out
258
+ }
259
+
260
+ sfn clamp01:double (v:double) {
261
+ if (v < 0.0) { return 0.0 }
262
+ if (v > 1.0) { return 1.0 }
263
+ return v
264
+ }
265
+
266
+ ; --- evaluation --------------------------------------------------------------
267
+
268
+ ; Input progress in, output progress out.
269
+ fn ease:double (t:double) {
270
+ def x:double t
271
+ if (x < 0.0) { x = 0.0 }
272
+ if (x > 1.0) { x = 1.0 }
273
+ if (kind == 1) {
274
+ return (this.stepAt(x))
275
+ }
276
+ ; The identity curve is worth short-circuiting: `linear` is the most
277
+ ; common easing there is and solving a cubic to be told t = t is waste
278
+ ; on every element of every frame.
279
+ if ((((x1 == 0.0) && (y1 == 0.0)) && (x2 == 1.0)) && (y2 == 1.0)) {
280
+ return x
281
+ }
282
+ return (this.sampleY((this.solveT(x))))
283
+ }
284
+
285
+ fn stepAt:double (x:double) {
286
+ def n:double (to_double stepCount)
287
+ def raw:double (x * n)
288
+ def k:int (floor raw)
289
+ if jumpStart {
290
+ k = (k + 1)
291
+ }
292
+ def v:double ((to_double k) / n)
293
+ if (v < 0.0) { return 0.0 }
294
+ if (v > 1.0) { return 1.0 }
295
+ return v
296
+ }
297
+
298
+ ; The polynomial form of a cubic Bézier with endpoints pinned at 0 and 1.
299
+ ; Writing it out beats evaluating the Bernstein basis three times a frame.
300
+ fn sampleX:double (t:double) {
301
+ def cx:double (3.0 * x1)
302
+ def bx:double (((3.0 * (x2 - x1))) - cx)
303
+ def a:double ((1.0 - cx) - bx)
304
+ return (((((a * t) + bx) * t) + cx) * t)
305
+ }
306
+
307
+ fn sampleY:double (t:double) {
308
+ def cy:double (3.0 * y1)
309
+ def by:double (((3.0 * (y2 - y1))) - cy)
310
+ def a:double ((1.0 - cy) - by)
311
+ return (((((a * t) + by) * t) + cy) * t)
312
+ }
313
+
314
+ fn slopeX:double (t:double) {
315
+ def cx:double (3.0 * x1)
316
+ def bx:double (((3.0 * (x2 - x1))) - cx)
317
+ def a:double ((1.0 - cx) - bx)
318
+ return (((((3.0 * a) * t) + (2.0 * bx)) * t) + cx)
319
+ }
320
+
321
+ ; Find the curve parameter whose x is the input progress.
322
+ ;
323
+ ; Newton first, from t = x, which is already close because x is monotonic
324
+ ; from 0 to 1. Where the derivative is near zero — which happens exactly
325
+ ; where a control point has been pushed outside [0,1] to make an overshoot —
326
+ ; Newton either crawls or leaves the interval, so bisection takes over. It
327
+ ; is slower and it always converges, and the combination is what keeps the
328
+ ; error at 5e-6 across the whole range instead of only the easy part of it.
329
+ fn solveT:double (x:double) {
330
+ def t:double x
331
+ def i:int 0
332
+ while (i < 8) {
333
+ def err:double ((this.sampleX(t)) - x)
334
+ if ((fabs err) < 0.0000001) {
335
+ return t
336
+ }
337
+ def d:double (this.slopeX(t))
338
+ if ((fabs d) < 0.000001) {
339
+ i = 8
340
+ } {
341
+ t = (t - (err / d))
342
+ if ((t < 0.0) || (t > 1.0)) {
343
+ i = 8
344
+ }
345
+ i = (i + 1)
346
+ }
347
+ }
348
+ def lo:double 0.0
349
+ def hi:double 1.0
350
+ def m:double x
351
+ if ((m < lo) || (m > hi)) {
352
+ m = 0.5
353
+ }
354
+ def j:int 0
355
+ while (j < 64) {
356
+ def v:double (this.sampleX(m))
357
+ if ((fabs (v - x)) < 0.0000001) {
358
+ return m
359
+ }
360
+ if (v < x) {
361
+ lo = m
362
+ } {
363
+ hi = m
364
+ }
365
+ m = ((lo + hi) / 2.0)
366
+ j = (j + 1)
367
+ }
368
+ return m
369
+ }
370
+ }
@@ -0,0 +1,253 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EVGEffectTest — an effect that belongs to an ELEMENT, declared in the sheet
5
+ ; ==============================================================================
6
+ ;
7
+ ; What `evg-surface-effect` used to mean: one post-process over the whole
8
+ ; document, whose parameters were fields on EVGElement (`evg-ripple-speed` and
9
+ ; thirteen siblings), and whose drops were pushed in by hand from the page's
10
+ ; own `pointerdown` — every press, anywhere, rippled everything. Nothing in
11
+ ; the document said WHICH box reacts or WHAT starts it, because there was
12
+ ; nowhere to say it.
13
+ ;
14
+ ; What it means now, without disturbing any of that:
15
+ ;
16
+ ; evg-surface-effect: starfield WHAT runs. A string. The engine does not
17
+ ; know what a starfield is and never will —
18
+ ; the renderer's plugin does.
19
+ ; evg-effect-on: press drag WHAT STARTS IT. The host's driver reads
20
+ ; this; `always` is a thing that runs on its
21
+ ; own clock.
22
+ ; evg-fx-density: 2.6 PARAMETERS, under names this file has
23
+ ; never heard of, carried through untouched.
24
+ ;
25
+ ; and WHERE is the element's own border box, because the layout already knows
26
+ ; it. That is the whole of the change: three properties and a box, so that
27
+ ; which element has the effect is a question the document answers.
28
+ ;
29
+ ; Everything below runs without a GPU. What the shader does with an instance
30
+ ; is the painter's business; that the document produces the right instance is
31
+ ; this file's.
32
+ ; ==============================================================================
33
+
34
+ Import "EVGElement.rgr"
35
+ Import "EVGStyleSheet.rgr"
36
+ Import "EVGLayout.rgr"
37
+ Import "EVGDisplayList.rgr"
38
+
39
+ class FxCheck {
40
+ def passed:int 0
41
+ def failed:int 0
42
+
43
+ fn ok:void (name:string cond:boolean) {
44
+ if cond {
45
+ passed = (passed + 1)
46
+ print (" PASS " + name)
47
+ } {
48
+ failed = (failed + 1)
49
+ print (" FAIL " + name)
50
+ }
51
+ }
52
+
53
+ fn has:void (name:string hay:string needle:string) {
54
+ def good:boolean ((indexOf hay needle) >= 0)
55
+ if (good == false) {
56
+ print (" looked for " + needle)
57
+ print (" in " + hay)
58
+ }
59
+ this.ok(name good)
60
+ }
61
+
62
+ fn hasNot:void (name:string hay:string needle:string) {
63
+ def good:boolean ((indexOf hay needle) < 0)
64
+ if (good == false) {
65
+ print (" did not want " + needle)
66
+ print (" in " + hay)
67
+ }
68
+ this.ok(name good)
69
+ }
70
+
71
+ fn eqInt:void (name:string got:int want:int) {
72
+ def good:boolean (got == want)
73
+ if (good == false) {
74
+ print (" got " + (to_string got) + " want " + (to_string want))
75
+ }
76
+ this.ok(name good)
77
+ }
78
+
79
+ fn eqStr:void (name:string got:string want:string) {
80
+ def good:boolean (got == want)
81
+ if (good == false) {
82
+ print (" got '" + got + "' want '" + want + "'")
83
+ }
84
+ this.ok(name good)
85
+ }
86
+ }
87
+
88
+ class EVGEffectTest {
89
+
90
+ ; A page with one card in it, styled by a sheet. The sheet is the point:
91
+ ; an effect nobody can declare in CSS is an effect the application owns,
92
+ ; which is what this replaces.
93
+ sfn page:EVGElement (css:string) {
94
+ def root (new EVGElement())
95
+ root.setAttribute("width" "400px")
96
+ root.setAttribute("height" "300px")
97
+ def card (EVGElement.createDiv())
98
+ card.id = "sky"
99
+ card.className = "card"
100
+ card.setAttribute("width" "200px")
101
+ card.setAttribute("height" "120px")
102
+ root.addChild(card)
103
+ if ((strlen css) > 0) {
104
+ def sheet (new EVGStyleSheet())
105
+ sheet.parse(css)
106
+ sheet.setViewport(400.0 300.0 false)
107
+ sheet.applyTree(root "")
108
+ }
109
+ return root
110
+ }
111
+
112
+ sfn listOf:EVGDisplayList (root:EVGElement) {
113
+ def lay (new EVGLayout())
114
+ lay.setPageSize(400.0 300.0)
115
+ lay.layout(root)
116
+ def dl (new EVGDisplayList())
117
+ dl.setTextEngine((lay.getTextEngine()))
118
+ dl.build(root)
119
+ return dl
120
+ }
121
+
122
+ sfn jsonOf:string (root:EVGElement) {
123
+ def dl:EVGDisplayList (EVGEffectTest.listOf(root))
124
+ return (dl.toJson())
125
+ }
126
+
127
+ ; --- the declaration ------------------------------------------------------
128
+
129
+ sfn testDeclared:void (c:FxCheck) {
130
+ print "-- the sheet says which element has the effect"
131
+ def css:string (".card { evg-surface-effect: starfield;"
132
+ + " evg-effect-on: always;"
133
+ + " evg-fx-density: 2.6;"
134
+ + " evg-fx-drift: 0.4 }")
135
+ def root:EVGElement (EVGEffectTest.page(css))
136
+ def dl:EVGDisplayList (EVGEffectTest.listOf(root))
137
+ c.eqInt("one instance, for the one element that asked" (array_length dl.fxIds) 1)
138
+ c.eqStr("named by the element's own id" (itemAt dl.fxIds 0) "sky")
139
+ c.eqStr("carrying the kind verbatim" (itemAt dl.fxKinds 0) "starfield")
140
+ c.eqStr("and the trigger" (itemAt dl.fxTriggers 0) "always")
141
+
142
+ ; THE BOX IS THE LAYOUT'S, not a rectangle somebody typed. This is the
143
+ ; difference between an effect on an element and an effect on a page
144
+ ; that happens to have an element on it.
145
+ c.ok("the box is the card's own width" ((itemAt dl.fxW 0) == 200.0))
146
+ c.ok("and its height" ((itemAt dl.fxH 0) == 120.0))
147
+
148
+ def js:string (dl.toJson())
149
+ c.has("the JSON carries the instance" js "\"kind\":\"starfield\"")
150
+ c.has("with its box" js "\"box\":[0.00,0.00,200.00,120.00]")
151
+ c.has("a parameter this engine has never heard of" js "\"density\":2.60")
152
+ c.has("and another" js "\"drift\":0.40")
153
+ }
154
+
155
+ ; --- the link into paint order --------------------------------------------
156
+
157
+ sfn testPaintOrder:void (c:FxCheck) {
158
+ print "-- the effect is anchored where the element paints"
159
+ ; No background: the card draws nothing of its own, and the effect
160
+ ; still needs a place in the command stream, because paint order is
161
+ ; the only thing that says whether a starfield is behind the text on
162
+ ; the card or over it.
163
+ def css:string ".card { evg-surface-effect: starfield }"
164
+ def root:EVGElement (EVGEffectTest.page(css))
165
+ def js:string (EVGEffectTest.jsonOf(root))
166
+ c.has("a carrier rectangle names the instance" js "\"efx\":\"sky\"")
167
+
168
+ ; And with a background, it rides that rectangle rather than adding a
169
+ ; second one.
170
+ def css2:string ".card { background-color: rgb(10,12,30); evg-surface-effect: starfield }"
171
+ def root2:EVGElement (EVGEffectTest.page(css2))
172
+ def dl2:EVGDisplayList (EVGEffectTest.listOf(root2))
173
+ def named:int 0
174
+ def i:int 0
175
+ while (i < (array_length dl2.cmds)) {
176
+ def cmd:EVGDrawCmd (itemAt dl2.cmds i)
177
+ if ((strlen cmd.effectId) > 0) {
178
+ named = (named + 1)
179
+ }
180
+ i = (i + 1)
181
+ }
182
+ c.eqInt("one rectangle carries it, not two" named 1)
183
+ }
184
+
185
+ ; --- the ripple, through the general channel ------------------------------
186
+
187
+ sfn testRippleParams:void (c:FxCheck) {
188
+ print "-- an element-scoped ripple keeps its own property names"
189
+ ; `evg-ripple-speed` predates all of this. An element-scoped ripple
190
+ ; reads the same numbers as generic parameters, so a page that already
191
+ ; styles a ripple does not learn a second spelling.
192
+ def css:string (".card { evg-surface-effect: ripple;"
193
+ + " evg-effect-on: press drag;"
194
+ + " evg-ripple-speed: 300;"
195
+ + " evg-fx-strength: 11 }")
196
+ def root:EVGElement (EVGEffectTest.page(css))
197
+ def js:string (EVGEffectTest.jsonOf(root))
198
+ c.has("the ripple's own property arrives as a parameter" js "\"speed\":300.00")
199
+ c.has("the defaults come with it" js "\"gloss\":120.00")
200
+ c.has("what the page wrote under evg-fx- wins" js "\"strength\":11.00")
201
+ c.has("and the trigger is a list" js "\"on\":\"press drag\"")
202
+ }
203
+
204
+ ; --- a page with no effect on it ------------------------------------------
205
+
206
+ sfn testSilence:void (c:FxCheck) {
207
+ print "-- a page with no effect writes nothing new"
208
+ def root:EVGElement (EVGEffectTest.page(".card { background-color: rgb(1,2,3) }"))
209
+ def js:string (EVGEffectTest.jsonOf(root))
210
+ c.hasNot("no effects array" js "\"effects\":")
211
+ c.hasNot("and no fx on any command" js "\"efx\":")
212
+ }
213
+
214
+ ; --- the old whole-surface effect is untouched ----------------------------
215
+
216
+ sfn testLegacy:void (c:FxCheck) {
217
+ print "-- and the original whole-surface effect still works"
218
+ def root:EVGElement (EVGEffectTest.page(""))
219
+ root.setAttribute("evg-surface-effect" "ripple")
220
+ def xs:[double]
221
+ def ys:[double]
222
+ def ages:[double]
223
+ push xs 40.0
224
+ push ys 60.0
225
+ push ages 0.25
226
+ root.rippleXs = xs
227
+ root.rippleYs = ys
228
+ root.rippleAges = ages
229
+ def js:string (EVGEffectTest.jsonOf(root))
230
+ c.has("the document-wide effect is written as it always was" js "\"effect\":{\"kind\":\"ripple\"")
231
+ c.has("with the application's drops on it" js "[40.00,60.00,0.25]")
232
+ ; It is ALSO an instance now — the root is an element like any other,
233
+ ; and a host that reads instances sees it without the page changing.
234
+ c.has("and it is an instance too" js "\"kind\":\"ripple\"")
235
+ }
236
+
237
+ sfn main:void () {
238
+ def c (new FxCheck())
239
+ print "=== EVG element-scoped surface effects ==="
240
+ EVGEffectTest.testDeclared(c)
241
+ EVGEffectTest.testPaintOrder(c)
242
+ EVGEffectTest.testRippleParams(c)
243
+ EVGEffectTest.testSilence(c)
244
+ EVGEffectTest.testLegacy(c)
245
+ print ""
246
+ print ("passed=" + (to_string c.passed) + " failed=" + (to_string c.failed))
247
+ if (c.failed > 0) {
248
+ print "FAILURES"
249
+ } {
250
+ print "ALL PASS"
251
+ }
252
+ }
253
+ }