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,1003 @@
1
+ //! EVGr: the layout of EVG documents as a strict Rust module
2
+ //! (docs/plans/PLAN_RUST_SYNTAX.md), beside the Ranger engine in `lib/evg`.
3
+ //!
4
+ //! An experiment: the same kind of document -- boxes styled with CSS
5
+ //! declarations, laid out as flexbox with EVG's box model and initial values
6
+ //! -- written once in Rust, built by cargo for native code and by `rgrc` for
7
+ //! every Ranger target. `bench/compare.mjs` lays out the cases of
8
+ //! `lib/evg/bench/layout-cases.mjs` with EVG, EVGr and Chromium;
9
+ //! `bench/speed.mjs` and `src/bin/bench.rs` time the fixtures of
10
+ //! `lib/evg/bench/layout-bench.mjs`.
11
+ //!
12
+ //! What is laid out: `display` block / flex / none, `flex-direction` (with
13
+ //! the reverse forms), `flex-wrap`, width / height and their min / max (px,
14
+ //! %), padding, margin (px), gap, `flex-grow` / `flex-shrink` /
15
+ //! `flex-basis` / `flex`, `justify-content`, `align-items`, `align-self`,
16
+ //! `align-content`, `position: absolute` with top / right / bottom / left,
17
+ //! `aspect-ratio`, `calc()` of px and %, grid (src/grid.rs), and text
18
+ //! measured with EVG's default advance table.
19
+ //!
20
+ //! The tree is an arena: a node is an index, its children a list of
21
+ //! indices. Layout writes `x`, `y` (page coordinates), `w` and `h`
22
+ //! (border box: padding is inside, as in EVG).
23
+
24
+ use ranger::prelude::*;
25
+
26
+ mod grid;
27
+ mod style;
28
+ mod text;
29
+
30
+ use style::Len;
31
+
32
+ const INF: double = 1000000000000000000.0;
33
+
34
+ pub struct EvgrNode {
35
+ /// 0 block, 1 flex, 2 none, 3 grid
36
+ pub display: int,
37
+ pub row: bool,
38
+ pub reverse: bool,
39
+ pub wrap: bool,
40
+ pub width: Len,
41
+ pub height: Len,
42
+ pub min_w: Len,
43
+ pub max_w: Len,
44
+ pub min_h: Len,
45
+ pub max_h: Len,
46
+ pub basis: Len,
47
+ pub grow: double,
48
+ pub shrink: double,
49
+ pub pad_t_len: Len,
50
+ pub pad_r_len: Len,
51
+ pub pad_b_len: Len,
52
+ pub pad_l_len: Len,
53
+ /// the padding in pixels, resolved against the containing block
54
+ pub pad_t: double,
55
+ pub pad_r: double,
56
+ pub pad_b: double,
57
+ pub pad_l: double,
58
+ /// `aspect-ratio` as width / height, 0.0 when none
59
+ pub ratio: double,
60
+ // grid: the container's templates, the item's placement
61
+ pub grid_cols: String,
62
+ pub grid_rows: String,
63
+ pub grid_areas: String,
64
+ pub grid_auto_rows: String,
65
+ pub grid_dense: bool,
66
+ pub grid_column: String,
67
+ pub grid_row: String,
68
+ pub grid_area: String,
69
+ pub mar_t: double,
70
+ pub mar_r: double,
71
+ pub mar_b: double,
72
+ pub mar_l: double,
73
+ pub row_gap: double,
74
+ pub col_gap: double,
75
+ pub justify: int,
76
+ pub align_items: int,
77
+ pub align_self: int,
78
+ pub align_content: int,
79
+ pub absolute: bool,
80
+ pub top: Len,
81
+ pub right: Len,
82
+ pub bottom: Len,
83
+ pub left: Len,
84
+ /// the declared font size, -1.0 when inherited
85
+ pub font_size: double,
86
+ pub text: String,
87
+ pub children: Vec<int>,
88
+ pub parent: int,
89
+ // the result
90
+ pub x: double,
91
+ pub y: double,
92
+ pub w: double,
93
+ pub h: double,
94
+ // this pass: the font size in effect, the width it was laid out at and
95
+ // the height it was given (-1.0 auto), the max-content width
96
+ fs: double,
97
+ // the text measured at `text_fs`: its width and its widest word
98
+ text_fs: double,
99
+ text_w: double,
100
+ text_min: double,
101
+ laid: bool,
102
+ lay_w: double,
103
+ max_cw: double,
104
+ }
105
+
106
+ impl EvgrNode {
107
+ pub fn new(parent: int) -> EvgrNode {
108
+ EvgrNode {
109
+ display: 0,
110
+ row: false,
111
+ reverse: false,
112
+ // EVG's initial values: column, wrap, align-items flex-start
113
+ wrap: true,
114
+ width: Len::auto(),
115
+ height: Len::auto(),
116
+ min_w: Len::auto(),
117
+ max_w: Len::auto(),
118
+ min_h: Len::auto(),
119
+ max_h: Len::auto(),
120
+ basis: Len::auto(),
121
+ grow: 0.0,
122
+ shrink: 1.0,
123
+ pad_t_len: Len::px(0.0),
124
+ pad_r_len: Len::px(0.0),
125
+ pad_b_len: Len::px(0.0),
126
+ pad_l_len: Len::px(0.0),
127
+ pad_t: 0.0,
128
+ pad_r: 0.0,
129
+ pad_b: 0.0,
130
+ pad_l: 0.0,
131
+ ratio: 0.0,
132
+ grid_cols: String::new(),
133
+ grid_rows: String::new(),
134
+ grid_areas: String::new(),
135
+ grid_auto_rows: String::new(),
136
+ grid_dense: false,
137
+ grid_column: String::new(),
138
+ grid_row: String::new(),
139
+ grid_area: String::new(),
140
+ mar_t: 0.0,
141
+ mar_r: 0.0,
142
+ mar_b: 0.0,
143
+ mar_l: 0.0,
144
+ row_gap: 0.0,
145
+ col_gap: 0.0,
146
+ justify: style::START,
147
+ align_items: style::UNSET,
148
+ align_self: style::UNSET,
149
+ align_content: style::START,
150
+ absolute: false,
151
+ top: Len::auto(),
152
+ right: Len::auto(),
153
+ bottom: Len::auto(),
154
+ left: Len::auto(),
155
+ font_size: -1.0,
156
+ text: String::new(),
157
+ children: Vec::new(),
158
+ parent,
159
+ x: 0.0,
160
+ y: 0.0,
161
+ w: 0.0,
162
+ h: 0.0,
163
+ fs: 14.0,
164
+ text_fs: -1.0,
165
+ text_w: 0.0,
166
+ text_min: 0.0,
167
+ laid: false,
168
+ lay_w: -1.0,
169
+ max_cw: -1.0,
170
+ }
171
+ }
172
+
173
+ /// Padding in pixels; a percentage is of `cb_w`, the width of the
174
+ /// containing block, on all four sides.
175
+ pub fn resolve_pads(&mut self, cb_w: double) {
176
+ self.pad_t = self.pad_t_len.resolve(cb_w).max(0.0);
177
+ self.pad_r = self.pad_r_len.resolve(cb_w).max(0.0);
178
+ self.pad_b = self.pad_b_len.resolve(cb_w).max(0.0);
179
+ self.pad_l = self.pad_l_len.resolve(cb_w).max(0.0);
180
+ }
181
+ }
182
+
183
+ pub struct EvgrTree {
184
+ pub nodes: Vec<EvgrNode>,
185
+ table: Vec<double>,
186
+ /// `property:value` declarations that were not laid out
187
+ pub unsupported: Vec<String>,
188
+ }
189
+
190
+ impl EvgrTree {
191
+ pub fn new() -> EvgrTree {
192
+ EvgrTree { nodes: Vec::new(), table: text::advance_table(), unsupported: Vec::new() }
193
+ }
194
+
195
+ /// A box styled by `css`, under `parent` (-1 for the root). Answers its
196
+ /// index.
197
+ pub fn add(&mut self, parent: int, css: &str) -> int {
198
+ let i = self.nodes.len() as int;
199
+ self.nodes.push(EvgrNode::new(parent));
200
+ if parent >= 0 {
201
+ self.nodes[parent as usize].children.push(i);
202
+ }
203
+ self.apply_css(i, css);
204
+ i
205
+ }
206
+
207
+ /// A text leaf.
208
+ pub fn add_text(&mut self, parent: int, css: &str, text: &str) -> int {
209
+ let i = self.add(parent, css);
210
+ self.nodes[i as usize].text = text.to_string();
211
+ i
212
+ }
213
+
214
+ pub fn count(&self) -> int {
215
+ self.nodes.len() as int
216
+ }
217
+
218
+ pub fn x(&self, i: int) -> double {
219
+ self.nodes[i as usize].x
220
+ }
221
+
222
+ pub fn y(&self, i: int) -> double {
223
+ self.nodes[i as usize].y
224
+ }
225
+
226
+ pub fn w(&self, i: int) -> double {
227
+ self.nodes[i as usize].w
228
+ }
229
+
230
+ pub fn h(&self, i: int) -> double {
231
+ self.nodes[i as usize].h
232
+ }
233
+
234
+ pub fn unsupported_count(&self) -> int {
235
+ self.unsupported.len() as int
236
+ }
237
+
238
+ pub fn unsupported_at(&self, k: int) -> String {
239
+ self.unsupported[k as usize].clone()
240
+ }
241
+
242
+ fn apply_css(&mut self, i: int, css: &str) {
243
+ for part in css.split(';') {
244
+ let decl = part.trim();
245
+ if decl.is_empty() {
246
+ continue;
247
+ }
248
+ if let Some(colon) = decl.find(':') {
249
+ let name = decl[..colon].trim().to_string();
250
+ let value = decl[colon + 1..].trim().to_string();
251
+ let known = style::apply(&mut self.nodes[i as usize], &name, &value);
252
+ if !known {
253
+ self.unsupported.push(format!("{}:{}", name, value));
254
+ }
255
+ }
256
+ }
257
+ }
258
+
259
+ // ------------------------------------------------------------ layout
260
+
261
+ /// Lays the tree out from its root (node 0) in a viewport of `width` x
262
+ /// `height`.
263
+ pub fn layout(&mut self, width: double, height: double) {
264
+ if self.nodes.is_empty() {
265
+ return;
266
+ }
267
+ let mut k = 0;
268
+ while k < self.nodes.len() {
269
+ self.nodes[k].laid = false;
270
+ self.nodes[k].max_cw = -1.0;
271
+ k += 1;
272
+ }
273
+ self.inherit_fonts(0, 14.0);
274
+ self.nodes[0].resolve_pads(width);
275
+ let mut w = self.nodes[0].width.resolve(width);
276
+ if w < 0.0 {
277
+ w = width;
278
+ }
279
+ w = self.clamp_w(0, w, width);
280
+ // EVG: a root without a height is as tall as the viewport
281
+ let mut h = self.nodes[0].height.resolve(height);
282
+ if h < 0.0 {
283
+ h = height;
284
+ }
285
+ self.place(0, 0.0, 0.0, w, h);
286
+ }
287
+
288
+ fn inherit_fonts(&mut self, i: int, from: double) {
289
+ let own = self.nodes[i as usize].font_size;
290
+ let fs = if own > 0.0 { own } else { from };
291
+ self.nodes[i as usize].fs = fs;
292
+ let kids = self.nodes[i as usize].children.clone();
293
+ for k in &kids {
294
+ self.inherit_fonts(*k, fs);
295
+ }
296
+ }
297
+
298
+ /// Measures a text leaf once per font size.
299
+ fn measure_text(&mut self, i: int) {
300
+ let iu = i as usize;
301
+ let fs = self.nodes[iu].fs;
302
+ if self.nodes[iu].text_fs == fs {
303
+ return;
304
+ }
305
+ let t = self.nodes[iu].text.clone();
306
+ self.nodes[iu].text_w = text::measure(&self.table, &t, fs);
307
+ self.nodes[iu].text_min = text::min_width(&self.table, &t, fs);
308
+ self.nodes[iu].text_fs = fs;
309
+ }
310
+
311
+ fn is_text(&self, i: int) -> bool {
312
+ let n = &self.nodes[i as usize];
313
+ !n.text.is_empty() && n.children.is_empty()
314
+ }
315
+
316
+ fn pad_x(&self, i: int) -> double {
317
+ self.nodes[i as usize].pad_l + self.nodes[i as usize].pad_r
318
+ }
319
+
320
+ fn pad_y(&self, i: int) -> double {
321
+ self.nodes[i as usize].pad_t + self.nodes[i as usize].pad_b
322
+ }
323
+
324
+ fn clamp_w(&self, i: int, w: double, base: double) -> double {
325
+ let mut r = w;
326
+ let mx = self.nodes[i as usize].max_w.resolve(base);
327
+ if mx >= 0.0 && r > mx {
328
+ r = mx;
329
+ }
330
+ // min last: it wins over max
331
+ let mn = self.nodes[i as usize].min_w.resolve(base);
332
+ if mn >= 0.0 && r < mn {
333
+ r = mn;
334
+ }
335
+ r
336
+ }
337
+
338
+ fn clamp_h(&self, i: int, h: double, base: double) -> double {
339
+ let mut r = h;
340
+ let mx = self.nodes[i as usize].max_h.resolve(base);
341
+ if mx >= 0.0 && r > mx {
342
+ r = mx;
343
+ }
344
+ let mn = self.nodes[i as usize].min_h.resolve(base);
345
+ if mn >= 0.0 && r < mn {
346
+ r = mn;
347
+ }
348
+ r
349
+ }
350
+
351
+ fn is_row(&self, i: int) -> bool {
352
+ self.nodes[i as usize].display == 1 && self.nodes[i as usize].row
353
+ }
354
+
355
+ fn in_flow(&self, k: int) -> bool {
356
+ self.nodes[k as usize].display != 2 && !self.nodes[k as usize].absolute
357
+ }
358
+
359
+ /// The width the box takes when nothing limits it (border box).
360
+ fn max_content_w(&mut self, i: int) -> double {
361
+ let cached = self.nodes[i as usize].max_cw;
362
+ if cached >= 0.0 {
363
+ return cached;
364
+ }
365
+ let r = self.content_w(i, false, false);
366
+ self.nodes[i as usize].max_cw = r;
367
+ r
368
+ }
369
+
370
+ /// The narrowest the box can be without overflowing (border box).
371
+ fn min_content_w(&mut self, i: int) -> double {
372
+ self.content_w(i, true, false)
373
+ }
374
+
375
+ /// The content-based minimum of a flex item: its min-content width,
376
+ /// whatever width it declares (CSS's automatic minimum size).
377
+ fn min_content_own(&mut self, i: int) -> double {
378
+ self.content_w(i, true, true)
379
+ }
380
+
381
+ fn content_w(&mut self, i: int, want_min: bool, ignore_width: bool) -> double {
382
+ if self.nodes[i as usize].display == 2 {
383
+ return 0.0;
384
+ }
385
+ let fixed = self.nodes[i as usize].width.resolve(-1.0);
386
+ if fixed >= 0.0 && !ignore_width {
387
+ return fixed;
388
+ }
389
+ let pads = self.pad_x(i);
390
+ if self.is_text(i) {
391
+ self.measure_text(i);
392
+ let tw = if want_min { self.nodes[i as usize].text_min } else { self.nodes[i as usize].text_w };
393
+ return self.clamp_w(i, tw + pads, -1.0);
394
+ }
395
+ let row = self.is_row(i);
396
+ let kids = self.nodes[i as usize].children.clone();
397
+ let mut total = 0.0;
398
+ let mut count = 0;
399
+ for k in &kids {
400
+ if !self.in_flow(*k) {
401
+ continue;
402
+ }
403
+ let kw = if want_min { self.min_content_w(*k) } else { self.max_content_w(*k) };
404
+ let outer = kw + self.nodes[*k as usize].mar_l + self.nodes[*k as usize].mar_r;
405
+ if row && !want_min {
406
+ total += outer;
407
+ } else if row && want_min && !self.nodes[i as usize].wrap {
408
+ total += outer;
409
+ } else if outer > total {
410
+ total = outer;
411
+ }
412
+ count += 1;
413
+ }
414
+ if row && count > 1 && (!want_min || !self.nodes[i as usize].wrap) {
415
+ total += self.nodes[i as usize].col_gap * ((count - 1) as double);
416
+ }
417
+ self.clamp_w(i, total + pads, -1.0)
418
+ }
419
+
420
+ /// The height of `i` laid out at width `w`.
421
+ fn height_for(&mut self, i: int, w: double) -> double {
422
+ let fixed = self.nodes[i as usize].height.resolve(-1.0);
423
+ if fixed >= 0.0 {
424
+ return self.clamp_h(i, fixed, -1.0);
425
+ }
426
+ let ratio = self.nodes[i as usize].ratio;
427
+ if ratio > 0.0 {
428
+ return self.clamp_h(i, w / ratio, -1.0);
429
+ }
430
+ self.place(i, 0.0, 0.0, w, -1.0);
431
+ self.nodes[i as usize].h
432
+ }
433
+
434
+ fn translate(&mut self, i: int, dx: double, dy: double) {
435
+ self.nodes[i as usize].x += dx;
436
+ self.nodes[i as usize].y += dy;
437
+ let kids = self.nodes[i as usize].children.clone();
438
+ for k in &kids {
439
+ self.translate(*k, dx, dy);
440
+ }
441
+ }
442
+
443
+ /// Puts the box at (x, y) with width `w` and height `h` (-1.0: from
444
+ /// its content), and lays out what is inside.
445
+ fn place(&mut self, i: int, x: double, y: double, w: double, h: double) {
446
+ let iu = i as usize;
447
+ // laid out at this width already this pass: the same boxes, moved
448
+ if self.nodes[iu].laid && self.nodes[iu].lay_w == w && (h < 0.0 || (h - self.nodes[iu].h).abs() < 0.0000001) {
449
+ let dx = x - self.nodes[iu].x;
450
+ let dy = y - self.nodes[iu].y;
451
+ if dx != 0.0 || dy != 0.0 {
452
+ self.translate(i, dx, dy);
453
+ }
454
+ return;
455
+ }
456
+ self.nodes[iu].x = x;
457
+ self.nodes[iu].y = y;
458
+ self.nodes[iu].w = w;
459
+ self.nodes[iu].laid = true;
460
+ self.nodes[iu].lay_w = w;
461
+ if self.nodes[iu].display == 2 {
462
+ self.nodes[iu].w = 0.0;
463
+ self.nodes[iu].h = 0.0;
464
+ return;
465
+ }
466
+ let iw = (w - self.pad_x(i)).max(0.0);
467
+ let mut hh = h;
468
+ if hh < 0.0 && self.nodes[iu].ratio > 0.0 {
469
+ hh = w / self.nodes[iu].ratio;
470
+ }
471
+ if self.is_text(i) {
472
+ let fs = self.nodes[iu].fs;
473
+ self.measure_text(i);
474
+ // one line when it fits, else wrapped at spaces
475
+ let mut lines = 1;
476
+ if self.nodes[iu].text_w > iw + 0.001 {
477
+ let t = self.nodes[iu].text.clone();
478
+ let (wrapped, _widest) = text::wrap(&self.table, &t, fs, iw);
479
+ lines = wrapped;
480
+ }
481
+ if hh < 0.0 {
482
+ hh = (lines as double) * text::line_height(fs) + self.pad_y(i);
483
+ }
484
+ } else {
485
+ let ih = if hh >= 0.0 { (hh - self.pad_y(i)).max(0.0) } else { -1.0 };
486
+ let content = if self.nodes[iu].display == 3 { self.layout_grid(i, iw, ih) } else { self.layout_box(i, iw, ih) };
487
+ if hh < 0.0 {
488
+ hh = content + self.pad_y(i);
489
+ }
490
+ }
491
+ hh = self.clamp_h(i, hh, -1.0);
492
+ self.nodes[iu].h = hh;
493
+ self.place_absolutes(i);
494
+ }
495
+
496
+ fn place_absolutes(&mut self, i: int) {
497
+ let kids = self.nodes[i as usize].children.clone();
498
+ let x0 = self.nodes[i as usize].x + self.nodes[i as usize].pad_l;
499
+ let y0 = self.nodes[i as usize].y + self.nodes[i as usize].pad_t;
500
+ let cw = (self.nodes[i as usize].w - self.pad_x(i)).max(0.0);
501
+ let ch = (self.nodes[i as usize].h - self.pad_y(i)).max(0.0);
502
+ for k in &kids {
503
+ let ku = *k as usize;
504
+ if !self.nodes[ku].absolute || self.nodes[ku].display == 2 {
505
+ continue;
506
+ }
507
+ let l = self.nodes[ku].left.resolve(cw);
508
+ let r = self.nodes[ku].right.resolve(cw);
509
+ let t = self.nodes[ku].top.resolve(ch);
510
+ let b = self.nodes[ku].bottom.resolve(ch);
511
+ let mut w = self.nodes[ku].width.resolve(cw);
512
+ if w < 0.0 && l >= 0.0 && r >= 0.0 {
513
+ w = cw - l - r - self.nodes[ku].mar_l - self.nodes[ku].mar_r;
514
+ }
515
+ if w < 0.0 {
516
+ w = self.max_content_w(*k);
517
+ }
518
+ w = self.clamp_w(*k, w, cw);
519
+ let mut h = self.nodes[ku].height.resolve(ch);
520
+ if h < 0.0 && t >= 0.0 && b >= 0.0 {
521
+ h = ch - t - b - self.nodes[ku].mar_t - self.nodes[ku].mar_b;
522
+ }
523
+ if h < 0.0 {
524
+ h = self.height_for(*k, w);
525
+ }
526
+ h = self.clamp_h(*k, h, ch);
527
+ let mut x = x0;
528
+ if l >= 0.0 {
529
+ x = x0 + l;
530
+ } else if r >= 0.0 {
531
+ x = x0 + cw - r - w - self.nodes[ku].mar_r - self.nodes[ku].mar_l;
532
+ }
533
+ let mut y = y0;
534
+ if t >= 0.0 {
535
+ y = y0 + t;
536
+ } else if b >= 0.0 {
537
+ y = y0 + ch - b - h - self.nodes[ku].mar_b - self.nodes[ku].mar_t;
538
+ }
539
+ self.place(*k, x + self.nodes[ku].mar_l, y + self.nodes[ku].mar_t, w, h);
540
+ }
541
+ }
542
+
543
+ /// The alignment of item `k` in container `c` on the cross axis.
544
+ fn align_of(&self, c: int, k: int) -> int {
545
+ let own = self.nodes[k as usize].align_self;
546
+ if own != style::UNSET {
547
+ return own;
548
+ }
549
+ let items = self.nodes[c as usize].align_items;
550
+ if items != style::UNSET {
551
+ // EVG: a text leaf without a width fits its text even where the
552
+ // column stretches its boxes
553
+ if items == style::STRETCH && !self.is_row(c) && self.is_text(k) {
554
+ return style::START;
555
+ }
556
+ return items;
557
+ }
558
+ // EVG: a box in a column fills the width, a text leaf fits its text;
559
+ // in a row nothing stretches
560
+ if !self.is_row(c) && !self.is_text(k) {
561
+ return style::STRETCH;
562
+ }
563
+ style::START
564
+ }
565
+
566
+ /// Lays out the children of `c` inside its content box (`iw` wide, `ih`
567
+ /// high or -1.0 when that is to come from the content). Answers the
568
+ /// content height.
569
+ fn layout_box(&mut self, c: int, iw: double, ih: double) -> double {
570
+ let cu = c as usize;
571
+ let row = self.is_row(c);
572
+ let wrap = self.nodes[cu].display == 1 && self.nodes[cu].wrap;
573
+ let main_size = if row { iw } else { ih };
574
+ let cross_size = if row { ih } else { iw };
575
+ let main_gap = if row { self.nodes[cu].col_gap } else { self.nodes[cu].row_gap };
576
+ let cross_gap = if row { self.nodes[cu].row_gap } else { self.nodes[cu].col_gap };
577
+ let kids = self.nodes[cu].children.clone();
578
+ let mut items: Vec<int> = Vec::new();
579
+ for k in &kids {
580
+ self.nodes[*k as usize].resolve_pads(iw);
581
+ if self.in_flow(*k) {
582
+ items.push(*k);
583
+ }
584
+ }
585
+ let n = items.len();
586
+ if n == 0 {
587
+ return 0.0;
588
+ }
589
+ // flex base sizes and their limits
590
+ let mut base: Vec<double> = Vec::new();
591
+ let mut hypo: Vec<double> = Vec::new();
592
+ let mut min_m: Vec<double> = Vec::new();
593
+ let mut max_m: Vec<double> = Vec::new();
594
+ let mut main_mar: Vec<double> = Vec::new();
595
+ let mut cross_mar: Vec<double> = Vec::new();
596
+ let mut j = 0;
597
+ while j < n {
598
+ let k = items[j];
599
+ let ku = k as usize;
600
+ let mm = if row { self.nodes[ku].mar_l + self.nodes[ku].mar_r } else { self.nodes[ku].mar_t + self.nodes[ku].mar_b };
601
+ let cm = if row { self.nodes[ku].mar_t + self.nodes[ku].mar_b } else { self.nodes[ku].mar_l + self.nodes[ku].mar_r };
602
+ main_mar.push(mm);
603
+ cross_mar.push(cm);
604
+ let spec = if row { self.nodes[ku].width.resolve(main_size) } else { self.nodes[ku].height.resolve(main_size) };
605
+ let mut b = self.nodes[ku].basis.resolve(main_size);
606
+ if b < 0.0 {
607
+ b = spec;
608
+ }
609
+ if b < 0.0 {
610
+ if row {
611
+ b = self.max_content_w(k);
612
+ } else {
613
+ let cw = self.item_cross_w(c, k, cross_size, cm);
614
+ b = self.height_for(k, cw);
615
+ }
616
+ }
617
+ let mut lo = if row { self.nodes[ku].min_w.resolve(main_size) } else { self.nodes[ku].min_h.resolve(main_size) };
618
+ if lo < 0.0 {
619
+ // the automatic minimum: no narrower than the content
620
+ if row {
621
+ lo = self.min_content_own(k);
622
+ if spec >= 0.0 && spec < lo {
623
+ lo = spec;
624
+ }
625
+ } else if !self.nodes[ku].children.is_empty() || self.is_text(k) {
626
+ if spec < 0.0 {
627
+ let cw2 = self.item_cross_w(c, k, cross_size, cm);
628
+ lo = self.content_height(k, cw2);
629
+ } else {
630
+ lo = 0.0;
631
+ }
632
+ } else {
633
+ lo = 0.0;
634
+ }
635
+ }
636
+ let mut hi = if row { self.nodes[ku].max_w.resolve(main_size) } else { self.nodes[ku].max_h.resolve(main_size) };
637
+ if hi < 0.0 {
638
+ hi = INF;
639
+ }
640
+ base.push(b);
641
+ // min wins over max when they conflict
642
+ hypo.push(b.min(hi).max(lo));
643
+ min_m.push(lo);
644
+ max_m.push(hi);
645
+ j += 1;
646
+ }
647
+ // lines
648
+ let mut line_start: Vec<int> = Vec::new();
649
+ let mut line_end: Vec<int> = Vec::new();
650
+ let mut cur_start = 0;
651
+ let mut used = 0.0;
652
+ j = 0;
653
+ while j < n {
654
+ let outer = hypo[j] + main_mar[j];
655
+ if wrap && main_size >= 0.0 && j > cur_start && used + main_gap + outer > main_size + 0.0001 {
656
+ line_start.push(cur_start as int);
657
+ line_end.push(j as int);
658
+ cur_start = j;
659
+ used = outer;
660
+ } else if j == cur_start {
661
+ used = outer;
662
+ } else {
663
+ used = used + main_gap + outer;
664
+ }
665
+ j += 1;
666
+ }
667
+ line_start.push(cur_start as int);
668
+ line_end.push(n as int);
669
+ // main sizes: grow or shrink each line into the container
670
+ let mut main_final: Vec<double> = hypo.clone();
671
+ let lines = line_start.len();
672
+ let mut li = 0;
673
+ while li < lines {
674
+ let a = line_start[li] as usize;
675
+ let e = line_end[li] as usize;
676
+ // grow and shrink are for flex items; a block's children keep
677
+ // their sizes
678
+ if main_size >= 0.0 && self.nodes[cu].display == 1 {
679
+ self.resolve_flex(&items, a, e, main_size, main_gap, &base, &hypo, &min_m, &max_m, &main_mar, &mut main_final);
680
+ }
681
+ li += 1;
682
+ }
683
+ // cross sizes, and each line's
684
+ let mut cross: Vec<double> = Vec::new();
685
+ let mut stretch: Vec<bool> = Vec::new();
686
+ j = 0;
687
+ while j < n {
688
+ let k = items[j];
689
+ let ku = k as usize;
690
+ let al = self.align_of(c, k);
691
+ let spec = if row { self.nodes[ku].height.resolve(cross_size) } else { self.nodes[ku].width.resolve(cross_size) };
692
+ let st = spec < 0.0 && al == style::STRETCH;
693
+ let cs = if spec >= 0.0 {
694
+ if row { self.clamp_h(k, spec, cross_size) } else { self.clamp_w(k, spec, cross_size) }
695
+ } else if row {
696
+ self.height_for(k, main_final[j])
697
+ } else {
698
+ self.item_cross_w(c, k, cross_size, cross_mar[j])
699
+ };
700
+ cross.push(cs);
701
+ stretch.push(st);
702
+ j += 1;
703
+ }
704
+ // baseline alignment (rows): each item's first baseline, from its top
705
+ let mut bl: Vec<double> = Vec::new();
706
+ j = 0;
707
+ while j < n {
708
+ let k = items[j];
709
+ if row && self.align_of(c, k) == style::BASELINE {
710
+ bl.push(self.baseline_of(k, cross[j]));
711
+ } else {
712
+ bl.push(-1.0);
713
+ }
714
+ j += 1;
715
+ }
716
+ let mut line_cross: Vec<double> = Vec::new();
717
+ let mut line_base: Vec<double> = Vec::new();
718
+ li = 0;
719
+ while li < lines {
720
+ let a = line_start[li] as usize;
721
+ let e = line_end[li] as usize;
722
+ let mut m = 0.0;
723
+ let mut above = 0.0;
724
+ let mut below = 0.0;
725
+ let mut q = a;
726
+ while q < e {
727
+ let o = cross[q] + cross_mar[q];
728
+ if o > m {
729
+ m = o;
730
+ }
731
+ if bl[q] >= 0.0 {
732
+ let up = self.nodes[items[q] as usize].mar_t + bl[q];
733
+ if up > above {
734
+ above = up;
735
+ }
736
+ if o - up > below {
737
+ below = o - up;
738
+ }
739
+ }
740
+ q += 1;
741
+ }
742
+ if above + below > m {
743
+ m = above + below;
744
+ }
745
+ line_cross.push(m);
746
+ line_base.push(above);
747
+ li += 1;
748
+ }
749
+ if !wrap && cross_size >= 0.0 {
750
+ line_cross[0] = cross_size;
751
+ }
752
+ // align-content: the lines in the container's cross size
753
+ let mut total_cross = 0.0;
754
+ li = 0;
755
+ while li < lines {
756
+ total_cross += line_cross[li];
757
+ li += 1;
758
+ }
759
+ total_cross += cross_gap * ((lines - 1) as double);
760
+ let mut cross_pos = 0.0;
761
+ let mut line_space = cross_gap;
762
+ if wrap && cross_size >= 0.0 {
763
+ let free = cross_size - total_cross;
764
+ let ac = self.nodes[cu].align_content;
765
+ if ac == style::STRETCH && free > 0.0 {
766
+ let add = free / (lines as double);
767
+ li = 0;
768
+ while li < lines {
769
+ line_cross[li] += add;
770
+ li += 1;
771
+ }
772
+ } else if ac == style::END {
773
+ cross_pos = free;
774
+ } else if ac == style::CENTER {
775
+ cross_pos = free / 2.0;
776
+ } else if ac == style::BETWEEN && lines > 1 && free > 0.0 {
777
+ line_space = cross_gap + free / ((lines - 1) as double);
778
+ } else if ac == style::AROUND && free > 0.0 {
779
+ cross_pos = free / (2.0 * (lines as double));
780
+ line_space = cross_gap + free / (lines as double);
781
+ } else if ac == style::EVENLY && free > 0.0 {
782
+ cross_pos = free / ((lines + 1) as double);
783
+ line_space = cross_gap + free / ((lines + 1) as double);
784
+ }
785
+ }
786
+ // place each line
787
+ let x0 = self.nodes[cu].x + self.nodes[cu].pad_l;
788
+ let y0 = self.nodes[cu].y + self.nodes[cu].pad_t;
789
+ let reverse = self.nodes[cu].reverse;
790
+ let mut content_main = 0.0;
791
+ li = 0;
792
+ while li < lines {
793
+ let a = line_start[li] as usize;
794
+ let e = line_end[li] as usize;
795
+ let count = e - a;
796
+ let mut line_used = main_gap * ((count - 1) as double);
797
+ let mut q = a;
798
+ while q < e {
799
+ line_used += main_final[q] + main_mar[q];
800
+ q += 1;
801
+ }
802
+ if line_used > content_main {
803
+ content_main = line_used;
804
+ }
805
+ let avail = if main_size >= 0.0 { main_size } else { line_used };
806
+ let free = avail - line_used;
807
+ let mut pos = 0.0;
808
+ let mut space = main_gap;
809
+ let jc = self.nodes[cu].justify;
810
+ if free > 0.0 {
811
+ if jc == style::END {
812
+ pos = free;
813
+ } else if jc == style::CENTER {
814
+ pos = free / 2.0;
815
+ } else if jc == style::BETWEEN && count > 1 {
816
+ space = main_gap + free / ((count - 1) as double);
817
+ } else if jc == style::AROUND {
818
+ pos = free / (2.0 * (count as double));
819
+ space = main_gap + free / (count as double);
820
+ } else if jc == style::EVENLY {
821
+ pos = free / ((count + 1) as double);
822
+ space = main_gap + free / ((count + 1) as double);
823
+ }
824
+ }
825
+ let lc = line_cross[li];
826
+ q = a;
827
+ while q < e {
828
+ let k = items[q];
829
+ let ku = k as usize;
830
+ let size_m = main_final[q];
831
+ let mut size_c = cross[q];
832
+ if stretch[q] {
833
+ size_c = lc - cross_mar[q];
834
+ size_c = if row { self.clamp_h(k, size_c, cross_size) } else { self.clamp_w(k, size_c, cross_size) };
835
+ }
836
+ let al = self.align_of(c, k);
837
+ let outer_c = size_c + cross_mar[q];
838
+ let mut off_c = 0.0;
839
+ if al == style::END {
840
+ off_c = lc - outer_c;
841
+ } else if al == style::CENTER {
842
+ off_c = (lc - outer_c) / 2.0;
843
+ } else if bl[q] >= 0.0 {
844
+ off_c = line_base[li] - bl[q] - self.nodes[ku].mar_t;
845
+ }
846
+ let mut main_at = pos;
847
+ if reverse {
848
+ main_at = avail - pos - size_m - main_mar[q];
849
+ }
850
+ if row {
851
+ let px = x0 + main_at + self.nodes[ku].mar_l;
852
+ let py = y0 + cross_pos + off_c + self.nodes[ku].mar_t;
853
+ self.place(k, px, py, size_m, size_c);
854
+ } else {
855
+ let px2 = x0 + cross_pos + off_c + self.nodes[ku].mar_l;
856
+ let py2 = y0 + main_at + self.nodes[ku].mar_t;
857
+ self.place(k, px2, py2, size_c, size_m);
858
+ }
859
+ pos = pos + size_m + main_mar[q] + space;
860
+ q += 1;
861
+ }
862
+ cross_pos = cross_pos + lc + line_space;
863
+ li += 1;
864
+ }
865
+ if row {
866
+ total_cross = 0.0;
867
+ li = 0;
868
+ while li < lines {
869
+ total_cross += line_cross[li];
870
+ li += 1;
871
+ }
872
+ total_cross += cross_gap * ((lines - 1) as double);
873
+ return total_cross;
874
+ }
875
+ content_main
876
+ }
877
+
878
+ /// The first baseline of `k`, from the top of its border box, when it is
879
+ /// `h` high: a text leaf's first line (the half-leading model, with the
880
+ /// measurer's ascent and descent), a box's first child's, or else the
881
+ /// bottom edge.
882
+ fn baseline_of(&mut self, k: int, h: double) -> double {
883
+ let ku = k as usize;
884
+ if self.is_text(k) {
885
+ let fs = self.nodes[ku].fs;
886
+ let lh = text::line_height(fs);
887
+ return self.nodes[ku].pad_t + (lh - (0.905 + 0.212) * fs) / 2.0 + 0.905 * fs;
888
+ }
889
+ let kids = self.nodes[ku].children.clone();
890
+ for c in &kids {
891
+ if self.in_flow(*c) {
892
+ let ch = self.nodes[*c as usize].h;
893
+ return self.nodes[ku].pad_t + self.nodes[*c as usize].mar_t + self.baseline_of(*c, ch);
894
+ }
895
+ }
896
+ h
897
+ }
898
+
899
+ /// The width a column item takes on its cross axis before stretching.
900
+ fn item_cross_w(&mut self, c: int, k: int, cross_size: double, cross_mar: double) -> double {
901
+ let spec = self.nodes[k as usize].width.resolve(cross_size);
902
+ if spec >= 0.0 {
903
+ return self.clamp_w(k, spec, cross_size);
904
+ }
905
+ let avail = if cross_size >= 0.0 { cross_size - cross_mar } else { INF };
906
+ if self.align_of(c, k) == style::STRETCH && cross_size >= 0.0 {
907
+ return self.clamp_w(k, avail.max(0.0), cross_size);
908
+ }
909
+ let fit = self.max_content_w(k);
910
+ self.clamp_w(k, fit.min(avail), cross_size)
911
+ }
912
+
913
+ /// The height of the content of `k` at width `w`, without its declared
914
+ /// height: the automatic minimum of a column item.
915
+ fn content_height(&mut self, k: int, w: double) -> double {
916
+ if self.nodes[k as usize].height.is_auto() {
917
+ return self.height_for(k, w);
918
+ }
919
+ 0.0
920
+ }
921
+
922
+ /// Grows or shrinks the items `a..e` of one line into `main_size`,
923
+ /// freezing an item at its min or max and sharing the rest again, as the
924
+ /// CSS algorithm does.
925
+ fn resolve_flex(&self, items: &Vec<int>, a: usize, e: usize, main_size: double, gap: double, base: &Vec<double>, hypo: &Vec<double>, min_m: &Vec<double>, max_m: &Vec<double>, mar: &Vec<double>, out: &mut Vec<double>) {
926
+ let count = e - a;
927
+ let mut used = gap * ((count - 1) as double);
928
+ let mut q = a;
929
+ while q < e {
930
+ used += hypo[q] + mar[q];
931
+ q += 1;
932
+ }
933
+ let growing = used < main_size;
934
+ let mut frozen: Vec<bool> = Vec::new();
935
+ q = a;
936
+ while q < e {
937
+ let ku = items[q] as usize;
938
+ let f = if growing { self.nodes[ku].grow <= 0.0 || base[q] > hypo[q] } else { self.nodes[ku].shrink <= 0.0 || base[q] < hypo[q] };
939
+ frozen.push(f);
940
+ out[q] = hypo[q];
941
+ q += 1;
942
+ }
943
+ let mut rounds = 0;
944
+ while rounds <= count {
945
+ rounds += 1;
946
+ let mut free = main_size - gap * ((count - 1) as double);
947
+ let mut weight = 0.0;
948
+ let mut grow_sum = 0.0;
949
+ q = a;
950
+ while q < e {
951
+ let ku = items[q] as usize;
952
+ if frozen[q - a] {
953
+ free -= out[q] + mar[q];
954
+ } else {
955
+ free -= base[q] + mar[q];
956
+ if growing {
957
+ weight += self.nodes[ku].grow;
958
+ grow_sum += self.nodes[ku].grow;
959
+ } else {
960
+ weight += self.nodes[ku].shrink * base[q];
961
+ }
962
+ }
963
+ q += 1;
964
+ }
965
+ if weight <= 0.0 {
966
+ break;
967
+ }
968
+ // a total grow under 1 hands out only that share of the space
969
+ if growing && grow_sum < 1.0 {
970
+ free = free * grow_sum;
971
+ }
972
+ let mut violation = 0.0;
973
+ q = a;
974
+ while q < e {
975
+ if !frozen[q - a] {
976
+ let ku = items[q] as usize;
977
+ let share = if growing { self.nodes[ku].grow / weight } else { self.nodes[ku].shrink * base[q] / weight };
978
+ let want = base[q] + free * share;
979
+ let clamped = want.min(max_m[q]).max(min_m[q]).max(0.0);
980
+ violation += clamped - want;
981
+ out[q] = clamped;
982
+ }
983
+ q += 1;
984
+ }
985
+ if violation.abs() < 0.0000001 {
986
+ break;
987
+ }
988
+ // freeze the items the clamp moved the way the total moved
989
+ q = a;
990
+ while q < e {
991
+ if !frozen[q - a] {
992
+ let ku = items[q] as usize;
993
+ let share2 = if growing { self.nodes[ku].grow / weight } else { self.nodes[ku].shrink * base[q] / weight };
994
+ let want2 = base[q] + free * share2;
995
+ if (violation > 0.0 && out[q] > want2 + 0.0000001) || (violation < 0.0 && out[q] < want2 - 0.0000001) {
996
+ frozen[q - a] = true;
997
+ }
998
+ }
999
+ q += 1;
1000
+ }
1001
+ }
1002
+ }
1003
+ }