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,531 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EvgResponsiveDemo — one page, laid out by EVG, at whatever width the window is
5
+ ; ==============================================================================
6
+ ;
7
+ ; Every other EVG page in this repository is laid out ONCE, at a size somebody
8
+ ; typed: a sheet of A4 for the PDF, 420×320 for the conformance playground,
9
+ ; `boxmodel.json` at whatever it was exported at. That is a fair test of the
10
+ ; layout, and no test at all of the part CSS calls responsive — `@media`, `vw`,
11
+ ; percentages, a grid that changes how many columns it has.
12
+ ;
13
+ ; So this one is laid out on every frame, at the width of the browser window,
14
+ ; and NOTHING about it is precomputed. Drag the window and the whole pipeline
15
+ ; runs again:
16
+ ;
17
+ ; 1. build the tree (this file, `build()`)
18
+ ; 2. state the viewport `EVGStyleSheet.setViewport(w, h, coarse)`
19
+ ; 3. resolve the cascade `applyTree` — the `@media` blocks that match
20
+ ; this width contribute, the others do not
21
+ ; 4. lay out `EVGLayout.layout` with `setPageSize(w, h)`,
22
+ ; which is also what `vw` / `vh` resolve to
23
+ ; 5. flatten to draw commands `EVGDisplayList.build`
24
+ ;
25
+ ; The page is then painted by `lib/evg/html/evg-html.js` — the SVG backend,
26
+ ; 500 lines, which knows about rectangles, glyph runs and clips and nothing at
27
+ ; all about CSS. The browser never lays anything out. It is handed absolute
28
+ ; pixels that EVG computed.
29
+ ;
30
+ ; --- WHAT IS ACTUALLY BEING DEMONSTRATED --------------------------------------
31
+ ;
32
+ ; The tree below has no width, no colour and no size anywhere in it. It is a
33
+ ; list of names. Every number on the screen comes from `defaultCss()`, and the
34
+ ; three `@media` blocks in it are the entire difference between the wide layout
35
+ ; and the phone one:
36
+ ;
37
+ ; > 1080px sidebar beside the content, cards four across
38
+ ; ≤ 1080px cards three across
39
+ ; ≤ 820px sidebar above the content, cards two across
40
+ ; ≤ 560px one card per row, smaller type, tighter padding
41
+ ;
42
+ ; The badge in the top bar is the one thing this file computes rather than
43
+ ; declares, because it is reporting the input: it says what the host told the
44
+ ; stylesheet the viewport was. Everything else is the cascade's answer.
45
+ ; ==============================================================================
46
+
47
+ Import "../../EVGElement.rgr"
48
+ Import "../../EVGUnit.rgr"
49
+ Import "../../EVGBox.rgr"
50
+ Import "../../EVGLayout.rgr"
51
+ Import "../../EVGHostTree.rgr"
52
+ Import "../../EVGStyleSheet.rgr"
53
+ Import "../../EVGDisplayList.rgr"
54
+
55
+ ; The tags this page is built from. Names only — a tag carries a class and,
56
+ ; for the text nodes, `elementType 1`, and never a visual attribute.
57
+ treefactory Rp {
58
+ child addChild
59
+ text textContent
60
+
61
+ tag Page EVGElement (props (className "page"))
62
+
63
+ tag Bar EVGElement (props (className "bar"))
64
+ tag Brand EVGElement (props (className "brand") (elementType 1))
65
+ tag BarTitle EVGElement (props (className "bar-title") (elementType 1))
66
+ tag Spacer EVGElement (props (className "spacer"))
67
+ tag Badge EVGElement (props (className "badge") (elementType 1))
68
+
69
+ tag Hero EVGElement (props (className "hero"))
70
+ tag HeroH EVGElement (props (className "hero-h") (elementType 1))
71
+ tag HeroP EVGElement (props (className "hero-p") (elementType 1))
72
+
73
+ tag Chips EVGElement (props (className "chips"))
74
+ tag ChipW EVGElement (props (className "chip chip-wide") (elementType 1))
75
+ tag ChipL EVGElement (props (className "chip chip-lap") (elementType 1))
76
+ tag ChipT EVGElement (props (className "chip chip-tab") (elementType 1))
77
+ tag ChipP EVGElement (props (className "chip chip-phone") (elementType 1))
78
+
79
+ tag Body EVGElement (props (className "body"))
80
+ tag Side EVGElement (props (className "side"))
81
+ tag SideH EVGElement (props (className "side-h") (elementType 1))
82
+ tag NavList EVGElement (props (className "nav"))
83
+ tag NavItem EVGElement (props (className "nav-item") (elementType 1))
84
+ tag Main EVGElement (props (className "main"))
85
+
86
+ tag SecH EVGElement (props (className "sec-h") (elementType 1))
87
+ tag Cards EVGElement (props (className "cards"))
88
+ tag Card EVGElement (props (className "card"))
89
+ tag CardTag EVGElement (props (className "card-tag") (elementType 1))
90
+ tag CardH EVGElement (props (className "card-h") (elementType 1))
91
+ tag CardP EVGElement (props (className "card-p") (elementType 1))
92
+
93
+ tag Stats EVGElement (props (className "stats"))
94
+ tag Stat EVGElement (props (className "stat"))
95
+ tag StatN EVGElement (props (className "stat-n") (elementType 1))
96
+ tag StatL EVGElement (props (className "stat-l") (elementType 1))
97
+
98
+ tag Foot EVGElement (props (className "foot"))
99
+ tag FootT EVGElement (props (className "foot-t") (elementType 1))
100
+ }
101
+
102
+ class EvgResponsiveDemo {
103
+
104
+ ; The surface, as the host reports it. `vw` / `vh` and every `@media` bound
105
+ ; are resolved against exactly these two numbers — a Ranger program has no
106
+ ; window to ask, so the host has to say.
107
+ def pageW:double 1200.0
108
+ def pageH:double 800.0
109
+ ; A finger rather than a mouse, for `@media (pointer: coarse)`.
110
+ def coarse:boolean false
111
+
112
+ def css:string ""
113
+
114
+ ; What the last render worked out, so a caller can report it without
115
+ ; parsing the JSON back.
116
+ def lastHeight:double 0.0
117
+ def lastCommands:int 0
118
+ def lastErrors:int 0
119
+
120
+ ; The host tree (`EVGHostTree`), kept across renders: `renderHost` says
121
+ ; what changed since the last one, keyed by the inspector's path, so a
122
+ ; host that keeps DOM nodes patches them. The tree literal builds every
123
+ ; element anew each render and the ops still come out empty for a page
124
+ ; that did not change — identity is the PATH, not the object.
125
+ def host:EVGHostTree (new EVGHostTree())
126
+
127
+ Constructor () {
128
+ css = (EvgResponsiveDemo.defaultCss())
129
+ }
130
+
131
+ fn setViewport:void (w:double h:double c:boolean) {
132
+ pageW = w
133
+ pageH = h
134
+ coarse = c
135
+ }
136
+
137
+ ; The page's own stylesheet, so the demo can show it and let it be edited.
138
+ fn stylesheet:string () {
139
+ return css
140
+ }
141
+
142
+ fn setStylesheet:void (text:string) {
143
+ css = text
144
+ }
145
+
146
+ fn contentHeight:double () {
147
+ return lastHeight
148
+ }
149
+
150
+ fn commandCount:int () {
151
+ return lastCommands
152
+ }
153
+
154
+ fn cssErrorCount:int () {
155
+ return lastErrors
156
+ }
157
+
158
+ ; ------------------------------------------------------------------------
159
+ ; The stylesheet. Every number on the page is in here.
160
+ ; ------------------------------------------------------------------------
161
+ sfn defaultCss:string () {
162
+ def s:string ""
163
+
164
+ ; --- the page ---------------------------------------------------------
165
+ ; `font-family` is declared once and inherits from here. It is a
166
+ ; GENERIC on purpose: `SimpleTextMeasurer`'s advances were measured off
167
+ ; a browser's sans fallback, so naming that same fallback is what makes
168
+ ; the width EVG computed and the width the browser paints the same
169
+ ; number. A named face nobody has installed would silently be measured
170
+ ; as one thing and drawn as another.
171
+ s = s + ".page { display: flex; flex-direction: column; width: 100vw;"
172
+ s = s + " font-family: sans-serif;"
173
+ s = s + " background-color: #f6f7fb; padding-bottom: 28px }\n"
174
+
175
+ ; --- top bar ----------------------------------------------------------
176
+ s = s + ".bar { display: flex; flex-direction: row; align-items: center;"
177
+ s = s + " gap: 12px; padding: 18px 32px; background-color: #10162b }\n"
178
+ s = s + ".brand { font-size: 15px; font-weight: 700; color: #ffffff }\n"
179
+ s = s + ".bar-title { font-size: 13px; color: #8ea0c8 }\n"
180
+ s = s + ".spacer { flex: 1 }\n"
181
+ s = s + ".badge { font-size: 12px; font-weight: 600; color: #06122e;"
182
+ s = s + " background-color: #7cc4ff; border-radius: 999px;"
183
+ s = s + " padding: 6px 14px }\n"
184
+
185
+ ; --- hero -------------------------------------------------------------
186
+ ; `padding-left: 4vw` is the viewport unit doing the work a percentage
187
+ ; cannot: it is a share of the PAGE, not of this element's parent.
188
+ s = s + ".hero { display: flex; flex-direction: column; gap: 10px;"
189
+ s = s + " padding-top: 30px; padding-bottom: 26px;"
190
+ s = s + " padding-left: 4vw; padding-right: 4vw;"
191
+ s = s + " background-color: #ffffff }\n"
192
+ s = s + ".hero-h { font-size: 30px; font-weight: 700; color: #10162b;"
193
+ s = s + " line-height: 1.2 }\n"
194
+ s = s + ".hero-p { font-size: 14px; color: #55617e; line-height: 1.5 }\n"
195
+
196
+ ; --- the breakpoint chips --------------------------------------------
197
+ ; Four chips, one per band. They are grey here, and each `@media` block
198
+ ; below lights its own one up — so the page says which rules are firing
199
+ ; without anything in the tree knowing how wide the window is.
200
+ s = s + ".chips { display: flex; flex-direction: row; flex-wrap: wrap;"
201
+ s = s + " gap: 8px; padding-top: 6px }\n"
202
+ s = s + ".chip { font-size: 12px; color: #7a869f;"
203
+ s = s + " background-color: #eef0f6; border-radius: 6px;"
204
+ s = s + " padding: 6px 10px }\n"
205
+ s = s + ".chip-wide { color: #06122e; background-color: #b9e2ff }\n"
206
+
207
+ ; --- the body split ---------------------------------------------------
208
+ s = s + ".body { display: flex; flex-direction: row; gap: 24px;"
209
+ s = s + " padding-top: 26px;"
210
+ s = s + " padding-left: 4vw; padding-right: 4vw }\n"
211
+ s = s + ".side { display: flex; flex-direction: column; gap: 8px;"
212
+ s = s + " width: 240px; padding: 16px; background-color: #ffffff;"
213
+ s = s + " border-radius: 12px }\n"
214
+ s = s + ".side-h { font-size: 11px; font-weight: 700; color: #8b95ad;"
215
+ s = s + " padding-bottom: 4px }\n"
216
+ ; `width: 100%` rather than nothing. EVG's `align-items` default on a
217
+ ; column is `flex-start`, not `stretch`, so an auto cross size here is
218
+ ; fit-content — which is not what a list of rows in a fixed-width
219
+ ; sidebar means. Saying the percentage says it.
220
+ s = s + ".nav { display: flex; flex-direction: column; gap: 6px;"
221
+ s = s + " width: 100% }\n"
222
+ ; `min-width` so the rows are a consistent size — and so that no label
223
+ ; sits on the wrap threshold. A shrink-to-fit box comes out at exactly
224
+ ; its own text's width, and the content width is that number minus the
225
+ ; padding it was added to, which for some strings loses a ulp and wraps
226
+ ; a label that fits. See lib/evg/ISSUES.md, "shrink-to-fit text".
227
+ s = s + ".nav-item { font-size: 13px; color: #26314c;"
228
+ s = s + " background-color: #f2f4fa; border-radius: 8px;"
229
+ s = s + " min-width: 104px; padding: 9px 12px }\n"
230
+ s = s + ".main { display: flex; flex-direction: column; gap: 18px;"
231
+ s = s + " flex: 1 }\n"
232
+ s = s + ".sec-h { font-size: 16px; font-weight: 700; color: #10162b }\n"
233
+
234
+ ; --- the card grid ----------------------------------------------------
235
+ s = s + ".cards { display: grid;"
236
+ s = s + " grid-template-columns: repeat(4, 1fr); gap: 16px }\n"
237
+ s = s + ".card { display: flex; flex-direction: column; gap: 8px;"
238
+ s = s + " padding: 16px; background-color: #ffffff;"
239
+ s = s + " border-radius: 12px; border-width: 1px; border-color: #e3e7f1 }\n"
240
+ s = s + ".card-tag { font-size: 11px; font-weight: 700; color: #2f7fd0 }\n"
241
+ s = s + ".card-h { font-size: 15px; font-weight: 700; color: #10162b }\n"
242
+ s = s + ".card-p { font-size: 13px; color: #55617e; line-height: 1.45 }\n"
243
+
244
+ ; --- the stat strip ---------------------------------------------------
245
+ ; `flex-wrap: wrap` with a minimum width is the other way a layout
246
+ ; answers a narrow window: no rule fires, the line simply runs out.
247
+ s = s + ".stats { display: flex; flex-direction: row; flex-wrap: wrap;"
248
+ s = s + " gap: 12px }\n"
249
+ s = s + ".stat { display: flex; flex-direction: column; gap: 4px;"
250
+ s = s + " flex: 1; min-width: 150px; padding: 14px 16px;"
251
+ s = s + " background-color: #10162b; border-radius: 12px }\n"
252
+ s = s + ".stat-n { font-size: 22px; font-weight: 700; color: #ffffff }\n"
253
+ s = s + ".stat-l { font-size: 12px; color: #8ea0c8 }\n"
254
+
255
+ ; --- footer -----------------------------------------------------------
256
+ s = s + ".foot { display: flex; flex-direction: row;"
257
+ s = s + " padding-top: 22px;"
258
+ s = s + " padding-left: 4vw; padding-right: 4vw }\n"
259
+ s = s + ".foot-t { font-size: 12px; color: #8b95ad; line-height: 1.5 }\n"
260
+
261
+ ; ======================================================================
262
+ ; The breakpoints. This is the whole responsive behaviour of the page.
263
+ ; ======================================================================
264
+
265
+ ; Laptop: one column out of the card grid.
266
+ s = s + "@media (max-width: 1080px) {\n"
267
+ s = s + " .cards { grid-template-columns: repeat(3, 1fr) }\n"
268
+ s = s + " .hero-h { font-size: 26px }\n"
269
+ s = s + " .chip-wide { color: #7a869f; background-color: #eef0f6 }\n"
270
+ s = s + " .chip-lap { color: #06122e; background-color: #b9e2ff }\n"
271
+ s = s + "}\n"
272
+
273
+ ; Tablet: the sidebar stops being a sidebar. One declaration —
274
+ ; `flex-direction: column` on the split — moves it above the content,
275
+ ; and `width: auto` lets it fill the line it now has to itself.
276
+ s = s + "@media (max-width: 820px) {\n"
277
+ s = s + " .body { flex-direction: column; gap: 18px }\n"
278
+ s = s + " .side { width: auto }\n"
279
+ s = s + " .nav { flex-direction: row; flex-wrap: wrap }\n"
280
+ s = s + " .cards { grid-template-columns: repeat(2, 1fr) }\n"
281
+ s = s + " .chip-lap { color: #7a869f; background-color: #eef0f6 }\n"
282
+ s = s + " .chip-tab { color: #06122e; background-color: #b9e2ff }\n"
283
+ s = s + "}\n"
284
+
285
+ ; Phone: one card per row, and the type and padding come down with it.
286
+ s = s + "@media (max-width: 560px) {\n"
287
+ s = s + " .bar { padding-left: 18px; padding-right: 18px }\n"
288
+ s = s + " .bar-title { font-size: 12px }\n"
289
+ s = s + " .hero { padding-top: 22px; padding-bottom: 20px }\n"
290
+ s = s + " .hero-h { font-size: 21px }\n"
291
+ s = s + " .hero-p { font-size: 13px }\n"
292
+ s = s + " .cards { grid-template-columns: repeat(1, 1fr); gap: 12px }\n"
293
+ s = s + " .stat { min-width: 120px }\n"
294
+ s = s + " .chip-tab { color: #7a869f; background-color: #eef0f6 }\n"
295
+ s = s + " .chip-phone { color: #06122e; background-color: #b9e2ff }\n"
296
+ s = s + "}\n"
297
+
298
+ ; A finger needs a bigger target than a mouse does. Nothing on this page
299
+ ; is clickable, but the rule is here because it is the third thing a
300
+ ; media query can ask about and it costs one block to prove it works.
301
+ s = s + "@media (pointer: coarse) {\n"
302
+ s = s + " .nav-item { padding-top: 13px; padding-bottom: 13px }\n"
303
+ s = s + "}\n"
304
+
305
+ return s
306
+ }
307
+
308
+ ; ------------------------------------------------------------------------
309
+ ; The tree. Names, and not one number.
310
+ ; ------------------------------------------------------------------------
311
+
312
+ fn card:EVGElement (tag:string title:string body:string) {
313
+ def c (tree Rp (Card))
314
+ c.addChild((tree Rp (CardTag tag)))
315
+ c.addChild((tree Rp (CardH title)))
316
+ c.addChild((tree Rp (CardP body)))
317
+ return c
318
+ }
319
+
320
+ fn stat:EVGElement (value:string label:string) {
321
+ def s (tree Rp (Stat))
322
+ s.addChild((tree Rp (StatN value)))
323
+ s.addChild((tree Rp (StatL label)))
324
+ return s
325
+ }
326
+
327
+ fn navItem:EVGElement (label:string) {
328
+ return (tree Rp (NavItem label))
329
+ }
330
+
331
+ ; What the badge says. This is the ONE thing the tree is told about the
332
+ ; window, and it is reporting the input rather than reacting to it.
333
+ fn badgeText:string () {
334
+ def w:int (to_int pageW)
335
+ def h:int (to_int pageH)
336
+ def band:string "wide"
337
+ if (pageW <= 1080.0) { band = "laptop" }
338
+ if (pageW <= 820.0) { band = "tablet" }
339
+ if (pageW <= 560.0) { band = "phone" }
340
+ return (((((to_string w) + " × ") + (to_string h)) + " px · ") + band)
341
+ }
342
+
343
+ fn build:EVGElement () {
344
+ def page (tree Rp (Page))
345
+
346
+ ; --- bar --------------------------------------------------------------
347
+ def bar (tree Rp (Bar))
348
+ bar.addChild((tree Rp (Brand "EVG")))
349
+ bar.addChild((tree Rp (BarTitle "responsive layout, laid out on every frame")))
350
+ bar.addChild((tree Rp (Spacer)))
351
+ bar.addChild((tree Rp (Badge (this.badgeText()))))
352
+ page.addChild(bar)
353
+
354
+ ; --- hero -------------------------------------------------------------
355
+ def hero (tree Rp (Hero))
356
+ hero.addChild((tree Rp (HeroH "Sama puu, sama tyylitiedosto, mikä tahansa leveys")))
357
+ hero.addChild((tree Rp (HeroP ("Selain ei aseta tällä sivulla mitään. EVG saa ikkunan koon, "
358
+ + "ratkaisee @media-säännöt sitä vasten, laskee laatikot ja antaa SVG-piirtäjälle "
359
+ + "valmiit pikselit. Muuta ikkunan kokoa — koko putki ajetaan uudelleen."))))
360
+
361
+ def chips (tree Rp (Chips))
362
+ chips.addChild((tree Rp (ChipW "> 1080px · 4 saraketta")))
363
+ chips.addChild((tree Rp (ChipL "≤ 1080px · 3 saraketta")))
364
+ chips.addChild((tree Rp (ChipT "≤ 820px · sivupalkki ylös")))
365
+ chips.addChild((tree Rp (ChipP "≤ 560px · 1 sarake")))
366
+ hero.addChild(chips)
367
+ page.addChild(hero)
368
+
369
+ ; --- body -------------------------------------------------------------
370
+ def body (tree Rp (Body))
371
+
372
+ def side (tree Rp (Side))
373
+ side.addChild((tree Rp (SideH "MOOTTORI")))
374
+ def nav (tree Rp (NavList))
375
+ nav.addChild((this.navItem("Layout")))
376
+ nav.addChild((this.navItem("Stylesheet")))
377
+ nav.addChild((this.navItem("Text engine")))
378
+ nav.addChild((this.navItem("Display list")))
379
+ nav.addChild((this.navItem("Hit test")))
380
+ nav.addChild((this.navItem("A11y tree")))
381
+ side.addChild(nav)
382
+ body.addChild(side)
383
+
384
+ def main (tree Rp (Main))
385
+ main.addChild((tree Rp (SecH "Mitä leveys muuttaa")))
386
+
387
+ def cards (tree Rp (Cards))
388
+ cards.addChild((this.card("GRID" "Sarakkeet"
389
+ "grid-template-columns vaihtuu neljästä yhteen. Sama solulista, eri raidat.")))
390
+ cards.addChild((this.card("FLEX" "Suunta"
391
+ "Sivupalkin ja sisällön jako on flex-rivi, joka kääntyy sarakkeeksi 820 pikselissä.")))
392
+ cards.addChild((this.card("VW" "Marginaali"
393
+ "Reunojen padding on 4vw eli osuus sivusta, ei vanhemmasta. Se kapenee ikkunan mukana.")))
394
+ cards.addChild((this.card("WRAP" "Rivitys"
395
+ "Tilastorivi ei kysy leveyttä keneltäkään: min-width ja flex-wrap katkaisevat rivin itse.")))
396
+ cards.addChild((this.card("TEXT" "Katkot"
397
+ "Teksti mitataan samalla moottorilla joka sen piirtää, joten rivitys on se mikä näkyy.")))
398
+ cards.addChild((this.card("MEDIA" "Ehdot"
399
+ "@media on ehto säännöille, ei uusi valitsin: spesifisyys säilyy ennallaan.")))
400
+ cards.addChild((this.card("POINTER" "Osoitin"
401
+ "(pointer: coarse) kasvattaa navin kohteet sormelle. Isäntä kertoo kumpi on käytössä.")))
402
+ cards.addChild((this.card("SAMA" "Yksi puu"
403
+ "Tämä sivu kelpaa sellaisenaan PDF:ksi ja PNG:ksi. Vain sivun koko on eri.")))
404
+ main.addChild(cards)
405
+
406
+ def stats (tree Rp (Stats))
407
+ stats.addChild((this.stat("3" "@media-lohkoa")))
408
+ stats.addChild((this.stat("0" "kovaa pikseliä puussa")))
409
+ stats.addChild((this.stat("1" "tyylitiedosto")))
410
+ stats.addChild((this.stat("6" "piirtokohdetta")))
411
+ main.addChild(stats)
412
+
413
+ body.addChild(main)
414
+ page.addChild(body)
415
+
416
+ ; --- foot -------------------------------------------------------------
417
+ def foot (tree Rp (Foot))
418
+ foot.addChild((tree Rp (FootT ("lib/evg/web/responsive — puu rakennetaan, tyylit "
419
+ + "ratkaistaan ja laatikot lasketaan uudelleen jokaisella koon muutoksella."))))
420
+ page.addChild(foot)
421
+
422
+ return page
423
+ }
424
+
425
+ ; How tall the page turned out.
426
+ ;
427
+ ; NOT `root.calculatedHeight`: `EVGLayout` gives a root with no stated
428
+ ; height the page height, because a document's root IS the page — which is
429
+ ; right for paper and wrong for a window, where the content is free to be
430
+ ; taller than the viewport and scroll. So the answer is the lowest edge any
431
+ ; child reached, plus the root's own bottom padding, and the caller sizes
432
+ ; the surface to that.
433
+ fn measuredHeight:double (root:EVGElement) {
434
+ def bottom:double 0.0
435
+ def i:int 0
436
+ def n:int (root.getChildCount())
437
+ while (i < n) {
438
+ def c:EVGElement (root.getChild(i))
439
+ def b:double (c.calculatedY + c.calculatedHeight)
440
+ if (b > bottom) {
441
+ bottom = b
442
+ }
443
+ i = (i + 1)
444
+ }
445
+ ; The RESOLVED box, not the declared unit: `paddingBottom` is still the
446
+ ; `28px` the sheet wrote, and `box` is what layout made of it.
447
+ def box:EVGBox root.box
448
+ bottom = (bottom + box.paddingBottomPx)
449
+ if (bottom < pageH) {
450
+ bottom = pageH
451
+ }
452
+ return bottom
453
+ }
454
+
455
+ ; ------------------------------------------------------------------------
456
+ ; One frame: tree, cascade, layout, draw commands, JSON.
457
+ ; ------------------------------------------------------------------------
458
+ fn render:string () {
459
+ def root:EVGElement (this.build())
460
+
461
+ def sheet (new EVGStyleSheet())
462
+ sheet.parse(css)
463
+ lastErrors = (array_length sheet.errors)
464
+ ; The viewport is stated, not guessed: with none, a conditional rule
465
+ ; does not apply at all.
466
+ sheet.setViewport(pageW pageH coarse)
467
+ sheet.applyTree(root "")
468
+
469
+ def lay (new EVGLayout())
470
+ lay.setPageSize(pageW pageH)
471
+ lay.layout(root)
472
+
473
+ ; A second pass, and only when the content came out taller than the
474
+ ; window. `EVGLayout` gives an unstated root the PAGE height, so the
475
+ ; first pass leaves the page background 900px tall under 1800px of
476
+ ; cards; stating the measured height and laying out again paints it to
477
+ ; the bottom. The page SIZE is not touched, so `vw`, `vh` and every
478
+ ; `@media` bound still mean the window and not the document.
479
+ def tall:double (this.measuredHeight(root))
480
+ if (tall > pageH) {
481
+ root.height = (EVGUnit.px(tall))
482
+ lay.layout(root)
483
+ }
484
+
485
+ def dl (new EVGDisplayList())
486
+ ; The list must break paragraphs exactly where layout broke them.
487
+ dl.setTextEngine((lay.getTextEngine()))
488
+ dl.build(root)
489
+
490
+ lastHeight = (this.measuredHeight(root))
491
+ lastCommands = (dl.count())
492
+
493
+ def json:string "{\"width\":"
494
+ json = json + (EVGDisplayList.num(pageW))
495
+ json = json + ",\"height\":" + (EVGDisplayList.num(lastHeight))
496
+ json = json + ",\"cssErrors\":" + (to_string lastErrors)
497
+ json = json + ",\"list\":" + (dl.toJson()) + "}"
498
+ return json
499
+ }
500
+
501
+ ; The same frame, as the ops a host that keeps nodes applies — the
502
+ ; retained DOM painter (`html/evg-dom.js`) reads this. Same tree, same
503
+ ; cascade, same layout; the display list is not built, because nothing
504
+ ; below the seam is asked for.
505
+ fn renderHost:string () {
506
+ def root:EVGElement (this.build())
507
+ def sheet (new EVGStyleSheet())
508
+ sheet.parse(css)
509
+ lastErrors = (array_length sheet.errors)
510
+ sheet.setViewport(pageW pageH coarse)
511
+ sheet.applyTree(root "")
512
+ def lay (new EVGLayout())
513
+ lay.setPageSize(pageW pageH)
514
+ lay.layout(root)
515
+ def tall:double (this.measuredHeight(root))
516
+ if (tall > pageH) {
517
+ root.height = (EVGUnit.px(tall))
518
+ lay.layout(root)
519
+ }
520
+ host.setTextEngine((lay.getTextEngine()))
521
+ host.build(root)
522
+ lastHeight = (this.measuredHeight(root))
523
+ lastCommands = host.count
524
+ def json:string "{\"width\":"
525
+ json = json + (EVGDisplayList.num(pageW))
526
+ json = json + ",\"height\":" + (EVGDisplayList.num(lastHeight))
527
+ json = json + ",\"cssErrors\":" + (to_string lastErrors)
528
+ json = json + ",\"host\":" + (host.toJson()) + "}"
529
+ return json
530
+ }
531
+ }
@@ -0,0 +1,97 @@
1
+ # Responsive layout, live
2
+
3
+ A page as wide as the browser window, laid out **again on every resize** by the
4
+ EVG engine compiled into the browser. The browser lays out nothing: it is handed
5
+ an `<svg>` full of absolute coordinates that EVG computed.
6
+
7
+ ```sh
8
+ npm run evg:responsive:web:serve # build and serve on http://localhost:8007/
9
+ npm run evg:responsive:check # the same layout at four widths, no browser
10
+ npm run evg:responsive:web:smoke # the built page, driven in Chromium
11
+ npm run evg:dom:check # the same page painted as retained DOM (?painter=dom), checked
12
+ npm run evg:responsive:web # build only -> dist/
13
+ ```
14
+
15
+ The showcase build ships the same files to `/evg/responsive/` on Pages.
16
+
17
+ ## Why it exists
18
+
19
+ Every other EVG page in this repository is laid out **once**, at a size somebody
20
+ typed: a sheet of A4 for the PDF, 420×320 for the conformance playground,
21
+ `boxmodel.json` at whatever it was exported at. That is a fair test of the
22
+ layout and no test at all of the part CSS calls responsive — `@media`, `vw`,
23
+ percentages, a grid that changes how many columns it has.
24
+
25
+ Here every frame runs the whole pipeline:
26
+
27
+ ```
28
+ build the tree EvgResponsiveDemo.build()
29
+ state the viewport EVGStyleSheet.setViewport(w, h, coarse)
30
+ resolve the cascade applyTree — matching @media blocks contribute
31
+ lay out EVGLayout.layout, setPageSize(w, h) ← also vw / vh
32
+ flatten EVGDisplayList.build
33
+ paint ../../html/evg-html.js, the SVG backend
34
+ ```
35
+
36
+ About a millisecond of layout per frame at 1400px, reported in the strip at the
37
+ bottom of the page along with the width EVG was given and how many draw commands
38
+ came out.
39
+
40
+ ## What is being demonstrated
41
+
42
+ The tree in [`EvgResponsiveDemo.rgr`](EvgResponsiveDemo.rgr) has no width, no
43
+ colour and no size anywhere in it — it is a list of names. Every number on the
44
+ screen comes from `defaultCss()`, and its three `@media` blocks are the entire
45
+ difference between the wide layout and the phone one:
46
+
47
+ | Width | |
48
+ | --- | --- |
49
+ | `> 1080px` | sidebar beside the content, cards four across |
50
+ | `≤ 1080px` | cards three across |
51
+ | `≤ 820px` | sidebar above the content, cards two across |
52
+ | `≤ 560px` | one card per row, smaller type, tighter padding |
53
+
54
+ Plus two things no breakpoint decides: the page margins are `4vw`, a share of
55
+ the window rather than of the parent, and the stat strip wraps on its own
56
+ because its tiles state a `min-width` and the line runs out.
57
+
58
+ `@media (pointer: coarse)` is in there too — the *pointer: coarse* button in the
59
+ strip toggles what the host reports, and the sidebar's rows grow for a finger.
60
+
61
+ ## The files
62
+
63
+ | | |
64
+ | --- | --- |
65
+ | `EvgResponsiveDemo.rgr` | the page: the tree, the stylesheet, and one `render()` that returns a display list as JSON |
66
+ | `EvgResponsiveCheck.rgr` | the same layout at four widths, asserted in Node |
67
+ | `index.html` | the stage, the resize observer and the controls |
68
+ | `build.mjs` | compiles the demo to a browser IIFE and copies the painter beside it |
69
+ | `smoke.mjs` | serves `dist/` and drives it in Chromium |
70
+ | `dom-check.mjs` | the same page through `html/evg-dom.js` — a DOM node per element, patched from `EVGHostTree`'s ops — asked whether every node is where the engine put it and whether a resize kept them |
71
+
72
+ ## What it found
73
+
74
+ The page did what a demo is for. Dragging the window edge flickered: the content
75
+ dropped below the sidebar and came back up a pixel later, over and over.
76
+
77
+ `.side` and `.main` are a flex row and `.main` is `flex: 1`, so its width is
78
+ computed by the layout out of the same line it is then measured against — and
79
+ `(a - b - c) + b + c` can land one ulp above `a`, at which point the row is too
80
+ wide for itself and wraps. It failed at **127 of the 680 integer widths between
81
+ 821 and 1500**, scattered rather than in a band, which is why it read as a
82
+ flicker rather than as a breakpoint.
83
+
84
+ Fixed in `EVGLayout` by allowing a hundredth of a pixel of overflow before the
85
+ row wraps (`ISSUES.md` #8). Guarded in three places: `EVGFlexWrapTest.rgr` in
86
+ the engine, the width sweep in `EvgResponsiveCheck` here, and a sweep in
87
+ `smoke.mjs` that reads it off the painted boxes in Chromium.
88
+
89
+ ## The checks
90
+
91
+ `EvgResponsiveCheck` counts card columns by **grouping the laid-out cards by
92
+ their `y`** rather than by reading the stylesheet back: however the grid decided
93
+ to place them, the cards sharing the top row are the columns. The sidebar's move
94
+ is checked the same way — where its box ended up, not what rule put it there.
95
+ It also checks the rule that a stylesheet with **no viewport stated** applies no
96
+ conditional rule at all, because a media query that cannot be evaluated has no
97
+ truth value.