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,21 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "evgr"
7
+ version = "0.1.0"
8
+ dependencies = [
9
+ "ranger",
10
+ ]
11
+
12
+ [[package]]
13
+ name = "ranger"
14
+ version = "0.1.0"
15
+ dependencies = [
16
+ "ranger-macros",
17
+ ]
18
+
19
+ [[package]]
20
+ name = "ranger-macros"
21
+ version = "0.1.0"
@@ -0,0 +1,19 @@
1
+ # SPDX-License-Identifier: MIT
2
+ #
3
+ # EVGr: EVG's layout as a strict Rust module (see src/lib.rs). The same
4
+ # source builds here with cargo and with `rgrc` for the other targets.
5
+
6
+ [package]
7
+ name = "evgr"
8
+ version = "0.1.0"
9
+ edition = "2021"
10
+ license = "MIT"
11
+ publish = false
12
+
13
+ [dependencies]
14
+ ranger = { path = "../../runtime/rust/ranger" }
15
+
16
+ [profile.release]
17
+ overflow-checks = false
18
+
19
+ [workspace]
@@ -0,0 +1,140 @@
1
+ # EVGr — EVG's layout as a strict Rust module
2
+
3
+ An experiment beside [`lib/evg`](../evg), which it does not replace: the layout
4
+ of an EVG document — boxes styled with CSS declarations, laid out as flexbox
5
+ and grid with EVG's box model and initial values — written once in Rust
6
+ (`src/`, 2,300 lines) and built two ways:
7
+
8
+ - by **cargo** into native code (`cargo run --release --bin bench`);
9
+ - by **`rgrc`** into every Ranger target, the way any `.rs` module is
10
+ (`docs/plans/PLAN_RUST_SYNTAX.md`): `npm run evgr:build` writes
11
+ `bin/Evgr.cjs`, and `bench/NativeBench.rgr` — a Ranger program that imports
12
+ `src/lib.rs` beside `lib/evg` — builds for C++ and Go.
13
+
14
+ The questions were how it does on the layout cases EVG is measured with, and
15
+ how its speed compares with the Ranger engine.
16
+
17
+ ```sh
18
+ npm run evgr:compare # the layout cases: EVGr, EVG and Chromium
19
+ npm run evgr:speed # the layout-bench fixtures at 1k / 10k / 100k
20
+ npx vitest run --config tests/vitest.config.ts evgr.test.ts
21
+ ```
22
+
23
+ ## What it lays out
24
+
25
+ `display` block / flex / grid / none, `flex-direction` (and the reverse
26
+ forms), `flex-wrap`, width / height and their min / max (px, %, `calc()` of
27
+ px and %), padding (a percentage of the containing block's width), margin,
28
+ gap, `flex-grow` / `-shrink` / `-basis` / `flex`, `justify-content`,
29
+ `align-items` / `-self` / `-content` (with `baseline`), `aspect-ratio`,
30
+ `position: absolute` with top / right / bottom / left, grid templates (px, %,
31
+ fr, auto, `minmax()`, `fit-content()`, `repeat(n, …)`,
32
+ `repeat(auto-fit | auto-fill, …)`), placement by line numbers, `span`,
33
+ `grid-template-areas` / `grid-area`, auto placement with `dense`, and text
34
+ measured with EVG's default advance table, wrapped at spaces.
35
+
36
+ Not there: borders, images, overlays, connectors, the stylesheet, scrolling,
37
+ RTL — everything of EVG that is not the box layout. A property EVGr does not
38
+ know is reported (`unsupported_count` / `unsupported_at`).
39
+
40
+ The tree is an arena (a node is an index), and a subtree laid out at the same
41
+ width in the same pass is moved rather than laid out again, which is what
42
+ keeps a column of rows linear.
43
+
44
+ ## The layout cases
45
+
46
+ `bench/compare.mjs` runs the 47 cases of `lib/evg/bench/layout-cases.mjs`
47
+ through the three engines; two agree on a case when every box is within half
48
+ a pixel.
49
+
50
+ | | agree |
51
+ | --- | --- |
52
+ | EVGr and Chromium | 42 of 47 |
53
+ | EVGr and EVG | 39 of 47 |
54
+ | EVG and Chromium | 34 of 47 |
55
+
56
+ Where EVGr and Chromium differ, EVGr keeps a choice EVG made on purpose:
57
+ the initial values of `flex-direction` (column), `flex-wrap` (wrap) and
58
+ `align-items` (flex-start: `defaults-*`, `nested-flex-in-flex`), and an
59
+ absolute box placed against the content box (`absolute-child`). EVGr also
60
+ keeps two of EVG's rules the cases do not reach: a root without a height is
61
+ as tall as the viewport, and a text leaf without a width fits its text even
62
+ where a column stretches its boxes.
63
+
64
+ Where EVGr and EVG differ, EVGr agrees with Chromium: `align-content:
65
+ stretch` over wrapped lines, `row-reverse`, a grid cell holding a flex row, a
66
+ grid template mixing px / % / fr / auto, `max-content` as a width,
67
+ `aspect-ratio`, `calc()`, and `repeat(auto-fit, …)`.
68
+
69
+ The three text cases hold on EVGr's boxes, and EVGr's text boxes are EVG's
70
+ (same advance table, same line height).
71
+
72
+ ## Speed
73
+
74
+ `bench/speed.mjs` builds the three fixtures of
75
+ `lib/evg/bench/layout-bench.mjs` — nested flex (a column of cards, each a row
76
+ of a rail and a growing column), a four-column grid of small flex columns,
77
+ and the flex fixture with a line of text per card — and times a re-layout of
78
+ the built tree (median of five). Every engine's boxes are summed into a
79
+ checksum: on all nine fixture sizes EVG and EVGr lay the tree out the same,
80
+ in JavaScript, C++, Go and native Rust.
81
+
82
+ Re-layout, milliseconds, one run on the development container:
83
+
84
+ | fixture | nodes | EVG js | EVGr js | EVGr rustc | EVG / EVGr (js) | EVG js / EVGr rustc |
85
+ | --- | ---: | ---: | ---: | ---: | ---: | ---: |
86
+ | flex | 1,002 | 3.7 | 2.9 | 0.24 | 1.3x | 16x |
87
+ | flex | 10,004 | 12.1 | 6.7 | 2.7 | 1.8x | 4.4x |
88
+ | flex | 100,003 | 284 | 105 | 49 | 2.7x | 5.8x |
89
+ | grid | 1,001 | 6.5 | 3.3 | 0.17 | 2.0x | 38x |
90
+ | grid | 10,001 | 20.6 | 7.0 | 1.8 | 3.0x | 11x |
91
+ | grid | 100,001 | 380 | 85 | 35 | 4.5x | 11x |
92
+ | text | 1,002 | 4.1 | 4.2 | 0.30 | 1.0x | 14x |
93
+ | text | 10,004 | 19.6 | 10.7 | 2.7 | 1.8x | 7.2x |
94
+ | text | 100,003 | 345 | 97 | 43 | 3.6x | 8.0x |
95
+
96
+ The same program through Ranger to C++ (`g++ -O2`) and Go:
97
+
98
+ | fixture | nodes | EVG C++ | EVGr C++ | EVG Go | EVGr Go |
99
+ | --- | ---: | ---: | ---: | ---: | ---: |
100
+ | flex | 100,003 | 198 | 144 | 148 | 129 |
101
+ | grid | 100,001 | 329 | 125 | 285 | 73 |
102
+ | text | 100,003 | 397 | 152 | 180 | 200 |
103
+
104
+ What the numbers say:
105
+
106
+ - Written as Rust and compiled by Ranger, EVGr's layout is faster than EVG's
107
+ on every target at 10k boxes and above — 2–4x in JavaScript. EVGr does less
108
+ (no stylesheet, no overlays, no paint bookkeeping) and caches more (a
109
+ subtree laid out at the same width is moved), so this measures the two
110
+ engines, not the two source languages.
111
+ - The same Rust source built by rustc is 2–3x faster again than its
112
+ JavaScript build at 100k boxes, and 4–38x faster than EVG in JavaScript.
113
+ - Ranger's C++ output is not the fast path for this code: EVGr through C++ is
114
+ slower than EVGr through JavaScript (`shared_ptr` everywhere, and the
115
+ `children.clone()` the Rust source does per node becomes a vector copy).
116
+ Go sits between.
117
+ - Building the tree (parsing the CSS text) is where EVGr is slower than EVG
118
+ in JavaScript, 1–2x: its string handling is lowered from Rust's `split`,
119
+ `trim` and `find` one operation at a time.
120
+
121
+ ## Found on the way
122
+
123
+ Writing a 2,300-line module in the subset found these, fixed in the
124
+ compiler or the runtime:
125
+
126
+ - `str::strip_prefix` / `strip_suffix` were not in the subset.
127
+ - An associated function named like a field of its struct (`Len::px` beside
128
+ `Len.px`) came out under one name, which C++ rejects; it is now written as
129
+ `px_m`.
130
+ - `f64::floor` / `ceil` lowered to Ranger's `floor` / `ceil`, which answer an
131
+ int: Go rejected it. They have their own templates now.
132
+
133
+ Two limits of Ranger itself, met in `NativeBench.rgr`, are fixed too:
134
+
135
+ - A static method named like an operator (`count`, `make`, `size`, `sort`,
136
+ …) was rewritten into the operator-method form and then looked up as an
137
+ instance method: `Util.count(3)` failed with "Class Util does not have
138
+ method count".
139
+ - `sort` took only a comparison callback. `(sort xs)` of a `[double]` or
140
+ `[int]` now gives a new array in ascending order on every target.
@@ -0,0 +1,246 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; EVG and EVGr in one program, for a target the JavaScript harness cannot
4
+ ; drive: the fixtures of lib/evg/bench/layout-bench.mjs built for both
5
+ ; engines, laid out, and timed. One line per fixture, size and engine:
6
+ ;
7
+ ; <fixture> <size> <engine> <nodes> <layout ms> <checksum>
8
+ ;
9
+ ; `layout ms` is the median of five re-layouts after one warm-up; the
10
+ ; checksum sums x + y + w + h over every box, so the two engines can be
11
+ ; compared on the same tree. `bench/speed.mjs --targets cpp,go` builds this
12
+ ; for C++ and Go and prints the table.
13
+
14
+ Import "../../evg/EVGElement.rgr"
15
+ Import "../../evg/EVGUnit.rgr"
16
+ Import "../../evg/EVGLayout.rgr"
17
+ Import "../src/lib.rs"
18
+
19
+ class NativeBench {
20
+
21
+ sfn setCss:void (el:EVGElement css:string) {
22
+ def decls:[string] (strsplit css ";")
23
+ for decls d:string i {
24
+ def t:string (trim d)
25
+ if ((strlen t) == 0) {
26
+ continue
27
+ }
28
+ def c:int (indexOf t ":")
29
+ if (c < 0) {
30
+ continue
31
+ }
32
+ el.setAttribute((trim (substring t 0 c)) (trim (substring t (c + 1) (strlen t))))
33
+ }
34
+ }
35
+
36
+ sfn node:EVGElement (css:string) {
37
+ def el:EVGElement (new EVGElement())
38
+ NativeBench.setCss(el css)
39
+ return el
40
+ }
41
+
42
+ sfn css:string (name:string) {
43
+ if (name == "page") {
44
+ return "display:flex;flex-direction:column;flex-wrap:nowrap;width:1200px;gap:8px;align-items:stretch"
45
+ }
46
+ if (name == "card") {
47
+ return "display:flex;flex-direction:row;flex-wrap:nowrap;gap:12px;padding:8px;align-items:stretch"
48
+ }
49
+ if (name == "rail") {
50
+ return "width:48px;height:56px;background-color:#e4e4e7"
51
+ }
52
+ if (name == "body") {
53
+ return "display:flex;flex-direction:column;flex-wrap:nowrap;flex-grow:1;gap:4px;align-items:stretch"
54
+ }
55
+ if (name == "line") {
56
+ return "height:16px;background-color:#f4f4f5"
57
+ }
58
+ if (name == "gridc") {
59
+ return "display:grid;grid-template-columns:repeat(4, 1fr);gap:10px;width:1200px"
60
+ }
61
+ if (name == "cell") {
62
+ return "display:flex;flex-direction:column;flex-wrap:nowrap;gap:4px;padding:6px;align-items:stretch"
63
+ }
64
+ return "font-size:14px"
65
+ }
66
+
67
+ sfn word:string (i:int) {
68
+ def words:[string] ([] _:string ("Ada Lovelace" "Grace Hopper" "Alan Turing" "Edsger Dijkstra" "Barbara McClintock"))
69
+ return (itemAt words (i % 5))
70
+ }
71
+
72
+ sfn count:int (n:int per:int) {
73
+ def c:int (to_int ((to_double n) / (to_double per) + 0.5))
74
+ if (c < 1) {
75
+ return 1
76
+ }
77
+ return c
78
+ }
79
+
80
+ ; --- EVG
81
+
82
+ sfn evgTree:EVGElement (fixture:string n:int) {
83
+ if (fixture == "grid") {
84
+ def g:EVGElement (NativeBench.node((NativeBench.css("gridc"))))
85
+ def cells:int (NativeBench.count(n 5))
86
+ def i:int 0
87
+ while (i < cells) {
88
+ def cell:EVGElement (NativeBench.node((NativeBench.css("cell"))))
89
+ def j:int 0
90
+ while (j < 4) {
91
+ cell.addChild((NativeBench.node((NativeBench.css("line")))))
92
+ j = j + 1
93
+ }
94
+ g.addChild(cell)
95
+ i = i + 1
96
+ }
97
+ return g
98
+ }
99
+ def page:EVGElement (NativeBench.node((NativeBench.css("page"))))
100
+ def cards:int (NativeBench.count(n 7))
101
+ def k:int 0
102
+ while (k < cards) {
103
+ def card:EVGElement (NativeBench.node((NativeBench.css("card"))))
104
+ card.addChild((NativeBench.node((NativeBench.css("rail")))))
105
+ def body:EVGElement (NativeBench.node((NativeBench.css("body"))))
106
+ def q:int 0
107
+ while (q < 4) {
108
+ if ((fixture == "text") && (q == 0)) {
109
+ def tx:EVGElement (NativeBench.node((NativeBench.css("text"))))
110
+ tx.elementType = 1
111
+ tx.textContent = (NativeBench.word(k))
112
+ body.addChild(tx)
113
+ } {
114
+ body.addChild((NativeBench.node((NativeBench.css("line")))))
115
+ }
116
+ q = q + 1
117
+ }
118
+ card.addChild(body)
119
+ page.addChild(card)
120
+ k = k + 1
121
+ }
122
+ return page
123
+ }
124
+
125
+ sfn evgSum:double (el:EVGElement) {
126
+ def s:double (((el.calculatedX + el.calculatedY) + el.calculatedWidth) + el.calculatedHeight)
127
+ for el.children k:EVGElement i {
128
+ s = s + (NativeBench.evgSum(k))
129
+ }
130
+ return s
131
+ }
132
+
133
+ sfn evgCount:int (el:EVGElement) {
134
+ def c:int 1
135
+ for el.children k:EVGElement i {
136
+ c = c + (NativeBench.evgCount(k))
137
+ }
138
+ return c
139
+ }
140
+
141
+ ; --- EVGr
142
+
143
+ sfn evgrTree:EvgrTree (fixture:string n:int) {
144
+ def t:EvgrTree (EvgrTree.new_())
145
+ if (fixture == "grid") {
146
+ def g:int (t.add(-1 (NativeBench.css("gridc"))))
147
+ def cells:int (NativeBench.count(n 5))
148
+ def i:int 0
149
+ while (i < cells) {
150
+ def cell:int (t.add(g (NativeBench.css("cell"))))
151
+ def j:int 0
152
+ while (j < 4) {
153
+ t.add(cell (NativeBench.css("line")))
154
+ j = j + 1
155
+ }
156
+ i = i + 1
157
+ }
158
+ return t
159
+ }
160
+ def page:int (t.add(-1 (NativeBench.css("page"))))
161
+ def cards:int (NativeBench.count(n 7))
162
+ def k:int 0
163
+ while (k < cards) {
164
+ def card:int (t.add(page (NativeBench.css("card"))))
165
+ t.add(card (NativeBench.css("rail")))
166
+ def body:int (t.add(card (NativeBench.css("body"))))
167
+ def q:int 0
168
+ while (q < 4) {
169
+ if ((fixture == "text") && (q == 0)) {
170
+ t.add_text(body (NativeBench.css("text")) (NativeBench.word(k)))
171
+ } {
172
+ t.add(body (NativeBench.css("line")))
173
+ }
174
+ q = q + 1
175
+ }
176
+ k = k + 1
177
+ }
178
+ return t
179
+ }
180
+
181
+ sfn evgrSum:double (t:EvgrTree) {
182
+ def s:double 0.0
183
+ def i:int 0
184
+ def n:int (t.count())
185
+ while (i < n) {
186
+ s = s + (((t.x(i) + t.y(i)) + t.w(i)) + t.h(i))
187
+ i = i + 1
188
+ }
189
+ return s
190
+ }
191
+
192
+ sfn median:double (xs:[double]) {
193
+ def s:[double] (sort xs)
194
+ return (itemAt s (idiv (array_length s) 2))
195
+ }
196
+
197
+ sfn fmt:string (v:double) {
198
+ def whole:int (to_int (v * 1000.0))
199
+ return (to_string ((to_double whole) / 1000.0))
200
+ }
201
+
202
+ sfn report:void (fx:string n:int engine:string nodes:int ms:double sum:double) {
203
+ def line:string ((fx + " ") + (to_string n))
204
+ line = ((line + " ") + engine)
205
+ line = ((line + " ") + (to_string nodes))
206
+ line = ((line + " ") + (NativeBench.fmt(ms)))
207
+ ; the checksum in hundreds, which an int of every target holds
208
+ line = ((line + " ") + (to_string (to_int (sum / 100.0))))
209
+ print line
210
+ }
211
+
212
+ sfn main:void () {
213
+ def fixtures:[string] ([] _:string ("flex" "grid" "text"))
214
+ def sizes:[int] ([] _:int (1000 10000 100000))
215
+ for fixtures fx:string fi {
216
+ for sizes n:int si {
217
+ ; EVG
218
+ def root:EVGElement (NativeBench.evgTree(fx n))
219
+ def lay:EVGLayout (new EVGLayout())
220
+ lay.setPageSize(1200.0 900.0)
221
+ lay.layout(root)
222
+ def times:[double]
223
+ def r:int 0
224
+ while (r < 5) {
225
+ def a:double (wall_clock_ms)
226
+ lay.layout(root)
227
+ push times ((wall_clock_ms) - a)
228
+ r = r + 1
229
+ }
230
+ NativeBench.report(fx n "evg" (NativeBench.evgCount(root)) (NativeBench.median(times)) (NativeBench.evgSum(root)))
231
+ ; EVGr
232
+ def t:EvgrTree (NativeBench.evgrTree(fx n))
233
+ t.layout(1200.0 900.0)
234
+ def times2:[double]
235
+ def r2:int 0
236
+ while (r2 < 5) {
237
+ def b:double (wall_clock_ms)
238
+ t.layout(1200.0 900.0)
239
+ push times2 ((wall_clock_ms) - b)
240
+ r2 = r2 + 1
241
+ }
242
+ NativeBench.report(fx n "evgr" (t.count()) (NativeBench.median(times2)) (NativeBench.evgrSum(t)))
243
+ }
244
+ }
245
+ }
246
+ }
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env node
2
+ // SPDX-License-Identifier: MIT
3
+ //
4
+ // The layout cases of lib/evg/bench/layout-cases.mjs, laid out by three
5
+ // engines: EVG (Ranger, compiled to JavaScript), EVGr (the strict Rust module
6
+ // lib/evgr/src, compiled to JavaScript by rgrc) and Chromium.
7
+ //
8
+ // npm run evgr:compare [-- --only <id>] [--verbose] [--json] [--no-browser]
9
+ //
10
+ // Every case is CSS text, split into declarations for EVG and EVGr and put in
11
+ // a `style=` attribute for Chromium, exactly as layout-conformance.mjs does.
12
+ // A pair of engines AGREES on a case when every box is within half a pixel.
13
+ // Chromium is the reference for what the CSS says; EVG is the engine EVGr
14
+ // sits beside, so both comparisons are reported.
15
+
16
+ import fs from "node:fs";
17
+ import path from "node:path";
18
+ import { createRequire } from "node:module";
19
+ import { fileURLToPath } from "node:url";
20
+ import { CASES, TEXT_CASES } from "../../evg/bench/layout-cases.mjs";
21
+
22
+ const HERE = path.dirname(fileURLToPath(import.meta.url));
23
+ const ROOT = path.resolve(HERE, "..", "..", "..");
24
+ const require = createRequire(import.meta.url);
25
+ const EVG = require(path.join(ROOT, "lib/evg/bin/EvgLayoutBench.cjs"));
26
+ const R = require(path.join(ROOT, "lib/evgr/bin/Evgr.cjs"));
27
+
28
+ const argv = process.argv.slice(2);
29
+ const AS_JSON = argv.includes("--json");
30
+ const VERBOSE = argv.includes("--verbose");
31
+ const NO_BROWSER = argv.includes("--no-browser");
32
+ const ONLY = argv.includes("--only") ? argv[argv.indexOf("--only") + 1] : null;
33
+ const EPS = 0.5;
34
+
35
+ // --- EVG ---------------------------------------------------------------------
36
+
37
+ function evgBuild(node) {
38
+ const el = new EVG.EVGElement();
39
+ for (const decl of (node.s || "").split(";")) {
40
+ const t = decl.trim();
41
+ if (!t) continue;
42
+ const i = t.indexOf(":");
43
+ if (i < 0) continue;
44
+ el.setAttribute(t.slice(0, i).trim(), t.slice(i + 1).trim());
45
+ }
46
+ if (node.text !== undefined) {
47
+ el.elementType = 1;
48
+ el.textContent = node.text;
49
+ }
50
+ for (const k of node.kids || []) el.addChild(evgBuild(k));
51
+ return el;
52
+ }
53
+
54
+ function evgBoxes(spec) {
55
+ EVG.EVGReject.clearNotes();
56
+ const root = evgBuild(spec);
57
+ const lay = new EVG.EVGLayout();
58
+ lay.setPageSize(1200, 900);
59
+ lay.layout(root);
60
+ const flat = [];
61
+ (function collect(el) {
62
+ flat.push({ x: el.calculatedX, y: el.calculatedY, w: el.calculatedWidth, h: el.calculatedHeight });
63
+ for (const k of el.children) collect(k);
64
+ })(root);
65
+ return flat;
66
+ }
67
+
68
+ // --- EVGr --------------------------------------------------------------------
69
+
70
+ function evgrBuild(t, node, parent) {
71
+ const i = node.text !== undefined ? t.add_text(parent, node.s || "", node.text) : t.add(parent, node.s || "");
72
+ for (const k of node.kids || []) evgrBuild(t, k, i);
73
+ return i;
74
+ }
75
+
76
+ function evgrBoxes(spec) {
77
+ const t = R.EvgrTree.new_();
78
+ evgrBuild(t, spec, -1);
79
+ t.layout(1200, 900);
80
+ const flat = [];
81
+ for (let i = 0; i < t.count(); i++) flat.push({ x: t.x(i), y: t.y(i), w: t.w(i), h: t.h(i) });
82
+ const unsupported = [];
83
+ for (let k = 0; k < t.unsupported_count(); k++) unsupported.push(t.unsupported_at(k));
84
+ return { flat, unsupported };
85
+ }
86
+
87
+ // --- Chromium ----------------------------------------------------------------
88
+
89
+ function html(spec) {
90
+ const render = (n) =>
91
+ `<div style="${(n.s || "").replace(/"/g, "&quot;")}">` +
92
+ (n.text !== undefined ? n.text.replace(/[<&]/g, (c) => (c === "<" ? "&lt;" : "&amp;")) : "") +
93
+ (n.kids || []).map(render).join("") +
94
+ `</div>`;
95
+ return (
96
+ `<!doctype html><meta charset="utf-8"><style>` +
97
+ `*{box-sizing:border-box;margin:0;padding:0;border:0 solid #000}` +
98
+ `html,body{margin:0;padding:0;font:16px/1.2 monospace}` +
99
+ `#host{position:absolute;left:0;top:0}` +
100
+ `</style><div id="host">${render(spec)}</div>`
101
+ );
102
+ }
103
+
104
+ async function browserBoxes(page, spec) {
105
+ await page.setContent(html(spec));
106
+ return page.evaluate(() => {
107
+ const out = [];
108
+ const host = document.getElementById("host");
109
+ const origin = host.firstElementChild.getBoundingClientRect();
110
+ (function collect(el) {
111
+ const r = el.getBoundingClientRect();
112
+ out.push({ x: r.left - origin.left, y: r.top - origin.top, w: r.width, h: r.height });
113
+ for (const c of el.children) collect(c);
114
+ })(host.firstElementChild);
115
+ return out;
116
+ });
117
+ }
118
+
119
+ // Whatever Chromium is on disk: this container's, a playwright cache's, or
120
+ // the user's own Chrome.
121
+ function chromiumPath() {
122
+ const roots = [process.env.PLAYWRIGHT_BROWSERS_PATH, "/opt/pw-browsers", path.join(process.env.HOME || "", "Library/Caches/ms-playwright"), path.join(process.env.HOME || "", ".cache/ms-playwright")];
123
+ for (const root of roots) {
124
+ if (!root || !fs.existsSync(root)) continue;
125
+ for (const dir of fs.readdirSync(root).filter((d) => d.startsWith("chromium-")).sort().reverse()) {
126
+ for (const rel of [
127
+ "chrome-linux/chrome",
128
+ "chrome-mac-arm64/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing",
129
+ "chrome-mac/Chromium.app/Contents/MacOS/Chromium",
130
+ ]) {
131
+ const p = path.join(root, dir, rel);
132
+ if (fs.existsSync(p)) return p;
133
+ }
134
+ }
135
+ }
136
+ return null;
137
+ }
138
+
139
+ // --- compare -----------------------------------------------------------------
140
+
141
+ function agree(a, b) {
142
+ if (!a || !b) return null;
143
+ if (a.length !== b.length) return [{ id: "count", miss: true }];
144
+ const rows = [];
145
+ for (let i = 0; i < a.length; i++) {
146
+ const d = ["x", "y", "w", "h"].filter((k) => Math.abs(a[i][k] - b[i][k]) > EPS);
147
+ if (d.length) rows.push({ id: "n" + i, fields: d, a: a[i], b: b[i] });
148
+ }
149
+ return rows;
150
+ }
151
+
152
+ let page = null;
153
+ let browser = null;
154
+ if (!NO_BROWSER) {
155
+ const { chromium } = require("playwright-core");
156
+ const exe = chromiumPath();
157
+ browser = await chromium.launch(exe ? { executablePath: exe } : { channel: "chrome" });
158
+ page = await browser.newPage({ viewport: { width: 1200, height: 900 } });
159
+ }
160
+
161
+ const results = [];
162
+ for (const c of CASES) {
163
+ if (ONLY && c.id !== ONLY) continue;
164
+ const evg = evgBoxes(c.root);
165
+ const r = evgrBoxes(c.root);
166
+ const css = page ? await browserBoxes(page, c.root) : null;
167
+ results.push({
168
+ id: c.id,
169
+ group: c.group,
170
+ why: c.why,
171
+ nodes: evg.length,
172
+ unsupported: r.unsupported,
173
+ evg,
174
+ evgr: r.flat,
175
+ css,
176
+ rCss: agree(r.flat, css),
177
+ rEvg: agree(r.flat, evg),
178
+ eCss: agree(evg, css),
179
+ });
180
+ }
181
+
182
+ // Text cases: EVG's own assertions, run on EVGr's boxes, and the boxes of
183
+ // both engines side by side (they share the measurer's advance table).
184
+ const textResults = [];
185
+ for (const c of TEXT_CASES) {
186
+ if (ONLY && c.id !== ONLY) continue;
187
+ const evg = evgBoxes(c.root);
188
+ const r = evgrBoxes(c.root);
189
+ let ok = false;
190
+ try {
191
+ ok = !!c.assert(r.flat);
192
+ } catch (e) {
193
+ ok = false;
194
+ }
195
+ textResults.push({ id: c.id, why: c.why, ok, rEvg: agree(r.flat, evg), evg, evgr: r.flat });
196
+ }
197
+
198
+ if (browser) await browser.close();
199
+
200
+ if (AS_JSON) {
201
+ // no process.exit: it would cut a piped stdout short
202
+ process.stdout.write(JSON.stringify({ results, textResults }, null, 2) + "\n");
203
+ } else {
204
+ report();
205
+ }
206
+
207
+ function report() {
208
+
209
+ // --- report ------------------------------------------------------------------
210
+
211
+ const mark = (rows) => (rows === null ? " - " : rows.length ? "DIFF" : " ok ");
212
+ const pad = (s, n) => String(s).padEnd(n);
213
+ const r2 = (v) => Math.round(v * 100) / 100;
214
+ const f = (o) => `x=${r2(o.x)} y=${r2(o.y)} w=${r2(o.w)} h=${r2(o.h)}`;
215
+
216
+ console.log("\nEVGr (Rust, via rgrc to JS) beside EVG and Chromium — the same CSS\n");
217
+ console.log(` ${pad("case", 28)} EVGr=CSS EVGr=EVG EVG=CSS`);
218
+ let lastGroup = null;
219
+ const count = { rCss: 0, rEvg: 0, eCss: 0 };
220
+ for (const r of results) {
221
+ if (r.group !== lastGroup) {
222
+ console.log(` ── ${r.group}`);
223
+ lastGroup = r.group;
224
+ }
225
+ for (const k of Object.keys(count)) if (r[k] && r[k].length === 0) count[k]++;
226
+ const note = r.unsupported.length ? ` (not laid out: ${r.unsupported.slice(0, 2).join("; ")}${r.unsupported.length > 2 ? "; …" : ""})` : "";
227
+ console.log(` ${pad(r.id, 28)} ${mark(r.rCss)} ${mark(r.rEvg)} ${mark(r.eCss)}${note}`);
228
+ }
229
+ const n = results.length;
230
+ console.log(`\n EVGr agrees with Chromium on ${count.rCss} of ${n}, with EVG on ${count.rEvg} of ${n}; EVG agrees with Chromium on ${count.eCss} of ${n}.`);
231
+
232
+ console.log("\n Text (EVG's assertions on EVGr's boxes; boxes against EVG's)");
233
+ for (const t of textResults) {
234
+ console.log(` ${t.ok ? " ok " : "FAIL"} ${mark(t.rEvg)} ${pad(t.id, 26)} ${t.why}`);
235
+ }
236
+
237
+ if (VERBOSE) {
238
+ for (const r of results) {
239
+ const rows = r.rCss && r.rCss.length ? r.rCss : [];
240
+ if (!rows.length) continue;
241
+ console.log(`\n ${r.id} — ${r.why}`);
242
+ for (const d of rows.slice(0, 6)) {
243
+ if (d.miss) {
244
+ console.log(` box count differs`);
245
+ continue;
246
+ }
247
+ console.log(` ${d.id} [${d.fields.join(",")}] EVGr ${f(d.a)} CSS ${f(d.b)} EVG ${f(r.evg[Number(d.id.slice(1))])}`);
248
+ }
249
+ }
250
+ }
251
+ console.log("");
252
+ }