ranger-compiler 3.5.0 → 3.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (338) hide show
  1. package/CHANGELOG.md +1160 -19
  2. package/LICENSE +3 -1
  3. package/README.md +124 -29
  4. package/dist/Lang.rgr +1188 -290
  5. package/dist/api.d.ts +2343 -879
  6. package/dist/api.js +79924 -56922
  7. package/dist/lib/JSON.rgr +102 -91
  8. package/dist/lib/Shell.rgr +4 -4
  9. package/dist/lib/apple/AppleToolchain.rgr +4 -4
  10. package/dist/lib/apple/README.md +5 -4
  11. package/dist/lib/apple/apple_test.rgr +1 -1
  12. package/dist/lib/core/README.md +1 -1
  13. package/dist/lib/evg/EVG.rgr +12 -0
  14. package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
  15. package/dist/lib/evg/EVGA11yTree.rgr +894 -0
  16. package/dist/lib/evg/EVGBox.rgr +267 -0
  17. package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
  18. package/dist/lib/evg/EVGCodepoint.rgr +316 -0
  19. package/dist/lib/evg/EVGColor.rgr +700 -0
  20. package/dist/lib/evg/EVGCommands.rgr +177 -0
  21. package/dist/lib/evg/EVGComponent.rgr +331 -0
  22. package/dist/lib/evg/EVGComponentTest.rgr +387 -0
  23. package/dist/lib/evg/EVGConnector.rgr +541 -0
  24. package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
  25. package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
  26. package/dist/lib/evg/EVGEasing.rgr +370 -0
  27. package/dist/lib/evg/EVGEffectTest.rgr +253 -0
  28. package/dist/lib/evg/EVGElement.rgr +4914 -0
  29. package/dist/lib/evg/EVGFixedTest.rgr +289 -0
  30. package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
  31. package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
  32. package/dist/lib/evg/EVGFling.rgr +244 -0
  33. package/dist/lib/evg/EVGFocus.rgr +400 -0
  34. package/dist/lib/evg/EVGFocusTest.rgr +399 -0
  35. package/dist/lib/evg/EVGGradient.rgr +322 -0
  36. package/dist/lib/evg/EVGGrapheme.rgr +190 -0
  37. package/dist/lib/evg/EVGGrid.rgr +975 -0
  38. package/dist/lib/evg/EVGHitTest.rgr +208 -0
  39. package/dist/lib/evg/EVGHoles.rgr +294 -0
  40. package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
  41. package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
  42. package/dist/lib/evg/EVGHostTree.rgr +834 -0
  43. package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
  44. package/dist/lib/evg/EVGImageDecode.rgr +117 -0
  45. package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
  46. package/dist/lib/evg/EVGInspect.rgr +883 -0
  47. package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
  48. package/dist/lib/evg/EVGJsonTest.rgr +535 -0
  49. package/dist/lib/evg/EVGLayout.rgr +4220 -0
  50. package/dist/lib/evg/EVGMeasure.rgr +1267 -0
  51. package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
  52. package/dist/lib/evg/EVGPatch.rgr +1721 -0
  53. package/dist/lib/evg/EVGPatchTest.rgr +692 -0
  54. package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
  55. package/dist/lib/evg/EVGReconcile.rgr +226 -0
  56. package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
  57. package/dist/lib/evg/EVGReject.rgr +126 -0
  58. package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
  59. package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
  60. package/dist/lib/evg/EVGRuler.rgr +232 -0
  61. package/dist/lib/evg/EVGRulerTest.rgr +172 -0
  62. package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
  63. package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
  64. package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
  65. package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
  66. package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
  67. package/dist/lib/evg/EVGText.rgr +105 -0
  68. package/dist/lib/evg/EVGTextEngine.rgr +536 -0
  69. package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
  70. package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
  71. package/dist/lib/evg/EVGToolbar.rgr +1369 -0
  72. package/dist/lib/evg/EVGTransition.rgr +728 -0
  73. package/dist/lib/evg/EVGTreeJson.rgr +721 -0
  74. package/dist/lib/evg/EVGUnit.rgr +554 -0
  75. package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
  76. package/dist/lib/evg/EvgApp.rgr +189 -0
  77. package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
  78. package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
  79. package/dist/lib/evg/EvgHost.rgr +451 -0
  80. package/dist/lib/evg/EvgTest.rgr +91 -0
  81. package/dist/lib/evg/EvgTraceColor.rgr +236 -0
  82. package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
  83. package/dist/lib/evg/EvgTraceFit.rgr +767 -0
  84. package/dist/lib/evg/EvgTracePath.rgr +435 -0
  85. package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
  86. package/dist/lib/evg/EvgViewport.rgr +313 -0
  87. package/dist/lib/evg/FxDemoDoc.rgr +185 -0
  88. package/dist/lib/evg/HOSTS.md +227 -0
  89. package/dist/lib/evg/ISSUES.md +835 -0
  90. package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
  91. package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
  92. package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
  93. package/dist/lib/evg/PLAN_EVG.md +518 -0
  94. package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
  95. package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
  96. package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
  97. package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
  98. package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
  99. package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
  100. package/dist/lib/evg/PathBuilder.rgr +333 -0
  101. package/dist/lib/evg/README.md +1236 -0
  102. package/dist/lib/evg/SPEC.md +1252 -0
  103. package/dist/lib/evg/SVGPathParser.rgr +1199 -0
  104. package/dist/lib/evg/SvgParser.rgr +1736 -0
  105. package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
  106. package/dist/lib/evg/VectorShapes.rgr +331 -0
  107. package/dist/lib/evg/VectorStroke.rgr +107 -0
  108. package/dist/lib/evg/VectorViewBox.rgr +380 -0
  109. package/dist/lib/evg/agent/README.md +290 -0
  110. package/dist/lib/evg/agent/evg_agent.rgr +899 -0
  111. package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
  112. package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
  113. package/dist/lib/evg/agent/fixtures/connector.css +63 -0
  114. package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
  115. package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
  116. package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
  117. package/dist/lib/evg/agent/fixtures/popover.css +99 -0
  118. package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
  119. package/dist/lib/evg/agent/roundtrip.sh +74 -0
  120. package/dist/lib/evg/agent/smoke.sh +230 -0
  121. package/dist/lib/evg/android/README.md +97 -0
  122. package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
  123. package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
  124. package/dist/lib/evg/android/androidstubs/App.kt +30 -0
  125. package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
  126. package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
  127. package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
  128. package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
  129. package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
  130. package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
  131. package/dist/lib/evg/android/androidstubs/View.kt +113 -0
  132. package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
  133. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
  134. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
  135. package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
  136. package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
  137. package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
  138. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
  139. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
  140. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
  141. package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
  142. package/dist/lib/evg/apple/README.md +128 -0
  143. package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
  144. package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
  145. package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
  146. package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
  147. package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
  148. package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
  149. package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
  150. package/dist/lib/evg/bench/README.md +64 -0
  151. package/dist/lib/evg/bench/layout-bench.mjs +316 -0
  152. package/dist/lib/evg/bench/layout-cases.mjs +510 -0
  153. package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
  154. package/dist/lib/evg/bin/.gitignore +17 -0
  155. package/dist/lib/evg/evg_test.rgr +313 -0
  156. package/dist/lib/evg/gl/README.md +198 -0
  157. package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
  158. package/dist/lib/evg/gl/blur-check.mjs +399 -0
  159. package/dist/lib/evg/gl/boxmodel.json +1 -0
  160. package/dist/lib/evg/gl/demo.html +46 -0
  161. package/dist/lib/evg/gl/effect-presets.css +285 -0
  162. package/dist/lib/evg/gl/effect-presets.js +63 -0
  163. package/dist/lib/evg/gl/effect-shots.mjs +135 -0
  164. package/dist/lib/evg/gl/evg-a11y.js +566 -0
  165. package/dist/lib/evg/gl/evg-binary.js +160 -0
  166. package/dist/lib/evg/gl/evg-engine.js +296 -0
  167. package/dist/lib/evg/gl/evg-fx.js +237 -0
  168. package/dist/lib/evg/gl/evg-gestures.js +209 -0
  169. package/dist/lib/evg/gl/evg-list.js +167 -0
  170. package/dist/lib/evg/gl/evg-measure.js +186 -0
  171. package/dist/lib/evg/gl/evg-textinput.js +303 -0
  172. package/dist/lib/evg/gl/evg-view.js +144 -0
  173. package/dist/lib/evg/gl/evg-webgl.js +3942 -0
  174. package/dist/lib/evg/gl/fx-check.mjs +998 -0
  175. package/dist/lib/evg/gl/fx-demo.html +166 -0
  176. package/dist/lib/evg/gl/fx-demo.js +2 -0
  177. package/dist/lib/evg/gl/fx-serve.mjs +47 -0
  178. package/dist/lib/evg/gl/gestures-check.mjs +189 -0
  179. package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
  180. package/dist/lib/evg/gl/measure-check.mjs +135 -0
  181. package/dist/lib/evg/gl/rotation-check.mjs +207 -0
  182. package/dist/lib/evg/gl/shift-check.mjs +113 -0
  183. package/dist/lib/evg/gl/stroke-check.mjs +168 -0
  184. package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
  185. package/dist/lib/evg/gl/view-check.mjs +343 -0
  186. package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
  187. package/dist/lib/evg/html/evg-dom.js +318 -0
  188. package/dist/lib/evg/html/evg-html.js +600 -0
  189. package/dist/lib/evg/inspect/README.md +415 -0
  190. package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
  191. package/dist/lib/evg/inspect/evg-inspect.js +947 -0
  192. package/dist/lib/evg/inspect/shots/css.png +0 -0
  193. package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
  194. package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
  195. package/dist/lib/evg/inspect/shots/state.png +0 -0
  196. package/dist/lib/evg/inspect/shots.mjs +226 -0
  197. package/dist/lib/evg/oracle/css-blur.json +576 -0
  198. package/dist/lib/evg/oracle/css-box.json +157 -0
  199. package/dist/lib/evg/oracle/css-timing.json +709 -0
  200. package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
  201. package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
  202. package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
  203. package/dist/lib/evg/original/EVGColor.clj +310 -0
  204. package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
  205. package/dist/lib/evg/original/SVGPath.rgr +627 -0
  206. package/dist/lib/evg/original/Vec2.crgr +103 -0
  207. package/dist/lib/evg/ranger.json +9 -0
  208. package/dist/lib/evg/showcase/README.md +246 -0
  209. package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
  210. package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
  211. package/dist/lib/evg/showcase/build.mjs +651 -0
  212. package/dist/lib/evg/showcase/pages/album.tsx +30 -0
  213. package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
  214. package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
  215. package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
  216. package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
  217. package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
  218. package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
  219. package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
  220. package/dist/lib/evg/showcase/pages/more.tsx +332 -0
  221. package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
  222. package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
  223. package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
  224. package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
  225. package/dist/lib/evg/showcase/pages/units.tsx +35 -0
  226. package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
  227. package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
  228. package/dist/lib/evg/showcase/pages/views.tsx +223 -0
  229. package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
  230. package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
  231. package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
  232. package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
  233. package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
  234. package/dist/lib/evg/showcase/themes/more-default.css +128 -0
  235. package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
  236. package/dist/lib/evg/showcase/themes/showcase.css +508 -0
  237. package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
  238. package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
  239. package/dist/lib/evg/showcase/themes/views-default.css +15 -0
  240. package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
  241. package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
  242. package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
  243. package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
  244. package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
  245. package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
  246. package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
  247. package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
  248. package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
  249. package/dist/lib/evg/web/responsive/README.md +97 -0
  250. package/dist/lib/evg/web/responsive/build.mjs +90 -0
  251. package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
  252. package/dist/lib/evg/web/responsive/index.html +177 -0
  253. package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
  254. package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
  255. package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
  256. package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
  257. package/dist/lib/evg/web/tools/minify.mjs +60 -0
  258. package/dist/lib/evg/web/tracer/build.mjs +87 -0
  259. package/dist/lib/evg/web/tracer/index.html +2805 -0
  260. package/dist/lib/evg/web/tracer/sample.png +0 -0
  261. package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
  262. package/dist/lib/evgr/Cargo.lock +21 -0
  263. package/dist/lib/evgr/Cargo.toml +19 -0
  264. package/dist/lib/evgr/README.md +140 -0
  265. package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
  266. package/dist/lib/evgr/bench/compare.mjs +252 -0
  267. package/dist/lib/evgr/bench/speed.mjs +277 -0
  268. package/dist/lib/evgr/bin/.gitignore +3 -0
  269. package/dist/lib/evgr/src/bin/bench.rs +106 -0
  270. package/dist/lib/evgr/src/bin/smoke.rs +13 -0
  271. package/dist/lib/evgr/src/grid.rs +730 -0
  272. package/dist/lib/evgr/src/lib.rs +1003 -0
  273. package/dist/lib/evgr/src/style.rs +468 -0
  274. package/dist/lib/evgr/src/text.rs +83 -0
  275. package/dist/lib/image/BitReader.rgr +171 -0
  276. package/dist/lib/image/Buffer.rgr +173 -0
  277. package/dist/lib/image/DCT.rgr +283 -0
  278. package/dist/lib/image/Deflate.rgr +339 -0
  279. package/dist/lib/image/HuffmanDecoder.rgr +181 -0
  280. package/dist/lib/image/ImageBuffer.rgr +706 -0
  281. package/dist/lib/image/JPEGDecoder.rgr +808 -0
  282. package/dist/lib/image/PNGDecoder.rgr +544 -0
  283. package/dist/lib/image/PNGEncoder.rgr +388 -0
  284. package/dist/lib/image/PPMImage.rgr +224 -0
  285. package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
  286. package/dist/lib/image/README.md +33 -0
  287. package/dist/lib/image/RasterBuffer.rgr +294 -0
  288. package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
  289. package/dist/lib/image/WebPDecoder.rgr +433 -0
  290. package/dist/lib/image/WebPLossless.rgr +1035 -0
  291. package/dist/lib/image/WebPLossy.rgr +1929 -0
  292. package/dist/lib/image/ranger.json +9 -0
  293. package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
  294. package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
  295. package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
  296. package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
  297. package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
  298. package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
  299. package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
  300. package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
  301. package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
  302. package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
  303. package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
  304. package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
  305. package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
  306. package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
  307. package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
  308. package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
  309. package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
  310. package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
  311. package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
  312. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
  313. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
  314. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
  315. package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
  316. package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
  317. package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
  318. package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
  319. package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
  320. package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
  321. package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
  322. package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
  323. package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
  324. package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
  325. package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
  326. package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
  327. package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
  328. package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
  329. package/dist/lib/image/tests/run_webp_tests.sh +39 -0
  330. package/dist/lib/rust/RsJson.rgr +468 -0
  331. package/dist/lib/rust/RsPrelude.rgr +1663 -0
  332. package/dist/lib/shell_test.rgr +7 -7
  333. package/dist/lib/stdlib.rgr +21 -5
  334. package/dist/lib/zip/ranger.json +6 -0
  335. package/dist/rgrc.js +87318 -67610
  336. package/package.json +1010 -1040
  337. package/dist/README.md +0 -117
  338. package/dist/package.json +0 -47
