ranger-compiler 3.5.1 → 3.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (338) hide show
  1. package/CHANGELOG.md +1064 -20
  2. package/LICENSE +3 -1
  3. package/README.md +123 -28
  4. package/dist/Lang.rgr +1188 -290
  5. package/dist/api.d.ts +2343 -879
  6. package/dist/api.js +79923 -56921
  7. package/dist/lib/JSON.rgr +102 -91
  8. package/dist/lib/Shell.rgr +4 -4
  9. package/dist/lib/apple/AppleToolchain.rgr +4 -4
  10. package/dist/lib/apple/README.md +5 -4
  11. package/dist/lib/apple/apple_test.rgr +1 -1
  12. package/dist/lib/core/README.md +1 -1
  13. package/dist/lib/evg/EVG.rgr +12 -0
  14. package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
  15. package/dist/lib/evg/EVGA11yTree.rgr +894 -0
  16. package/dist/lib/evg/EVGBox.rgr +267 -0
  17. package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
  18. package/dist/lib/evg/EVGCodepoint.rgr +316 -0
  19. package/dist/lib/evg/EVGColor.rgr +700 -0
  20. package/dist/lib/evg/EVGCommands.rgr +177 -0
  21. package/dist/lib/evg/EVGComponent.rgr +331 -0
  22. package/dist/lib/evg/EVGComponentTest.rgr +387 -0
  23. package/dist/lib/evg/EVGConnector.rgr +541 -0
  24. package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
  25. package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
  26. package/dist/lib/evg/EVGEasing.rgr +370 -0
  27. package/dist/lib/evg/EVGEffectTest.rgr +253 -0
  28. package/dist/lib/evg/EVGElement.rgr +4914 -0
  29. package/dist/lib/evg/EVGFixedTest.rgr +289 -0
  30. package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
  31. package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
  32. package/dist/lib/evg/EVGFling.rgr +244 -0
  33. package/dist/lib/evg/EVGFocus.rgr +400 -0
  34. package/dist/lib/evg/EVGFocusTest.rgr +399 -0
  35. package/dist/lib/evg/EVGGradient.rgr +322 -0
  36. package/dist/lib/evg/EVGGrapheme.rgr +190 -0
  37. package/dist/lib/evg/EVGGrid.rgr +975 -0
  38. package/dist/lib/evg/EVGHitTest.rgr +208 -0
  39. package/dist/lib/evg/EVGHoles.rgr +294 -0
  40. package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
  41. package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
  42. package/dist/lib/evg/EVGHostTree.rgr +834 -0
  43. package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
  44. package/dist/lib/evg/EVGImageDecode.rgr +117 -0
  45. package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
  46. package/dist/lib/evg/EVGInspect.rgr +883 -0
  47. package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
  48. package/dist/lib/evg/EVGJsonTest.rgr +535 -0
  49. package/dist/lib/evg/EVGLayout.rgr +4220 -0
  50. package/dist/lib/evg/EVGMeasure.rgr +1267 -0
  51. package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
  52. package/dist/lib/evg/EVGPatch.rgr +1721 -0
  53. package/dist/lib/evg/EVGPatchTest.rgr +692 -0
  54. package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
  55. package/dist/lib/evg/EVGReconcile.rgr +226 -0
  56. package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
  57. package/dist/lib/evg/EVGReject.rgr +126 -0
  58. package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
  59. package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
  60. package/dist/lib/evg/EVGRuler.rgr +232 -0
  61. package/dist/lib/evg/EVGRulerTest.rgr +172 -0
  62. package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
  63. package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
  64. package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
  65. package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
  66. package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
  67. package/dist/lib/evg/EVGText.rgr +105 -0
  68. package/dist/lib/evg/EVGTextEngine.rgr +536 -0
  69. package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
  70. package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
  71. package/dist/lib/evg/EVGToolbar.rgr +1369 -0
  72. package/dist/lib/evg/EVGTransition.rgr +728 -0
  73. package/dist/lib/evg/EVGTreeJson.rgr +721 -0
  74. package/dist/lib/evg/EVGUnit.rgr +554 -0
  75. package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
  76. package/dist/lib/evg/EvgApp.rgr +189 -0
  77. package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
  78. package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
  79. package/dist/lib/evg/EvgHost.rgr +451 -0
  80. package/dist/lib/evg/EvgTest.rgr +91 -0
  81. package/dist/lib/evg/EvgTraceColor.rgr +236 -0
  82. package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
  83. package/dist/lib/evg/EvgTraceFit.rgr +767 -0
  84. package/dist/lib/evg/EvgTracePath.rgr +435 -0
  85. package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
  86. package/dist/lib/evg/EvgViewport.rgr +313 -0
  87. package/dist/lib/evg/FxDemoDoc.rgr +185 -0
  88. package/dist/lib/evg/HOSTS.md +227 -0
  89. package/dist/lib/evg/ISSUES.md +835 -0
  90. package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
  91. package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
  92. package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
  93. package/dist/lib/evg/PLAN_EVG.md +518 -0
  94. package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
  95. package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
  96. package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
  97. package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
  98. package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
  99. package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
  100. package/dist/lib/evg/PathBuilder.rgr +333 -0
  101. package/dist/lib/evg/README.md +1236 -0
  102. package/dist/lib/evg/SPEC.md +1252 -0
  103. package/dist/lib/evg/SVGPathParser.rgr +1199 -0
  104. package/dist/lib/evg/SvgParser.rgr +1736 -0
  105. package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
  106. package/dist/lib/evg/VectorShapes.rgr +331 -0
  107. package/dist/lib/evg/VectorStroke.rgr +107 -0
  108. package/dist/lib/evg/VectorViewBox.rgr +380 -0
  109. package/dist/lib/evg/agent/README.md +290 -0
  110. package/dist/lib/evg/agent/evg_agent.rgr +899 -0
  111. package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
  112. package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
  113. package/dist/lib/evg/agent/fixtures/connector.css +63 -0
  114. package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
  115. package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
  116. package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
  117. package/dist/lib/evg/agent/fixtures/popover.css +99 -0
  118. package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
  119. package/dist/lib/evg/agent/roundtrip.sh +74 -0
  120. package/dist/lib/evg/agent/smoke.sh +230 -0
  121. package/dist/lib/evg/android/README.md +97 -0
  122. package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
  123. package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
  124. package/dist/lib/evg/android/androidstubs/App.kt +30 -0
  125. package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
  126. package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
  127. package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
  128. package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
  129. package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
  130. package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
  131. package/dist/lib/evg/android/androidstubs/View.kt +113 -0
  132. package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
  133. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
  134. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
  135. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
  136. package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
  137. package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
  138. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
  139. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
  140. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
  141. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
  142. package/dist/lib/evg/apple/README.md +128 -0
  143. package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
  144. package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
  145. package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
  146. package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
  147. package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
  148. package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
  149. package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
  150. package/dist/lib/evg/bench/README.md +64 -0
  151. package/dist/lib/evg/bench/layout-bench.mjs +316 -0
  152. package/dist/lib/evg/bench/layout-cases.mjs +510 -0
  153. package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
  154. package/dist/lib/evg/bin/.gitignore +17 -0
  155. package/dist/lib/evg/evg_test.rgr +313 -0
  156. package/dist/lib/evg/gl/README.md +198 -0
  157. package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
  158. package/dist/lib/evg/gl/blur-check.mjs +399 -0
  159. package/dist/lib/evg/gl/boxmodel.json +1 -0
  160. package/dist/lib/evg/gl/demo.html +46 -0
  161. package/dist/lib/evg/gl/effect-presets.css +285 -0
  162. package/dist/lib/evg/gl/effect-presets.js +63 -0
  163. package/dist/lib/evg/gl/effect-shots.mjs +135 -0
  164. package/dist/lib/evg/gl/evg-a11y.js +566 -0
  165. package/dist/lib/evg/gl/evg-binary.js +160 -0
  166. package/dist/lib/evg/gl/evg-engine.js +296 -0
  167. package/dist/lib/evg/gl/evg-fx.js +237 -0
  168. package/dist/lib/evg/gl/evg-gestures.js +209 -0
  169. package/dist/lib/evg/gl/evg-list.js +167 -0
  170. package/dist/lib/evg/gl/evg-measure.js +186 -0
  171. package/dist/lib/evg/gl/evg-textinput.js +303 -0
  172. package/dist/lib/evg/gl/evg-view.js +144 -0
  173. package/dist/lib/evg/gl/evg-webgl.js +3942 -0
  174. package/dist/lib/evg/gl/fx-check.mjs +998 -0
  175. package/dist/lib/evg/gl/fx-demo.html +166 -0
  176. package/dist/lib/evg/gl/fx-demo.js +2 -0
  177. package/dist/lib/evg/gl/fx-serve.mjs +47 -0
  178. package/dist/lib/evg/gl/gestures-check.mjs +189 -0
  179. package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
  180. package/dist/lib/evg/gl/measure-check.mjs +135 -0
  181. package/dist/lib/evg/gl/rotation-check.mjs +207 -0
  182. package/dist/lib/evg/gl/shift-check.mjs +113 -0
  183. package/dist/lib/evg/gl/stroke-check.mjs +168 -0
  184. package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
  185. package/dist/lib/evg/gl/view-check.mjs +343 -0
  186. package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
  187. package/dist/lib/evg/html/evg-dom.js +318 -0
  188. package/dist/lib/evg/html/evg-html.js +600 -0
  189. package/dist/lib/evg/inspect/README.md +415 -0
  190. package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
  191. package/dist/lib/evg/inspect/evg-inspect.js +947 -0
  192. package/dist/lib/evg/inspect/shots/css.png +0 -0
  193. package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
  194. package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
  195. package/dist/lib/evg/inspect/shots/state.png +0 -0
  196. package/dist/lib/evg/inspect/shots.mjs +226 -0
  197. package/dist/lib/evg/oracle/css-blur.json +576 -0
  198. package/dist/lib/evg/oracle/css-box.json +157 -0
  199. package/dist/lib/evg/oracle/css-timing.json +709 -0
  200. package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
  201. package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
  202. package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
  203. package/dist/lib/evg/original/EVGColor.clj +310 -0
  204. package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
  205. package/dist/lib/evg/original/SVGPath.rgr +627 -0
  206. package/dist/lib/evg/original/Vec2.crgr +103 -0
  207. package/dist/lib/evg/ranger.json +9 -0
  208. package/dist/lib/evg/showcase/README.md +246 -0
  209. package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
  210. package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
  211. package/dist/lib/evg/showcase/build.mjs +651 -0
  212. package/dist/lib/evg/showcase/pages/album.tsx +30 -0
  213. package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
  214. package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
  215. package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
  216. package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
  217. package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
  218. package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
  219. package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
  220. package/dist/lib/evg/showcase/pages/more.tsx +332 -0
  221. package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
  222. package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
  223. package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
  224. package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
  225. package/dist/lib/evg/showcase/pages/units.tsx +35 -0
  226. package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
  227. package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
  228. package/dist/lib/evg/showcase/pages/views.tsx +223 -0
  229. package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
  230. package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
  231. package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
  232. package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
  233. package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
  234. package/dist/lib/evg/showcase/themes/more-default.css +128 -0
  235. package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
  236. package/dist/lib/evg/showcase/themes/showcase.css +508 -0
  237. package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
  238. package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
  239. package/dist/lib/evg/showcase/themes/views-default.css +15 -0
  240. package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
  241. package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
  242. package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
  243. package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
  244. package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
  245. package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
  246. package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
  247. package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
  248. package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
  249. package/dist/lib/evg/web/responsive/README.md +97 -0
  250. package/dist/lib/evg/web/responsive/build.mjs +90 -0
  251. package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
  252. package/dist/lib/evg/web/responsive/index.html +177 -0
  253. package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
  254. package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
  255. package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
  256. package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
  257. package/dist/lib/evg/web/tools/minify.mjs +60 -0
  258. package/dist/lib/evg/web/tracer/build.mjs +87 -0
  259. package/dist/lib/evg/web/tracer/index.html +2805 -0
  260. package/dist/lib/evg/web/tracer/sample.png +0 -0
  261. package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
  262. package/dist/lib/evgr/Cargo.lock +21 -0
  263. package/dist/lib/evgr/Cargo.toml +19 -0
  264. package/dist/lib/evgr/README.md +140 -0
  265. package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
  266. package/dist/lib/evgr/bench/compare.mjs +252 -0
  267. package/dist/lib/evgr/bench/speed.mjs +277 -0
  268. package/dist/lib/evgr/bin/.gitignore +3 -0
  269. package/dist/lib/evgr/src/bin/bench.rs +106 -0
  270. package/dist/lib/evgr/src/bin/smoke.rs +13 -0
  271. package/dist/lib/evgr/src/grid.rs +730 -0
  272. package/dist/lib/evgr/src/lib.rs +1003 -0
  273. package/dist/lib/evgr/src/style.rs +468 -0
  274. package/dist/lib/evgr/src/text.rs +83 -0
  275. package/dist/lib/image/BitReader.rgr +171 -0
  276. package/dist/lib/image/Buffer.rgr +173 -0
  277. package/dist/lib/image/DCT.rgr +283 -0
  278. package/dist/lib/image/Deflate.rgr +339 -0
  279. package/dist/lib/image/HuffmanDecoder.rgr +181 -0
  280. package/dist/lib/image/ImageBuffer.rgr +706 -0
  281. package/dist/lib/image/JPEGDecoder.rgr +808 -0
  282. package/dist/lib/image/PNGDecoder.rgr +544 -0
  283. package/dist/lib/image/PNGEncoder.rgr +388 -0
  284. package/dist/lib/image/PPMImage.rgr +224 -0
  285. package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
  286. package/dist/lib/image/README.md +33 -0
  287. package/dist/lib/image/RasterBuffer.rgr +294 -0
  288. package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
  289. package/dist/lib/image/WebPDecoder.rgr +433 -0
  290. package/dist/lib/image/WebPLossless.rgr +1035 -0
  291. package/dist/lib/image/WebPLossy.rgr +1929 -0
  292. package/dist/lib/image/ranger.json +9 -0
  293. package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
  294. package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
  295. package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
  296. package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
  297. package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
  298. package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
  299. package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
  300. package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
  301. package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
  302. package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
  303. package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
  304. package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
  305. package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
  306. package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
  307. package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
  308. package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
  309. package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
  310. package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
  311. package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
  312. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
  313. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
  314. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
  315. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
  316. package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
  317. package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
  318. package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
  319. package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
  320. package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
  321. package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
  322. package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
  323. package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
  324. package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
  325. package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
  326. package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
  327. package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
  328. package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
  329. package/dist/lib/image/tests/run_webp_tests.sh +39 -0
  330. package/dist/lib/rust/RsJson.rgr +468 -0
  331. package/dist/lib/rust/RsPrelude.rgr +1663 -0
  332. package/dist/lib/shell_test.rgr +7 -7
  333. package/dist/lib/stdlib.rgr +21 -5
  334. package/dist/lib/zip/ranger.json +6 -0
  335. package/dist/rgrc.js +87318 -67610
  336. package/package.json +1010 -1040
  337. package/dist/README.md +0 -117
  338. package/dist/package.json +0 -47
