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,541 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EVGConnector — a line between two elements, solved after layout
5
+ ; ==============================================================================
6
+ ;
7
+ ; A `path` is geometry the author owns: `d` says exactly where it goes, and a
8
+ ; responsive layout moves everything around it. That is how the arrow on the
9
+ ; Northwind dashboard came to be written `left: 171px; top: 148px` — correct at
10
+ ; 390 wide and wrong at every other width.
11
+ ;
12
+ ; A `connector` turns that around. The author says which two boxes it joins and
13
+ ; how it should look; the LAYOUT writes its `d`, from the rectangles those two
14
+ ; boxes came out as, on every pass. Move the cards, reflow the grid, stack them
15
+ ; on a phone — the line is re-solved and still joins them.
16
+ ;
17
+ ; from / to an anchor name (`--orders`) or an id (`#orders`)
18
+ ; from-side/to-side left right top bottom center + the four corners,
19
+ ; or `auto`, which picks the facing pair
20
+ ; routing straight | orthogonal | bezier
21
+ ; arrow-start/-end none | open | triangle, arrow-size
22
+ ;
23
+ ; Everything about how it LOOKS is the stroke vocabulary a `path` already has —
24
+ ; `stroke`, `stroke-width`, `stroke-linecap`, `stroke-linejoin`,
25
+ ; `stroke-dasharray`. Nothing here invents a style property.
26
+ ;
27
+ ; The output is an ordinary path: `svgPath` in page coordinates with a `viewBox`
28
+ ; equal to the element's own box, so the fit is 1:1 and every renderer that
29
+ ; draws a `path` draws this with no changes of its own.
30
+ ; ==============================================================================
31
+
32
+ Import "EVGElement.rgr"
33
+
34
+ ; A point on a box's edge, with the direction that edge faces. The normal is
35
+ ; what `orthogonal` turns along and what an offset pushes out by.
36
+ class ConnPt {
37
+ def x:double 0.0
38
+ def y:double 0.0
39
+ def nx:double 0.0
40
+ def ny:double 0.0
41
+ }
42
+
43
+ class EVGConnector {
44
+
45
+ ; Every connector in the tree, re-solved. Returns what could not be
46
+ ; resolved, for the layout to report with its other warnings.
47
+ sfn resolveAll:[string] (root:EVGElement) {
48
+ def names:[string]
49
+ def nodes:[EVGElement]
50
+ EVGConnector.collectAnchors(root names nodes)
51
+ return (EVGConnector.resolveWith(root names nodes))
52
+ }
53
+
54
+ ; The same, against a table of names somebody else already collected —
55
+ ; which the layout has, because the surfaces are anchored by the same
56
+ ; names and one walk is enough for both.
57
+ sfn resolveWith:[string] (root:EVGElement names:[string] nodes:[EVGElement]) {
58
+ def warnings:[string]
59
+ def conns:[EVGElement]
60
+ EVGConnector.collect(root conns)
61
+ if ((array_length conns) == 0) {
62
+ return warnings
63
+ }
64
+ def i:int 0
65
+ while (i < (array_length conns)) {
66
+ def c:EVGElement (itemAt conns i)
67
+ EVGConnector.solve(c names nodes warnings)
68
+ i = (i + 1)
69
+ }
70
+ return warnings
71
+ }
72
+
73
+ sfn collect:void (el:EVGElement out:[EVGElement]) {
74
+ if (el.tagName == "connector") {
75
+ push out el
76
+ }
77
+ def i:int 0
78
+ def n:int (el.getChildCount())
79
+ while (i < n) {
80
+ def kid:EVGElement (el.getChild(i))
81
+ EVGConnector.collect(kid out)
82
+ i = (i + 1)
83
+ }
84
+ }
85
+
86
+ ; Both vocabularies in one table: `anchor-name` as written, and `#id` for
87
+ ; a document that never adopted anchor names.
88
+ sfn collectAnchors:void (el:EVGElement names:[string] nodes:[EVGElement]) {
89
+ if ((strlen el.anchorName) > 0) {
90
+ push names el.anchorName
91
+ push nodes el
92
+ }
93
+ if ((strlen el.id) > 0) {
94
+ push names ("#" + el.id)
95
+ push nodes el
96
+ }
97
+ def i:int 0
98
+ def n:int (el.getChildCount())
99
+ while (i < n) {
100
+ def kid:EVGElement (el.getChild(i))
101
+ EVGConnector.collectAnchors(kid names nodes)
102
+ i = (i + 1)
103
+ }
104
+ }
105
+
106
+ ; Not `find`: the compiler resolves that name elsewhere and every call
107
+ ; site fails with "does not have method find".
108
+ sfn lookup@(optional):EVGElement (key:string names:[string] nodes:[EVGElement]) {
109
+ def miss@(optional):EVGElement
110
+ def k:string (trim key)
111
+ if ((strlen k) == 0) {
112
+ return miss
113
+ }
114
+ def i:int 0
115
+ def n:int (array_length names)
116
+ while (i < n) {
117
+ def nm:string (itemAt names i)
118
+ if (nm == k) {
119
+ def hit@(optional):EVGElement (itemAt nodes i)
120
+ return hit
121
+ }
122
+ i = (i + 1)
123
+ }
124
+ return miss
125
+ }
126
+
127
+ ; The point named by a side, and the direction that side faces.
128
+ sfn pointOn:ConnPt (el:EVGElement side:string) {
129
+ def p (new ConnPt())
130
+ def x:double el.calculatedX
131
+ def y:double el.calculatedY
132
+ def w:double el.calculatedWidth
133
+ def h:double el.calculatedHeight
134
+ def cx:double (x + (w / 2.0))
135
+ def cy:double (y + (h / 2.0))
136
+ p.x = cx
137
+ p.y = cy
138
+ p.nx = 0.0
139
+ p.ny = 0.0
140
+ if (side == "left") {
141
+ p.x = x
142
+ p.nx = (0.0 - 1.0)
143
+ }
144
+ if (side == "right") {
145
+ p.x = (x + w)
146
+ p.nx = 1.0
147
+ }
148
+ if (side == "top") {
149
+ p.y = y
150
+ p.ny = (0.0 - 1.0)
151
+ }
152
+ if (side == "bottom") {
153
+ p.y = (y + h)
154
+ p.ny = 1.0
155
+ }
156
+ if (side == "top-left") {
157
+ p.x = x
158
+ p.y = y
159
+ p.nx = (0.0 - 0.7071)
160
+ p.ny = (0.0 - 0.7071)
161
+ }
162
+ if (side == "top-right") {
163
+ p.x = (x + w)
164
+ p.y = y
165
+ p.nx = 0.7071
166
+ p.ny = (0.0 - 0.7071)
167
+ }
168
+ if (side == "bottom-left") {
169
+ p.x = x
170
+ p.y = (y + h)
171
+ p.nx = (0.0 - 0.7071)
172
+ p.ny = 0.7071
173
+ }
174
+ if (side == "bottom-right") {
175
+ p.x = (x + w)
176
+ p.y = (y + h)
177
+ p.nx = 0.7071
178
+ p.ny = 0.7071
179
+ }
180
+ return p
181
+ }
182
+
183
+ sfn knownSide:boolean (side:string) {
184
+ if (((side == "left") || (side == "right")) || (side == "top")) {
185
+ return true
186
+ }
187
+ if (((side == "bottom") || (side == "center")) || (side == "top-left")) {
188
+ return true
189
+ }
190
+ if (((side == "top-right") || (side == "bottom-left")) || (side == "bottom-right")) {
191
+ return true
192
+ }
193
+ return false
194
+ }
195
+
196
+ ; A path number. `to_string` on a double prints differently per target —
197
+ ; 7 in JavaScript, 7.0 in Python — and a `d` string is compared in tests,
198
+ ; so it is written here once, to two decimals, the same everywhere.
199
+ sfn num:string (v:double) {
200
+ def x:double v
201
+ def neg:boolean false
202
+ if (x < 0.0) {
203
+ neg = true
204
+ x = (0.0 - x)
205
+ }
206
+ def scaled:int (to_int ((x * 100.0) + 0.5))
207
+ def whole:int (idiv scaled 100)
208
+ def frac:int (scaled - (whole * 100))
209
+ def out:string (to_string whole)
210
+ if (frac > 0) {
211
+ def fs:string (to_string frac)
212
+ if (frac < 10) {
213
+ fs = ("0" + fs)
214
+ }
215
+ if ((frac - ((idiv frac 10) * 10)) == 0) {
216
+ fs = (to_string (idiv frac 10))
217
+ }
218
+ out = ((out + ".") + fs)
219
+ }
220
+ if neg {
221
+ out = ("-" + out)
222
+ }
223
+ return out
224
+ }
225
+
226
+ sfn moveTo:string (x:double y:double) {
227
+ return ((("M " + (EVGConnector.num(x))) + " ") + (EVGConnector.num(y)))
228
+ }
229
+
230
+ sfn lineTo:string (x:double y:double) {
231
+ return (((" L " + (EVGConnector.num(x))) + " ") + (EVGConnector.num(y)))
232
+ }
233
+
234
+ ; One arrowhead at (tx,ty), pointing along (dx,dy). `open` is two barbs
235
+ ; stroked; `triangle` is a closed head, filled by the fill the solver turns
236
+ ; on for it.
237
+ sfn arrowHead:string (kind:string tx:double ty:double dx:double dy:double size:double) {
238
+ def len:double (sqrt ((dx * dx) + (dy * dy)))
239
+ if (len < 0.000001) {
240
+ return ""
241
+ }
242
+ def ux:double (dx / len)
243
+ def uy:double (dy / len)
244
+ ; The barbs are the direction turned ±150°, which is 30° of overhang
245
+ ; either side of the shaft — the proportions of an ordinary arrow.
246
+ def ca:double (0.0 - 0.8660254)
247
+ def sa:double 0.5
248
+ def b1x:double (tx + (size * ((ux * ca) - (uy * sa))))
249
+ def b1y:double (ty + (size * ((ux * sa) + (uy * ca))))
250
+ def b2x:double (tx + (size * ((ux * ca) + (uy * sa))))
251
+ def b2y:double (ty + (size * ((0.0 - (ux * sa)) + (uy * ca))))
252
+ if (kind == "triangle") {
253
+ def tri:string (EVGConnector.moveTo(tx ty))
254
+ tri = (tri + (EVGConnector.lineTo(b1x b1y)))
255
+ tri = (tri + (EVGConnector.lineTo(b2x b2y)))
256
+ tri = (tri + " Z")
257
+ return tri
258
+ }
259
+ def open:string (EVGConnector.moveTo(b1x b1y))
260
+ open = (open + (EVGConnector.lineTo(tx ty)))
261
+ open = (open + (EVGConnector.lineTo(b2x b2y)))
262
+ return open
263
+ }
264
+
265
+ sfn wantsArrow:boolean (kind:string) {
266
+ if ((strlen kind) == 0) {
267
+ return false
268
+ }
269
+ if (kind == "none") {
270
+ return false
271
+ }
272
+ if (kind == "false") {
273
+ return false
274
+ }
275
+ return true
276
+ }
277
+
278
+ sfn headKind:string (kind:string) {
279
+ if (kind == "open") {
280
+ return "open"
281
+ }
282
+ return "triangle"
283
+ }
284
+
285
+ sfn solve:void (c:EVGElement names:[string] nodes:[EVGElement] warnings:[string]) {
286
+ c.connectorResolved = false
287
+ if ((strlen c.connectorFrom) == 0) {
288
+ push warnings "connector: `from` names no element"
289
+ c.svgPath = ""
290
+ c.arrowPath = ""
291
+ return
292
+ }
293
+ if ((strlen c.connectorTo) == 0) {
294
+ push warnings "connector: `to` names no element"
295
+ c.svgPath = ""
296
+ c.arrowPath = ""
297
+ return
298
+ }
299
+ def fromEl@(optional):EVGElement (EVGConnector.lookup(c.connectorFrom names nodes))
300
+ def toEl@(optional):EVGElement (EVGConnector.lookup(c.connectorTo names nodes))
301
+ if (null? fromEl) {
302
+ push warnings (("connector: nothing is called \"" + c.connectorFrom) + "\" — give the target an anchor-name or an id")
303
+ c.svgPath = ""
304
+ c.arrowPath = ""
305
+ return
306
+ }
307
+ if (null? toEl) {
308
+ push warnings (("connector: nothing is called \"" + c.connectorTo) + "\" — give the target an anchor-name or an id")
309
+ c.svgPath = ""
310
+ c.arrowPath = ""
311
+ return
312
+ }
313
+ def a:EVGElement (unwrap fromEl)
314
+ def b:EVGElement (unwrap toEl)
315
+
316
+ def acx:double (a.calculatedX + (a.calculatedWidth / 2.0))
317
+ def acy:double (a.calculatedY + (a.calculatedHeight / 2.0))
318
+ def bcx:double (b.calculatedX + (b.calculatedWidth / 2.0))
319
+ def bcy:double (b.calculatedY + (b.calculatedHeight / 2.0))
320
+ def dx:double (bcx - acx)
321
+ def dy:double (bcy - acy)
322
+ def horizontal:boolean ((fabs dx) >= (fabs dy))
323
+
324
+ ; `auto` is the whole responsive story: the same connector leaves the
325
+ ; right edge when the cards sit side by side and the bottom edge when
326
+ ; the same layout stacks them.
327
+ def fs:string (EVGConnector.resolveSide(c.connectorFromSide horizontal dx dy false warnings))
328
+ def ts:string (EVGConnector.resolveSide(c.connectorToSide horizontal dx dy true warnings))
329
+
330
+ def p0:ConnPt (EVGConnector.pointOn(a fs))
331
+ def p1:ConnPt (EVGConnector.pointOn(b ts))
332
+ p0.x = (p0.x + (p0.nx * c.connectorFromOffset))
333
+ p0.y = (p0.y + (p0.ny * c.connectorFromOffset))
334
+ p1.x = (p1.x + (p1.nx * c.connectorToOffset))
335
+ p1.y = (p1.y + (p1.ny * c.connectorToOffset))
336
+
337
+ ; The vertices, in page coordinates. Bezier keeps its two controls
338
+ ; beside them: they are not on the line, but they bound it.
339
+ def xs:[double]
340
+ def ys:[double]
341
+ def routing:string c.connectorRouting
342
+ if ((strlen routing) == 0) {
343
+ routing = "straight"
344
+ }
345
+ def bezier:boolean (routing == "bezier")
346
+ def c0x:double 0.0
347
+ def c0y:double 0.0
348
+ def c1x:double 0.0
349
+ def c1y:double 0.0
350
+
351
+ push xs p0.x
352
+ push ys p0.y
353
+ if (routing == "orthogonal") {
354
+ def turnsHorizontally:boolean ((fabs p0.nx) > 0.000001)
355
+ if (((fabs p0.nx) < 0.000001) && ((fabs p0.ny) < 0.000001)) {
356
+ turnsHorizontally = horizontal
357
+ }
358
+ if turnsHorizontally {
359
+ def midX:double ((p0.x + p1.x) / 2.0)
360
+ push xs midX
361
+ push ys p0.y
362
+ push xs midX
363
+ push ys p1.y
364
+ } {
365
+ def midY:double ((p0.y + p1.y) / 2.0)
366
+ push xs p0.x
367
+ push ys midY
368
+ push xs p1.x
369
+ push ys midY
370
+ }
371
+ }
372
+ if bezier {
373
+ def span:double (sqrt ((dx * dx) + (dy * dy)))
374
+ def k:double (span * 0.4)
375
+ if (k < 40.0) {
376
+ k = 40.0
377
+ }
378
+ c0x = (p0.x + (p0.nx * k))
379
+ c0y = (p0.y + (p0.ny * k))
380
+ c1x = (p1.x + (p1.nx * k))
381
+ c1y = (p1.y + (p1.ny * k))
382
+ }
383
+ push xs p1.x
384
+ push ys p1.y
385
+
386
+ def count:int (array_length xs)
387
+ ; Which way the head at each end points, and where it sits.
388
+ def endDx:double (p1.x - (itemAt xs (count - 2)))
389
+ def endDy:double (p1.y - (itemAt ys (count - 2)))
390
+ def startDx:double (p0.x - (itemAt xs 1))
391
+ def startDy:double (p0.y - (itemAt ys 1))
392
+ if bezier {
393
+ endDx = (p1.x - c1x)
394
+ endDy = (p1.y - c1y)
395
+ startDx = (p0.x - c0x)
396
+ startDy = (p0.y - c0y)
397
+ }
398
+
399
+ def headEnd:boolean (EVGConnector.wantsArrow(c.arrowEnd))
400
+ def headStart:boolean (EVGConnector.wantsArrow(c.arrowStart))
401
+ ; The shaft: stroked, never filled. The heads are built below into
402
+ ; `arrowPath`, which is the element's filled half — see
403
+ ; `EVGElement.arrowPath` for why the two cannot share one `d`.
404
+ def d:string (EVGConnector.moveTo(p0.x p0.y))
405
+ if bezier {
406
+ d = (d + (EVGConnector.curveTo(c0x c0y c1x c1y p1.x p1.y)))
407
+ } {
408
+ def i:int 1
409
+ while (i < count) {
410
+ d = (d + (EVGConnector.lineTo((itemAt xs i) (itemAt ys i))))
411
+ i = (i + 1)
412
+ }
413
+ }
414
+
415
+ def size:double c.arrowSize
416
+ if (size <= 0.0) {
417
+ size = 10.0
418
+ }
419
+ ; An `open` head is two strokes, so it belongs on the shaft's own
420
+ ; path and inherits its cap and join. A `triangle` is filled, so it
421
+ ; goes on the filled path beside it.
422
+ def heads:string ""
423
+ if headEnd {
424
+ def kindE:string (EVGConnector.headKind(c.arrowEnd))
425
+ def head:string (EVGConnector.arrowHead(kindE p1.x p1.y endDx endDy size))
426
+ if ((strlen head) > 0) {
427
+ if (kindE == "triangle") {
428
+ heads = (heads + head)
429
+ } {
430
+ d = ((d + " ") + head)
431
+ }
432
+ }
433
+ }
434
+ if headStart {
435
+ def kindS:string (EVGConnector.headKind(c.arrowStart))
436
+ def head2:string (EVGConnector.arrowHead(kindS p0.x p0.y startDx startDy size))
437
+ if ((strlen head2) > 0) {
438
+ if (kindS == "triangle") {
439
+ if ((strlen heads) > 0) {
440
+ heads = (heads + " ")
441
+ }
442
+ heads = (heads + head2)
443
+ } {
444
+ d = ((d + " ") + head2)
445
+ }
446
+ }
447
+ }
448
+ c.arrowPath = heads
449
+
450
+ ; The box. It is the geometry's own bounds, grown by what a stroke and
451
+ ; a head put outside them, and the viewBox is set to exactly the same
452
+ ; rectangle — so the path is drawn 1:1 where it was solved, with no
453
+ ; fitting of any kind.
454
+ def minX:double (itemAt xs 0)
455
+ def maxX:double minX
456
+ def minY:double (itemAt ys 0)
457
+ def maxY:double minY
458
+ def k2:int 0
459
+ while (k2 < count) {
460
+ def px:double (itemAt xs k2)
461
+ def py:double (itemAt ys k2)
462
+ if (px < minX) { minX = px }
463
+ if (px > maxX) { maxX = px }
464
+ if (py < minY) { minY = py }
465
+ if (py > maxY) { maxY = py }
466
+ k2 = (k2 + 1)
467
+ }
468
+ if bezier {
469
+ if (c0x < minX) { minX = c0x }
470
+ if (c0x > maxX) { maxX = c0x }
471
+ if (c1x < minX) { minX = c1x }
472
+ if (c1x > maxX) { maxX = c1x }
473
+ if (c0y < minY) { minY = c0y }
474
+ if (c0y > maxY) { maxY = c0y }
475
+ if (c1y < minY) { minY = c1y }
476
+ if (c1y > maxY) { maxY = c1y }
477
+ }
478
+ def pad:double ((c.strokeWidth / 2.0) + 1.0)
479
+ if (headEnd || headStart) {
480
+ pad = (pad + size)
481
+ }
482
+ minX = (minX - pad)
483
+ minY = (minY - pad)
484
+ maxX = (maxX + pad)
485
+ maxY = (maxY + pad)
486
+
487
+ def bw:double (maxX - minX)
488
+ def bh:double (maxY - minY)
489
+ c.svgPath = d
490
+ c.viewBox = (((((EVGConnector.num(minX)) + " ") + (EVGConnector.num(minY))) + " ") + (((EVGConnector.num(bw)) + " ") + (EVGConnector.num(bh))))
491
+ c.calculatedX = minX
492
+ c.calculatedY = minY
493
+ c.calculatedWidth = bw
494
+ c.calculatedHeight = bh
495
+ c.calculatedInnerWidth = bw
496
+ c.calculatedInnerHeight = bh
497
+ c.connectorResolved = true
498
+ }
499
+
500
+ sfn curveTo:string (ax:double ay:double bx:double by:double ex:double ey:double) {
501
+ def out:string (" C " + (EVGConnector.num(ax)))
502
+ out = ((out + " ") + (EVGConnector.num(ay)))
503
+ out = ((out + " ") + (EVGConnector.num(bx)))
504
+ out = ((out + " ") + (EVGConnector.num(by)))
505
+ out = ((out + " ") + (EVGConnector.num(ex)))
506
+ out = ((out + " ") + (EVGConnector.num(ey)))
507
+ return out
508
+ }
509
+
510
+ ; `auto`, or a side the author named. An unknown side is reported and
511
+ ; treated as auto rather than silently drawing from the middle.
512
+ sfn resolveSide:string (declared:string horizontal:boolean dx:double dy:double isTarget:boolean warnings:[string]) {
513
+ def s:string (trim declared)
514
+ if ((strlen s) > 0) {
515
+ if ((s == "auto") == false) {
516
+ if (EVGConnector.knownSide(s)) {
517
+ return s
518
+ }
519
+ push warnings (("connector: unknown side \"" + s) + "\" — use left, right, top, bottom, center, a corner, or auto")
520
+ }
521
+ }
522
+ def forward:double dx
523
+ if (horizontal == false) {
524
+ forward = dy
525
+ }
526
+ def positive:boolean (forward >= 0.0)
527
+ if isTarget {
528
+ positive = (positive == false)
529
+ }
530
+ if horizontal {
531
+ if positive {
532
+ return "right"
533
+ }
534
+ return "left"
535
+ }
536
+ if positive {
537
+ return "bottom"
538
+ }
539
+ return "top"
540
+ }
541
+ }