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,225 @@
1
+ // SPDX-License-Identifier: MIT
2
+ //
3
+ // The walk: an `EVGDisplayList` in, calls on an `EvgSurface` out.
4
+ //
5
+ // Android and Apple differ in how they fill a rounded box, not in what a
6
+ // command *means*, so what a command means is decided exactly once — here —
7
+ // and this file is a transliteration of `lib/evg/android`'s `EvgPainter`
8
+ // rather than a second reading of the format. Where the two disagree, one of
9
+ // them is wrong.
10
+ //
11
+ // Two things this painter honours that a JSON-fed backend cannot:
12
+ //
13
+ // * **Gradients and shadows.** `EVGDisplayList.toJson` carries neither, so a
14
+ // browser host cannot draw them. Reading the objects directly — which is
15
+ // what a Swift host can do — brings both back.
16
+ // * **Clipping and multi-ring paths.** `save`/`clipRect`/`restore` and a real
17
+ // even-odd fill are one line each on CoreGraphics.
18
+
19
+ import CoreGraphics
20
+
21
+ enum EvgPainter {
22
+
23
+ private static let RECT = 0
24
+ private static let BORDER = 1
25
+ private static let IMAGE = 2
26
+ private static let TEXT = 3
27
+ private static let PUSH_CLIP = 4
28
+ private static let POP_CLIP = 5
29
+ private static let PATH = 6
30
+ private static let STROKE = 7
31
+
32
+ /// Anything below this is invisible; drawing it is work for nothing.
33
+ private static let MIN_ALPHA = 0.001
34
+
35
+ /// Paint every command in order. Answers how many were actually drawn,
36
+ /// which is what a host puts in a debug overlay — a frame that draws 0 of
37
+ /// 350 commands is a bug you want to see rather than a black screen.
38
+ @discardableResult
39
+ static func paint(_ list: EVGDisplayList, into surface: EvgSurface) -> Int {
40
+ var drawn = 0
41
+ // A list that pushes more clips than it pops must not leave the surface
42
+ // with a clip nobody asked for, and one that pops more than it pushes
43
+ // must not restore past the state the host handed us. The depth counter
44
+ // is the whole of both guarantees.
45
+ var clipDepth = 0
46
+ let n = list.count()
47
+ var i = 0
48
+ while i < n {
49
+ let c = list.at(i: i)
50
+ i += 1
51
+
52
+ if c.kind == PUSH_CLIP {
53
+ surface.save()
54
+ surface.clipRect(
55
+ x: CGFloat(c.x), y: CGFloat(c.y),
56
+ w: CGFloat(c.w), h: CGFloat(c.h)
57
+ )
58
+ clipDepth += 1
59
+ continue
60
+ }
61
+ if c.kind == POP_CLIP {
62
+ if clipDepth > 0 {
63
+ surface.restore()
64
+ clipDepth -= 1
65
+ }
66
+ continue
67
+ }
68
+
69
+ // A rotation turns the command about the point the display list
70
+ // names, and about the command's own box centre only when it names
71
+ // none. `EVGDisplayList` resolves `transform-origin` into
72
+ // rotOriginX/Y and sets hasRotOrigin, exactly because the centre is
73
+ // "right for a lone rotated label and wrong for everything else: a
74
+ // box, its text and its children have to turn about ONE point or
75
+ // they come apart".
76
+ //
77
+ // Ignoring it is what made RealTrainer's loading spinner a single
78
+ // small bar. Its twelve blades are one 8x26 box each, fanned into a
79
+ // ring by `transform: rotate(Ndeg)` about `transform-origin: 4px
80
+ // 54px` -- a point 41px BELOW each blade's own centre. Turned about
81
+ // their centres they all spin in place and land on top of each
82
+ // other. Wrapping it in save/restore keeps the clip stack above
83
+ // untouched.
84
+ let turned = c.rotate > 0.001 || c.rotate < -0.001
85
+ if turned {
86
+ surface.save()
87
+ surface.rotate(
88
+ degrees: CGFloat(c.rotate),
89
+ px: c.hasRotOrigin ? CGFloat(c.rotOriginX) : CGFloat(c.x + c.w * 0.5),
90
+ py: c.hasRotOrigin ? CGFloat(c.rotOriginY) : CGFloat(c.y + c.h * 0.5)
91
+ )
92
+ }
93
+
94
+ if drawOne(c, surface) { drawn += 1 }
95
+
96
+ if turned { surface.restore() }
97
+ }
98
+ while clipDepth > 0 {
99
+ surface.restore()
100
+ clipDepth -= 1
101
+ }
102
+ return drawn
103
+ }
104
+
105
+ private static func drawOne(_ c: EVGDrawCmd, _ surface: EvgSurface) -> Bool {
106
+ switch c.kind {
107
+ case RECT:
108
+ let shadow = shadowOf(c)
109
+ let gradient = gradientOf(c)
110
+ if c.a < MIN_ALPHA && gradient == nil && shadow == nil { return false }
111
+ surface.fillRect(
112
+ x: CGFloat(c.x), y: CGFloat(c.y), w: CGFloat(c.w), h: CGFloat(c.h),
113
+ radius: CGFloat(c.radius),
114
+ color: colorOf(c),
115
+ gradient: gradient,
116
+ shadow: shadow
117
+ )
118
+ return true
119
+
120
+ case BORDER:
121
+ if c.a < MIN_ALPHA { return false }
122
+ // A border with no thickness is still a border: the display list
123
+ // leaves the default at 0 for a hairline, and a stroke of width 0
124
+ // is invisible.
125
+ let t = c.thickness > 0.0 ? CGFloat(c.thickness) : 1.0
126
+ surface.strokeRect(
127
+ x: CGFloat(c.x), y: CGFloat(c.y), w: CGFloat(c.w), h: CGFloat(c.h),
128
+ radius: CGFloat(c.radius), thickness: t,
129
+ color: colorOf(c)
130
+ )
131
+ return true
132
+
133
+ case IMAGE:
134
+ if c.src.isEmpty { return false }
135
+ surface.drawImage(
136
+ src: c.src,
137
+ x: CGFloat(c.x), y: CGFloat(c.y), w: CGFloat(c.w), h: CGFloat(c.h),
138
+ radius: CGFloat(c.radius),
139
+ flipH: c.flipH, flipV: c.flipV
140
+ )
141
+ return true
142
+
143
+ case TEXT:
144
+ if c.text.isEmpty { return false }
145
+ if c.a < MIN_ALPHA { return false }
146
+ surface.drawTextRun(
147
+ text: c.text,
148
+ x: CGFloat(c.x), top: CGFloat(c.y),
149
+ sizePx: CGFloat(c.fontSize),
150
+ family: c.fontFamily,
151
+ bold: isBold(c.fontWeight),
152
+ // `addText` has nowhere else to record a slanted face, so it
153
+ // writes "italic" into textAlign and `toJson` reads it back out
154
+ // the same way. Not lovely, but it is the format.
155
+ italic: c.textAlign == "italic",
156
+ color: colorOf(c)
157
+ )
158
+ return true
159
+
160
+ case PATH:
161
+ if c.a < MIN_ALPHA { return false }
162
+ if c.pts.count < 6 { return false }
163
+ surface.fillPath(
164
+ pts: c.pts, ringEnds: ringsOf(c), evenOdd: c.evenOdd,
165
+ color: colorOf(c), shadow: shadowOf(c)
166
+ )
167
+ return true
168
+
169
+ case STROKE:
170
+ if c.a < MIN_ALPHA { return false }
171
+ if c.pts.count < 4 { return false }
172
+ let t = c.thickness > 0.0 ? CGFloat(c.thickness) : 1.0
173
+ surface.strokePath(
174
+ pts: c.pts, ringEnds: ringsOf(c), thickness: t, color: colorOf(c)
175
+ )
176
+ return true
177
+
178
+ default:
179
+ return false
180
+ }
181
+ }
182
+
183
+ /// A path emitted by the SVG walk carries its ring boundaries; one emitted
184
+ /// by `addPolygon` / `addPolyline` may not. A single implicit ring covering
185
+ /// every point is the right reading of an empty `ringEnds` — it is what the
186
+ /// polygon filler assumes.
187
+ private static func ringsOf(_ c: EVGDrawCmd) -> [Int] {
188
+ c.ringEnds.isEmpty ? [c.pts.count] : c.ringEnds
189
+ }
190
+
191
+ private static func gradientOf(_ c: EVGDrawCmd) -> EvgGradient? {
192
+ if !c.hasGrad { return nil }
193
+ return EvgGradient(
194
+ color1: EvgColor(r: c.r, g: c.g, b: c.b, a: c.a),
195
+ color2: EvgColor(r: c.r2, g: c.g2, b: c.b2, a: c.a2),
196
+ // dir 0 = vertical (top to bottom), 1 = horizontal (left to right)
197
+ vertical: c.gradDir != 1
198
+ )
199
+ }
200
+
201
+ private static func shadowOf(_ c: EVGDrawCmd) -> EvgShadow? {
202
+ if !c.hasShadow { return nil }
203
+ if c.shadowA < MIN_ALPHA { return nil }
204
+ return EvgShadow(
205
+ dx: CGFloat(c.shadowX),
206
+ dy: CGFloat(c.shadowY),
207
+ blur: CGFloat(c.shadowBlur),
208
+ color: EvgColor(r: c.shadowR, g: c.shadowG, b: c.shadowB, a: c.shadowA)
209
+ )
210
+ }
211
+
212
+ private static func colorOf(_ c: EVGDrawCmd) -> EvgColor {
213
+ EvgColor(r: c.r, g: c.g, b: c.b, a: c.a)
214
+ }
215
+
216
+ /// The display list writes the word, not the number — `addText` only ever
217
+ /// says "bold" — but a stylesheet path could put a CSS weight here, so a
218
+ /// number is read as one.
219
+ static func isBold(_ weight: String) -> Bool {
220
+ if weight.isEmpty { return false }
221
+ if weight == "bold" || weight == "bolder" { return true }
222
+ guard let n = Int(weight) else { return false }
223
+ return n >= 600
224
+ }
225
+ }
@@ -0,0 +1,163 @@
1
+ // SPDX-License-Identifier: MIT
2
+ //
3
+ // Everything a backend has to be able to draw, and nothing else.
4
+ //
5
+ // `EVGDisplayList` is eight command kinds of absolute pixels and resolved
6
+ // colours — no tree, no units, no fonts to resolve. That is small enough that a
7
+ // backend is a page of delegation rather than a renderer, which is the point:
8
+ // `CoreGraphicsEvgSurface` paints with a `CGContext` (so a `UIView` on iOS and
9
+ // a SwiftUI `Canvas` on watchOS share one implementation), `RecordingSurface`
10
+ // counts what was dispatched without drawing anything, and the walk that
11
+ // decides what each command *means* — `EvgPainter` — is written once.
12
+ //
13
+ // This is the Apple sibling of `lib/evg/android`, and the interface is
14
+ // deliberately the same one: a port that diverges here would make the two
15
+ // painters two programs to keep in step rather than one idea with two
16
+ // backends.
17
+ //
18
+ // Geometry is in the app's own points. A host that wants device pixels scales
19
+ // its context and leaves these numbers alone — text then rasterises at the
20
+ // panel's real resolution instead of being blown up from a bitmap made at some
21
+ // other size.
22
+
23
+ import CoreGraphics
24
+
25
+ /// A colour as the display list carries it: 0-255 channels and a 0-1 alpha.
26
+ struct EvgColor {
27
+ let r: Int
28
+ let g: Int
29
+ let b: Int
30
+ let a: Double
31
+
32
+ init(r: Int, g: Int, b: Int, a: Double) {
33
+ self.r = r
34
+ self.g = g
35
+ self.b = b
36
+ self.a = a
37
+ }
38
+
39
+ private static func clamp255(_ v: Int) -> CGFloat {
40
+ if v < 0 { return 0 }
41
+ if v > 255 { return 1 }
42
+ return CGFloat(v) / 255.0
43
+ }
44
+
45
+ var cgColor: CGColor {
46
+ let alpha = a < 0 ? 0 : (a > 1 ? 1 : a)
47
+ return CGColor(
48
+ srgbRed: EvgColor.clamp255(r),
49
+ green: EvgColor.clamp255(g),
50
+ blue: EvgColor.clamp255(b),
51
+ alpha: CGFloat(alpha)
52
+ )
53
+ }
54
+
55
+ /// The same colour with the alpha replaced, for a shadow that carries its
56
+ /// own.
57
+ func withAlpha(_ alpha: Double) -> EvgColor {
58
+ EvgColor(r: r, g: g, b: b, a: alpha)
59
+ }
60
+ }
61
+
62
+ /// A two-stop linear gradient. `vertical` is EVG's `gradDir == 0`.
63
+ struct EvgGradient {
64
+ let color1: EvgColor
65
+ let color2: EvgColor
66
+ let vertical: Bool
67
+
68
+ init(color1: EvgColor, color2: EvgColor, vertical: Bool) {
69
+ self.color1 = color1
70
+ self.color2 = color2
71
+ self.vertical = vertical
72
+ }
73
+ }
74
+
75
+ /// An outer drop shadow: offset, blur radius, colour.
76
+ struct EvgShadow {
77
+ let dx: CGFloat
78
+ let dy: CGFloat
79
+ let blur: CGFloat
80
+ let color: EvgColor
81
+
82
+ init(dx: CGFloat, dy: CGFloat, blur: CGFloat, color: EvgColor) {
83
+ self.dx = dx
84
+ self.dy = dy
85
+ self.blur = blur
86
+ self.color = color
87
+ }
88
+ }
89
+
90
+ protocol EvgSurface: AnyObject {
91
+
92
+ /// Push the clip/transform stack. Paired with `restore`.
93
+ func save()
94
+
95
+ /// Pop back to the state the matching `save` recorded.
96
+ func restore()
97
+
98
+ /// Intersect the clip with this rectangle. Only ever inside a `save`.
99
+ func clipRect(x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat)
100
+
101
+ /// Turn the coordinate system `degrees` about (`px`, `py`).
102
+ func rotate(degrees: CGFloat, px: CGFloat, py: CGFloat)
103
+
104
+ /// A filled box, possibly rounded, possibly a two-stop gradient, possibly
105
+ /// under a drop shadow. The shadow is painted first and is the shape's own
106
+ /// silhouette — a rounded box casts a rounded shadow.
107
+ func fillRect(
108
+ x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat,
109
+ radius: CGFloat,
110
+ color: EvgColor,
111
+ gradient: EvgGradient?,
112
+ shadow: EvgShadow?
113
+ )
114
+
115
+ /// A stroked outline, drawn as a band of `thickness` INSIDE the box.
116
+ func strokeRect(
117
+ x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat,
118
+ radius: CGFloat, thickness: CGFloat,
119
+ color: EvgColor
120
+ )
121
+
122
+ /// A filled vector outline. The rings are already flattened and already in
123
+ /// page coordinates; `ringEnds` gives the index in `pts` one past each
124
+ /// ring's last coordinate, so a shape with a hole arrives as two rings.
125
+ func fillPath(
126
+ pts: [Double], ringEnds: [Int], evenOdd: Bool,
127
+ color: EvgColor,
128
+ shadow: EvgShadow?
129
+ )
130
+
131
+ /// The same rings, stroked rather than filled.
132
+ func strokePath(
133
+ pts: [Double], ringEnds: [Int],
134
+ thickness: CGFloat,
135
+ color: EvgColor
136
+ )
137
+
138
+ /// A picture, by the name the page gave it. A surface that has no bytes for
139
+ /// `src` should draw the placeholder rather than nothing — a missing
140
+ /// texture and a blank card look identical otherwise.
141
+ func drawImage(
142
+ src: String,
143
+ x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat,
144
+ radius: CGFloat,
145
+ flipH: Bool, flipV: Bool
146
+ )
147
+
148
+ /// One run, on one line, in one face.
149
+ ///
150
+ /// `top` is the top of the LINE BOX, not the baseline: EVG measured the run
151
+ /// with its own width estimate and the baseline sits one face-ascent below.
152
+ /// Placing the ink at `top` instead lifts every run by the empty space
153
+ /// above its capitals — a couple of points on a caption, most of a line on
154
+ /// a heading. The surface owns that conversion because only it knows what
155
+ /// its own font metrics say.
156
+ func drawTextRun(
157
+ text: String,
158
+ x: CGFloat, top: CGFloat,
159
+ sizePx: CGFloat,
160
+ family: String, bold: Bool, italic: Bool,
161
+ color: EvgColor
162
+ )
163
+ }
@@ -0,0 +1,110 @@
1
+ // SPDX-License-Identifier: MIT
2
+ //
3
+ // A surface that draws nothing and counts everything.
4
+ //
5
+ // Wrap a real surface in one of these and the frame is painted exactly as it
6
+ // would be, with a tally of what was dispatched on the other side. "Some ink
7
+ // appeared" is a weak check — a painter that had quietly stopped drawing text
8
+ // would pass it — so a check asserts the counts instead: this page reaches
9
+ // text, filled boxes, borders, rounded corners, clipping, a filled path and
10
+ // stroked paths, and every `save` is matched by a `restore`.
11
+ //
12
+ // The Ranger side of this port counts the same things one step earlier, on the
13
+ // display list itself (`gallery/ui/ios/ranger/check_ios.rgr`), because that can
14
+ // run without a Mac. This is for the half that cannot: it says whether the
15
+ // PAINTER dispatched them, not merely whether the page produced them.
16
+
17
+ import CoreGraphics
18
+
19
+ final class RecordingSurface: EvgSurface {
20
+
21
+ private(set) var calls: [String: Int] = [:]
22
+ private let inner: EvgSurface?
23
+
24
+ init(wrapping inner: EvgSurface? = nil) {
25
+ self.inner = inner
26
+ }
27
+
28
+ func count(_ kind: String) -> Int {
29
+ calls[kind] ?? 0
30
+ }
31
+
32
+ private func note(_ kind: String) {
33
+ calls[kind, default: 0] += 1
34
+ }
35
+
36
+ var summary: String {
37
+ calls.keys.sorted().map { "\($0)=\(calls[$0]!)" }.joined(separator: " ")
38
+ }
39
+
40
+ func save() {
41
+ note("save")
42
+ inner?.save()
43
+ }
44
+
45
+ func restore() {
46
+ note("restore")
47
+ inner?.restore()
48
+ }
49
+
50
+ func clipRect(x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat) {
51
+ note("clipRect")
52
+ inner?.clipRect(x: x, y: y, w: w, h: h)
53
+ }
54
+
55
+ func rotate(degrees: CGFloat, px: CGFloat, py: CGFloat) {
56
+ note("rotate")
57
+ inner?.rotate(degrees: degrees, px: px, py: py)
58
+ }
59
+
60
+ func fillRect(
61
+ x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat,
62
+ radius: CGFloat, color: EvgColor,
63
+ gradient: EvgGradient?, shadow: EvgShadow?
64
+ ) {
65
+ note("fillRect")
66
+ if radius > 0 { note("roundedRect") }
67
+ if gradient != nil { note("gradient") }
68
+ if shadow != nil { note("shadow") }
69
+ inner?.fillRect(x: x, y: y, w: w, h: h, radius: radius, color: color, gradient: gradient, shadow: shadow)
70
+ }
71
+
72
+ func strokeRect(
73
+ x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat,
74
+ radius: CGFloat, thickness: CGFloat, color: EvgColor
75
+ ) {
76
+ note("strokeRect")
77
+ inner?.strokeRect(x: x, y: y, w: w, h: h, radius: radius, thickness: thickness, color: color)
78
+ }
79
+
80
+ func fillPath(
81
+ pts: [Double], ringEnds: [Int], evenOdd: Bool,
82
+ color: EvgColor, shadow: EvgShadow?
83
+ ) {
84
+ note("fillPath")
85
+ if shadow != nil { note("shadow") }
86
+ inner?.fillPath(pts: pts, ringEnds: ringEnds, evenOdd: evenOdd, color: color, shadow: shadow)
87
+ }
88
+
89
+ func strokePath(pts: [Double], ringEnds: [Int], thickness: CGFloat, color: EvgColor) {
90
+ note("strokePath")
91
+ inner?.strokePath(pts: pts, ringEnds: ringEnds, thickness: thickness, color: color)
92
+ }
93
+
94
+ func drawImage(
95
+ src: String, x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat,
96
+ radius: CGFloat, flipH: Bool, flipV: Bool
97
+ ) {
98
+ note("drawImage")
99
+ inner?.drawImage(src: src, x: x, y: y, w: w, h: h, radius: radius, flipH: flipH, flipV: flipV)
100
+ }
101
+
102
+ func drawTextRun(
103
+ text: String, x: CGFloat, top: CGFloat, sizePx: CGFloat,
104
+ family: String, bold: Bool, italic: Bool, color: EvgColor
105
+ ) {
106
+ note("drawTextRun")
107
+ if italic { note("italicText") }
108
+ inner?.drawTextRun(text: text, x: x, top: top, sizePx: sizePx, family: family, bold: bold, italic: italic, color: color)
109
+ }
110
+ }
@@ -0,0 +1,34 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EvgLayoutBench — the layout engine, exported so a harness can drive it
5
+ ; ==============================================================================
6
+ ; The benchmark and the conformance probe beside this file are JavaScript,
7
+ ; because the other side of both comparisons is a browser and the case list has
8
+ ; to be written once. This module exists only so `-nodemodule` publishes the
9
+ ; engine's classes: the harness builds `EVGElement` trees itself, calls
10
+ ; `setAttribute` with CSS property names, and reads `calculated*` back.
11
+ ;
12
+ ; Nothing here is part of the engine. The one function is the count a harness
13
+ ; would otherwise have to re-derive, and it is here rather than in JS so the
14
+ ; tree walk is the engine's own.
15
+ ; ==============================================================================
16
+
17
+ Import "../EVGElement.rgr"
18
+ Import "../EVGUnit.rgr"
19
+ Import "../EVGLayout.rgr"
20
+ Import "../EVGDisplayList.rgr"
21
+
22
+ class EvgLayoutBench {
23
+
24
+ sfn countElements:int (el:EVGElement) {
25
+ def n:int 1
26
+ def i:int 0
27
+ while (i < (array_length el.children)) {
28
+ def kid:EVGElement (itemAt el.children i)
29
+ n = (n + (EvgLayoutBench.countElements(kid)))
30
+ i = (i + 1)
31
+ }
32
+ return n
33
+ }
34
+ }
@@ -0,0 +1,64 @@
1
+ # `bench/` — the same CSS, two engines
2
+
3
+ Two harnesses. Both drive the compiled engine from JavaScript, which is worth
4
+ saying on its own: `-nodemodule` publishes `EVGElement`, `EVGLayout` and the
5
+ rest, so a tree is `new EVGElement()`, `setAttribute` with CSS property names,
6
+ `addChild`, `layout()` — no Ranger, no JSX, no stylesheet in the way.
7
+
8
+ ```sh
9
+ npm run evg:layout:conformance # box for box against Chromium
10
+ npm run evg:layout:bench # 1k / 10k / 100k, three fixtures
11
+ ```
12
+
13
+ ## `layout-conformance.mjs` — where an EVG document and its CSS disagree
14
+
15
+ The cases in `layout-cases.mjs` are written ONCE, as CSS text. The runner
16
+ splits that text into `setAttribute` calls for EVG and drops it verbatim into a
17
+ `style=` attribute for Chromium, so a differing box is a difference between the
18
+ engines and not between two transcriptions of the same intent.
19
+
20
+ This is a measurement, not a test suite: Chromium is the definition of what the
21
+ CSS says, and a case that differs names a place where a document written as CSS
22
+ does not lay out as CSS. The report separates the deliberate divergences —
23
+ EVG's initial values for `flex-direction`, `flex-wrap` and `align-items`, which
24
+ are documented choices — from the rest, and says for each whether **the engine
25
+ said anything about it**. That last column is the one that mattered: of the
26
+ nineteen divergences the first run found, eighteen were silent.
27
+
28
+ The three text cases are not compared pixel for pixel. EVG's default measurer
29
+ is a heuristic and the browser's is a real face, so a diff there would measure
30
+ the fixture; what is asserted instead is that text participates in layout at
31
+ all. Font parity has its own suite (`evg:measure:web`, the textbox oracle).
32
+
33
+ ## `layout-bench.mjs` — what it costs at size
34
+
35
+ Three fixtures, because "layout" is not one cost: nested flex (an application
36
+ UI's shape, four levels), a wide flat grid (track sizing at size), and the flex
37
+ fixture with text in it. Sizes 1k / 10k / 100k. `layout` is a RE-layout of a
38
+ tree that already exists — what a resize costs, not what a first paint does.
39
+
40
+ Chromium is timed on the same tree with a forced reflow. Read it as an
41
+ order-of-magnitude reference for a production C++ layout engine on the same
42
+ boxes, not a like-for-like race: the browser is doing line layout and paint
43
+ invalidation that this pass is not, and it is not paying for a heuristic text
44
+ measurer either.
45
+
46
+ `--ab` builds a second copy of the engine from the pre-change sources
47
+ (`EvgLayoutBenchBase.cjs`, compiled from a `git archive` of the tree you are
48
+ comparing against) and alternates the two inside one process, best-of-runs with
49
+ `--min`. A laptop's noise floor on these fixtures is a few per cent and two runs
50
+ taken minutes apart cannot see through it; alternating can.
51
+
52
+ ```sh
53
+ git archive HEAD lib/evg | tar -x -C /tmp/base
54
+ cp lib/evg/bench/EvgLayoutBench.rgr /tmp/base/lib/evg/bench/
55
+ RANGER_LIB=./compiler/Lang.rgr:./lib/stdops.rgr node dist/rgrc.js -es6 -nodemodule \
56
+ /tmp/base/lib/evg/bench/EvgLayoutBench.rgr -d=./lib/evg/bin -o=EvgLayoutBenchBase.cjs
57
+ node --expose-gc lib/evg/bench/layout-bench.mjs --ab --min --no-browser
58
+ ```
59
+
60
+ ## What it needs
61
+
62
+ `playwright-core` and a Chromium on disk. The harness takes whatever revision is
63
+ actually installed rather than the one `playwright-core` was built against,
64
+ because those drift; `--no-browser` skips the browser half entirely.