@@ -0,0 +1,471 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EVGStyleVarTest — the palette, and where it is allowed to live
5
+ ; ==============================================================================
6
+ ;
7
+ ; `@vars { --ink: #09090b }` and `color: var(--ink)`. Two claims are worth
8
+ ; testing and one of them is not about colour at all:
9
+ ;
10
+ ; WHAT IT MEANS. A theme replaces a palette rather than ninety rules, a
11
+ ; fallback stands in for a name nobody defined, and a name
12
+ ; nobody defined and no fallback is an ERROR — the
13
+ ; declaration is dropped rather than written half resolved,
14
+ ; because half a shorthand is worse than the value that was
15
+ ; there before.
16
+ ;
17
+ ; WHAT IT COSTS. `var()` is resolved when a PLAN is built, so two elements
18
+ ; of the same class resolve once between them. That is the
19
+ ; whole performance claim of the feature and it is checked
20
+ ; here against the sheet's own counters, not asserted in a
21
+ ; comment.
22
+ ;
23
+ ; And the honesty rule the syntax exists for: this engine has no root element
24
+ ; and no inheritance, so a palette written on a class would look element-scoped
25
+ ; and not be. `--x` in a class rule is reported, not quietly ignored.
26
+ ; ==============================================================================
27
+
28
+ Import "EVGElement.rgr"
29
+ Import "EVGUnit.rgr"
30
+ Import "EVGStyleSheet.rgr"
31
+
32
+ class VarCheck {
33
+ def passed:int 0
34
+ def failed:int 0
35
+
36
+ fn ok:void (name:string cond:boolean) {
37
+ if cond {
38
+ passed = (passed + 1)
39
+ print (" PASS " + name)
40
+ } {
41
+ failed = (failed + 1)
42
+ print (" FAIL " + name)
43
+ }
44
+ }
45
+
46
+ fn eqStr:void (name:string got:string want:string) {
47
+ def good:boolean (got == want)
48
+ if (good == false) {
49
+ print (((" got '" + got) + "' want '") + want + "'")
50
+ }
51
+ this.ok(name good)
52
+ }
53
+
54
+ fn eqInt:void (name:string got:int want:int) {
55
+ def good:boolean (got == want)
56
+ if (good == false) {
57
+ print ((" got " + (to_string got)) + " want " + (to_string want))
58
+ }
59
+ this.ok(name good)
60
+ }
61
+ }
62
+
63
+ class EVGStyleVarTest {
64
+
65
+ sfn sheetOf:EVGStyleSheet (css:string) {
66
+ def s (new EVGStyleSheet())
67
+ s.parse(css)
68
+ s.setViewport(800.0 600.0 false)
69
+ return s
70
+ }
71
+
72
+ sfn boxWith:EVGElement (cls:string) {
73
+ def el (EVGElement.createDiv())
74
+ el.id = "box"
75
+ el.className = cls
76
+ return el
77
+ }
78
+
79
+ ; The background's red channel, or -1 when nothing was written. A number
80
+ ; the failure can print, rather than "not equal".
81
+ ;
82
+ ; `isSet`, and not whether the field is there: a fresh element carries
83
+ ; `EVGColor.noColor()`, whose red is 0 — so "nothing was written" and
84
+ ; "black was written" look identical to anything that reads the channel.
85
+ sfn bgRed:int (el:EVGElement) {
86
+ if el.backgroundColor {
87
+ def c:EVGColor (unwrap el.backgroundColor)
88
+ if (c.isSet == false) {
89
+ return (0 - 1)
90
+ }
91
+ return (c.red())
92
+ }
93
+ return (0 - 1)
94
+ }
95
+
96
+ sfn inkRed:int (el:EVGElement) {
97
+ if el.color {
98
+ def c:EVGColor (unwrap el.color)
99
+ if (c.isSet == false) {
100
+ return (0 - 1)
101
+ }
102
+ return (c.red())
103
+ }
104
+ return (0 - 1)
105
+ }
106
+
107
+ ; The BOX's border colour, which is where the `border` shorthand puts it —
108
+ ; the element has a field of the same name and the shorthand does not write
109
+ ; to it.
110
+ sfn borderRed:int (el:EVGElement) {
111
+ if el.box.borderColor {
112
+ def c:EVGColor (unwrap el.box.borderColor)
113
+ if (c.isSet == false) {
114
+ return (0 - 1)
115
+ }
116
+ return (c.red())
117
+ }
118
+ return (0 - 1)
119
+ }
120
+
121
+ ; --- what it means --------------------------------------------------------
122
+
123
+ sfn testSubstitution:void (c:VarCheck) {
124
+ print "--- a value can name the palette ---"
125
+ def css:string ("@vars { --ink: rgb(20,0,0); }"
126
+ + " .box { color: var(--ink); }")
127
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
128
+ c.eqInt("the palette was read" (s.getVarCount()) 1)
129
+ c.eqInt("and it is not a rule" (s.getRuleCount()) 1)
130
+ c.eqInt("nothing was rejected" (s.getErrorCount()) 0)
131
+
132
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
133
+ s.applyTree(el "")
134
+ c.eqInt("the element got the palette's value" (EVGStyleVarTest.inkRed(el)) 20)
135
+
136
+ ; And the palette does not have to be written first. Nothing is
137
+ ; resolved while the sheet is being read — the whole file is parsed,
138
+ ; and a value is resolved when a plan for it is built.
139
+ def later:EVGStyleSheet (EVGStyleVarTest.sheetOf(".box { color: var(--ink); } @vars { --ink: rgb(21,0,0); }"))
140
+ def el2:EVGElement (EVGStyleVarTest.boxWith("box"))
141
+ later.applyTree(el2 "")
142
+ c.eqInt("declared after it is used" (EVGStyleVarTest.inkRed(el2)) 21)
143
+ c.eqInt("and still no error" (later.getErrorCount()) 0)
144
+ }
145
+
146
+ sfn testShorthand:void (c:VarCheck) {
147
+ print "--- and it works inside a shorthand ---"
148
+ ; The point of substituting TEXT before the value reaches
149
+ ; `setAttribute`: no property has to know that variables exist, so this
150
+ ; reaches the border shorthand's colour with nothing added for it.
151
+ def css:string ("@vars { --line: rgb(90,0,0); }"
152
+ + " .box { border: 2px solid var(--line); }")
153
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
154
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
155
+ s.applyTree(el "")
156
+ c.eqInt("no error" (s.getErrorCount()) 0)
157
+ c.eqInt("the shorthand's colour came from the palette" (EVGStyleVarTest.borderRed(el)) 90)
158
+ el.box.resolveUnits(400.0 200.0 16.0 16.0 0.0 0.0)
159
+ c.eqInt("and the rest of the shorthand survived" (to_int el.box.borderWidthPx) 2)
160
+ }
161
+
162
+ sfn testTheme:void (c:VarCheck) {
163
+ print "--- a theme is a palette, not a second set of rules ---"
164
+ def css:string ("@vars { --paper: rgb(10,0,0); }"
165
+ + " @vars marine { --paper: rgb(200,0,0); }"
166
+ + " .box { background-color: var(--paper); }")
167
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
168
+ c.eqInt("one rule, two declarations of one name" (s.getRuleCount()) 1)
169
+ c.eqInt("both are in the palette" (s.getVarCount()) 2)
170
+
171
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
172
+ s.applyTree(el "")
173
+ c.eqInt("with no theme the unscoped value" (EVGStyleVarTest.bgRed(el)) 10)
174
+ s.applyTree(el "marine")
175
+ c.eqInt("under the theme the scoped one" (EVGStyleVarTest.bgRed(el)) 200)
176
+ ; The thing a theme built out of rules has to be careful about — a
177
+ ; property with no unscoped counterpart stays behind — cannot happen
178
+ ; here: there is one declaration and it is resolved per theme.
179
+ s.applyTree(el "")
180
+ c.eqInt("and leaving it puts the first back" (EVGStyleVarTest.bgRed(el)) 10)
181
+ ; A theme nobody wrote a palette for is not an error: it falls through
182
+ ; to the unscoped values, which is what "optional theming" means.
183
+ s.applyTree(el "sunset")
184
+ c.eqInt("an unknown theme is just the unscoped palette" (EVGStyleVarTest.bgRed(el)) 10)
185
+ c.eqInt("and says nothing" (s.getErrorCount()) 0)
186
+ }
187
+
188
+ sfn testThemeList:void (c:VarCheck) {
189
+ print "--- more than one theme can be on at once ---"
190
+ ; The case an app hits the moment it has both: some rules scoped to a
191
+ ; PLACE — a screen, a print size — and its colours to a PALETTE. With
192
+ ; one slot the two fight over it.
193
+ def css:string ("@vars { --paper: rgb(10,0,0); }"
194
+ + " @vars ocean { --paper: rgb(30,0,0); }"
195
+ + " .box { background-color: var(--paper); }"
196
+ + " .theme-session .box { color: rgb(1,0,0); }")
197
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
198
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
199
+
200
+ s.applyTree(el "session")
201
+ c.eqInt("the screen's rule applies" (EVGStyleVarTest.inkRed(el)) 1)
202
+ c.eqInt("and the palette is the unscoped one" (EVGStyleVarTest.bgRed(el)) 10)
203
+
204
+ ; Both names, and both hold.
205
+ s.applyTree(el "session ocean")
206
+ c.eqInt("the screen's rule still applies" (EVGStyleVarTest.inkRed(el)) 1)
207
+ c.eqInt("and now so does the palette" (EVGStyleVarTest.bgRed(el)) 30)
208
+
209
+ ; Order in the list buys nothing, and a name nobody wrote is not an
210
+ ; error — the same as a single unknown theme.
211
+ s.applyTree(el "ocean session")
212
+ c.eqInt("the order of the list does not matter" (EVGStyleVarTest.bgRed(el)) 30)
213
+ s.applyTree(el "ocean sunset")
214
+ c.eqInt("an unknown name in the list is ignored" (EVGStyleVarTest.bgRed(el)) 30)
215
+ c.eqInt("and says nothing" (s.getErrorCount()) 0)
216
+
217
+ ; A prefix is not a name: "ocean" must not be found inside "oceanic".
218
+ s.applyTree(el "oceanic")
219
+ c.eqInt("a name is a whole token" (EVGStyleVarTest.bgRed(el)) 10)
220
+ }
221
+
222
+ sfn testIndirection:void (c:VarCheck) {
223
+ print "--- a variable may be written in terms of another ---"
224
+ def css:string ("@vars { --brand: rgb(70,0,0); --button: var(--brand); }"
225
+ + " .box { background-color: var(--button); }")
226
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
227
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
228
+ s.applyTree(el "")
229
+ c.eqInt("resolved through the chain" (EVGStyleVarTest.bgRed(el)) 70)
230
+ c.eqInt("no error" (s.getErrorCount()) 0)
231
+ }
232
+
233
+ sfn testThemeIndirection:void (c:VarCheck) {
234
+ print "--- and a theme may re-point one name and move everything under it ---"
235
+ ; What a palette is FOR: "marine" says one thing about the brand and
236
+ ; the button follows, because the button was never a colour.
237
+ def css:string ("@vars { --brand: rgb(70,0,0); --button: var(--brand); }"
238
+ + " @vars marine { --brand: rgb(180,0,0); }"
239
+ + " .box { background-color: var(--button); }")
240
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
241
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
242
+ s.applyTree(el "marine")
243
+ c.eqInt("the theme reached through the indirection" (EVGStyleVarTest.bgRed(el)) 180)
244
+ }
245
+
246
+ sfn testFallback:void (c:VarCheck) {
247
+ print "--- a fallback stands in, and steps aside ---"
248
+ def css:string ("@vars { --known: rgb(30,0,0); }"
249
+ + " .a { color: var(--known, rgb(240,0,0)); }"
250
+ + " .b { color: var(--missing, rgb(240,0,0)); }"
251
+ + " .c { color: var(--missing, rgb(0,0,0)); background-color: var(--nope, rgb(120,0,0)); }")
252
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
253
+ def a:EVGElement (EVGStyleVarTest.boxWith("a"))
254
+ s.applyTree(a "")
255
+ c.eqInt("a defined name ignores the fallback" (EVGStyleVarTest.inkRed(a)) 30)
256
+ def b:EVGElement (EVGStyleVarTest.boxWith("b"))
257
+ s.applyTree(b "")
258
+ c.eqInt("an undefined one takes it" (EVGStyleVarTest.inkRed(b)) 240)
259
+ def d:EVGElement (EVGStyleVarTest.boxWith("c"))
260
+ s.applyTree(d "")
261
+ c.eqInt("and a fallback may be a function call" (EVGStyleVarTest.bgRed(d)) 120)
262
+ c.eqInt("none of which is an error" (s.getErrorCount()) 0)
263
+ }
264
+
265
+ ; --- what it refuses to guess at ------------------------------------------
266
+
267
+ sfn testUndefined:void (c:VarCheck) {
268
+ print "--- an undefined name with no fallback is reported, not painted ---"
269
+ def css:string (".box { background-color: rgb(5,0,0); }"
270
+ + " .box { background-color: var(--nobody); }")
271
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
272
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
273
+ s.applyTree(el "")
274
+ c.eqInt("the sheet says so" (s.getErrorCount()) 1)
275
+ ; The declaration is DROPPED, so what shows is the rule before it and
276
+ ; not an unparseable colour. A page with a typo in it keeps working and
277
+ ; the error list says where.
278
+ c.eqInt("and the value before it stands" (EVGStyleVarTest.bgRed(el)) 5)
279
+ }
280
+
281
+ sfn testReportedOnce:void (c:VarCheck) {
282
+ print "--- and reported once, however many classes use it ---"
283
+ ; Parsing happens once; resolution happens wherever a plan is built. So
284
+ ; one typo used by six classes would be six copies of one sentence in
285
+ ; the panel that exists to say which sentence it is.
286
+ def css:string (".a { color: var(--nobody); }"
287
+ + " .b { color: var(--nobody); }"
288
+ + " .c { color: var(--nobody); }")
289
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
290
+ def root:EVGElement (EVGStyleVarTest.boxWith("wrap"))
291
+ root.addChild((EVGStyleVarTest.boxWith("a")))
292
+ root.addChild((EVGStyleVarTest.boxWith("b")))
293
+ root.addChild((EVGStyleVarTest.boxWith("c")))
294
+ s.applyTree(root "")
295
+ c.eqInt("three plans, one sentence" (s.getErrorCount()) 1)
296
+ }
297
+
298
+ sfn testCustomPropertyOnAClass:void (c:VarCheck) {
299
+ print "--- and a palette written on a class is refused ---"
300
+ ; There is no inheritance here, so this would look element-scoped and
301
+ ; not be: `.box` would be the only place the name existed, and it
302
+ ; would reach nothing. `@vars` is the only place it means something.
303
+ def css:string ".box { --ink: rgb(10,0,0); color: rgb(60,0,0); }"
304
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
305
+ c.eqInt("it is reported" (s.getErrorCount()) 1)
306
+ c.eqInt("and it did not join the palette" (s.getVarCount()) 0)
307
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
308
+ s.applyTree(el "")
309
+ c.eqInt("the rest of the rule is untouched" (EVGStyleVarTest.inkRed(el)) 60)
310
+ }
311
+
312
+ sfn testMalformed:void (c:VarCheck) {
313
+ print "--- malformed palettes and malformed uses ---"
314
+ def s1:EVGStyleSheet (EVGStyleVarTest.sheetOf("@vars theme marine { --a: rgb(1,0,0); }"))
315
+ c.eqInt("@vars takes at most a theme name" (s1.getErrorCount()) 1)
316
+ c.eqInt("and stores nothing from a header it did not understand" (s1.getVarCount()) 0)
317
+
318
+ def s2:EVGStyleSheet (EVGStyleVarTest.sheetOf("@vars { color: rgb(1,0,0); }"))
319
+ c.eqInt("a property inside @vars is reported" (s2.getErrorCount()) 1)
320
+
321
+ ; What follows asserts that NOTHING was written, which is the half of
322
+ ; "reported rather than painted" that matters — see `bgRed` for why
323
+ ; that is a question about `isSet` and not about a colour channel.
324
+ def s3:EVGStyleSheet (EVGStyleVarTest.sheetOf("@vars { --a: rgb(9,0,0); } .box { background-color: var(--a; }"))
325
+ def el3:EVGElement (EVGStyleVarTest.boxWith("box"))
326
+ s3.applyTree(el3 "")
327
+ c.eqInt("an unclosed var() is reported" (s3.getErrorCount()) 1)
328
+ c.eqInt("and writes nothing" (EVGStyleVarTest.bgRed(el3)) (0 - 1))
329
+
330
+ ; `--a: var(--b)` and `--b: var(--a)`. The check that matters is that
331
+ ; this RETURNS.
332
+ def s4:EVGStyleSheet (EVGStyleVarTest.sheetOf("@vars { --a: var(--b); --b: var(--a); } .box { background-color: var(--a); }"))
333
+ def el4:EVGElement (EVGStyleVarTest.boxWith("box"))
334
+ s4.applyTree(el4 "")
335
+ c.ok("a cycle is reported rather than spun on" ((s4.getErrorCount()) > 0))
336
+ c.eqInt("and writes nothing" (EVGStyleVarTest.bgRed(el4)) (0 - 1))
337
+ }
338
+
339
+ ; --- what it costs --------------------------------------------------------
340
+
341
+ sfn testResolvedPerPlanNotPerElement:void (c:VarCheck) {
342
+ print "--- resolved once per plan, not once per element ---"
343
+ def css:string ("@vars { --ink: rgb(40,0,0); }"
344
+ + " .box { color: var(--ink); background-color: var(--ink); }")
345
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
346
+ def parent:EVGElement (EVGStyleVarTest.boxWith("wrap"))
347
+ def i:int 0
348
+ while (i < 50) {
349
+ parent.addChild((EVGStyleVarTest.boxWith("box")))
350
+ i = (i + 1)
351
+ }
352
+ s.applyTree(parent "")
353
+ ; Fifty-one elements, two distinct class strings, and the sheet built
354
+ ; a plan for each: every other element replayed one. The palette was
355
+ ; therefore consulted twice — once for each declaration of `.box` —
356
+ ; however many rows the page has.
357
+ c.eqInt("one plan per distinct class" s.planMisses 2)
358
+ c.eqInt("everything else replayed one" s.planHits 49)
359
+ def kid:EVGElement (parent.getChild(7))
360
+ c.eqInt("and they all got the value" (EVGStyleVarTest.inkRed(kid)) 40)
361
+ }
362
+
363
+ ; --- the palette answers the viewport too ---------------------------------
364
+
365
+ sfn testMediaScoped:void (c:VarCheck) {
366
+ print "--- a variable may answer a media query ---"
367
+ def css:string ("@vars { --pad: 20px; }"
368
+ + " @media (max-width: 640px) { @vars { --pad: 4px; } }"
369
+ + " .box { padding: var(--pad); }")
370
+ def s (new EVGStyleSheet())
371
+ s.parse(css)
372
+ s.setViewport(1000.0 800.0 false)
373
+ def wide:EVGElement (EVGStyleVarTest.boxWith("box"))
374
+ s.applyTree(wide "")
375
+ wide.box.resolveUnits(400.0 200.0 16.0 16.0 0.0 0.0)
376
+ c.eqInt("on a wide surface the unconditional value" (to_int wide.box.paddingTopPx) 20)
377
+ ; And the narrow one is not a second element: the same sheet, told the
378
+ ; surface changed. `setViewport` drops the plans, so the palette is
379
+ ; consulted again rather than the old answer being replayed.
380
+ s.setViewport(500.0 800.0 false)
381
+ def narrow:EVGElement (EVGStyleVarTest.boxWith("box"))
382
+ s.applyTree(narrow "")
383
+ narrow.box.resolveUnits(400.0 200.0 16.0 16.0 0.0 0.0)
384
+ c.eqInt("on a narrow one the conditional value" (to_int narrow.box.paddingTopPx) 4)
385
+ c.eqInt("no error either way" (s.getErrorCount()) 0)
386
+ }
387
+
388
+ ; --- reloading -------------------------------------------------------------
389
+
390
+ sfn testReload:void (c:VarCheck) {
391
+ print "--- reloading replaces the palette rather than adding to it ---"
392
+ def s (new EVGStyleSheet())
393
+ s.parse("@vars { --ink: rgb(11,0,0); } .box { color: var(--ink); }")
394
+ s.setViewport(800.0 600.0 false)
395
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
396
+ s.applyTree(el "")
397
+ c.eqInt("the first sheet" (EVGStyleVarTest.inkRed(el)) 11)
398
+ ; The failure this guards: `parse` APPENDS, and the later of two equal
399
+ ; declarations wins — so a palette that is not cleared means the OLD
400
+ ; value outlives the edit. Which is exactly the case the inspector's
401
+ ; live editing walks into.
402
+ s.reload("@vars { --ink: rgb(222,0,0); } .box { color: var(--ink); }")
403
+ c.eqInt("and only one name after the reload" (s.getVarCount()) 1)
404
+ s.applyTree(el "")
405
+ c.eqInt("the edited value shows" (EVGStyleVarTest.inkRed(el)) 222)
406
+ }
407
+
408
+ sfn testTransitionThroughAVariable:void (c:VarCheck) {
409
+ print "--- a transition may be built out of the palette ---"
410
+ ; `transition` is checked for a timing function nobody implements, and
411
+ ; that check runs when the sheet is parsed — where `var(--speed)` reads
412
+ ; as a function call and would be reported as an unsupported one. The
413
+ ; check has to wait for the value.
414
+ def css:string ("@vars { --speed: 150ms; }"
415
+ + " .box { transition: background-color var(--speed) ease; background-color: rgb(1,0,0); }")
416
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
417
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
418
+ s.applyTree(el "")
419
+ c.eqInt("the variable is not mistaken for a timing function" (s.getErrorCount()) 0)
420
+ c.eqStr("and the resolved transition reached the element" el.transitionSpec
421
+ "background-color 150ms ease")
422
+
423
+ ; And a timing function that really is unsupported is still reported,
424
+ ; now that the check happens later: `spring()` is CSS-shaped and is not
425
+ ; CSS.
426
+ def bad:EVGStyleSheet (EVGStyleVarTest.sheetOf("@vars { --e: spring(1, 2); } .box { transition: opacity 100ms var(--e); }"))
427
+ def el2:EVGElement (EVGStyleVarTest.boxWith("box"))
428
+ bad.applyTree(el2 "")
429
+ c.eqInt("an unsupported one still is" (bad.getErrorCount()) 1)
430
+ }
431
+
432
+ sfn testNoVariables:void (c:VarCheck) {
433
+ print "--- a sheet with no variables in it is untouched ---"
434
+ def css:string ".box { color: rgb(3,0,0); background-color: rgb(4,0,0); }"
435
+ def s:EVGStyleSheet (EVGStyleVarTest.sheetOf(css))
436
+ def el:EVGElement (EVGStyleVarTest.boxWith("box"))
437
+ s.applyTree(el "")
438
+ c.eqInt("no palette" (s.getVarCount()) 0)
439
+ c.eqInt("no errors" (s.getErrorCount()) 0)
440
+ c.eqInt("and the values it always had" (EVGStyleVarTest.inkRed(el)) 3)
441
+ c.eqInt("both of them" (EVGStyleVarTest.bgRed(el)) 4)
442
+ }
443
+
444
+ sfn main:void () {
445
+ def c (new VarCheck())
446
+ print "=== EVG stylesheet: custom properties ==="
447
+ EVGStyleVarTest.testSubstitution(c)
448
+ EVGStyleVarTest.testShorthand(c)
449
+ EVGStyleVarTest.testTheme(c)
450
+ EVGStyleVarTest.testThemeList(c)
451
+ EVGStyleVarTest.testIndirection(c)
452
+ EVGStyleVarTest.testThemeIndirection(c)
453
+ EVGStyleVarTest.testFallback(c)
454
+ EVGStyleVarTest.testUndefined(c)
455
+ EVGStyleVarTest.testReportedOnce(c)
456
+ EVGStyleVarTest.testCustomPropertyOnAClass(c)
457
+ EVGStyleVarTest.testMalformed(c)
458
+ EVGStyleVarTest.testResolvedPerPlanNotPerElement(c)
459
+ EVGStyleVarTest.testMediaScoped(c)
460
+ EVGStyleVarTest.testTransitionThroughAVariable(c)
461
+ EVGStyleVarTest.testReload(c)
462
+ EVGStyleVarTest.testNoVariables(c)
463
+ print ""
464
+ print (("passed=" + (to_string c.passed)) + " failed=" + (to_string c.failed))
465
+ if (c.failed > 0) {
466
+ print "FAILURES"
467
+ } {
468
+ print "ALL PASS"
469
+ }
470
+ }
471
+ }
@@ -0,0 +1,105 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; EVGText.rgr - Text element for EVG layout
4
+
5
+ Import "EVGElement.rgr"
6
+ Import "EVGTextMeasurer.rgr"
7
+
8
+ class EVGText {
9
+ ; Extend base element
10
+ def element@(optional):EVGElement
11
+
12
+ ; Text content
13
+ def text:string ""
14
+
15
+ ; Calculated text metrics
16
+ def measuredWidth:double 0.0
17
+ def measuredHeight:double 0.0
18
+ def lineCount:int 1
19
+ def lines:[string]
20
+
21
+ Constructor () {
22
+ def el (new EVGElement())
23
+ el.tagName = "span"
24
+ el.elementType = 1
25
+ element = el
26
+ }
27
+
28
+ sfn create:EVGText (content:string) {
29
+ def t (new EVGText())
30
+ t.text = content
31
+ return t
32
+ }
33
+
34
+ fn getElement:EVGElement () {
35
+ return (unwrap element)
36
+ }
37
+
38
+ fn setText:void (content:string) {
39
+ text = content
40
+ }
41
+
42
+ fn setFontSize:void (size:double) {
43
+ element.fontSize = (EVGUnit.px(size))
44
+ element.inheritedFontSize = size
45
+ }
46
+
47
+ fn setFontFamily:void (family:string) {
48
+ element.fontFamily = family
49
+ }
50
+
51
+ fn setColor:void (c:EVGColor) {
52
+ element.color = c
53
+ }
54
+
55
+ fn measureText:void (measurer:EVGTextMeasurer maxWidth:double) {
56
+ ; Measure text and wrap if needed
57
+ def fs:double element.inheritedFontSize
58
+ def ff:string element.fontFamily
59
+
60
+ if (maxWidth > 0.0) {
61
+ ; Wrap text to fit width
62
+ lines = (measurer.wrapText(text ff fs maxWidth))
63
+ lineCount = (array_length lines)
64
+
65
+ ; Calculate total dimensions
66
+ def lineHeight:double (measurer.getLineHeight(ff fs))
67
+ measuredHeight = ((to_double lineCount) * lineHeight)
68
+
69
+ ; Find widest line
70
+ measuredWidth = 0.0
71
+ def i:int 0
72
+ while (i < lineCount) {
73
+ def line:string (itemAt lines i)
74
+ def lineWidth:double (measurer.measureTextWidth(line ff fs))
75
+ if (lineWidth > measuredWidth) {
76
+ measuredWidth = lineWidth
77
+ }
78
+ i = i + 1
79
+ }
80
+ } {
81
+ ; No wrapping - single line
82
+ def metrics:EVGTextMetrics (measurer.measureText(text ff fs))
83
+ measuredWidth = metrics.width
84
+ measuredHeight = metrics.height
85
+ lineCount = 1
86
+ clear lines
87
+ push lines text
88
+ }
89
+
90
+ ; Update element calculated dimensions
91
+ element.calculatedWidth = measuredWidth
92
+ element.calculatedHeight = measuredHeight
93
+ }
94
+
95
+ fn getLine:string (index:int) {
96
+ if (index < (array_length lines)) {
97
+ return (itemAt lines index)
98
+ }
99
+ return ""
100
+ }
101
+
102
+ fn toString:string () {
103
+ return ("EVGText[\"" + text + "\" " + (to_string measuredWidth) + "x" + (to_string measuredHeight) + " lines:" + (to_string lineCount) + "]")
104
+ }
105
+ }