@@ -0,0 +1,720 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; EVGTextMeasurer.rgr - Abstract text measurement interface for EVG layout
4
+
5
+ Import "EVGCodepoint.rgr"
6
+
7
+ class EVGTextMetrics {
8
+ def width:double 0.0
9
+ def height:double 0.0
10
+ def ascent:double 0.0
11
+ def descent:double 0.0
12
+ def lineHeight:double 0.0
13
+
14
+ Constructor () {
15
+ width = 0.0
16
+ height = 0.0
17
+ ascent = 0.0
18
+ descent = 0.0
19
+ lineHeight = 0.0
20
+ }
21
+
22
+ sfn create:EVGTextMetrics (w:double h:double) {
23
+ def m (new EVGTextMetrics())
24
+ m.width = w
25
+ m.height = h
26
+ return m
27
+ }
28
+ }
29
+
30
+ ; Abstract interface - implementations must override
31
+ class EVGTextMeasurer {
32
+
33
+ ; --- WHAT `measureChar` IS NOT ALLOWED TO DO AGAIN PER CHARACTER ----------
34
+ ;
35
+ ; `measureChar` is called once per character of every string the layout
36
+ ; measures, and a wrap measures the same string many times over, so
37
+ ; anything it does is done millions of times in a frame. It used to do two
38
+ ; things there that had no business being in that loop:
39
+ ;
40
+ ; `isMono(fontFamily)` — six substring searches over the family name,
41
+ ; for an answer that is the same for every character of the run. It was
42
+ ; 38% of the whole profile of a scroll in `gallery/realtrainer`: the
43
+ ; single most expensive function in the frame, computing one boolean
44
+ ; over and over.
45
+ ;
46
+ ; `advanceEm()` — a NINETY-FIVE ELEMENT ARRAY LITERAL, freshly allocated
47
+ ; for each character, to read one slot out of it. That is what put minor
48
+ ; GC and the collector's `drop` next in the same profile.
49
+ ;
50
+ ; Both are constants of the run, so they are held here instead: the tables
51
+ ; materialised once per measurer, and the family's monospace-ness
52
+ ; remembered for the last family asked about — which, inside a run, is
53
+ ; every character after the first.
54
+ def advTable:[double]
55
+ def monoTable:[double]
56
+ def latinTable:[double]
57
+ def punctTable:[double]
58
+ def tablesReady:boolean false
59
+ ; The last family `monoFor` was asked about and the answer it gave.
60
+ ; `monoKnown` is what distinguishes "not asked yet" from "asked about the
61
+ ; empty family", which `monoFamily` alone cannot.
62
+ def monoFamily:string ""
63
+ def monoKnown:boolean false
64
+ def monoCached:boolean false
65
+ ; …and whether it is the bold cut, remembered with it. The layout asks
66
+ ; for `Arial-Bold` when the element is bold (`EVGElement.effectiveFontFamily`),
67
+ ; and a bold face is measured with the bold tables below.
68
+ def boldCached:boolean false
69
+ def boldTable:[double]
70
+ def boldLatinTable:[double]
71
+ def boldPunctTable:[double]
72
+
73
+ ; --- THE FACE'S VERTICAL METRICS, MEASURED ---------------------------------
74
+ ;
75
+ ; These used to be 0.80 and 0.20, which sum to exactly 1.00em — and no real
76
+ ; face does. Measured at 1000px in Chromium, the sans fallback is 0.905 and
77
+ ; 0.212, summing to 1.117em; see `oracle/textbox.json`, which records the
78
+ ; serif and monospace faces too.
79
+ ;
80
+ ; The ASCENT is what puts the baseline inside the line box, so an ascent
81
+ ; that is a tenth of an em short draws every run of text that much high. It
82
+ ; is not a rounding error, it is the difference between text sitting in a
83
+ ; row and text sitting above one.
84
+ ;
85
+ ; They are still an ESTIMATE — a measurer with no font file cannot know the
86
+ ; face — but an estimate taken from a real fallback rather than from a
87
+ ; round number. A measurer that opens fonts overrides `measureText` and
88
+ ; reports the truth.
89
+ sfn fallbackAscentEm:double () {
90
+ return 0.905
91
+ }
92
+
93
+ sfn fallbackDescentEm:double () {
94
+ return 0.212
95
+ }
96
+
97
+ ; `line-height: normal`, which is NOT 1.2. It is the face's own line box —
98
+ ; ascent plus descent plus the line gap — and it is 1.15em for the sans
99
+ ; fallback, 1.164 for monospace. 1.2 is a number people type, not a number
100
+ ; a browser computes.
101
+ sfn normalLineHeightEm:double () {
102
+ return 1.15
103
+ }
104
+
105
+ ; Does this measurer report real metrics from the font file that will be
106
+ ; painted? The default implementation below does NOT — it guesses from the
107
+ ; font size and never opens a font — so it must not silently drive print
108
+ ; layout. EVGTextEngine consults this to decide whether a document that
109
+ ; names custom fonts can be measured honestly.
110
+ fn isFontAccurate:boolean () {
111
+ return false
112
+ }
113
+
114
+ ; Is a concrete face available for this family? A measurer with no font
115
+ ; files has none, whatever the family is called.
116
+ fn hasFace:boolean (fontFamily:string) {
117
+ return false
118
+ }
119
+
120
+ ; --- WHAT WOULD MAKE THIS MEASURER ANSWER DIFFERENTLY --------------------
121
+ ;
122
+ ; `EVGTextEngine` caches wraps and metrics, and this string goes in the
123
+ ; key. A measurer whose answers depend on nothing but its arguments — this
124
+ ; one, whose tables are constants — has nothing to report and returns the
125
+ ; empty string.
126
+ ;
127
+ ; A measurer that can CHANGE ITS MIND must override it: one that loads
128
+ ; faces answers differently once a face is loaded, and one that is told a
129
+ ; weight before each run answers differently for bold. Without the change
130
+ ; showing up here, the engine would hand back a width measured before it.
131
+ ; The rule is simply that anything read by `measureText` and not passed to
132
+ ; it belongs in this string.
133
+ fn measureKey:string () {
134
+ return ""
135
+ }
136
+
137
+ fn measureText:EVGTextMetrics (text:string fontFamily:string fontSize:double) {
138
+ ; Default implementation - estimate based on font size
139
+ ; Average character width is approximately 0.5-0.6 of font size
140
+ def avgCharWidth:double (fontSize * 0.55)
141
+ def textLen:int (strlen text)
142
+ def width:double ((to_double textLen) * avgCharWidth)
143
+ def lineHeight:double (fontSize * (EVGTextMeasurer.normalLineHeightEm()))
144
+
145
+ def metrics (new EVGTextMetrics())
146
+ metrics.width = width
147
+ metrics.height = lineHeight
148
+ metrics.ascent = (fontSize * (EVGTextMeasurer.fallbackAscentEm()))
149
+ metrics.descent = (fontSize * (EVGTextMeasurer.fallbackDescentEm()))
150
+ metrics.lineHeight = lineHeight
151
+ return metrics
152
+ }
153
+
154
+ fn measureTextWidth:double (text:string fontFamily:string fontSize:double) {
155
+ def metrics:EVGTextMetrics (this.measureText(text fontFamily fontSize))
156
+ return metrics.width
157
+ }
158
+
159
+ fn getLineHeight:double (fontFamily:string fontSize:double) {
160
+ return (fontSize * (EVGTextMeasurer.normalLineHeightEm()))
161
+ }
162
+
163
+
164
+ ; --- how wide a character really is ---------------------------------------
165
+ ;
166
+ ; MEASURED, one advance per printable character, as a fraction of the em.
167
+ ; `advance_oracle.mjs` asks a browser for each one with canvas
168
+ ; `measureText` at a 100px reference and this is what it said.
169
+ ;
170
+ ; What it replaces was a handful of buckets — space and `i l j t f` at 0.3
171
+ ; of the size, `m w` at 0.8, `M W` at 0.9, everything else in between — and
172
+ ; those buckets put "At least 8 characters." 12.4 pixels wide of the truth
173
+ ; at 13px, and "ada.example.com" 7.9 wide. That second number is the bug
174
+ ; this was written for: a caret is drawn at the measured width of the text
175
+ ; before it, so the caret sat eight pixels past the end of the text.
176
+ ;
177
+ ; It is worse than a caret being untidy. The RENDERER does not estimate —
178
+ ; the GL backend builds its glyph atlas with the browser's own
179
+ ; `measureText` — so the text was DRAWN at its true width while the layout
180
+ ; believed the buckets. Two measurements of one string, and everything
181
+ ; placed from the wrong one: the caret, the selection band, the index a
182
+ ; click maps to, the width of a box meant to fit its label.
183
+ ;
184
+ ; WHAT THIS TABLE IS NOT. It is a sum of single advances, and a browser
185
+ ; kerns pairs, which no per-character table can express. Measured over
186
+ ; fifteen strings the sum is EXACT for twelve and drifts at most 3.9px on
187
+ ; the all-caps pairs that kern hardest — "AVATAR", "To Wave". So the table
188
+ ; is right for text and slightly wide for capitals, which is a different
189
+ ; and much smaller error than the one it replaces, and the check reports it
190
+ ; rather than hiding it.
191
+ ;
192
+ ; AND IT IS ONE FACE. Arial, Helvetica and `sans-serif` all measured
193
+ ; identically here because they resolve to the same substitute; a machine
194
+ ; with a different Arial will differ slightly. The honest fix for that is
195
+ ; to measure with the face actually in use, which the browser can do
196
+ ; through `setMeasurer` — this table is what every target can carry.
197
+ ; The same, for the BOLD cut. Bold Arial is not the regular face drawn
198
+ ; thicker: `i`, `l`, `r`, `t` and `s` are a twentieth of an em wider each,
199
+ ; and "Päivitä suunnitelma" at 14px is 131px bold against 121px regular.
200
+ ; A button whose label was measured regular and drawn bold had its text
201
+ ; against its right edge — the padding the sheet gave it went to the
202
+ ; ten pixels the measurement was short. Measured as `advanceEm` was.
203
+ sfn boldAdvanceEm:[double] () {
204
+ return ([] _:double (
205
+ 0.27783 0.33301 0.47412 0.55615 0.55615 0.88916 0.72217 0.23779
206
+ 0.33301 0.33301 0.38916 0.58398 0.27783 0.33301 0.27783 0.27783
207
+ 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615
208
+ 0.55615 0.55615 0.33301 0.33301 0.58398 0.58398 0.58398 0.61084
209
+ 0.97510 0.72217 0.72217 0.72217 0.72217 0.66699 0.61084 0.77783
210
+ 0.72217 0.27783 0.55615 0.72217 0.61084 0.83301 0.72217 0.77783
211
+ 0.66699 0.77783 0.72217 0.66699 0.61084 0.72217 0.66699 0.94385
212
+ 0.66699 0.66699 0.61084 0.33301 0.27783 0.33301 0.58398 0.55615
213
+ 0.33301 0.55615 0.61084 0.55615 0.61084 0.55615 0.33301 0.61084
214
+ 0.61084 0.27783 0.27783 0.55615 0.27783 0.88916 0.61084 0.61084
215
+ 0.61084 0.61084 0.38916 0.55615 0.33301 0.61084 0.55615 0.77783
216
+ 0.55615 0.55615 0.50000 0.38916 0.27979 0.38916 0.58398
217
+ ))
218
+ }
219
+
220
+ sfn boldLatin1Em:[double] () {
221
+ return ([] _:double (
222
+ 0.27783 0.33301 0.55615 0.55615 0.55615 0.55615 0.27979 0.55615
223
+ 0.33301 0.73682 0.37012 0.55615 0.58398 0.00000 0.73682 0.55225
224
+ 0.39990 0.54883 0.33301 0.33301 0.33301 0.57617 0.55615 0.33301
225
+ 0.33301 0.33301 0.36523 0.55615 0.83398 0.83398 0.83398 0.61084
226
+ 0.72217 0.72217 0.72217 0.72217 0.72217 0.72217 1.00000 0.72217
227
+ 0.66699 0.66699 0.66699 0.66699 0.27783 0.27783 0.27783 0.27783
228
+ 0.72217 0.72217 0.77783 0.77783 0.77783 0.77783 0.77783 0.58398
229
+ 0.77783 0.72217 0.72217 0.72217 0.72217 0.66699 0.66699 0.61084
230
+ 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.88916 0.55615
231
+ 0.55615 0.55615 0.55615 0.55615 0.27783 0.27783 0.27783 0.27783
232
+ 0.61084 0.61084 0.61084 0.61084 0.61084 0.61084 0.61084 0.54883
233
+ 0.61084 0.61084 0.61084 0.61084 0.61084 0.55615 0.61084 0.55615
234
+ ))
235
+ }
236
+
237
+ sfn boldPunctEm:[double] () {
238
+ return ([] _:double (
239
+ 0.33301 0.33301 0.55615 0.55615 1.00000 1.00000 0.49756 0.55225
240
+ 0.27783 0.27783 0.27783 0.27783 0.50000 0.50000 0.50000 0.50000
241
+ 0.55615 0.55615 0.35010 0.58984 0.33447 0.66748 1.00000
242
+ ))
243
+ }
244
+
245
+ sfn advanceEm:[double] () {
246
+ return ([] _:double (
247
+ 0.27783 0.27783 0.35498 0.55615 0.55615 0.88916 0.66699 0.19092
248
+ 0.33301 0.33301 0.38916 0.58398 0.27783 0.33301 0.27783 0.27783
249
+ 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615
250
+ 0.55615 0.55615 0.27783 0.27783 0.58398 0.58398 0.58398 0.55615
251
+ 1.01514 0.66699 0.66699 0.72217 0.72217 0.66699 0.61084 0.77783
252
+ 0.72217 0.27783 0.50000 0.66699 0.55615 0.83301 0.72217 0.77783
253
+ 0.66699 0.77783 0.72217 0.66699 0.61084 0.72217 0.66699 0.94385
254
+ 0.66699 0.66699 0.61084 0.27783 0.27783 0.27783 0.46924 0.55615
255
+ 0.33301 0.55615 0.55615 0.50000 0.55615 0.55615 0.27783 0.55615
256
+ 0.55615 0.22217 0.22217 0.50000 0.22217 0.83301 0.55615 0.55615
257
+ 0.55615 0.55615 0.33301 0.50000 0.27783 0.55615 0.50000 0.72217
258
+ 0.50000 0.50000 0.50000 0.33398 0.25977 0.33398 0.58398
259
+ ))
260
+ }
261
+
262
+ ; The same for a monospace face, where every advance is the same number and
263
+ ; the sum is exact by construction.
264
+ sfn monoAdvanceEm:[double] () {
265
+ return ([] _:double (
266
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
267
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
268
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
269
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
270
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
271
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
272
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
273
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
274
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
275
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
276
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
277
+ 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
278
+ ))
279
+ }
280
+
281
+ ; Latin-1 Supplement, U+00A0 … U+00FF, measured the same way at the same
282
+ ; reference: the umlauts every Finnish string has, the degree, the
283
+ ; multiplication sign, and the soft hyphen at zero. Before this table
284
+ ; an a-umlaut was the half-em guess below — 0.5 where the face has
285
+ ; 0.55615 — and a caret after "Päiväkirja" was two pixels short.
286
+ sfn latin1Em:[double] () {
287
+ return ([] _:double (
288
+ 0.27783 0.33301 0.55615 0.55615 0.55615 0.55615 0.25977 0.55615
289
+ 0.33301 0.73682 0.37012 0.55615 0.58398 0.00000 0.73682 0.55225
290
+ 0.39990 0.54883 0.33301 0.33301 0.33301 0.57617 0.53711 0.33301
291
+ 0.33301 0.33301 0.36523 0.55615 0.83398 0.83398 0.83398 0.61084
292
+ 0.66699 0.66699 0.66699 0.66699 0.66699 0.66699 1.00000 0.72217
293
+ 0.66699 0.66699 0.66699 0.66699 0.27783 0.27783 0.27783 0.27783
294
+ 0.72217 0.72217 0.77783 0.77783 0.77783 0.77783 0.77783 0.58398
295
+ 0.77783 0.72217 0.72217 0.72217 0.72217 0.66699 0.66699 0.61084
296
+ 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.88916 0.50000
297
+ 0.55615 0.55615 0.55615 0.55615 0.27783 0.27783 0.27783 0.27783
298
+ 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.54883
299
+ 0.61084 0.55615 0.55615 0.55615 0.55615 0.50000 0.55615 0.50000
300
+ ))
301
+ }
302
+
303
+ ; General Punctuation, U+2010 … U+2026: the dashes, the curly quotes,
304
+ ; the daggers, the bullet and the ellipsis. The bullet is the one that
305
+ ; was seen wrong: a password field draws one per character and the caret
306
+ ; sat at the guessed 0.5 em each where the face draws 0.3501 — nine
307
+ ; characters in, the caret was fifteen pixels past the last bullet.
308
+ sfn punctEm:[double] () {
309
+ return ([] _:double (
310
+ 0.33301 0.33301 0.55615 0.55615 1.00000 1.00000 0.41309 0.55225
311
+ 0.22217 0.22217 0.22217 0.22217 0.33301 0.33301 0.33301 0.33301
312
+ 0.55615 0.55615 0.35010 0.59000 0.33000 0.67000 1.00000
313
+ ))
314
+ }
315
+
316
+ ; A few beyond those ranges the gallery draws: the single guillemets,
317
+ ; the trade mark, the check mark.
318
+ sfn extraEm:double (ch:int) {
319
+ if (ch == 8249) { return 0.33301 }
320
+ if (ch == 8250) { return 0.33301 }
321
+ if (ch == 8482) { return 1.0 }
322
+ if (ch == 10003) { return 0.84 }
323
+ if (ch == 10004) { return 0.84 }
324
+ if (ch == 8242) { return 0.1875 }
325
+ if (ch == 8243) { return 0.354 }
326
+ return -1.0
327
+ }
328
+
329
+ ; The euro, which the invoice demo puts in front of an amount and which
330
+ ; was, before the two tables above, the one character outside printable
331
+ ; ASCII the gallery asked for.
332
+ sfn euroEm:double () {
333
+ return 0.55615
334
+ }
335
+
336
+ sfn monoEuroEm:double () {
337
+ return 0.60205
338
+ }
339
+
340
+ ; Is this family drawn with one advance for every character?
341
+ ; Is this family drawn with one advance for every character?
342
+ ;
343
+ ; By name, and in both spellings, because Ranger has no case folding to
344
+ ; reach for here. The families the gallery actually names are `monospace`,
345
+ ; `Courier New` and `Consolas`; anything else is measured with the
346
+ ; proportional table, which is the safer way to be wrong — a proportional
347
+ ; table on a monospace face is a little narrow, a monospace table on a
348
+ ; proportional face is wrong for every character.
349
+ sfn isMono:boolean (fontFamily:string) {
350
+ if ((indexOf fontFamily "mono") >= 0) {
351
+ return true
352
+ }
353
+ if ((indexOf fontFamily "Mono") >= 0) {
354
+ return true
355
+ }
356
+ if ((indexOf fontFamily "courier") >= 0) {
357
+ return true
358
+ }
359
+ if ((indexOf fontFamily "Courier") >= 0) {
360
+ return true
361
+ }
362
+ if ((indexOf fontFamily "Consol") >= 0) {
363
+ return true
364
+ }
365
+ if ((indexOf fontFamily "consol") >= 0) {
366
+ return true
367
+ }
368
+ return false
369
+ }
370
+
371
+ ; `isMono` for a family, asked once and remembered. A run is measured one
372
+ ; character at a time and every one of them names the same family, so the
373
+ ; answer after the first is a pointer comparison rather than six searches.
374
+ fn monoFor:boolean (fontFamily:string) {
375
+ if monoKnown {
376
+ if (monoFamily == fontFamily) {
377
+ return monoCached
378
+ }
379
+ }
380
+ monoFamily = fontFamily
381
+ monoCached = (EVGTextMeasurer.isMono(fontFamily))
382
+ boldCached = (EVGTextMeasurer.isBold(fontFamily))
383
+ monoKnown = true
384
+ return monoCached
385
+ }
386
+
387
+ ; The bold cut, as the layout names it: the family with `-Bold` on it.
388
+ sfn isBold:boolean (fontFamily:string) {
389
+ return ((indexOf fontFamily "-Bold") >= 0)
390
+ }
391
+
392
+ ; The advance tables, built once per measurer rather than once per
393
+ ; character. Lazily, because a measurer that overrides `measureText` and
394
+ ; never reaches `measureChar` should not pay for four arrays it will not
395
+ ; read.
396
+ fn prepareTables:void () {
397
+ advTable = (EVGTextMeasurer.advanceEm())
398
+ monoTable = (EVGTextMeasurer.monoAdvanceEm())
399
+ latinTable = (EVGTextMeasurer.latin1Em())
400
+ punctTable = (EVGTextMeasurer.punctEm())
401
+ boldTable = (EVGTextMeasurer.boldAdvanceEm())
402
+ boldLatinTable = (EVGTextMeasurer.boldLatin1Em())
403
+ boldPunctTable = (EVGTextMeasurer.boldPunctEm())
404
+ tablesReady = true
405
+ }
406
+
407
+ fn measureChar:double (ch:int fontFamily:string fontSize:double) {
408
+ if (tablesReady == false) {
409
+ this.prepareTables()
410
+ }
411
+ def mono:boolean (this.monoFor(fontFamily))
412
+ def bold:boolean boldCached
413
+ if (ch == 8364) {
414
+ if mono {
415
+ return ((EVGTextMeasurer.monoEuroEm()) * fontSize)
416
+ }
417
+ return ((EVGTextMeasurer.euroEm()) * fontSize)
418
+ }
419
+ if ((ch >= 32) && (ch <= 126)) {
420
+ def t:[double] advTable
421
+ if mono {
422
+ t = monoTable
423
+ } {
424
+ if bold {
425
+ t = boldTable
426
+ }
427
+ }
428
+ return ((itemAt t (ch - 32)) * fontSize)
429
+ }
430
+ ; The soft hyphen takes no space in either kind of face.
431
+ if (ch == 173) {
432
+ return 0.0
433
+ }
434
+ ; A monospace face has one advance for everything it holds, and it
435
+ ; holds all of these — measured: every code below came back 0.60205.
436
+ if mono {
437
+ if (((ch >= 160) && (ch <= 255)) || ((ch >= 8208) && (ch <= 8230))) {
438
+ return ((EVGTextMeasurer.monoEuroEm()) * fontSize)
439
+ }
440
+ if ((EVGTextMeasurer.extraEm(ch)) >= 0.0) {
441
+ return ((EVGTextMeasurer.monoEuroEm()) * fontSize)
442
+ }
443
+ }
444
+ if ((ch >= 160) && (ch <= 255)) {
445
+ if bold {
446
+ return ((itemAt boldLatinTable (ch - 160)) * fontSize)
447
+ }
448
+ return ((itemAt latinTable (ch - 160)) * fontSize)
449
+ }
450
+ if ((ch >= 8208) && (ch <= 8230)) {
451
+ if bold {
452
+ return ((itemAt boldPunctTable (ch - 8208)) * fontSize)
453
+ }
454
+ return ((itemAt punctTable (ch - 8208)) * fontSize)
455
+ }
456
+ def extra:double (EVGTextMeasurer.extraEm(ch))
457
+ if (extra >= 0.0) {
458
+ return (extra * fontSize)
459
+ }
460
+ ; --- surrogate pairs, which is to say emoji -------------------------
461
+ ;
462
+ ; A code point above the BMP arrives as TWO code units, and half an em
463
+ ; each made an emoji exactly one em wide. Measured in Chromium at
464
+ ; 13px and 16px — the fractions are identical at both, so they really
465
+ ; are per-em:
466
+ ;
467
+ ; thumbs up 1.2477 em crying face 1.1685 em eye 1.0 em
468
+ ;
469
+ ; So the pair was under-measured by a factor of about 1.2, and a chat
470
+ ; bubble sized from that wrapped its emoji onto a second line and
471
+ ; spilled it out of the box. That is what this fixes.
472
+ ;
473
+ ; The HIGH surrogate carries the whole width and the low one carries
474
+ ; none, so a caret index still lands between characters rather than
475
+ ; inside one.
476
+ ;
477
+ ; 1.25 em for an emoji this does not know individually, and that
478
+ ; number is deliberately the WIDEST measured rather than the average.
479
+ ; The two failure modes are not symmetric: over-measuring leaves a box
480
+ ; a few pixels wide, and under-measuring wraps a line that was meant
481
+ ; to fit and pushes it out of its container.
482
+ if ((ch >= 55296) && (ch <= 56319)) {
483
+ if (ch == 55357) {
484
+ return (fontSize * 1.25)
485
+ }
486
+ return (fontSize * 1.25)
487
+ }
488
+ if ((ch >= 56320) && (ch <= 57343)) {
489
+ return 0.0
490
+ }
491
+ ; A zero-width joiner and a variation selector take no space of their
492
+ ; own — they modify the run around them. Counting them as half an em
493
+ ; each is how a family of four ends up measured as seven characters.
494
+ if (ch == 8205) {
495
+ return 0.0
496
+ }
497
+ if (ch == 65039) {
498
+ return 0.0
499
+ }
500
+ ; Outside the table — anything beyond printable ASCII and the euro.
501
+ ; Half an em, which is the middle of the measured range rather than a
502
+ ; number picked by feel, and it is a GUESS: the honest fix for a
503
+ ; character this table does not hold is to measure with the face that
504
+ ; will draw it, through `EVGTextEngine.setMeasurer`.
505
+ ;
506
+ ; Latin-1 and the general punctuation block are in the tables above
507
+ ; now; this is what is left — other scripts, symbols, arrows. A left
508
+ ; arrow measured 1.0 em and an up arrow 0.5, so half an em is the
509
+ ; middle of the range rather than a number picked by feel, and it is
510
+ ; a GUESS: fine for a glyph alone in a box, not for a sentence.
511
+ return (fontSize * 0.5)
512
+ }
513
+
514
+ fn wrapText:[string] (text:string fontFamily:string fontSize:double maxWidth:double) {
515
+ ; Wrap text to fit within maxWidth
516
+ ; Returns array of lines
517
+ def lines:[string]
518
+ def currentLine:string ""
519
+ def currentWidth:double 0.0
520
+ def wordStart:int 0
521
+ ; What goes between this word and the next: a space, or nothing when
522
+ ; the break was a hyphen the word already carries.
523
+ def joiner:string " "
524
+ def textLen:int (strlen text)
525
+ def i:int 0
526
+
527
+ while (i <= textLen) {
528
+ def ch:int 0
529
+ def isEnd:boolean (i == textLen)
530
+ if (isEnd == false) {
531
+ ch = (charAt text i)
532
+ }
533
+
534
+ ; Where a line may be broken: a space, a newline, the end — and
535
+ ; after a hyphen. The last one was missing, so a hyphenated
536
+ ; compound was one unbreakable word: a box too narrow for the whole
537
+ ; of "Liiketoiminta-logiikka" had nowhere to break it. The rule is
538
+ ; `EVGCodepoint.breaksAfter`, shared with the .pptx wrapper so the
539
+ ; two cannot disagree.
540
+ def isWordEnd:boolean false
541
+ if isEnd {
542
+ isWordEnd = true
543
+ }
544
+ if (ch == 32) { ; space
545
+ isWordEnd = true
546
+ }
547
+ if (ch == 10) { ; newline
548
+ isWordEnd = true
549
+ }
550
+ def hyphen:boolean false
551
+ if (isEnd == false) {
552
+ if (EVGCodepoint.breaksAfter(ch)) {
553
+ ; …but not on the first character of a word: "-5" is not a
554
+ ; place to break, and an empty word would loop.
555
+ if (i > wordStart) {
556
+ isWordEnd = true
557
+ hyphen = true
558
+ }
559
+ }
560
+ }
561
+
562
+ if isWordEnd {
563
+ ; Extract word. A hyphen belongs to the word BEFORE it and
564
+ ; stays on that line — which is the whole point of breaking
565
+ ; there rather than one character earlier.
566
+ def wordEnd:int i
567
+ if hyphen {
568
+ wordEnd = (i + 1)
569
+ }
570
+ def word:string ""
571
+ if (wordEnd > wordStart) {
572
+ word = (substring text wordStart wordEnd)
573
+ }
574
+ def wordWidth:double (this.measureTextWidth(word fontFamily fontSize))
575
+
576
+ ; What joins this word to the one before it: a space normally,
577
+ ; nothing when the line before ended in a hyphen.
578
+ def spaceWidth:double 0.0
579
+ if ((strlen currentLine) > 0) {
580
+ if ((strlen joiner) > 0) {
581
+ spaceWidth = (this.measureTextWidth(joiner fontFamily fontSize))
582
+ }
583
+ }
584
+
585
+ if ((currentWidth + spaceWidth + wordWidth) <= maxWidth) {
586
+ ; Word fits
587
+ if ((strlen currentLine) > 0) {
588
+ currentLine = (currentLine + joiner)
589
+ currentWidth = currentWidth + spaceWidth
590
+ }
591
+ currentLine = (currentLine + word)
592
+ currentWidth = currentWidth + wordWidth
593
+ } {
594
+ ; Word doesn't fit - start new line. A word wider than the
595
+ ; box goes on one anyway and overflows, which is what every
596
+ ; office program does; none of them hyphenates on its own.
597
+ if ((strlen currentLine) > 0) {
598
+ push lines currentLine
599
+ }
600
+ currentLine = word
601
+ currentWidth = wordWidth
602
+ }
603
+
604
+ ; Handle explicit newline
605
+ if (ch == 10) {
606
+ push lines currentLine
607
+ currentLine = ""
608
+ currentWidth = 0.0
609
+ }
610
+
611
+ joiner = " "
612
+ if hyphen {
613
+ joiner = ""
614
+ }
615
+ wordStart = i + 1
616
+ }
617
+
618
+ i = i + 1
619
+ }
620
+
621
+ ; Add final line
622
+ if ((strlen currentLine) > 0) {
623
+ push lines currentLine
624
+ }
625
+
626
+ return lines
627
+ }
628
+ }
629
+
630
+ ; Simple measurer that uses fixed-width approximation
631
+ class SimpleTextMeasurer {
632
+ Extends(EVGTextMeasurer)
633
+
634
+ ; Character width ratios for common fonts
635
+ def charWidthRatio:double 0.55
636
+
637
+ fn setCharWidthRatio:void (ratio:double) {
638
+ charWidthRatio = ratio
639
+ }
640
+
641
+ fn measureText:EVGTextMetrics (text:string fontFamily:string fontSize:double) {
642
+ def textLen:int (strlen text)
643
+ def width:double 0.0
644
+
645
+ ; Sum up character widths
646
+ def i:int 0
647
+ while (i < textLen) {
648
+ def ch:int (charAt text i)
649
+ width = width + (this.measureChar(ch fontFamily fontSize))
650
+ i = i + 1
651
+ }
652
+
653
+ def lineHeight:double (fontSize * (EVGTextMeasurer.normalLineHeightEm()))
654
+
655
+ def metrics (new EVGTextMetrics())
656
+ metrics.width = width
657
+ metrics.height = lineHeight
658
+ metrics.ascent = (fontSize * (EVGTextMeasurer.fallbackAscentEm()))
659
+ metrics.descent = (fontSize * (EVGTextMeasurer.fallbackDescentEm()))
660
+ metrics.lineHeight = lineHeight
661
+ return metrics
662
+ }
663
+ }
664
+
665
+ ; ==============================================================================
666
+ ; EVGDefaultMeasurer — the measurer a layout gets when nobody handed it one
667
+ ; ==============================================================================
668
+ ;
669
+ ; Twenty-five places in the gallery say `new EVGLayout()` and never call
670
+ ; `setMeasurer`: every demo, the RealTrainer page, the pptx chrome. Each of
671
+ ; them measured with a fresh `SimpleTextMeasurer`, which is the table. For a
672
+ ; platform to measure for ALL of them — PLAN_NATIVE_HOSTS.md S0 — there has
673
+ ; to be one place a host can put the measurer it made, and this is it: a
674
+ ; process-wide default that `EVGLayout` and `EVGTextEngine` consult in their
675
+ ; constructors. An app that installs a measurer explicitly (`setMeasurer`,
676
+ ; the TTF one for print) is unaffected; it overrides the default the way it
677
+ ; always did.
678
+ ;
679
+ ; It is a singleton per compiled module, which is what a host wants: a page
680
+ ; that bundles several generated modules installs into each, because two
681
+ ; copies of a class are two classes (`gallery/ui/demo/main.js` says so).
682
+ ;
683
+ ; The default is read at CONSTRUCTION. A layout built before the host
684
+ ; installed keeps the table; that is why a host installs before `start` —
685
+ ; and why `EVGHostTextMeasurer` can be installed unattached and attached
686
+ ; later, so the order of "install" and "the platform is ready" does not
687
+ ; matter, only the order of "install" and "build the first layout".
688
+ class EVGDefaultMeasurer @singleton(true) {
689
+ def current@(optional):EVGTextMeasurer
690
+ def installs:int 0
691
+
692
+ sfn install:void (m:EVGTextMeasurer) {
693
+ def r:EVGDefaultMeasurer (EVGDefaultMeasurer.__singleton())
694
+ r.current = m
695
+ r.installs = (r.installs + 1)
696
+ }
697
+
698
+ sfn uninstall:void () {
699
+ def r:EVGDefaultMeasurer (EVGDefaultMeasurer.__singleton())
700
+ def none@(optional):EVGTextMeasurer
701
+ r.current = none
702
+ }
703
+
704
+ sfn isInstalled:boolean () {
705
+ def r:EVGDefaultMeasurer (EVGDefaultMeasurer.__singleton())
706
+ return (!null? r.current)
707
+ }
708
+
709
+ ; What a new layout or engine measures with: the installed measurer, or a
710
+ ; fresh table when there is none — exactly what the constructors made
711
+ ; before this existed.
712
+ sfn measurer:EVGTextMeasurer () {
713
+ def r:EVGDefaultMeasurer (EVGDefaultMeasurer.__singleton())
714
+ if (!null? r.current) {
715
+ return (unwrap r.current)
716
+ }
717
+ def m (new SimpleTextMeasurer())
718
+ return m
719
+ }
720
+ }