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.
- package/CHANGELOG.md +1064 -20
- package/LICENSE +3 -1
- package/README.md +123 -28
- package/dist/Lang.rgr +1188 -290
- package/dist/api.d.ts +2343 -879
- package/dist/api.js +79923 -56921
- package/dist/lib/JSON.rgr +102 -91
- package/dist/lib/Shell.rgr +4 -4
- package/dist/lib/apple/AppleToolchain.rgr +4 -4
- package/dist/lib/apple/README.md +5 -4
- package/dist/lib/apple/apple_test.rgr +1 -1
- package/dist/lib/core/README.md +1 -1
- package/dist/lib/evg/EVG.rgr +12 -0
- package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
- package/dist/lib/evg/EVGA11yTree.rgr +894 -0
- package/dist/lib/evg/EVGBox.rgr +267 -0
- package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
- package/dist/lib/evg/EVGCodepoint.rgr +316 -0
- package/dist/lib/evg/EVGColor.rgr +700 -0
- package/dist/lib/evg/EVGCommands.rgr +177 -0
- package/dist/lib/evg/EVGComponent.rgr +331 -0
- package/dist/lib/evg/EVGComponentTest.rgr +387 -0
- package/dist/lib/evg/EVGConnector.rgr +541 -0
- package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
- package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
- package/dist/lib/evg/EVGEasing.rgr +370 -0
- package/dist/lib/evg/EVGEffectTest.rgr +253 -0
- package/dist/lib/evg/EVGElement.rgr +4914 -0
- package/dist/lib/evg/EVGFixedTest.rgr +289 -0
- package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
- package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
- package/dist/lib/evg/EVGFling.rgr +244 -0
- package/dist/lib/evg/EVGFocus.rgr +400 -0
- package/dist/lib/evg/EVGFocusTest.rgr +399 -0
- package/dist/lib/evg/EVGGradient.rgr +322 -0
- package/dist/lib/evg/EVGGrapheme.rgr +190 -0
- package/dist/lib/evg/EVGGrid.rgr +975 -0
- package/dist/lib/evg/EVGHitTest.rgr +208 -0
- package/dist/lib/evg/EVGHoles.rgr +294 -0
- package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
- package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
- package/dist/lib/evg/EVGHostTree.rgr +834 -0
- package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
- package/dist/lib/evg/EVGImageDecode.rgr +117 -0
- package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
- package/dist/lib/evg/EVGInspect.rgr +883 -0
- package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
- package/dist/lib/evg/EVGJsonTest.rgr +535 -0
- package/dist/lib/evg/EVGLayout.rgr +4220 -0
- package/dist/lib/evg/EVGMeasure.rgr +1267 -0
- package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
- package/dist/lib/evg/EVGPatch.rgr +1721 -0
- package/dist/lib/evg/EVGPatchTest.rgr +692 -0
- package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
- package/dist/lib/evg/EVGReconcile.rgr +226 -0
- package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
- package/dist/lib/evg/EVGReject.rgr +126 -0
- package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
- package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
- package/dist/lib/evg/EVGRuler.rgr +232 -0
- package/dist/lib/evg/EVGRulerTest.rgr +172 -0
- package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
- package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
- package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
- package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
- package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
- package/dist/lib/evg/EVGText.rgr +105 -0
- package/dist/lib/evg/EVGTextEngine.rgr +536 -0
- package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
- package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
- package/dist/lib/evg/EVGToolbar.rgr +1369 -0
- package/dist/lib/evg/EVGTransition.rgr +728 -0
- package/dist/lib/evg/EVGTreeJson.rgr +721 -0
- package/dist/lib/evg/EVGUnit.rgr +554 -0
- package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
- package/dist/lib/evg/EvgApp.rgr +189 -0
- package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
- package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
- package/dist/lib/evg/EvgHost.rgr +451 -0
- package/dist/lib/evg/EvgTest.rgr +91 -0
- package/dist/lib/evg/EvgTraceColor.rgr +236 -0
- package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
- package/dist/lib/evg/EvgTraceFit.rgr +767 -0
- package/dist/lib/evg/EvgTracePath.rgr +435 -0
- package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
- package/dist/lib/evg/EvgViewport.rgr +313 -0
- package/dist/lib/evg/FxDemoDoc.rgr +185 -0
- package/dist/lib/evg/HOSTS.md +227 -0
- package/dist/lib/evg/ISSUES.md +835 -0
- package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
- package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
- package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
- package/dist/lib/evg/PLAN_EVG.md +518 -0
- package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
- package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
- package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
- package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
- package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
- package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
- package/dist/lib/evg/PathBuilder.rgr +333 -0
- package/dist/lib/evg/README.md +1236 -0
- package/dist/lib/evg/SPEC.md +1252 -0
- package/dist/lib/evg/SVGPathParser.rgr +1199 -0
- package/dist/lib/evg/SvgParser.rgr +1736 -0
- package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
- package/dist/lib/evg/VectorShapes.rgr +331 -0
- package/dist/lib/evg/VectorStroke.rgr +107 -0
- package/dist/lib/evg/VectorViewBox.rgr +380 -0
- package/dist/lib/evg/agent/README.md +290 -0
- package/dist/lib/evg/agent/evg_agent.rgr +899 -0
- package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
- package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
- package/dist/lib/evg/agent/fixtures/connector.css +63 -0
- package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
- package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
- package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
- package/dist/lib/evg/agent/fixtures/popover.css +99 -0
- package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
- package/dist/lib/evg/agent/roundtrip.sh +74 -0
- package/dist/lib/evg/agent/smoke.sh +230 -0
- package/dist/lib/evg/android/README.md +97 -0
- package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
- package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
- package/dist/lib/evg/android/androidstubs/App.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
- package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
- package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
- package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
- package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
- package/dist/lib/evg/android/androidstubs/View.kt +113 -0
- package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
- package/dist/lib/evg/apple/README.md +128 -0
- package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
- package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
- package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
- package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
- package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
- package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
- package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
- package/dist/lib/evg/bench/README.md +64 -0
- package/dist/lib/evg/bench/layout-bench.mjs +316 -0
- package/dist/lib/evg/bench/layout-cases.mjs +510 -0
- package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
- package/dist/lib/evg/bin/.gitignore +17 -0
- package/dist/lib/evg/evg_test.rgr +313 -0
- package/dist/lib/evg/gl/README.md +198 -0
- package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
- package/dist/lib/evg/gl/blur-check.mjs +399 -0
- package/dist/lib/evg/gl/boxmodel.json +1 -0
- package/dist/lib/evg/gl/demo.html +46 -0
- package/dist/lib/evg/gl/effect-presets.css +285 -0
- package/dist/lib/evg/gl/effect-presets.js +63 -0
- package/dist/lib/evg/gl/effect-shots.mjs +135 -0
- package/dist/lib/evg/gl/evg-a11y.js +566 -0
- package/dist/lib/evg/gl/evg-binary.js +160 -0
- package/dist/lib/evg/gl/evg-engine.js +296 -0
- package/dist/lib/evg/gl/evg-fx.js +237 -0
- package/dist/lib/evg/gl/evg-gestures.js +209 -0
- package/dist/lib/evg/gl/evg-list.js +167 -0
- package/dist/lib/evg/gl/evg-measure.js +186 -0
- package/dist/lib/evg/gl/evg-textinput.js +303 -0
- package/dist/lib/evg/gl/evg-view.js +144 -0
- package/dist/lib/evg/gl/evg-webgl.js +3942 -0
- package/dist/lib/evg/gl/fx-check.mjs +998 -0
- package/dist/lib/evg/gl/fx-demo.html +166 -0
- package/dist/lib/evg/gl/fx-demo.js +2 -0
- package/dist/lib/evg/gl/fx-serve.mjs +47 -0
- package/dist/lib/evg/gl/gestures-check.mjs +189 -0
- package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
- package/dist/lib/evg/gl/measure-check.mjs +135 -0
- package/dist/lib/evg/gl/rotation-check.mjs +207 -0
- package/dist/lib/evg/gl/shift-check.mjs +113 -0
- package/dist/lib/evg/gl/stroke-check.mjs +168 -0
- package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
- package/dist/lib/evg/gl/view-check.mjs +343 -0
- package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
- package/dist/lib/evg/html/evg-dom.js +318 -0
- package/dist/lib/evg/html/evg-html.js +600 -0
- package/dist/lib/evg/inspect/README.md +415 -0
- package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
- package/dist/lib/evg/inspect/evg-inspect.js +947 -0
- package/dist/lib/evg/inspect/shots/css.png +0 -0
- package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
- package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
- package/dist/lib/evg/inspect/shots/state.png +0 -0
- package/dist/lib/evg/inspect/shots.mjs +226 -0
- package/dist/lib/evg/oracle/css-blur.json +576 -0
- package/dist/lib/evg/oracle/css-box.json +157 -0
- package/dist/lib/evg/oracle/css-timing.json +709 -0
- package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
- package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
- package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
- package/dist/lib/evg/original/EVGColor.clj +310 -0
- package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
- package/dist/lib/evg/original/SVGPath.rgr +627 -0
- package/dist/lib/evg/original/Vec2.crgr +103 -0
- package/dist/lib/evg/ranger.json +9 -0
- package/dist/lib/evg/showcase/README.md +246 -0
- package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
- package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
- package/dist/lib/evg/showcase/build.mjs +651 -0
- package/dist/lib/evg/showcase/pages/album.tsx +30 -0
- package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
- package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
- package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
- package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
- package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
- package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
- package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
- package/dist/lib/evg/showcase/pages/more.tsx +332 -0
- package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
- package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
- package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
- package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
- package/dist/lib/evg/showcase/pages/units.tsx +35 -0
- package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
- package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
- package/dist/lib/evg/showcase/pages/views.tsx +223 -0
- package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
- package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
- package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
- package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
- package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
- package/dist/lib/evg/showcase/themes/more-default.css +128 -0
- package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
- package/dist/lib/evg/showcase/themes/showcase.css +508 -0
- package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
- package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
- package/dist/lib/evg/showcase/themes/views-default.css +15 -0
- package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
- package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
- package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
- package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
- package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
- package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
- package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
- package/dist/lib/evg/web/responsive/README.md +97 -0
- package/dist/lib/evg/web/responsive/build.mjs +90 -0
- package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
- package/dist/lib/evg/web/responsive/index.html +177 -0
- package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
- package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
- package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
- package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
- package/dist/lib/evg/web/tools/minify.mjs +60 -0
- package/dist/lib/evg/web/tracer/build.mjs +87 -0
- package/dist/lib/evg/web/tracer/index.html +2805 -0
- package/dist/lib/evg/web/tracer/sample.png +0 -0
- package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
- package/dist/lib/evgr/Cargo.lock +21 -0
- package/dist/lib/evgr/Cargo.toml +19 -0
- package/dist/lib/evgr/README.md +140 -0
- package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
- package/dist/lib/evgr/bench/compare.mjs +252 -0
- package/dist/lib/evgr/bench/speed.mjs +277 -0
- package/dist/lib/evgr/bin/.gitignore +3 -0
- package/dist/lib/evgr/src/bin/bench.rs +106 -0
- package/dist/lib/evgr/src/bin/smoke.rs +13 -0
- package/dist/lib/evgr/src/grid.rs +730 -0
- package/dist/lib/evgr/src/lib.rs +1003 -0
- package/dist/lib/evgr/src/style.rs +468 -0
- package/dist/lib/evgr/src/text.rs +83 -0
- package/dist/lib/image/BitReader.rgr +171 -0
- package/dist/lib/image/Buffer.rgr +173 -0
- package/dist/lib/image/DCT.rgr +283 -0
- package/dist/lib/image/Deflate.rgr +339 -0
- package/dist/lib/image/HuffmanDecoder.rgr +181 -0
- package/dist/lib/image/ImageBuffer.rgr +706 -0
- package/dist/lib/image/JPEGDecoder.rgr +808 -0
- package/dist/lib/image/PNGDecoder.rgr +544 -0
- package/dist/lib/image/PNGEncoder.rgr +388 -0
- package/dist/lib/image/PPMImage.rgr +224 -0
- package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
- package/dist/lib/image/README.md +33 -0
- package/dist/lib/image/RasterBuffer.rgr +294 -0
- package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
- package/dist/lib/image/WebPDecoder.rgr +433 -0
- package/dist/lib/image/WebPLossless.rgr +1035 -0
- package/dist/lib/image/WebPLossy.rgr +1929 -0
- package/dist/lib/image/ranger.json +9 -0
- package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
- package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
- package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
- package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
- package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
- package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
- package/dist/lib/image/tests/run_webp_tests.sh +39 -0
- package/dist/lib/rust/RsJson.rgr +468 -0
- package/dist/lib/rust/RsPrelude.rgr +1663 -0
- package/dist/lib/shell_test.rgr +7 -7
- package/dist/lib/stdlib.rgr +21 -5
- package/dist/lib/zip/ranger.json +6 -0
- package/dist/rgrc.js +87318 -67610
- package/package.json +1010 -1040
- package/dist/README.md +0 -117
- package/dist/package.json +0 -47
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; EVGGradient.rgr - Gradient parsing and storage for EVG layout
|
|
4
|
+
; Supports: linear-gradient, radial-gradient with multiple color stops
|
|
5
|
+
|
|
6
|
+
Import "EVGColor.rgr"
|
|
7
|
+
|
|
8
|
+
; A single color stop in a gradient
|
|
9
|
+
class EVGGradientStop {
|
|
10
|
+
def percentage:double 0.0 ; 0.0 to 1.0 (or 0 to 100 if not normalized)
|
|
11
|
+
def color:EVGColor (new EVGColor())
|
|
12
|
+
|
|
13
|
+
Constructor () {
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
sfn create:EVGGradientStop (pct:double col:EVGColor) {
|
|
17
|
+
def stop:EVGGradientStop (new EVGGradientStop())
|
|
18
|
+
stop.percentage = pct
|
|
19
|
+
stop.color = col
|
|
20
|
+
return stop
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
; Gradient definition with type, angle, and color stops
|
|
25
|
+
class EVGGradient {
|
|
26
|
+
def isSet:boolean false
|
|
27
|
+
def isLinear:boolean true ; true = linear, false = radial
|
|
28
|
+
def angle:double 0.0 ; degrees for linear gradient (0 = to top, 90 = to right)
|
|
29
|
+
def stops:[EVGGradientStop]
|
|
30
|
+
|
|
31
|
+
Constructor () {
|
|
32
|
+
def s:[EVGGradientStop]
|
|
33
|
+
stops = s
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
; Get the first color (for simple 2-color gradients)
|
|
37
|
+
fn getStartColor:EVGColor () {
|
|
38
|
+
if ((array_length stops) > 0) {
|
|
39
|
+
def stop:EVGGradientStop (itemAt stops 0)
|
|
40
|
+
return stop.color
|
|
41
|
+
}
|
|
42
|
+
return (EVGColor.noColor())
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
; Get the last color (for simple 2-color gradients)
|
|
46
|
+
fn getEndColor:EVGColor () {
|
|
47
|
+
def len:int (array_length stops)
|
|
48
|
+
if (len > 0) {
|
|
49
|
+
def stop:EVGGradientStop (itemAt stops (len - 1))
|
|
50
|
+
return stop.color
|
|
51
|
+
}
|
|
52
|
+
return (EVGColor.noColor())
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
; Get number of color stops
|
|
56
|
+
fn getStopCount:int () {
|
|
57
|
+
return (array_length stops)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
; Get a specific color stop
|
|
61
|
+
fn getStop:EVGGradientStop (index:int) {
|
|
62
|
+
return (itemAt stops index)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
; Add a color stop
|
|
66
|
+
fn addStop:void (percentage:double color:EVGColor) {
|
|
67
|
+
def stop:EVGGradientStop (EVGGradientStop.create(percentage color))
|
|
68
|
+
push stops stop
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
; Parse a CSS gradient string like:
|
|
72
|
+
; linear-gradient(90deg, #3498db, #9b59b6)
|
|
73
|
+
; linear-gradient(45deg, #e74c3c, #f39c12)
|
|
74
|
+
; radial-gradient(circle, #9b59b6, #2c3e50)
|
|
75
|
+
; linear-gradient(90deg, #e74c3c, #f39c12, #2ecc71, #3498db)
|
|
76
|
+
sfn parse:EVGGradient (gradStr:string) {
|
|
77
|
+
def grad:EVGGradient (new EVGGradient())
|
|
78
|
+
|
|
79
|
+
def len:int (strlen gradStr)
|
|
80
|
+
if (len == 0) {
|
|
81
|
+
return grad
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
def linearIdx:int (indexOf gradStr "linear-gradient")
|
|
85
|
+
def radialIdx:int (indexOf gradStr "radial-gradient")
|
|
86
|
+
|
|
87
|
+
if (linearIdx >= 0) {
|
|
88
|
+
grad.isLinear = true
|
|
89
|
+
grad.isSet = true
|
|
90
|
+
; CSS with no direction runs TOP TO BOTTOM. The field's own default
|
|
91
|
+
; is 0 â to the top â so a gradient written the shortest way came
|
|
92
|
+
; out upside down, and every painter agreed with the other about
|
|
93
|
+
; the wrong answer.
|
|
94
|
+
grad.angle = 180.0
|
|
95
|
+
}
|
|
96
|
+
if (radialIdx >= 0) {
|
|
97
|
+
grad.isLinear = false
|
|
98
|
+
grad.isSet = true
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (grad.isSet == false) {
|
|
102
|
+
return grad
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
; The arguments, split where CSS splits them. A naive split on every
|
|
106
|
+
; comma cuts `rgb(52,120,90)` into three pieces that are not colors,
|
|
107
|
+
; which is why a gradient written in `rgb()` used to parse to a
|
|
108
|
+
; gradient with NO STOPS â and an element with no stops emitted no
|
|
109
|
+
; background at all, so the node disappeared from the picture.
|
|
110
|
+
def args:[string]
|
|
111
|
+
EVGGradient.splitArgs(gradStr args)
|
|
112
|
+
def n:int (array_length args)
|
|
113
|
+
if (n == 0) {
|
|
114
|
+
return grad
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
def first:int 0
|
|
118
|
+
def head:string (trim (itemAt args 0))
|
|
119
|
+
if ((EVGGradient.colorOf(head)).isSet) {
|
|
120
|
+
} {
|
|
121
|
+
; Not a color, so it is the direction (or a radial's shape).
|
|
122
|
+
first = 1
|
|
123
|
+
if grad.isLinear {
|
|
124
|
+
grad.angle = (EVGGradient.angleOf(head grad.angle))
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
def colors:[EVGColor]
|
|
129
|
+
def stopsAt:[double]
|
|
130
|
+
def i:int first
|
|
131
|
+
while (i < n) {
|
|
132
|
+
def arg:string (trim (itemAt args i))
|
|
133
|
+
def col:EVGColor (EVGGradient.colorOf(arg))
|
|
134
|
+
if col.isSet {
|
|
135
|
+
push colors col
|
|
136
|
+
push stopsAt (EVGGradient.positionOf(arg))
|
|
137
|
+
}
|
|
138
|
+
i = (i + 1)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
def numColors:int (array_length colors)
|
|
142
|
+
if (numColors > 0) {
|
|
143
|
+
def colorIdx:int 0
|
|
144
|
+
while (colorIdx < numColors) {
|
|
145
|
+
def pct:double (itemAt stopsAt colorIdx)
|
|
146
|
+
if (pct < 0.0) {
|
|
147
|
+
pct = 0.0
|
|
148
|
+
if (numColors > 1) {
|
|
149
|
+
pct = ((to_double colorIdx) / (to_double (numColors - 1)))
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
def col:EVGColor (itemAt colors colorIdx)
|
|
153
|
+
grad.addStop(pct col)
|
|
154
|
+
colorIdx = colorIdx + 1
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return grad
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
; What is inside the outermost parentheses, cut at the commas that are not
|
|
162
|
+
; inside a nested call.
|
|
163
|
+
sfn splitArgs:void (src:string out:[string]) {
|
|
164
|
+
def len:int (strlen src)
|
|
165
|
+
def open:int (indexOf src "(")
|
|
166
|
+
if (open < 0) {
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
def depth:int 0
|
|
170
|
+
def cur:string ""
|
|
171
|
+
def i:int open
|
|
172
|
+
while (i < len) {
|
|
173
|
+
def c:int (charAt src i)
|
|
174
|
+
if (c == 40) {
|
|
175
|
+
depth = (depth + 1)
|
|
176
|
+
if (depth > 1) {
|
|
177
|
+
cur = (cur + "(")
|
|
178
|
+
}
|
|
179
|
+
} {
|
|
180
|
+
if (c == 41) {
|
|
181
|
+
depth = (depth - 1)
|
|
182
|
+
if (depth == 0) {
|
|
183
|
+
if ((strlen (trim cur)) > 0) {
|
|
184
|
+
push out cur
|
|
185
|
+
}
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
cur = (cur + ")")
|
|
189
|
+
} {
|
|
190
|
+
if ((c == 44) && (depth == 1)) {
|
|
191
|
+
if ((strlen (trim cur)) > 0) {
|
|
192
|
+
push out cur
|
|
193
|
+
}
|
|
194
|
+
cur = ""
|
|
195
|
+
} {
|
|
196
|
+
cur = (cur + (substring src i (i + 1)))
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
i = (i + 1)
|
|
201
|
+
}
|
|
202
|
+
if ((strlen (trim cur)) > 0) {
|
|
203
|
+
push out cur
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
; The color in one argument, ignoring a stop position written after it.
|
|
208
|
+
; `rgb(âŚ)` and friends end at their own closing bracket; everything else
|
|
209
|
+
; ends at the first space.
|
|
210
|
+
sfn colorOf:EVGColor (arg:string) {
|
|
211
|
+
def text:string (trim arg)
|
|
212
|
+
def n:int (strlen text)
|
|
213
|
+
if (n == 0) {
|
|
214
|
+
return (EVGColor.noColor())
|
|
215
|
+
}
|
|
216
|
+
def close:int (indexOf text ")")
|
|
217
|
+
if (close >= 0) {
|
|
218
|
+
return (EVGColor.parse((substring text 0 (close + 1))))
|
|
219
|
+
}
|
|
220
|
+
def sp:int (indexOf text " ")
|
|
221
|
+
if (sp > 0) {
|
|
222
|
+
return (EVGColor.parse((substring text 0 sp)))
|
|
223
|
+
}
|
|
224
|
+
return (EVGColor.parse(text))
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
; A stop written as a percentage, or -1 when the argument does not say.
|
|
228
|
+
sfn positionOf:double (arg:string) {
|
|
229
|
+
def text:string (trim arg)
|
|
230
|
+
def pct:int (indexOf text "%")
|
|
231
|
+
if (pct <= 0) {
|
|
232
|
+
return (0.0 - 1.0)
|
|
233
|
+
}
|
|
234
|
+
def start:int pct
|
|
235
|
+
while (start > 0) {
|
|
236
|
+
def c:int (charAt text (start - 1))
|
|
237
|
+
def isNum:boolean (((c >= 48) && (c <= 57)) || ((c == 46) || (c == 45)))
|
|
238
|
+
if (isNum == false) {
|
|
239
|
+
break
|
|
240
|
+
}
|
|
241
|
+
start = (start - 1)
|
|
242
|
+
}
|
|
243
|
+
if (start == pct) {
|
|
244
|
+
return (0.0 - 1.0)
|
|
245
|
+
}
|
|
246
|
+
def v@(optional):double (to_double (substring text start pct))
|
|
247
|
+
if (null? v) {
|
|
248
|
+
return (0.0 - 1.0)
|
|
249
|
+
}
|
|
250
|
+
return ((unwrap v) / 100.0)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
; `45deg`, or the `to âŚ` keywords CSS accepts in place of one. An angle is
|
|
254
|
+
; the direction the ramp TRAVELS, 0 to the top and 90 to the right.
|
|
255
|
+
sfn angleOf:double (spec:string fallback:double) {
|
|
256
|
+
def text:string (trim spec)
|
|
257
|
+
def deg:int (indexOf text "deg")
|
|
258
|
+
if (deg > 0) {
|
|
259
|
+
def v@(optional):double (to_double (trim (substring text 0 deg)))
|
|
260
|
+
if (null? v) {
|
|
261
|
+
return fallback
|
|
262
|
+
}
|
|
263
|
+
return (unwrap v)
|
|
264
|
+
}
|
|
265
|
+
if ((indexOf text "to ") == 0) {
|
|
266
|
+
def toTop:boolean ((indexOf text "top") > 0)
|
|
267
|
+
def toBottom:boolean ((indexOf text "bottom") > 0)
|
|
268
|
+
def toLeft:boolean ((indexOf text "left") > 0)
|
|
269
|
+
def toRight:boolean ((indexOf text "right") > 0)
|
|
270
|
+
if (toTop && toRight) {
|
|
271
|
+
return 45.0
|
|
272
|
+
}
|
|
273
|
+
if (toBottom && toRight) {
|
|
274
|
+
return 135.0
|
|
275
|
+
}
|
|
276
|
+
if (toBottom && toLeft) {
|
|
277
|
+
return 225.0
|
|
278
|
+
}
|
|
279
|
+
if (toTop && toLeft) {
|
|
280
|
+
return 315.0
|
|
281
|
+
}
|
|
282
|
+
if toTop {
|
|
283
|
+
return 0.0
|
|
284
|
+
}
|
|
285
|
+
if toRight {
|
|
286
|
+
return 90.0
|
|
287
|
+
}
|
|
288
|
+
if toBottom {
|
|
289
|
+
return 180.0
|
|
290
|
+
}
|
|
291
|
+
if toLeft {
|
|
292
|
+
return 270.0
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return fallback
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
; Convert back to CSS string
|
|
299
|
+
fn toCSSString:string () {
|
|
300
|
+
if (isSet == false) {
|
|
301
|
+
return ""
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
def result:string ""
|
|
305
|
+
if isLinear {
|
|
306
|
+
result = "linear-gradient(" + (to_string angle) + "deg"
|
|
307
|
+
} {
|
|
308
|
+
result = "radial-gradient(circle"
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
def numStops:int (array_length stops)
|
|
312
|
+
def i:int 0
|
|
313
|
+
while (i < numStops) {
|
|
314
|
+
def stop:EVGGradientStop (itemAt stops i)
|
|
315
|
+
result = result + ", " + (stop.color.toCSSString())
|
|
316
|
+
i = i + 1
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
result = result + ")"
|
|
320
|
+
return result
|
|
321
|
+
}
|
|
322
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; EVGGrapheme.rgr â the unit a reader calls "one character"
|
|
4
|
+
;
|
|
5
|
+
; A codepoint is not it. đŤđŽ is two, đđ˝ is two, 1ď¸âŁ is three, đ¨âđŠâđ§ is five, and
|
|
6
|
+
; every one of them is one thing on the page: one glyph, one advance, one
|
|
7
|
+
; position a cursor can sit at, and one place a line may not break.
|
|
8
|
+
;
|
|
9
|
+
; Stepping by codepoint instead cost three separate things:
|
|
10
|
+
;
|
|
11
|
+
; the FACE was chosen per codepoint, so 1ď¸âŁ put the "1" in the text face and
|
|
12
|
+
; the keycap in the emoji face â two runs, and the ligature that makes
|
|
13
|
+
; the keycap never got the chance to fire;
|
|
14
|
+
; the WIDTH was the sum of the parts, so a family of four measured four
|
|
15
|
+
; advances wide and drew one;
|
|
16
|
+
; the /ToUnicode entry named a single codepoint for a glyph made of five,
|
|
17
|
+
; so copying the emoji out of a PDF returned a fragment.
|
|
18
|
+
;
|
|
19
|
+
; This is a deliberate subset of UAX #29 â the emoji-relevant rules and the
|
|
20
|
+
; combining marks, not the full property tables, which would mean shipping
|
|
21
|
+
; Unicode data this engine has no other use for. What it does not model, it
|
|
22
|
+
; leaves as separate clusters, which is the same behaviour as before rather
|
|
23
|
+
; than a new kind of wrong.
|
|
24
|
+
|
|
25
|
+
Import "EVGCodepoint.rgr"
|
|
26
|
+
|
|
27
|
+
class EVGGrapheme {
|
|
28
|
+
|
|
29
|
+
; U+200D ZERO WIDTH JOINER â the glue in đ¨âđŠâđ§.
|
|
30
|
+
sfn isZWJ:boolean (cp:int) {
|
|
31
|
+
return (cp == 8205)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
; Regional indicators, U+1F1E6..U+1F1FF. A flag is exactly two of them,
|
|
35
|
+
; and the pairing is why a run of four is two flags rather than one long
|
|
36
|
+
; cluster.
|
|
37
|
+
sfn isRegionalIndicator:boolean (cp:int) {
|
|
38
|
+
if (cp < 127462) {
|
|
39
|
+
return false
|
|
40
|
+
}
|
|
41
|
+
return (cp <= 127487)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
; Skin tone modifiers, U+1F3FB..U+1F3FF.
|
|
45
|
+
sfn isEmojiModifier:boolean (cp:int) {
|
|
46
|
+
if (cp < 127995) {
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
return (cp <= 127999)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
; Tag characters, U+E0020..U+E007F â the subdivision flags (đ´ó §ó ˘ó łó Łó ´ó ż) spell
|
|
53
|
+
; a region code out of these.
|
|
54
|
+
sfn isTag:boolean (cp:int) {
|
|
55
|
+
if (cp < 917536) {
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
return (cp <= 917631)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
; Anything that attaches to the character before it: combining marks,
|
|
62
|
+
; variation selectors, the enclosing keycap, skin tones, tags.
|
|
63
|
+
;
|
|
64
|
+
; The ranges are the ones that actually occur in text this engine sets;
|
|
65
|
+
; a codepoint outside them starts a new cluster, which is the conservative
|
|
66
|
+
; answer.
|
|
67
|
+
sfn isExtend:boolean (cp:int) {
|
|
68
|
+
; Combining diacritical marks and their supplements/extensions.
|
|
69
|
+
if ((cp >= 768) && (cp <= 879)) {
|
|
70
|
+
return true
|
|
71
|
+
}
|
|
72
|
+
if ((cp >= 6832) && (cp <= 6911)) {
|
|
73
|
+
return true
|
|
74
|
+
}
|
|
75
|
+
if ((cp >= 7616) && (cp <= 7679)) {
|
|
76
|
+
return true
|
|
77
|
+
}
|
|
78
|
+
; Combining marks for symbols, U+20D0..U+20FF â U+20E3 KEYCAP is here.
|
|
79
|
+
if ((cp >= 8400) && (cp <= 8447)) {
|
|
80
|
+
return true
|
|
81
|
+
}
|
|
82
|
+
; Variation selectors VS1..VS16.
|
|
83
|
+
if ((cp >= 65024) && (cp <= 65039)) {
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
86
|
+
; Combining half marks.
|
|
87
|
+
if ((cp >= 65056) && (cp <= 65071)) {
|
|
88
|
+
return true
|
|
89
|
+
}
|
|
90
|
+
if (EVGGrapheme.isEmojiModifier(cp)) {
|
|
91
|
+
return true
|
|
92
|
+
}
|
|
93
|
+
return (EVGGrapheme.isTag(cp))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
; Index one past the cluster starting at `start`.
|
|
97
|
+
;
|
|
98
|
+
; Always advances by at least one, so a caller looping on this terminates
|
|
99
|
+
; even on input the rules below say nothing about.
|
|
100
|
+
sfn clusterEnd:int (cps:[int] start:int) {
|
|
101
|
+
def n:int (array_length cps)
|
|
102
|
+
if (start >= n) {
|
|
103
|
+
return n
|
|
104
|
+
}
|
|
105
|
+
def i:int (start + 1)
|
|
106
|
+
|
|
107
|
+
; A flag is a PAIR of regional indicators and no more. Without the
|
|
108
|
+
; limit, đŤđŽđ¸đŞ would be one four-part cluster and neither flag would
|
|
109
|
+
; find its ligature.
|
|
110
|
+
if (EVGGrapheme.isRegionalIndicator((itemAt cps start))) {
|
|
111
|
+
if (i < n) {
|
|
112
|
+
if (EVGGrapheme.isRegionalIndicator((itemAt cps i))) {
|
|
113
|
+
i = (i + 1)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return i
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
def more:boolean true
|
|
120
|
+
while more {
|
|
121
|
+
more = false
|
|
122
|
+
if (i < n) {
|
|
123
|
+
def cp:int (itemAt cps i)
|
|
124
|
+
if (EVGGrapheme.isExtend(cp)) {
|
|
125
|
+
i = (i + 1)
|
|
126
|
+
more = true
|
|
127
|
+
} {
|
|
128
|
+
; A joiner takes the character after it into the cluster â
|
|
129
|
+
; and a trailing joiner with nothing after it does not,
|
|
130
|
+
; because there is nothing to join to.
|
|
131
|
+
if (EVGGrapheme.isZWJ(cp)) {
|
|
132
|
+
if ((i + 1) < n) {
|
|
133
|
+
i = (i + 2)
|
|
134
|
+
more = true
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return i
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
; Cluster boundaries as codepoint indices, ending with the length.
|
|
144
|
+
; `starts[k]`..`starts[k+1]` is cluster k.
|
|
145
|
+
sfn boundaries:[int] (cps:[int]) {
|
|
146
|
+
def out:[int]
|
|
147
|
+
def i:int 0
|
|
148
|
+
def n:int (array_length cps)
|
|
149
|
+
while (i < n) {
|
|
150
|
+
push out i
|
|
151
|
+
i = (EVGGrapheme.clusterEnd(cps i))
|
|
152
|
+
}
|
|
153
|
+
push out n
|
|
154
|
+
return out
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
; How many clusters â "how long is this text" as a reader would answer it.
|
|
158
|
+
; (`count` is taken by the language, hence the name.)
|
|
159
|
+
sfn clusterCount:int (s:string) {
|
|
160
|
+
def cps:[int] (EVGCodepoint.toArray(s))
|
|
161
|
+
def n:int 0
|
|
162
|
+
def i:int 0
|
|
163
|
+
while (i < (array_length cps)) {
|
|
164
|
+
i = (EVGGrapheme.clusterEnd(cps i))
|
|
165
|
+
n = (n + 1)
|
|
166
|
+
}
|
|
167
|
+
return n
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
; The cluster starting at UTF-16 index `i`, as a string. Convenient where
|
|
171
|
+
; a caller works in strings rather than codepoint arrays.
|
|
172
|
+
sfn clusterAt:string (s:string i:int) {
|
|
173
|
+
def cps:[int] (EVGCodepoint.toArray(s))
|
|
174
|
+
; Map the UTF-16 index to a codepoint index.
|
|
175
|
+
def cpIdx:int 0
|
|
176
|
+
def u:int 0
|
|
177
|
+
while (u < i) {
|
|
178
|
+
u = (u + (EVGCodepoint.unitsAt(s u)))
|
|
179
|
+
cpIdx = (cpIdx + 1)
|
|
180
|
+
}
|
|
181
|
+
def end:int (EVGGrapheme.clusterEnd(cps cpIdx))
|
|
182
|
+
def out:string ""
|
|
183
|
+
def k:int cpIdx
|
|
184
|
+
while (k < end) {
|
|
185
|
+
out = out + (EVGCodepoint.toStr((itemAt cps k)))
|
|
186
|
+
k = (k + 1)
|
|
187
|
+
}
|
|
188
|
+
return out
|
|
189
|
+
}
|
|
190
|
+
}
|