ranger-compiler 3.5.0 → 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 +1160 -19
  2. package/LICENSE +3 -1
  3. package/README.md +124 -29
  4. package/dist/Lang.rgr +1188 -290
  5. package/dist/api.d.ts +2343 -879
  6. package/dist/api.js +79924 -56922
  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,728 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EVGTransition — the stylesheet's values, arrived at over time
5
+ ; ==============================================================================
6
+ ;
7
+ ; `transition: background-color 150ms` means: when this property's value
8
+ ; changes, do not jump to the new one — leave from where you are and get there
9
+ ; in 150ms. That is the whole feature, and it is worth being precise about the
10
+ ; three things it needs, because a hand-rolled version usually gets the third
11
+ ; one wrong:
12
+ ;
13
+ ; 1. the value the sheet WANTS. That is what `applyTree` already writes.
14
+ ; 2. the value the element is SHOWING. That is what the painter reads, and
15
+ ; while a flight is in the air it is neither end.
16
+ ; 3. where a REVERSAL starts. Not the original value — where the flight had
17
+ ; actually got to. A hover that leaves half way through must fade back
18
+ ; from half way, and starting from the target is the flicker every naive
19
+ ; implementation has.
20
+ ;
21
+ ; So the caller does two things per frame, and they are separate on purpose:
22
+ ;
23
+ ; reconcile(el) after applying the stylesheet: notice what changed, start
24
+ ; or retarget a flight, and put the SHOWING value back.
25
+ ; advance(el dt) move the clock and write the new showing value.
26
+ ;
27
+ ; It reads no clock of its own. A frame is however long the host says it is,
28
+ ; which is what makes every one of these testable to the millisecond and what
29
+ ; lets a PDF backend render frame 7 of an animation without a browser.
30
+ ; ==============================================================================
31
+
32
+ Import "EVGElement.rgr"
33
+ Import "EVGColor.rgr"
34
+ Import "EVGEasing.rgr"
35
+
36
+ ; One entry of the shorthand, resolved for one property.
37
+ class EVGTimingSpec {
38
+ ; False when the property is not mentioned at all — which is a different
39
+ ; answer from "mentioned with a duration of zero", and the two have to stay
40
+ ; distinguishable or `transition: all 200ms, opacity 0s` cannot work.
41
+ def found:boolean false
42
+ def durationMs:double 0.0
43
+ def delayMs:double 0.0
44
+ ; The default really is linear here: an unset `EVGEasing` is
45
+ ; cubic-bezier(0, 0, 1, 1). CSS's own default is `ease`, but that applies
46
+ ; to the shorthand's missing value, not to a missing shorthand.
47
+ def easing:EVGEasing (new EVGEasing())
48
+ def ok:boolean true
49
+
50
+ Constructor () {
51
+ }
52
+ }
53
+
54
+ class EVGTransition {
55
+
56
+ Constructor () {
57
+ }
58
+
59
+ ; --- what the sheet asked for ------------------------------------------------
60
+
61
+ ; The full shorthand, per property:
62
+ ;
63
+ ; transition: background-color 140ms ease-out 40ms, transform 200ms
64
+ ;
65
+ ; Order is the CSS one and it is only half positional: the property name
66
+ ; and the timing function can sit anywhere in an entry, but the two TIMES
67
+ ; are told apart by position — the first is the duration, the second the
68
+ ; delay. There is no other way to distinguish them, which is why
69
+ ; `transition: opacity 200ms` and `transition: opacity 0s 200ms` mean
70
+ ; completely different things.
71
+ ;
72
+ ; The list is scanned to the END rather than returning on the first hit, so
73
+ ; a later entry overrides an earlier one. That is what makes
74
+ ; `transition: all 200ms, opacity 0s` mean "everything but opacity", which
75
+ ; is a real and useful thing to write.
76
+ sfn specFor:EVGTimingSpec (spec:string property:string) {
77
+ def out (new EVGTimingSpec())
78
+ if ((strlen spec) == 0) {
79
+ return out
80
+ }
81
+ ; Splitting on commas has to respect parentheses: `cubic-bezier(0.25,
82
+ ; 0.1, 0.25, 1)` is one token with three commas inside it.
83
+ def parts:[string] (EVGEasing.splitTop(spec 44))
84
+ def i:int 0
85
+ while (i < (array_length parts)) {
86
+ def one:string (trim (itemAt parts i))
87
+ def words:[string] (EVGEasing.splitWordsTop(one))
88
+ def name:string ""
89
+ def fnText:string ""
90
+ def times:[double]
91
+ def w:int 0
92
+ while (w < (array_length words)) {
93
+ def word:string (itemAt words w)
94
+ if (EVGEasing.looksLikeFunction(word)) {
95
+ fnText = word
96
+ } {
97
+ if (EVGTransition.isTime(word)) {
98
+ push times (EVGTransition.parseMs(word))
99
+ } {
100
+ if ((strlen name) == 0) {
101
+ name = word
102
+ }
103
+ }
104
+ }
105
+ w = (w + 1)
106
+ }
107
+ if ((name == property) || (name == "all")) {
108
+ out.found = true
109
+ out.durationMs = 0.0
110
+ out.delayMs = 0.0
111
+ if ((array_length times) > 0) {
112
+ out.durationMs = (itemAt times 0)
113
+ }
114
+ if ((array_length times) > 1) {
115
+ out.delayMs = (itemAt times 1)
116
+ }
117
+ out.easing = (EVGEasing.parse(fnText))
118
+ out.ok = out.easing.ok
119
+ }
120
+ i = (i + 1)
121
+ }
122
+ return out
123
+ }
124
+
125
+ ; Kept because a great deal of code and several tests ask only "how long":
126
+ ; -1 means the property is not transitioned at all, which is a different
127
+ ; answer from 0.
128
+ sfn durationFor:double (spec:string property:string) {
129
+ def s:EVGTimingSpec (EVGTransition.specFor(spec property))
130
+ if (s.found == false) {
131
+ return (0.0 - 1.0)
132
+ }
133
+ return s.durationMs
134
+ }
135
+
136
+ ; A duration, or a property name? `200ms`, `0.15s` and a bare `0` are
137
+ ; times; `opacity` and `background-color` are not. Requiring the numeric
138
+ ; part to parse is what stops a property whose name happens to end in `s`
139
+ ; from being read as a duration.
140
+ sfn isTime:boolean (word:string) {
141
+ def t:string (trim word)
142
+ def n:int (strlen t)
143
+ if (n == 0) {
144
+ return false
145
+ }
146
+ if (n > 2) {
147
+ if ((substring t (n - 2) n) == "ms") {
148
+ def a@(optional):double (to_double (substring t 0 (n - 2)))
149
+ if a { return true }
150
+ return false
151
+ }
152
+ }
153
+ if (n > 1) {
154
+ if ((substring t (n - 1) n) == "s") {
155
+ def b@(optional):double (to_double (substring t 0 (n - 1)))
156
+ if b { return true }
157
+ return false
158
+ }
159
+ }
160
+ def c@(optional):double (to_double t)
161
+ if c { return true }
162
+ return false
163
+ }
164
+
165
+ ; "150ms" or "0.15s". A bare number is milliseconds, which is the reading
166
+ ; that cannot silently be a thousand times wrong.
167
+ sfn parseMs:double (text:string) {
168
+ def t:string (trim text)
169
+ def n:int (strlen t)
170
+ if (n == 0) {
171
+ return 0.0
172
+ }
173
+ if (n > 2) {
174
+ if ((substring t (n - 2) n) == "ms") {
175
+ def v@(optional):double (to_double (substring t 0 (n - 2)))
176
+ if v {
177
+ return (unwrap v)
178
+ }
179
+ return 0.0
180
+ }
181
+ }
182
+ if (n > 1) {
183
+ if ((substring t (n - 1) n) == "s") {
184
+ def v2@(optional):double (to_double (substring t 0 (n - 1)))
185
+ if v2 {
186
+ return ((unwrap v2) * 1000.0)
187
+ }
188
+ return 0.0
189
+ }
190
+ }
191
+ def v3@(optional):double (to_double t)
192
+ if v3 {
193
+ return (unwrap v3)
194
+ }
195
+ return 0.0
196
+ }
197
+
198
+ ; --- the flights on an element -------------------------------------------------
199
+
200
+ fn flightFor@(optional):EVGFlight (el:EVGElement property:string) {
201
+ def i:int 0
202
+ while (i < (array_length el.transitions)) {
203
+ def f:EVGFlight (itemAt el.transitions i)
204
+ if (f.property == property) {
205
+ def hit@(optional):EVGFlight f
206
+ return hit
207
+ }
208
+ i = (i + 1)
209
+ }
210
+ def miss@(optional):EVGFlight
211
+ return miss
212
+ }
213
+
214
+ sfn sameColor:boolean (a:EVGColor b:EVGColor) {
215
+ if ((to_int a.r) != (to_int b.r)) { return false }
216
+ if ((to_int a.g) != (to_int b.g)) { return false }
217
+ if ((to_int a.b) != (to_int b.b)) { return false }
218
+ if ((to_int (a.a * 255.0)) != (to_int (b.a * 255.0))) { return false }
219
+ return true
220
+ }
221
+
222
+ ; Colour interpolation, in PREMULTIPLIED alpha — which is what CSS does and
223
+ ; is not a detail anyone gets to skip.
224
+ ;
225
+ ; `transparent` is rgba(0, 0, 0, 0): a BLACK with no alpha. Mix the four
226
+ ; channels independently and every fade-in from no background at all drags
227
+ ; through a dark grey on its way to the colour — the classic "fade through
228
+ ; black", and it looks like dirt on the screen rather than like a bug.
229
+ ;
230
+ ; Multiplying by alpha first makes the invisible end carry no colour of its
231
+ ; own, so the mix travels along the visible colour and only its opacity
232
+ ; changes. Measured: Chromium fading `transparent` to rgb(244, 241, 254)
233
+ ; reports rgba(244, 241, 254, 0.25) a quarter of the way, not a grey.
234
+ ;
235
+ ; Where both ends are opaque the premultiplication is the identity, so
236
+ ; nothing about the ordinary case changes.
237
+ sfn mixColor:EVGColor (from:EVGColor to:EVGColor t:double) {
238
+ def c (new EVGColor())
239
+ def fa:double from.a
240
+ def ta:double to.a
241
+ def a:double (fa + ((ta - fa) * t))
242
+ def pr:double ((from.r * fa) + (((to.r * ta) - (from.r * fa)) * t))
243
+ def pg:double ((from.g * fa) + (((to.g * ta) - (from.g * fa)) * t))
244
+ def pb:double ((from.b * fa) + (((to.b * ta) - (from.b * fa)) * t))
245
+ if (a > 0.0001) {
246
+ c.r = (pr / a)
247
+ c.g = (pg / a)
248
+ c.b = (pb / a)
249
+ } {
250
+ ; Fully invisible, so there is nothing to divide out. The
251
+ ; premultiplied value is what is left, and it is also what the
252
+ ; browser reports: `transparent` at the very start of a fade comes
253
+ ; back as rgba(0, 0, 0, 0) and not as the destination at zero alpha.
254
+ ; Nothing is painted either way — this is about agreeing on the
255
+ ; number rather than about the picture.
256
+ c.r = pr
257
+ c.g = pg
258
+ c.b = pb
259
+ }
260
+ c.a = a
261
+ c.isSet = true
262
+ return c
263
+ }
264
+
265
+ ; The value the element is SHOWING for a flight at its current progress.
266
+ fn showColor:EVGColor (f:EVGFlight) {
267
+ return (EVGTransition.mixColor((unwrap f.fromColor) (unwrap f.toColor) (f.eased())))
268
+ }
269
+
270
+ fn showNumber:double (f:EVGFlight) {
271
+ return (f.fromNumber + ((f.toNumber - f.fromNumber) * (f.eased())))
272
+ }
273
+
274
+ ; --- reconcile ------------------------------------------------------------------
275
+ ; Called after the stylesheet has written what it wants. The element's field
276
+ ; holds the TARGET; a flight, if there is one, holds where it is actually at.
277
+
278
+ fn reconcile:void (el:EVGElement) {
279
+ if el.backgroundColor {
280
+ this.reconcileColor(el "background-color" (unwrap el.backgroundColor))
281
+ }
282
+ if el.color {
283
+ this.reconcileColor(el "color" (unwrap el.color))
284
+ }
285
+ this.reconcileNumber(el "opacity" el.opacity)
286
+ ; `transform` is one CSS property and four interpolable numbers. They
287
+ ; are kept as separate flights under separate keys but all look the
288
+ ; DECLARED duration up under the name the sheet used, so
289
+ ; `transition: transform 200ms` drives all four and they stay in step.
290
+ ;
291
+ ; Interpolating the composed similarity rather than the function list is
292
+ ; what makes `rotate(0deg) scale(1)` to `rotate(15deg) scale(1.1)` work
293
+ ; without matching the two lists up term by term — which is the part of
294
+ ; CSS transform interpolation that carries all the special cases.
295
+ this.reconcileNumberAs(el "transform.rotate" "transform" el.rotate)
296
+ this.reconcileNumberAs(el "transform.scale" "transform" el.scale)
297
+ this.reconcileNumberAs(el "transform.tx" "transform" el.translateX)
298
+ this.reconcileNumberAs(el "transform.ty" "transform" el.translateY)
299
+ ; `transform-origin` is its own CSS property with its own entry in the
300
+ ; shorthand, and it does animate — measured: 0% 0% to 100% 100% passes
301
+ ; through 25px 10px on a 100x40 box at a quarter of the way.
302
+ this.reconcileOriginAxis(el "transform-origin.x" el.transformOriginX)
303
+ this.reconcileOriginAxis(el "transform-origin.y" el.transformOriginY)
304
+ ; Put the showing values back, so the painter draws the flight and not
305
+ ; the destination.
306
+ this.writeBack(el)
307
+ }
308
+
309
+ fn reconcileColor:void (el:EVGElement property:string target:EVGColor) {
310
+ def spec:EVGTimingSpec (EVGTransition.specFor(el.transitionSpec property))
311
+ if ((spec.found == false) || (spec.durationMs <= 0.0)) {
312
+ ; Not transitioned: the target IS what shows, and any flight for it
313
+ ; is abandoned rather than left to land on a value nobody asked for.
314
+ this.drop(el property)
315
+ return
316
+ }
317
+ if (target.isSet == false) {
318
+ return
319
+ }
320
+ def existing@(optional):EVGFlight (this.flightFor(el property))
321
+ if existing {
322
+ def f:EVGFlight (unwrap existing)
323
+ if (EVGTransition.sameColor((unwrap f.toColor) target)) {
324
+ return
325
+ }
326
+ ; The element still holds what this flight last wrote there, so
327
+ ; nobody has re-declared anything and there is nothing to react to.
328
+ ; See `hasWrote` on EVGFlight for why reading one's own output back
329
+ ; would otherwise stop the animation dead.
330
+ if f.hasWrote {
331
+ if (EVGTransition.sameColor((unwrap f.wroteColor) target)) {
332
+ return
333
+ }
334
+ }
335
+ ; Where the flight has actually got to, which is where anything new
336
+ ; has to leave from. Using the declared start instead is the flicker
337
+ ; every naive implementation has.
338
+ def here:EVGColor (this.showColor(f))
339
+ if (EVGTransition.sameColor(here target)) {
340
+ ; Already there. Landing it now rather than flying a
341
+ ; zero-distance flight matters to the host: `busy()` would
342
+ ; otherwise keep asking for frames to animate nothing.
343
+ f.fromColor = target
344
+ f.toColor = target
345
+ f.elapsedMs = f.durationMs
346
+ return
347
+ }
348
+ if (EVGTransition.sameColor((unwrap f.reversingStartColor) target)) {
349
+ this.reverse(f spec)
350
+ ; The value being turned back towards becomes the thing a
351
+ ; further reversal is measured against.
352
+ f.reversingStartColor = (unwrap f.toColor)
353
+ } {
354
+ f.reversingStartColor = here
355
+ f.reversingFactor = 1.0
356
+ f.durationMs = spec.durationMs
357
+ }
358
+ f.fromColor = here
359
+ f.toColor = target
360
+ f.elapsedMs = 0.0
361
+ f.delayMs = spec.delayMs
362
+ f.easing = spec.easing
363
+ return
364
+ }
365
+ ; The first apply on a fresh element establishes the value rather than
366
+ ; animating to it from black — nothing was on screen to leave from.
367
+ def created (new EVGFlight())
368
+ created.property = property
369
+ created.isColor = true
370
+ created.fromColor = target
371
+ created.toColor = target
372
+ created.reversingStartColor = target
373
+ created.durationMs = spec.durationMs
374
+ created.delayMs = spec.delayMs
375
+ created.easing = spec.easing
376
+ created.elapsedMs = (spec.durationMs + spec.delayMs)
377
+ push el.transitions created
378
+ }
379
+
380
+ ; CSS's rule for turning a transition round, and it is more particular than
381
+ ; "halve what is left".
382
+ ;
383
+ ; The shortening factor is the flight's OUTPUT progress — after the timing
384
+ ; function — not the fraction of the clock that has run. On `ease-in` at the
385
+ ; midpoint those differ by a factor of nearly two: the clock says 0.5 and
386
+ ; the eye says 0.315, and the eye is right, because the eye is what has to
387
+ ; travel back. Measured against Chromium: a 200ms `ease-in` reversed at
388
+ ; 100ms comes back in 63ms, not 100ms.
389
+ ;
390
+ ; And the factor COMPOUNDS rather than replacing. Reversing a reversal makes
391
+ ; the leg longer again, not shorter: 200ms reversed at half way gives 100ms,
392
+ ; and reversing that at a quarter gives 125ms, because the value is now
393
+ ; further from the target than it was. `f * p + (1 - f)` is that arithmetic,
394
+ ; and a fresh flight has f = 1 so the first reversal is simply p.
395
+ ;
396
+ ; The DELAY is not scaled. That is measured too, and it is not obvious:
397
+ ; a reversed `200ms linear 100ms` waits the full 100ms again and then runs
398
+ ; for the shortened 100ms.
399
+ fn reverse:void (f:EVGFlight spec:EVGTimingSpec) {
400
+ def p:double (f.eased())
401
+ def nf:double (fabs ((p * f.reversingFactor) + (1.0 - f.reversingFactor)))
402
+ if (nf < 0.0) { nf = 0.0 }
403
+ if (nf > 1.0) { nf = 1.0 }
404
+ f.reversingFactor = nf
405
+ f.durationMs = (spec.durationMs * nf)
406
+ }
407
+
408
+ fn reconcileNumber:void (el:EVGElement property:string target:double) {
409
+ this.reconcileNumberAs(el property property target)
410
+ }
411
+
412
+ ; `key` names the flight; `cssName` is what the shorthand is searched for.
413
+ ; They differ only where one CSS property animates several numbers.
414
+ fn reconcileNumberAs:void (el:EVGElement key:string cssName:string target:double) {
415
+ def property:string key
416
+ def spec:EVGTimingSpec (EVGTransition.specFor(el.transitionSpec cssName))
417
+ if ((spec.found == false) || (spec.durationMs <= 0.0)) {
418
+ this.drop(el property)
419
+ return
420
+ }
421
+ def existing@(optional):EVGFlight (this.flightFor(el property))
422
+ if existing {
423
+ def f:EVGFlight (unwrap existing)
424
+ if (EVGTransition.sameNumber(f.toNumber target)) {
425
+ return
426
+ }
427
+ ; As above: this is our own showing value coming back, not a new
428
+ ; declaration.
429
+ if f.hasWrote {
430
+ if (EVGTransition.sameNumber(f.wroteNumber target)) {
431
+ return
432
+ }
433
+ }
434
+ def hereN:double (this.showNumber(f))
435
+ if (EVGTransition.sameNumber(hereN target)) {
436
+ f.fromNumber = target
437
+ f.toNumber = target
438
+ f.elapsedMs = f.durationMs
439
+ return
440
+ }
441
+ if (EVGTransition.sameNumber(f.reversingStartNumber target)) {
442
+ this.reverse(f spec)
443
+ f.reversingStartNumber = f.toNumber
444
+ } {
445
+ f.reversingStartNumber = hereN
446
+ f.reversingFactor = 1.0
447
+ f.durationMs = spec.durationMs
448
+ }
449
+ f.fromNumber = hereN
450
+ f.toNumber = target
451
+ f.elapsedMs = 0.0
452
+ f.delayMs = spec.delayMs
453
+ f.easing = spec.easing
454
+ return
455
+ }
456
+ def created (new EVGFlight())
457
+ created.property = property
458
+ created.isColor = false
459
+ created.fromNumber = target
460
+ created.toNumber = target
461
+ created.reversingStartNumber = target
462
+ created.durationMs = spec.durationMs
463
+ created.delayMs = spec.delayMs
464
+ created.easing = spec.easing
465
+ created.elapsedMs = (spec.durationMs + spec.delayMs)
466
+ push el.transitions created
467
+ }
468
+
469
+ sfn unitOf:EVGUnit (code:int value:double) {
470
+ def u (new EVGUnit())
471
+ u.unitType = code
472
+ u.value = value
473
+ u.pixels = value
474
+ u.isSet = true
475
+ return u
476
+ }
477
+
478
+ ; A thousandth is the resolution everything numeric here is compared at:
479
+ ; finer and floating point noise reads as a change worth animating.
480
+ sfn sameNumber:boolean (a:double b:double) {
481
+ return ((fabs (a - b)) < 0.001)
482
+ }
483
+
484
+ ; One axis of `transform-origin`.
485
+ ;
486
+ ; Separate from the plain number path because of the unit. The value is
487
+ ; kept as WRITTEN — a percentage stays a percentage — since the box it
488
+ ; resolves against is not known until the display list is built, and
489
+ ; resolving a frame early would use the previous layout's size. Two
490
+ ; percentages interpolate as percentages, two lengths as lengths, and both
491
+ ; give what the browser gives.
492
+ ;
493
+ ; A change of unit mid-flight is the case that cannot be interpolated
494
+ ; meaningfully, and it JUMPS rather than sliding through numbers that mean
495
+ ; nothing. CSS blends the resolved lengths there; nobody writes it, and
496
+ ; guessing quietly would be worse than the jump.
497
+ fn reconcileOriginAxis:void (el:EVGElement key:string u:EVGUnit) {
498
+ ; Unset is 50%, the same default the display list resolves — so an
499
+ ; element moving from no origin to `0%` travels from the centre, which
500
+ ; is where it visibly was.
501
+ def code:int 1
502
+ def target:double 50.0
503
+ if u.isSet {
504
+ code = u.unitType
505
+ target = u.value
506
+ }
507
+ def existing@(optional):EVGFlight (this.flightFor(el key))
508
+ if existing {
509
+ def f:EVGFlight (unwrap existing)
510
+ if (f.unitCode != code) {
511
+ this.drop(el key)
512
+ }
513
+ }
514
+ this.reconcileNumberAs(el key "transform-origin" target)
515
+ def now@(optional):EVGFlight (this.flightFor(el key))
516
+ if now {
517
+ def f2:EVGFlight (unwrap now)
518
+ f2.unitCode = code
519
+ }
520
+ }
521
+
522
+ ; Remove the flight for one property, if there is one.
523
+ ;
524
+ ; The EARLY RETURN is the whole of this. `reconcileTree` calls `drop` for
525
+ ; every animatable property of every element on the way past, and almost
526
+ ; none of them has a flight in progress: the list is empty or holds
527
+ ; something else. Rebuilding it regardless allocated one array per call,
528
+ ; which put this among the most expensive functions in a scroll frame of
529
+ ; `gallery/realtrainer` — 5.8% of it, to remove nothing from nothing.
530
+ fn drop:void (el:EVGElement property:string) {
531
+ def found:boolean false
532
+ def n:int 0
533
+ while (n < (array_length el.transitions)) {
534
+ def fn0:EVGFlight (itemAt el.transitions n)
535
+ if (fn0.property == property) {
536
+ found = true
537
+ }
538
+ n = (n + 1)
539
+ }
540
+ if (found == false) {
541
+ return
542
+ }
543
+ def kept:[EVGFlight]
544
+ def i:int 0
545
+ while (i < (array_length el.transitions)) {
546
+ def f:EVGFlight (itemAt el.transitions i)
547
+ if (f.property != property) {
548
+ push kept f
549
+ }
550
+ i = (i + 1)
551
+ }
552
+ clear el.transitions
553
+ def j:int 0
554
+ while (j < (array_length kept)) {
555
+ push el.transitions (itemAt kept j)
556
+ j = (j + 1)
557
+ }
558
+ }
559
+
560
+ ; --- advance ---------------------------------------------------------------------
561
+
562
+ fn advance:void (el:EVGElement dtMs:double) {
563
+ def i:int 0
564
+ while (i < (array_length el.transitions)) {
565
+ def f:EVGFlight (itemAt el.transitions i)
566
+ if ((f.done()) == false) {
567
+ f.elapsedMs = (f.elapsedMs + dtMs)
568
+ def endsAt:double (f.delayMs + f.durationMs)
569
+ if (f.elapsedMs > endsAt) {
570
+ f.elapsedMs = endsAt
571
+ }
572
+ }
573
+ i = (i + 1)
574
+ }
575
+ this.writeBack(el)
576
+ }
577
+
578
+ ; The showing values, into the fields the painter reads. This is the one
579
+ ; place a flight touches the element, and it happens after both reconcile
580
+ ; and advance so the two cannot disagree about what is on screen.
581
+ fn writeBack:void (el:EVGElement) {
582
+ ; An element with a flight in it no longer holds what the sheet
583
+ ; declared — it holds where the flight has got to — so the sheet is
584
+ ; told to re-declare rather than skip it next frame.
585
+ ;
586
+ ; ONLY when there is a flight. The first version said it
587
+ ; unconditionally, and `reconcile` calls this for every element in the
588
+ ; tree, so every element was invalidated every frame and the skip never
589
+ ; fired at all on any page that uses transitions — which is every page
590
+ ; here. The benchmark did not notice, because it runs no transitions;
591
+ ; `testSkipSurvivesTransitions` is what notices.
592
+ ;
593
+ ; Strictly this is belt and braces: `EVGFlight.hasWrote` already lets
594
+ ; `reconcile` recognise its own output and carry on. Kept because the
595
+ ; elements with flights are few and reasoning about that guard is not
596
+ ; something the next reader should have to redo.
597
+ def moving:boolean false
598
+ def i:int 0
599
+ while (i < (array_length el.transitions)) {
600
+ def f:EVGFlight (itemAt el.transitions i)
601
+ if ((f.done()) == false) {
602
+ moving = true
603
+ }
604
+ if (f.isColor) {
605
+ def c:EVGColor (this.showColor(f))
606
+ f.wroteColor = c
607
+ f.hasWrote = true
608
+ if (f.property == "background-color") {
609
+ el.backgroundColor = c
610
+ }
611
+ if (f.property == "color") {
612
+ el.color = c
613
+ }
614
+ } {
615
+ def n:double (this.showNumber(f))
616
+ f.wroteNumber = n
617
+ f.hasWrote = true
618
+ if (f.property == "opacity") {
619
+ el.opacity = n
620
+ }
621
+ if (f.property == "transform.rotate") {
622
+ el.rotate = n
623
+ }
624
+ if (f.property == "transform.scale") {
625
+ el.scale = n
626
+ }
627
+ if (f.property == "transform.tx") {
628
+ el.translateX = n
629
+ }
630
+ if (f.property == "transform.ty") {
631
+ el.translateY = n
632
+ }
633
+ if (f.property == "transform-origin.x") {
634
+ el.transformOriginX = (EVGTransition.unitOf(f.unitCode n))
635
+ }
636
+ if (f.property == "transform-origin.y") {
637
+ el.transformOriginY = (EVGTransition.unitOf(f.unitCode n))
638
+ }
639
+ }
640
+ i = (i + 1)
641
+ }
642
+ ; An element with a flight STILL IN THE AIR no longer holds what the
643
+ ; sheet declared — it holds where the flight has got to — so the sheet
644
+ ; is told to re-declare rather than skip it next frame.
645
+ ;
646
+ ; Only while it is MOVING. Two earlier versions were wrong in the same
647
+ ; direction: unconditional, so `reconcile` (which runs on every element)
648
+ ; made the whole tree stale every frame and nothing was ever skipped;
649
+ ; then "has any flight", which kept every element that has ever
650
+ ; transitioned stale forever, because a finished flight stays in the
651
+ ; list. A benchmark could see neither, because it runs no transitions —
652
+ ; `testSkipSurvivesTransitions` is what does.
653
+ ;
654
+ ; On the frame a flight LANDS this correctly does nothing: `writeBack`
655
+ ; has just written the target, which is what the sheet would write.
656
+ ;
657
+ ; And it is belt and braces rather than load-bearing. Removing it
658
+ ; entirely passes every test, because `EVGFlight.hasWrote` already lets
659
+ ; `reconcile` recognise its own output and carry on — that mutation was
660
+ ; run and survived. It stays because the elements it touches are the few
661
+ ; that are moving, and because the next person to change `hasWrote`
662
+ ; should not have to rediscover that it is holding this up.
663
+ if moving {
664
+ el.styleGen = (0 - 1)
665
+ }
666
+ }
667
+
668
+ ; --- whole trees -------------------------------------------------------------------
669
+
670
+ fn reconcileTree:void (root:EVGElement) {
671
+ this.reconcile(root)
672
+ def i:int 0
673
+ while (i < (array_length root.children)) {
674
+ this.reconcileTree((itemAt root.children i))
675
+ i = (i + 1)
676
+ }
677
+ }
678
+
679
+ ; …and says whether anything under `root` is in flight. A subtree with
680
+ ; a flight in it is being painted differently every frame, and its
681
+ ; `paintStamp` is moved on to say so: a display list keeping what it
682
+ ; drew for the subtree (`EVGDisplayList.emitFragment`) then draws it
683
+ ; afresh, and every subtree with no flight in it keeps what it had.
684
+ fn advanceTree:boolean (root:EVGElement dtMs:double) {
685
+ this.advance(root dtMs)
686
+ def any@(mutable):boolean false
687
+ def f:int 0
688
+ while (f < (array_length root.transitions)) {
689
+ def flight:EVGFlight (itemAt root.transitions f)
690
+ if ((flight.done()) == false) {
691
+ any = true
692
+ }
693
+ f = (f + 1)
694
+ }
695
+ def i:int 0
696
+ while (i < (array_length root.children)) {
697
+ if (this.advanceTree((itemAt root.children i) dtMs)) {
698
+ any = true
699
+ }
700
+ i = (i + 1)
701
+ }
702
+ if any {
703
+ root.paintStamp = (root.paintStamp + 1)
704
+ }
705
+ return any
706
+ }
707
+
708
+ ; Is anything still moving? A host that repaints on demand asks this to
709
+ ; know whether it needs another frame.
710
+ fn busy:boolean (root:EVGElement) {
711
+ def i:int 0
712
+ while (i < (array_length root.transitions)) {
713
+ def f:EVGFlight (itemAt root.transitions i)
714
+ if ((f.done()) == false) {
715
+ return true
716
+ }
717
+ i = (i + 1)
718
+ }
719
+ def j:int 0
720
+ while (j < (array_length root.children)) {
721
+ if (this.busy((itemAt root.children j))) {
722
+ return true
723
+ }
724
+ j = (j + 1)
725
+ }
726
+ return false
727
+ }
728
+ }