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,232 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EVGRuler — where the paper starts, where the text starts, and how far along
5
+ ; ==============================================================================
6
+ ;
7
+ ; A word processor without a ruler can be typed into but not laid out. It is
8
+ ; the one place a reader can SEE that the page has margins, that the paragraph
9
+ ; they are in is indented, and by how much — and the one place they can say so
10
+ ; without opening a dialog and knowing the word "indent" first.
11
+ ;
12
+ ; This is the geometry only: where the band is, where the ticks fall, where
13
+ ; the three markers sit and which one the pointer is on. The drawing is
14
+ ; `EVGRulerView`, and the split is the same one `EVGToolbar` has, for the same
15
+ ; reason — the numbers can be checked without a font, a canvas or a window,
16
+ ; and they are the half that is easy to get wrong.
17
+ ;
18
+ ; Everything is in SCREEN pixels except `pxPerUnit`, which is how many of them
19
+ ; a ruler unit is. An inch at 96 dpi is the default because that is the unit
20
+ ; Word's own ruler is marked in and the unit its measurements arrive in; a
21
+ ; caller working in centimetres passes 37.8 and gets a centimetre ruler with
22
+ ; no other change.
23
+ ;
24
+ ; npm run evg:ruler:test
25
+ ; ==============================================================================
26
+
27
+ class EVGRuler {
28
+ ; The band itself.
29
+ def x:int 0
30
+ def y:int 0
31
+ def w:int 0
32
+ def h:int 22
33
+
34
+ ; Where the paper is inside it. The ruler is as wide as the window and the
35
+ ; paper is not, so the two are separate: the numbers count from the left
36
+ ; edge of the PAPER, and the band beyond the paper is dead space.
37
+ def pageX:int 0
38
+ def pageW:int 0
39
+
40
+ ; The text column inside the paper, in pixels from the paper's left edge.
41
+ def marginL:int 0
42
+ def marginR:int 0
43
+
44
+ ; The paragraph's own indents, in pixels, measured from the text column —
45
+ ; not from the paper. That is what they are in the file and it is why a
46
+ ; hanging indent is a negative first line.
47
+ def indentFirst:int 0
48
+ def indentLeft:int 0
49
+ def indentRight:int 0
50
+
51
+ def pxPerUnit:double 96.0
52
+ ; Eight ticks to the unit: the eighths of an inch a Word ruler shows.
53
+ def ticksPerUnit:int 8
54
+
55
+ Constructor () {
56
+ }
57
+
58
+ ; --- the paper, in screen coordinates ------------------------------------
59
+
60
+ fn textLeftX:int () {
61
+ return ((pageX + marginL) + indentLeft)
62
+ }
63
+
64
+ fn textRightX:int () {
65
+ return (((pageX + pageW) - marginR) - indentRight)
66
+ }
67
+
68
+ ; The first line can start left of the rest of the paragraph — that is a
69
+ ; hanging indent, and it is why this is not clamped to the others.
70
+ fn firstLineX:int () {
71
+ return (((pageX + marginL) + indentLeft) + indentFirst)
72
+ }
73
+
74
+ fn marginLeftX:int () {
75
+ return (pageX + marginL)
76
+ }
77
+
78
+ fn marginRightX:int () {
79
+ return ((pageX + pageW) - marginR)
80
+ }
81
+
82
+ ; --- the marks ------------------------------------------------------------
83
+
84
+ ; How many ticks fit across the paper. Counted over the PAPER rather than
85
+ ; the band, because a ruler numbered from the window edge measures nothing
86
+ ; anybody cares about.
87
+ fn tickCount:int () {
88
+ if (pxPerUnit <= 0.0) {
89
+ return 0
90
+ }
91
+ def per:double (pxPerUnit / (to_double ticksPerUnit))
92
+ if (per <= 0.0) {
93
+ return 0
94
+ }
95
+ return ((to_int ((to_double pageW) / per)) + 1)
96
+ }
97
+
98
+ fn tickX:int (i:int) {
99
+ def per:double (pxPerUnit / (to_double ticksPerUnit))
100
+ return (pageX + (to_int ((to_double i) * per)))
101
+ }
102
+
103
+ ; A whole unit gets a number; the eighths get a mark and no number.
104
+ fn tickIsUnit:boolean (i:int) {
105
+ if (ticksPerUnit <= 0) {
106
+ return false
107
+ }
108
+ return ((i % ticksPerUnit) == 0)
109
+ }
110
+
111
+ ; Half units are drawn taller than eighths, which is what makes a ruler
112
+ ; countable at a glance rather than a row of identical scratches.
113
+ fn tickIsHalf:boolean (i:int) {
114
+ if (ticksPerUnit <= 0) {
115
+ return false
116
+ }
117
+ def half:int (idiv ticksPerUnit 2)
118
+ if (half <= 0) {
119
+ return false
120
+ }
121
+ return ((i % half) == 0)
122
+ }
123
+
124
+ fn tickLabel:int (i:int) {
125
+ if (ticksPerUnit <= 0) {
126
+ return 0
127
+ }
128
+ return (idiv i ticksPerUnit)
129
+ }
130
+
131
+ ; --- the markers ----------------------------------------------------------
132
+ ; 0 the first line, 1 the left indent, 2 the right indent, -1 none.
133
+
134
+ sfn markerFirst:int () { return 0 }
135
+ sfn markerLeft:int () { return 1 }
136
+ sfn markerRight:int () { return 2 }
137
+
138
+ fn markerX:int (which:int) {
139
+ if (which == 0) {
140
+ return (this.firstLineX())
141
+ }
142
+ if (which == 1) {
143
+ return (this.textLeftX())
144
+ }
145
+ return (this.textRightX())
146
+ }
147
+
148
+ ; Which marker the pointer is on, or -1.
149
+ ;
150
+ ; The first line and the left indent sit at the same x whenever the
151
+ ; paragraph has no first-line indent, which is most paragraphs. The FIRST
152
+ ; LINE wins there, because it is the one at the top of the band and the
153
+ ; one under the pointer coming down onto it — a hit test that answered the
154
+ ; left indent would make the top marker undraggable in the common case and
155
+ ; leave nobody able to say why.
156
+ fn hitMarker:int (px:int py:int) {
157
+ if (py < y) {
158
+ return -1
159
+ }
160
+ if (py >= (y + h)) {
161
+ return -1
162
+ }
163
+ def half:int (idiv h 2)
164
+ def top:boolean (py < (y + half))
165
+ if top {
166
+ if (this.nearX(px (this.firstLineX()))) {
167
+ return 0
168
+ }
169
+ } {
170
+ if (this.nearX(px (this.textLeftX()))) {
171
+ return 1
172
+ }
173
+ }
174
+ if (this.nearX(px (this.textRightX()))) {
175
+ return 2
176
+ }
177
+ return -1
178
+ }
179
+
180
+ fn nearX:boolean (px:int at:int) {
181
+ def d:int (px - at)
182
+ if (d < 0) {
183
+ d = (0 - d)
184
+ }
185
+ return (d <= 6)
186
+ }
187
+
188
+ ; Where a marker dragged to `px` puts its indent, in pixels from the text
189
+ ; column. Clamped so a marker cannot be dragged off its own paper: an
190
+ ; indent wider than the column is a paragraph with no width at all, and
191
+ ; the file will happily hold one.
192
+ fn indentFor:int (which:int px:int) {
193
+ def colL:int (pageX + marginL)
194
+ def colR:int ((pageX + pageW) - marginR)
195
+ def span:int (colR - colL)
196
+ if (span < 1) {
197
+ return 0
198
+ }
199
+ if (which == 2) {
200
+ def r:int (colR - px)
201
+ if (r < 0) {
202
+ r = 0
203
+ }
204
+ if (r > (span - 1)) {
205
+ r = (span - 1)
206
+ }
207
+ return r
208
+ }
209
+ def v:int (px - colL)
210
+ if (which == 1) {
211
+ if (v < 0) {
212
+ v = 0
213
+ }
214
+ if (v > (span - 1)) {
215
+ v = (span - 1)
216
+ }
217
+ return v
218
+ }
219
+ ; The first line is relative to the left indent and may be negative —
220
+ ; that is a hanging indent, and clamping it to zero is what makes a
221
+ ; bulleted list impossible to express.
222
+ def f:int ((px - colL) - indentLeft)
223
+ def lo:int (0 - (indentLeft + 1))
224
+ if (f < lo) {
225
+ f = lo
226
+ }
227
+ if (f > (span - 1)) {
228
+ f = (span - 1)
229
+ }
230
+ return f
231
+ }
232
+ }
@@ -0,0 +1,172 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EVGRulerTest — the numbers on the ruler, without a font in sight
5
+ ; ==============================================================================
6
+ ;
7
+ ; The ruler is split into geometry and drawing for exactly this: the numbers
8
+ ; can be checked without a canvas, and they are the half that is easy to get
9
+ ; wrong. What is checked here is what a reader would notice within a minute of
10
+ ; using it:
11
+ ;
12
+ ; * the numbers count from the left edge of the PAPER, not of the window
13
+ ; * the marks are the eighths of a unit, with the halves taller and the
14
+ ; whole units taller still and numbered
15
+ ; * a hanging indent puts the first line LEFT of the rest of the paragraph,
16
+ ; which is the case a clamp to zero silently destroys
17
+ ; * the two left markers sit on top of each other when there is no
18
+ ; first-line indent, and the hit test still tells them apart
19
+ ; * a marker dragged off the paper stops at the edge of the text column
20
+ ;
21
+ ; npm run evg:ruler:test
22
+ ; ==============================================================================
23
+
24
+ Import "EVGRuler.rgr"
25
+
26
+ class RulerCheck {
27
+ def passed:int 0
28
+ def failed:int 0
29
+
30
+ fn ok:void (name:string cond:boolean) {
31
+ if cond {
32
+ passed = (passed + 1)
33
+ print (" PASS " + name)
34
+ } {
35
+ failed = (failed + 1)
36
+ print (" FAIL " + name)
37
+ }
38
+ }
39
+
40
+ fn eqInt:void (name:string got:int want:int) {
41
+ this.ok(((((name + " (got ") + (to_string got)) + " want ") + ((to_string want) + ")")) (got == want))
42
+ }
43
+ }
44
+
45
+ class EVGRulerTest {
46
+ def c:RulerCheck (new RulerCheck)
47
+
48
+ sfn main:void () {
49
+ def t (new EVGRulerTest())
50
+ t.run()
51
+ }
52
+
53
+ ; A letter page at 96 dpi: 8.5 inches of paper with a one-inch margin
54
+ ; each side, sitting in a window wider than it.
55
+ sfn page:EVGRuler () {
56
+ def r (new EVGRuler)
57
+ r.x = 0
58
+ r.y = 40
59
+ r.w = 1000
60
+ r.h = 22
61
+ r.pageX = 100
62
+ r.pageW = 816
63
+ r.marginL = 96
64
+ r.marginR = 96
65
+ r.pxPerUnit = 96.0
66
+ return r
67
+ }
68
+
69
+ fn run:void () {
70
+ print "=== EVGRulerTest ==="
71
+ this.testColumn()
72
+ this.testTicks()
73
+ this.testIndents()
74
+ this.testHit()
75
+ this.testDrag()
76
+ print ""
77
+ print (("passed = " + (to_string c.passed)) + (" failed = " + (to_string c.failed)))
78
+ if (c.failed == 0) {
79
+ print "ALL PASS"
80
+ } {
81
+ print "SOME FAILED"
82
+ }
83
+ }
84
+
85
+ fn testColumn:void () {
86
+ print "--- where the paper and the text are ---"
87
+ def r:EVGRuler (EVGRulerTest.page())
88
+ c.eqInt("the text column starts an inch into the paper" (r.marginLeftX()) 196)
89
+ c.eqInt("and ends an inch before its right edge" (r.marginRightX()) 820)
90
+ c.eqInt("with no indents the text starts at the margin" (r.textLeftX()) 196)
91
+ c.eqInt("and ends at the other one" (r.textRightX()) 820)
92
+ }
93
+
94
+ fn testTicks:void () {
95
+ print "--- the marks ---"
96
+ def r:EVGRuler (EVGRulerTest.page())
97
+ ; Counted over the PAPER: a ruler numbered from the window edge
98
+ ; measures nothing anybody cares about.
99
+ c.eqInt("the first tick is at the left edge of the paper" (r.tickX(0)) 100)
100
+ c.eqInt("the eighth is one inch along" (r.tickX(8)) 196)
101
+ c.ok("and it is a whole unit" (r.tickIsUnit(8)))
102
+ c.eqInt("numbered 1" (r.tickLabel(8)) 1)
103
+ c.ok("a half is a half and not a unit"
104
+ ((r.tickIsHalf(4)) && ((r.tickIsUnit(4)) == false)))
105
+ c.ok("an eighth is neither"
106
+ (((r.tickIsHalf(3)) == false) && ((r.tickIsUnit(3)) == false)))
107
+ c.ok("the marks cover the paper" ((r.tickCount()) >= 68))
108
+ }
109
+
110
+ fn testIndents:void () {
111
+ print "--- and the paragraph's own indents ---"
112
+ def r:EVGRuler (EVGRulerTest.page())
113
+ r.indentLeft = 48
114
+ r.indentRight = 24
115
+ c.eqInt("a left indent moves the text in" (r.textLeftX()) 244)
116
+ c.eqInt("a right indent brings the other end in" (r.textRightX()) 796)
117
+ c.eqInt("and the first line follows the left one" (r.firstLineX()) 244)
118
+
119
+ ; A HANGING indent: the first line starts left of the rest, which is
120
+ ; how every bulleted list in every document is built. A first-line
121
+ ; indent clamped to zero cannot express it.
122
+ r.indentFirst = -24
123
+ c.eqInt("a hanging first line starts left of the paragraph" (r.firstLineX()) 220)
124
+ c.ok("which is left of the body" ((r.firstLineX()) < (r.textLeftX())))
125
+ }
126
+
127
+ fn testHit:void () {
128
+ print "--- which marker the pointer is on ---"
129
+ def r:EVGRuler (EVGRulerTest.page())
130
+ c.eqInt("the top half of the band is the first line"
131
+ (r.hitMarker(196 (r.y + 3))) (EVGRuler.markerFirst()))
132
+ ; The two left markers are at the SAME x when there is no first-line
133
+ ; indent, which is most paragraphs. The band is split top and bottom
134
+ ; so both stay reachable — a hit test that answered one of them for
135
+ ; the whole band would make the other undraggable and leave nobody
136
+ ; able to say why.
137
+ c.eqInt("the bottom half is the left indent"
138
+ (r.hitMarker(196 ((r.y + r.h) - 3))) (EVGRuler.markerLeft()))
139
+ c.eqInt("the right indent is at the other end"
140
+ (r.hitMarker(820 ((r.y + r.h) - 3))) (EVGRuler.markerRight()))
141
+ c.eqInt("the middle of the ruler is no marker"
142
+ (r.hitMarker(500 (r.y + 8))) -1)
143
+ c.eqInt("and neither is a point above the band"
144
+ (r.hitMarker(196 (r.y - 4))) -1)
145
+ ; A few pixels off still counts: a marker six pixels wide that only
146
+ ; answers its exact centre is a marker nobody can grab.
147
+ c.eqInt("a near miss still finds it"
148
+ (r.hitMarker(200 (r.y + 3))) (EVGRuler.markerFirst()))
149
+ }
150
+
151
+ fn testDrag:void () {
152
+ print "--- and where dragging one puts it ---"
153
+ def r:EVGRuler (EVGRulerTest.page())
154
+ c.eqInt("dragging the left indent an inch in" (r.indentFor(1 292)) 96)
155
+ c.eqInt("dragging the right indent an inch in" (r.indentFor(2 724)) 96)
156
+
157
+ ; Off the paper in either direction stops at the column.
158
+ c.eqInt("dragged off the left edge it stops at the margin" (r.indentFor(1 0)) 0)
159
+ c.eqInt("dragged off the right edge it stops too" (r.indentFor(2 5000)) 0)
160
+ def colR:int (r.marginRightX())
161
+ def colL:int (r.marginLeftX())
162
+ c.ok("and cannot be dragged past the far side"
163
+ ((r.indentFor(1 5000)) < (colR - colL)))
164
+
165
+ ; The first line may go negative — that is the hanging indent — but
166
+ ; not so far that it leaves the paper.
167
+ r.indentLeft = 48
168
+ c.eqInt("the first line can be dragged left of the paragraph"
169
+ (r.indentFor(0 220)) -24)
170
+ c.ok("but not off the paper" ((r.indentFor(0 0)) >= (0 - 49)))
171
+ }
172
+ }
@@ -0,0 +1,178 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; ==============================================================================
4
+ ; EVGSelectChrome - where the handles are, for any editor that has a selection
5
+ ; ==============================================================================
6
+ ;
7
+ ; Eight handles round a box, numbered clockwise from the top-left:
8
+ ;
9
+ ; 0 ── 1 ── 2
10
+ ; │ │
11
+ ; 7 3
12
+ ; │ │
13
+ ; 6 ── 5 ── 4
14
+ ;
15
+ ; That numbering is not arbitrary once it exists: a resize is implemented by
16
+ ; asking which edges a handle owns, and two editors that number their handles
17
+ ; differently cannot share a single line of that code. The slide editor picked
18
+ ; this order first; the book editor uses the same one, and both ask here rather
19
+ ; than each carrying its own copy of "handle 3 is the right edge".
20
+ ;
21
+ ; Pure geometry, in whatever unit the caller works in - slide points, page
22
+ ; points or window pixels. Nothing here knows what a slide or a page is.
23
+ ; ==============================================================================
24
+
25
+ class EVGSelectChrome {
26
+ ; The centre of handle `idx` on a box spanning x0..x1, y0..y1.
27
+ sfn handleCx:double (x0:double x1:double idx:int) {
28
+ def mid:double ((x0 + x1) * 0.5)
29
+ if (idx == 1) {
30
+ return mid
31
+ }
32
+ if (idx == 5) {
33
+ return mid
34
+ }
35
+ if (idx == 2) {
36
+ return x1
37
+ }
38
+ if (idx == 3) {
39
+ return x1
40
+ }
41
+ if (idx == 4) {
42
+ return x1
43
+ }
44
+ return x0
45
+ }
46
+
47
+ sfn handleCy:double (y0:double y1:double idx:int) {
48
+ def mid:double ((y0 + y1) * 0.5)
49
+ if (idx == 3) {
50
+ return mid
51
+ }
52
+ if (idx == 7) {
53
+ return mid
54
+ }
55
+ if (idx == 4) {
56
+ return y1
57
+ }
58
+ if (idx == 5) {
59
+ return y1
60
+ }
61
+ if (idx == 6) {
62
+ return y1
63
+ }
64
+ return y0
65
+ }
66
+
67
+ ; Which edges handle `idx` moves. A resize is these four answers and
68
+ ; nothing else, which is why they are here rather than written out again
69
+ ; in every editor's applyResize.
70
+ sfn movesWest:boolean (idx:int) {
71
+ if (idx == 0) {
72
+ return true
73
+ }
74
+ if (idx == 6) {
75
+ return true
76
+ }
77
+ return (idx == 7)
78
+ }
79
+
80
+ sfn movesEast:boolean (idx:int) {
81
+ if (idx == 2) {
82
+ return true
83
+ }
84
+ if (idx == 4) {
85
+ return true
86
+ }
87
+ return (idx == 3)
88
+ }
89
+
90
+ sfn movesNorth:boolean (idx:int) {
91
+ if (idx == 0) {
92
+ return true
93
+ }
94
+ if (idx == 2) {
95
+ return true
96
+ }
97
+ return (idx == 1)
98
+ }
99
+
100
+ sfn movesSouth:boolean (idx:int) {
101
+ if (idx == 4) {
102
+ return true
103
+ }
104
+ if (idx == 6) {
105
+ return true
106
+ }
107
+ return (idx == 5)
108
+ }
109
+
110
+ ; The handle under a point, or -1. `grab` is the half-width of a handle's
111
+ ; hit area - deliberately larger than the drawn square, because a handle
112
+ ; you cannot reliably hit is worse than one you cannot see.
113
+ sfn handleAt:int (x0:double y0:double x1:double y1:double px:double py:double grab:double) {
114
+ def i:int 0
115
+ while (i < 8) {
116
+ def hx:double (EVGSelectChrome.handleCx(x0 x1 i))
117
+ def hy:double (EVGSelectChrome.handleCy(y0 y1 i))
118
+ def dx:double (px - hx)
119
+ def dy:double (py - hy)
120
+ if (dx < 0.0) {
121
+ dx = (0.0 - dx)
122
+ }
123
+ if (dy < 0.0) {
124
+ dy = (0.0 - dy)
125
+ }
126
+ if ((dx <= grab) && (dy <= grab)) {
127
+ return i
128
+ }
129
+ i = (i + 1)
130
+ }
131
+ return -1
132
+ }
133
+
134
+ ; A drag from (ax, ay) to (bx, by) as a positive rectangle: x, y, w, h.
135
+ ; A marquee dragged up and to the left is the same rectangle as one
136
+ ; dragged down and to the right, and only one of them has positive sides.
137
+ sfn marquee:[double] (ax:double ay:double bx:double by:double) {
138
+ def out:[double]
139
+ def x0:double ax
140
+ def x1:double bx
141
+ if (bx < ax) {
142
+ x0 = bx
143
+ x1 = ax
144
+ }
145
+ def y0:double ay
146
+ def y1:double by
147
+ if (by < ay) {
148
+ y0 = by
149
+ y1 = ay
150
+ }
151
+ push out x0
152
+ push out y0
153
+ push out (x1 - x0)
154
+ push out (y1 - y0)
155
+ return out
156
+ }
157
+
158
+ ; Do two boxes overlap at all? A marquee selects what it touches.
159
+ sfn overlaps:boolean (ax:double ay:double aw:double ah:double bx:double by:double bw:double bh:double) {
160
+ def ax1:double (ax + aw)
161
+ def ay1:double (ay + ah)
162
+ def bx1:double (bx + bw)
163
+ def by1:double (by + bh)
164
+ if (ax1 < bx) {
165
+ return false
166
+ }
167
+ if (bx1 < ax) {
168
+ return false
169
+ }
170
+ if (ay1 < by) {
171
+ return false
172
+ }
173
+ if (by1 < ay) {
174
+ return false
175
+ }
176
+ return true
177
+ }
178
+ }