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.
- package/CHANGELOG.md +1160 -19
- package/LICENSE +3 -1
- package/README.md +124 -29
- package/dist/Lang.rgr +1188 -290
- package/dist/api.d.ts +2343 -879
- package/dist/api.js +79924 -56922
- 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,488 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; ==============================================================================
|
|
4
|
+
; evg_image_tool — a bitmap an agent can actually use
|
|
5
|
+
; ==============================================================================
|
|
6
|
+
;
|
|
7
|
+
; evg_image_tool <in.png|in.jpg> [--out=prefix] [--preset=poster]
|
|
8
|
+
; [--colorCount=N] [--at=PATH] [--index=N] [--width=N]
|
|
9
|
+
;
|
|
10
|
+
; A model handed a photograph can describe it and cannot put it on a screen.
|
|
11
|
+
; The picture is pixels; an EVG document is boxes and paths; and the bridge —
|
|
12
|
+
; `EvgBitmapTracer`, the same one `npm run evg:trace:cli` uses — has been
|
|
13
|
+
; here all along with nothing pointing an agent at it.
|
|
14
|
+
;
|
|
15
|
+
; So this turns an image into the two things an agent can act on:
|
|
16
|
+
;
|
|
17
|
+
; the picture as an `svg` node it can insert, written for it as an ops
|
|
18
|
+
; file, so it never has to carry the path data through its own
|
|
19
|
+
; context to use it
|
|
20
|
+
; the colours as a palette with each one's share of the pixels, so a screen
|
|
21
|
+
; can be themed from the photograph instead of from a guess
|
|
22
|
+
;
|
|
23
|
+
; --- WHY AN OPS FILE AND NOT A PRINTED SVG ------------------------------------
|
|
24
|
+
;
|
|
25
|
+
; A traced SVG is tens of kilobytes of coordinates. Printing it to stdout would
|
|
26
|
+
; put every one of them through the agent's context on the way back into a
|
|
27
|
+
; patch — paying, in tokens, for numbers no model needs to read. The ops file
|
|
28
|
+
; is the patch already written: `./evg-agent patch doc.evg.json photo.ops.json`
|
|
29
|
+
; and the picture is in the document. What comes back here is the summary: the
|
|
30
|
+
; size, the palette, and where the node landed.
|
|
31
|
+
;
|
|
32
|
+
; --- WHY THE PALETTE IS COUNTED AND NOT INFERRED ------------------------------
|
|
33
|
+
;
|
|
34
|
+
; The share of each colour is counted over the pixels, not read off the number
|
|
35
|
+
; of paths a layer produced: one huge background region and four hundred specks
|
|
36
|
+
; of the same colour say opposite things about which colour the picture IS.
|
|
37
|
+
; Every fourth pixel on each axis is sampled, which is a sixteenth of the work
|
|
38
|
+
; and has never moved a share by a point on a photograph.
|
|
39
|
+
; ==============================================================================
|
|
40
|
+
|
|
41
|
+
Import "../EvgBitmapTracer.rgr"
|
|
42
|
+
Import "../EVGTreeJson.rgr"
|
|
43
|
+
Import "pkg:image/PNGDecoder.rgr"
|
|
44
|
+
Import "pkg:image/JPEGDecoder.rgr"
|
|
45
|
+
Import "pkg:image/ProgressiveJPEGDecoder.rgr"
|
|
46
|
+
|
|
47
|
+
class EvgImageTool {
|
|
48
|
+
|
|
49
|
+
Constructor () {
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
sfn m@(main):void () {
|
|
53
|
+
def t (new EvgImageTool())
|
|
54
|
+
t.run()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fn usage:void () {
|
|
58
|
+
print "evg_image_tool — trace a bitmap into something an EVG document can hold"
|
|
59
|
+
print ""
|
|
60
|
+
print " evg_image_tool <in.png|in.jpg> [--out=prefix] [--preset=NAME]"
|
|
61
|
+
print " [--colorCount=N] [--at=PATH] [--index=N] [--width=N]"
|
|
62
|
+
print ""
|
|
63
|
+
print " --out prefix for the files written (default: the input, without its suffix)"
|
|
64
|
+
print " --preset lineart | poster | photo | broken | print (default: poster)"
|
|
65
|
+
print " --colorCount how many colours to trace with"
|
|
66
|
+
print " --at where the ops file inserts the picture (default: 0)"
|
|
67
|
+
print " --index the child index it inserts at (default: 0)"
|
|
68
|
+
print " --width the width to place it at, in px; the height follows the image"
|
|
69
|
+
print ""
|
|
70
|
+
print "Writes <prefix>.svg and <prefix>.ops.json, and prints the palette."
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
; --- arguments ------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
sfn textFlag:string (name:string fallback:string) {
|
|
76
|
+
def argc:int (shell_arg_cnt)
|
|
77
|
+
def head:string (name + "=")
|
|
78
|
+
def n:int (strlen head)
|
|
79
|
+
def i:int 0
|
|
80
|
+
while (i < argc) {
|
|
81
|
+
def a:string (shell_arg i)
|
|
82
|
+
if ((strlen a) > n) {
|
|
83
|
+
if ((substring a 0 n) == head) {
|
|
84
|
+
return (substring a n (strlen a))
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
i = (i + 1)
|
|
88
|
+
}
|
|
89
|
+
return fallback
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
sfn intFlag:int (name:string fallback:int) {
|
|
93
|
+
def v:string (EvgImageTool.textFlag(name ""))
|
|
94
|
+
if ((strlen v) == 0) {
|
|
95
|
+
return fallback
|
|
96
|
+
}
|
|
97
|
+
return (EvgImageTool.parseInt(v fallback))
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
; `to_int` on a string is optional-typed and behaves differently per
|
|
101
|
+
; target; a digit loop is the same everywhere.
|
|
102
|
+
sfn parseInt:int (s:string fallback:int) {
|
|
103
|
+
def n:int (strlen s)
|
|
104
|
+
if (n == 0) {
|
|
105
|
+
return fallback
|
|
106
|
+
}
|
|
107
|
+
def v:int 0
|
|
108
|
+
def seen:int 0
|
|
109
|
+
def i:int 0
|
|
110
|
+
while (i < n) {
|
|
111
|
+
def d:int (indexOf "0123456789" (substring s i (i + 1)))
|
|
112
|
+
if (d < 0) {
|
|
113
|
+
i = n
|
|
114
|
+
} {
|
|
115
|
+
v = ((v * 10) + d)
|
|
116
|
+
seen = (seen + 1)
|
|
117
|
+
i = (i + 1)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (seen == 0) {
|
|
121
|
+
return fallback
|
|
122
|
+
}
|
|
123
|
+
return v
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
sfn positional@(optional):string () {
|
|
127
|
+
def argc:int (shell_arg_cnt)
|
|
128
|
+
def none@(optional):string
|
|
129
|
+
def i:int 0
|
|
130
|
+
while (i < argc) {
|
|
131
|
+
def a:string (shell_arg i)
|
|
132
|
+
if ((indexOf a "--") == 0) {
|
|
133
|
+
} {
|
|
134
|
+
def hit@(optional):string a
|
|
135
|
+
return hit
|
|
136
|
+
}
|
|
137
|
+
i = (i + 1)
|
|
138
|
+
}
|
|
139
|
+
return none
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
sfn lastSepOf:int (path:string) {
|
|
143
|
+
def at:int (0 - 1)
|
|
144
|
+
def i:int 0
|
|
145
|
+
while (i < (strlen path)) {
|
|
146
|
+
def c:int (charAt path i)
|
|
147
|
+
if ((c == 47) || (c == 92)) {
|
|
148
|
+
at = i
|
|
149
|
+
}
|
|
150
|
+
i = (i + 1)
|
|
151
|
+
}
|
|
152
|
+
return at
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
sfn dirOf:string (path:string) {
|
|
156
|
+
def sep:int (EvgImageTool.lastSepOf(path))
|
|
157
|
+
if (sep < 0) {
|
|
158
|
+
return "."
|
|
159
|
+
}
|
|
160
|
+
return (substring path 0 sep)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
sfn fileOf:string (path:string) {
|
|
164
|
+
def sep:int (EvgImageTool.lastSepOf(path))
|
|
165
|
+
if (sep < 0) {
|
|
166
|
+
return path
|
|
167
|
+
}
|
|
168
|
+
return (substring path (sep + 1) (strlen path))
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
; The path without its last suffix, so `photo.png` writes `photo.svg`.
|
|
172
|
+
sfn stemOf:string (path:string) {
|
|
173
|
+
def dot:int (0 - 1)
|
|
174
|
+
def i:int (EvgImageTool.lastSepOf(path))
|
|
175
|
+
if (i < 0) {
|
|
176
|
+
i = 0
|
|
177
|
+
}
|
|
178
|
+
while (i < (strlen path)) {
|
|
179
|
+
if ((charAt path i) == 46) {
|
|
180
|
+
dot = i
|
|
181
|
+
}
|
|
182
|
+
i = (i + 1)
|
|
183
|
+
}
|
|
184
|
+
if (dot <= 0) {
|
|
185
|
+
return path
|
|
186
|
+
}
|
|
187
|
+
return (substring path 0 dot)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
; --- decoding -------------------------------------------------------------
|
|
191
|
+
|
|
192
|
+
sfn isProgressiveJpeg:boolean (bytes:buffer) {
|
|
193
|
+
def n:int (buffer_length bytes)
|
|
194
|
+
def i:int 2
|
|
195
|
+
while ((i + 1) < n) {
|
|
196
|
+
if ((buffer_get bytes i) == 255) {
|
|
197
|
+
def marker:int (buffer_get bytes (i + 1))
|
|
198
|
+
if (marker == 194) {
|
|
199
|
+
return true
|
|
200
|
+
}
|
|
201
|
+
if (marker == 192) {
|
|
202
|
+
return false
|
|
203
|
+
}
|
|
204
|
+
if (marker == 218) {
|
|
205
|
+
return false
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
i = (i + 1)
|
|
209
|
+
}
|
|
210
|
+
return false
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
fn decodeImage:ImageBuffer (bytes:buffer dir:string file:string) {
|
|
214
|
+
def n:int (buffer_length bytes)
|
|
215
|
+
def fail (new ImageBuffer())
|
|
216
|
+
fail.init(1 1)
|
|
217
|
+
if (n < 4) {
|
|
218
|
+
return fail
|
|
219
|
+
}
|
|
220
|
+
def b0:int (buffer_get bytes 0)
|
|
221
|
+
def b1:int (buffer_get bytes 1)
|
|
222
|
+
if ((b0 == 137) && (b1 == 80)) {
|
|
223
|
+
def png (new PNGDecoder())
|
|
224
|
+
return (png.decodeBytes(bytes))
|
|
225
|
+
}
|
|
226
|
+
if ((b0 == 255) && (b1 == 216)) {
|
|
227
|
+
if (EvgImageTool.isProgressiveJpeg(bytes)) {
|
|
228
|
+
def prog (new ProgressiveJPEGDecoder())
|
|
229
|
+
return (prog.decode(dir file))
|
|
230
|
+
}
|
|
231
|
+
def jpg (new JPEGDecoder())
|
|
232
|
+
jpg.quiet = true
|
|
233
|
+
return (jpg.decodeBytes(bytes))
|
|
234
|
+
}
|
|
235
|
+
return fail
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
; --- the palette ----------------------------------------------------------
|
|
239
|
+
|
|
240
|
+
sfn hexDigit:int (c:int) {
|
|
241
|
+
if ((c >= 48) && (c <= 57)) {
|
|
242
|
+
return (c - 48)
|
|
243
|
+
}
|
|
244
|
+
if ((c >= 97) && (c <= 102)) {
|
|
245
|
+
return ((c - 97) + 10)
|
|
246
|
+
}
|
|
247
|
+
if ((c >= 65) && (c <= 70)) {
|
|
248
|
+
return ((c - 65) + 10)
|
|
249
|
+
}
|
|
250
|
+
return 0
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
; "#1e293b" → the three channels. Anything shorter answers black, which is
|
|
254
|
+
; what the tracer's own default is.
|
|
255
|
+
sfn channelsOf:void (hex:string out:[int]) {
|
|
256
|
+
if ((strlen hex) < 7) {
|
|
257
|
+
push out 0
|
|
258
|
+
push out 0
|
|
259
|
+
push out 0
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
def i:int 1
|
|
263
|
+
while (i < 7) {
|
|
264
|
+
def hi:int (EvgImageTool.hexDigit((charAt hex i)))
|
|
265
|
+
def lo:int (EvgImageTool.hexDigit((charAt hex (i + 1))))
|
|
266
|
+
push out ((hi * 16) + lo)
|
|
267
|
+
i = (i + 2)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
; How much of the picture each traced colour actually covers. Every fourth
|
|
272
|
+
; pixel on each axis, by nearest palette entry in plain RGB distance — the
|
|
273
|
+
; same measure the tracer used to pick them.
|
|
274
|
+
fn coverage:void (img:ImageBuffer palR:[int] palG:[int] palB:[int] counts:[int]) {
|
|
275
|
+
def k:int (array_length palR)
|
|
276
|
+
def i:int 0
|
|
277
|
+
while (i < k) {
|
|
278
|
+
push counts 0
|
|
279
|
+
i = (i + 1)
|
|
280
|
+
}
|
|
281
|
+
def step:int 4
|
|
282
|
+
def y:int 0
|
|
283
|
+
while (y < (img.height)) {
|
|
284
|
+
def x:int 0
|
|
285
|
+
while (x < (img.width)) {
|
|
286
|
+
def c:Color (img.getPixel(x y))
|
|
287
|
+
def best:int 0
|
|
288
|
+
def bestD:int 1000000
|
|
289
|
+
def j:int 0
|
|
290
|
+
while (j < k) {
|
|
291
|
+
def dr:int ((c.r) - (itemAt palR j))
|
|
292
|
+
def dg:int ((c.g) - (itemAt palG j))
|
|
293
|
+
def db:int ((c.b) - (itemAt palB j))
|
|
294
|
+
def d:int (((dr * dr) + (dg * dg)) + (db * db))
|
|
295
|
+
if (d < bestD) {
|
|
296
|
+
bestD = d
|
|
297
|
+
best = j
|
|
298
|
+
}
|
|
299
|
+
j = (j + 1)
|
|
300
|
+
}
|
|
301
|
+
set counts best ((itemAt counts best) + 1)
|
|
302
|
+
x = (x + step)
|
|
303
|
+
}
|
|
304
|
+
y = (y + step)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
; --- the ops file ---------------------------------------------------------
|
|
309
|
+
|
|
310
|
+
; The patch that puts the picture in the document, written out so the agent
|
|
311
|
+
; never handles the path data itself.
|
|
312
|
+
sfn opsFor:string (at:string index:int svg:string w:int h:int) {
|
|
313
|
+
def target:string ((at + "/") + (to_string index))
|
|
314
|
+
def out:string "{\"ops\":[\n"
|
|
315
|
+
out = (((((out + " {\"op\":\"insert\",\"at\":") + (EVGTreeJson.str(at))) + ",\"index\":") + (to_string index)) + ",\"tag\":\"svg\"},\n")
|
|
316
|
+
out = (((out + " {\"op\":\"set-prop\",\"at\":") + (EVGTreeJson.str(target))) + ",\"prop\":\"width\",\"value\":")
|
|
317
|
+
out = (((out + (EVGTreeJson.str((to_string w) + "px"))) + "},\n"))
|
|
318
|
+
out = (((out + " {\"op\":\"set-prop\",\"at\":") + (EVGTreeJson.str(target))) + ",\"prop\":\"height\",\"value\":")
|
|
319
|
+
out = (((out + (EVGTreeJson.str((to_string h) + "px"))) + "},\n"))
|
|
320
|
+
out = (((out + " {\"op\":\"set-prop\",\"at\":") + (EVGTreeJson.str(target))) + ",\"prop\":\"svg\",\"value\":")
|
|
321
|
+
out = (((out + (EVGTreeJson.str(svg))) + "}\n"))
|
|
322
|
+
return (out + "]}\n")
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
; --- run ------------------------------------------------------------------
|
|
326
|
+
|
|
327
|
+
fn run:void () {
|
|
328
|
+
def argc:int (shell_arg_cnt)
|
|
329
|
+
if (argc < 1) {
|
|
330
|
+
this.usage()
|
|
331
|
+
return
|
|
332
|
+
}
|
|
333
|
+
def first@(optional):string (EvgImageTool.positional())
|
|
334
|
+
if (null? first) {
|
|
335
|
+
this.usage()
|
|
336
|
+
return
|
|
337
|
+
}
|
|
338
|
+
def inputPath:string (unwrap first)
|
|
339
|
+
def inDir:string (EvgImageTool.dirOf(inputPath))
|
|
340
|
+
def inFile:string (EvgImageTool.fileOf(inputPath))
|
|
341
|
+
if ((file_exists inDir inFile) == false) {
|
|
342
|
+
print (("{\"error\":\"no such file: " + inputPath) + "\"}")
|
|
343
|
+
return
|
|
344
|
+
}
|
|
345
|
+
def bytes:buffer (buffer_read_file inDir inFile)
|
|
346
|
+
if ((buffer_length bytes) == 0) {
|
|
347
|
+
print (("{\"error\":\"cannot read " + inputPath) + "\"}")
|
|
348
|
+
return
|
|
349
|
+
}
|
|
350
|
+
def img:ImageBuffer (this.decodeImage(bytes inDir inFile))
|
|
351
|
+
if (((img.width) < 2) && ((img.height) < 2)) {
|
|
352
|
+
print (("{\"error\":\"not a PNG or JPEG this build can decode: " + inputPath) + "\"}")
|
|
353
|
+
return
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
; `poster` rather than the bare defaults: a screen wants flat colour
|
|
357
|
+
; regions it can put behind text, and a photograph traced at default
|
|
358
|
+
; fidelity is a mosaic nobody asked for.
|
|
359
|
+
def presetName:string (EvgImageTool.textFlag("--preset" "poster"))
|
|
360
|
+
def opts:EvgTraceOptions (EvgTraceOptions.preset(presetName))
|
|
361
|
+
def wantColors:int (EvgImageTool.intFlag("--colorCount" 0))
|
|
362
|
+
if (wantColors > 0) {
|
|
363
|
+
opts.colorCount = wantColors
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
def tr:EvgBitmapTracer (EvgBitmapTracer.fromImageBuffer(img opts))
|
|
367
|
+
tr.trace()
|
|
368
|
+
def svg:string (tr.toSVG())
|
|
369
|
+
|
|
370
|
+
def stem:string (EvgImageTool.textFlag("--out" (EvgImageTool.stemOf(inputPath))))
|
|
371
|
+
def outDir:string (EvgImageTool.dirOf(stem))
|
|
372
|
+
def outName:string (EvgImageTool.fileOf(stem))
|
|
373
|
+
write_file outDir (outName + ".svg") svg
|
|
374
|
+
|
|
375
|
+
; The placed size: the image's own, unless a width is given, and then
|
|
376
|
+
; the height follows it so nothing is squashed.
|
|
377
|
+
def placeW:int (img.width)
|
|
378
|
+
def placeH:int (img.height)
|
|
379
|
+
def askW:int (EvgImageTool.intFlag("--width" 0))
|
|
380
|
+
if (askW > 0) {
|
|
381
|
+
placeW = askW
|
|
382
|
+
placeH = (idiv (askW * (img.height)) (img.width))
|
|
383
|
+
if (placeH < 1) {
|
|
384
|
+
placeH = 1
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
def at:string (EvgImageTool.textFlag("--at" "0"))
|
|
388
|
+
def index:int (EvgImageTool.intFlag("--index" 0))
|
|
389
|
+
def ops:string (EvgImageTool.opsFor(at index svg placeW placeH))
|
|
390
|
+
write_file outDir (outName + ".ops.json") ops
|
|
391
|
+
|
|
392
|
+
; --- the answer -------------------------------------------------------
|
|
393
|
+
def layers:[EvgTraceLayer] (tr.getLayers())
|
|
394
|
+
def palR:[int]
|
|
395
|
+
def palG:[int]
|
|
396
|
+
def palB:[int]
|
|
397
|
+
def hexes:[string]
|
|
398
|
+
def li:int 0
|
|
399
|
+
while (li < (array_length layers)) {
|
|
400
|
+
def layer:EvgTraceLayer (itemAt layers li)
|
|
401
|
+
def ch:[int]
|
|
402
|
+
EvgImageTool.channelsOf(layer.fillHex ch)
|
|
403
|
+
push palR (itemAt ch 0)
|
|
404
|
+
push palG (itemAt ch 1)
|
|
405
|
+
push palB (itemAt ch 2)
|
|
406
|
+
push hexes layer.fillHex
|
|
407
|
+
li = (li + 1)
|
|
408
|
+
}
|
|
409
|
+
def counts:[int]
|
|
410
|
+
this.coverage(img palR palG palB counts)
|
|
411
|
+
def total:int 0
|
|
412
|
+
def ci:int 0
|
|
413
|
+
while (ci < (array_length counts)) {
|
|
414
|
+
total = (total + (itemAt counts ci))
|
|
415
|
+
ci = (ci + 1)
|
|
416
|
+
}
|
|
417
|
+
if (total < 1) {
|
|
418
|
+
total = 1
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
def out:string "{\"width\":"
|
|
422
|
+
out = (out + (to_string (img.width)))
|
|
423
|
+
out = ((out + ",\"height\":") + (to_string (img.height)))
|
|
424
|
+
out = ((out + ",\"layers\":") + (to_string (tr.layerCount())))
|
|
425
|
+
out = ((out + ",\"rings\":") + (to_string (tr.ringCount())))
|
|
426
|
+
out = (out + ",\"colors\":[")
|
|
427
|
+
; Biggest share first: the first entry is the colour the picture IS.
|
|
428
|
+
def used:[int]
|
|
429
|
+
def u:int 0
|
|
430
|
+
while (u < (array_length hexes)) {
|
|
431
|
+
push used 0
|
|
432
|
+
u = (u + 1)
|
|
433
|
+
}
|
|
434
|
+
def wrote:int 0
|
|
435
|
+
def rank:int 0
|
|
436
|
+
while (rank < (array_length hexes)) {
|
|
437
|
+
def bestI:int (0 - 1)
|
|
438
|
+
def bestC:int (0 - 1)
|
|
439
|
+
def s:int 0
|
|
440
|
+
while (s < (array_length hexes)) {
|
|
441
|
+
if ((itemAt used s) == 0) {
|
|
442
|
+
if ((itemAt counts s) > bestC) {
|
|
443
|
+
bestC = (itemAt counts s)
|
|
444
|
+
bestI = s
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
s = (s + 1)
|
|
448
|
+
}
|
|
449
|
+
if (bestI >= 0) {
|
|
450
|
+
set used bestI 1
|
|
451
|
+
def pct:int (idiv (((itemAt counts bestI) * 1000) + (idiv total 2)) total)
|
|
452
|
+
if (wrote > 0) {
|
|
453
|
+
out = (out + ",")
|
|
454
|
+
}
|
|
455
|
+
out = (out + "\n {\"hex\":")
|
|
456
|
+
out = (out + (EVGTreeJson.str((itemAt hexes bestI))))
|
|
457
|
+
out = ((out + ",\"share\":") + (EvgImageTool.perMille(pct)))
|
|
458
|
+
out = (out + "}")
|
|
459
|
+
wrote = (wrote + 1)
|
|
460
|
+
}
|
|
461
|
+
rank = (rank + 1)
|
|
462
|
+
}
|
|
463
|
+
if (wrote > 0) {
|
|
464
|
+
out = (out + "\n")
|
|
465
|
+
}
|
|
466
|
+
out = (out + "],\"wrote\":{\"svg\":")
|
|
467
|
+
out = (out + (EVGTreeJson.str((outName + ".svg"))))
|
|
468
|
+
out = (out + ",\"ops\":")
|
|
469
|
+
out = (out + (EVGTreeJson.str((outName + ".ops.json"))))
|
|
470
|
+
out = (out + "},\"insertsAt\":")
|
|
471
|
+
out = (out + (EVGTreeJson.str((at + "/") + (to_string index))))
|
|
472
|
+
out = ((out + ",\"placed\":\"") + (to_string placeW))
|
|
473
|
+
out = (((out + "x") + (to_string placeH)) + "\"}")
|
|
474
|
+
print out
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
; Per mille as a fraction, so 0.42 rather than 420 and without a float
|
|
478
|
+
; formatter that prints differently on every target.
|
|
479
|
+
sfn perMille:string (v:int) {
|
|
480
|
+
def whole:int (idiv v 1000)
|
|
481
|
+
def frac:int (v - (whole * 1000))
|
|
482
|
+
def text:string (to_string frac)
|
|
483
|
+
while ((strlen text) < 3) {
|
|
484
|
+
text = ("0" + text)
|
|
485
|
+
}
|
|
486
|
+
return (((to_string whole) + ".") + text)
|
|
487
|
+
}
|
|
488
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; ==============================================================================
|
|
4
|
+
; evg_trace_bench.rgr — timing harness for EvgBitmapTracer
|
|
5
|
+
; ==============================================================================
|
|
6
|
+
; Prints JSON lines a Node bench can parse and compare against npm/CLI potrace.
|
|
7
|
+
;
|
|
8
|
+
; npm run evg:trace:bench
|
|
9
|
+
; ==============================================================================
|
|
10
|
+
|
|
11
|
+
Import "../EvgBitmapTracer.rgr"
|
|
12
|
+
|
|
13
|
+
class EvgTraceBench {
|
|
14
|
+
|
|
15
|
+
sfn m@(main):void () {
|
|
16
|
+
def b (new EvgTraceBench())
|
|
17
|
+
b.runCase("rect_64" 64 64 8 8 48 48 40)
|
|
18
|
+
b.runCase("rect_256" 256 256 32 32 192 192 20)
|
|
19
|
+
b.runCase("checker_128" 128 128 0 0 0 0 20)
|
|
20
|
+
b.runCase("ring_128" 128 128 16 16 96 96 30)
|
|
21
|
+
print "BENCH_DONE"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fn makeRect:EvgBinaryBitmap (w:int h:int x0:int y0:int rw:int rh:int) {
|
|
25
|
+
def bm:EvgBinaryBitmap (EvgBinaryBitmap.create(w h))
|
|
26
|
+
def y:int y0
|
|
27
|
+
while (y < (y0 + rh)) {
|
|
28
|
+
def x:int x0
|
|
29
|
+
while (x < (x0 + rw)) {
|
|
30
|
+
bm.setBit(x y true)
|
|
31
|
+
x = (x + 1)
|
|
32
|
+
}
|
|
33
|
+
y = (y + 1)
|
|
34
|
+
}
|
|
35
|
+
return bm
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
fn makeChecker:EvgBinaryBitmap (w:int h:int) {
|
|
39
|
+
def bm:EvgBinaryBitmap (EvgBinaryBitmap.create(w h))
|
|
40
|
+
def y:int 0
|
|
41
|
+
while (y < h) {
|
|
42
|
+
def x:int 0
|
|
43
|
+
while (x < w) {
|
|
44
|
+
def cell:int ((idiv x 8) + (idiv y 8))
|
|
45
|
+
if (((cell - ((idiv cell 2) * 2)) == 0)) {
|
|
46
|
+
bm.setBit(x y true)
|
|
47
|
+
}
|
|
48
|
+
x = (x + 1)
|
|
49
|
+
}
|
|
50
|
+
y = (y + 1)
|
|
51
|
+
}
|
|
52
|
+
return bm
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fn makeRing:EvgBinaryBitmap (w:int h:int x0:int y0:int rw:int rh:int) {
|
|
56
|
+
def bm:EvgBinaryBitmap (this.makeRect(w h x0 y0 rw rh))
|
|
57
|
+
def ix:int (x0 + (idiv rw 4))
|
|
58
|
+
def iy:int (y0 + (idiv rh 4))
|
|
59
|
+
def iw:int (idiv rw 2)
|
|
60
|
+
def ih:int (idiv rh 2)
|
|
61
|
+
def y:int iy
|
|
62
|
+
while (y < (iy + ih)) {
|
|
63
|
+
def x:int ix
|
|
64
|
+
while (x < (ix + iw)) {
|
|
65
|
+
bm.setBit(x y false)
|
|
66
|
+
x = (x + 1)
|
|
67
|
+
}
|
|
68
|
+
y = (y + 1)
|
|
69
|
+
}
|
|
70
|
+
return bm
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
fn runCase:void (name:string w:int h:int x0:int y0:int rw:int rh:int iters:int) {
|
|
74
|
+
def bm:EvgBinaryBitmap (EvgBinaryBitmap.create(w h))
|
|
75
|
+
if (name == "checker_128") {
|
|
76
|
+
bm = (this.makeChecker(w h))
|
|
77
|
+
} {
|
|
78
|
+
if (name == "ring_128") {
|
|
79
|
+
bm = (this.makeRing(w h x0 y0 rw rh))
|
|
80
|
+
} {
|
|
81
|
+
bm = (this.makeRect(w h x0 y0 rw rh))
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
def opts:EvgTraceOptions (EvgTraceOptions.defaults())
|
|
85
|
+
opts.turdsize = 2
|
|
86
|
+
opts.alphamax = 1.0
|
|
87
|
+
opts.opttolerance = 0.2
|
|
88
|
+
opts.optcurve = true
|
|
89
|
+
|
|
90
|
+
; Warmup
|
|
91
|
+
def warm:EvgBitmapTracer (EvgBitmapTracer.fromBinary(bm opts))
|
|
92
|
+
warm.trace()
|
|
93
|
+
|
|
94
|
+
def i:int 0
|
|
95
|
+
def last:EvgBitmapTracer warm
|
|
96
|
+
while (i < iters) {
|
|
97
|
+
def tr:EvgBitmapTracer (EvgBitmapTracer.fromBinary(bm opts))
|
|
98
|
+
tr.trace()
|
|
99
|
+
last = tr
|
|
100
|
+
i = (i + 1)
|
|
101
|
+
}
|
|
102
|
+
def d:string (last.getPathData())
|
|
103
|
+
def line:string ("BENCH_CASE {" )
|
|
104
|
+
line = (line + "\"name\":\"" + name + "\",")
|
|
105
|
+
line = (line + "\"w\":" + (to_string w) + ",")
|
|
106
|
+
line = (line + "\"h\":" + (to_string h) + ",")
|
|
107
|
+
line = (line + "\"iters\":" + (to_string iters) + ",")
|
|
108
|
+
line = (line + "\"rings\":" + (to_string (last.ringCount())) + ",")
|
|
109
|
+
line = (line + "\"commands\":" + (to_string (last.commandCount())) + ",")
|
|
110
|
+
line = (line + "\"pathChars\":" + (to_string (strlen d)) + ",")
|
|
111
|
+
line = (line + "\"svgChars\":" + (to_string (strlen (last.toSVG()))) + "}")
|
|
112
|
+
print line
|
|
113
|
+
}
|
|
114
|
+
}
|