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,662 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; ==============================================================================
|
|
4
|
+
; evg_trace_cli.rgr — bitmap → SVG from a command line
|
|
5
|
+
; ==============================================================================
|
|
6
|
+
;
|
|
7
|
+
; The tracer already runs in a browser and in the test harness. This is the
|
|
8
|
+
; third caller it needed: a file in, a file out, no page and no Node-only
|
|
9
|
+
; plumbing, so the same engine can be built for whichever runtime is at hand.
|
|
10
|
+
; Everything it uses — the PNG and JPEG decoders, the tracer, the SVG writer —
|
|
11
|
+
; is Ranger, so the compiled program is one self-contained file per target with
|
|
12
|
+
; no library to install.
|
|
13
|
+
;
|
|
14
|
+
; npm run evg:trace:cli -- in.png out.svg --preset broken
|
|
15
|
+
;
|
|
16
|
+
; The option names are exactly the fields of EvgTraceOptions, so there is
|
|
17
|
+
; nothing extra to learn and nothing to keep in sync: --colorCount 12 sets
|
|
18
|
+
; colorCount. See EvgTraceTypes.rgr for what each one means.
|
|
19
|
+
;
|
|
20
|
+
; Numbers are parsed here rather than with to_int, whose string form is
|
|
21
|
+
; optional-typed and behaves differently per target. A digit loop is the same
|
|
22
|
+
; everywhere.
|
|
23
|
+
; ==============================================================================
|
|
24
|
+
|
|
25
|
+
Import "../EvgBitmapTracer.rgr"
|
|
26
|
+
Import "pkg:image/PNGDecoder.rgr"
|
|
27
|
+
Import "pkg:image/JPEGDecoder.rgr"
|
|
28
|
+
Import "pkg:image/ProgressiveJPEGDecoder.rgr"
|
|
29
|
+
|
|
30
|
+
class EvgTraceCli {
|
|
31
|
+
|
|
32
|
+
Constructor () {
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
sfn m@(main):void () {
|
|
36
|
+
def cli (new EvgTraceCli())
|
|
37
|
+
cli.run()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
; --- parsing ----------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
sfn digitOf:int (ch:string) {
|
|
43
|
+
return (indexOf "0123456789" ch)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
sfn parseInt:int (s:string) {
|
|
47
|
+
def n:int (strlen s)
|
|
48
|
+
def i:int 0
|
|
49
|
+
def neg:boolean false
|
|
50
|
+
if (n > 0) {
|
|
51
|
+
def first:string (substring s 0 1)
|
|
52
|
+
if (first == "-") {
|
|
53
|
+
neg = true
|
|
54
|
+
i = 1
|
|
55
|
+
}
|
|
56
|
+
if (first == "+") {
|
|
57
|
+
i = 1
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
def v:int 0
|
|
61
|
+
while (i < n) {
|
|
62
|
+
def d:int (EvgTraceCli.digitOf((substring s i (i + 1))))
|
|
63
|
+
if (d < 0) {
|
|
64
|
+
i = n
|
|
65
|
+
} {
|
|
66
|
+
v = ((v * 10) + d)
|
|
67
|
+
i = (i + 1)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (neg) {
|
|
71
|
+
return (0 - v)
|
|
72
|
+
}
|
|
73
|
+
return v
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
sfn parseDouble:double (s:string) {
|
|
77
|
+
def n:int (strlen s)
|
|
78
|
+
def i:int 0
|
|
79
|
+
def neg:boolean false
|
|
80
|
+
if (n > 0) {
|
|
81
|
+
def first:string (substring s 0 1)
|
|
82
|
+
if (first == "-") {
|
|
83
|
+
neg = true
|
|
84
|
+
i = 1
|
|
85
|
+
}
|
|
86
|
+
if (first == "+") {
|
|
87
|
+
i = 1
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
def whole:double 0.0
|
|
91
|
+
def stop:boolean false
|
|
92
|
+
while ((i < n) && (stop == false)) {
|
|
93
|
+
def ch:string (substring s i (i + 1))
|
|
94
|
+
def d:int (EvgTraceCli.digitOf(ch))
|
|
95
|
+
if (d < 0) {
|
|
96
|
+
stop = true
|
|
97
|
+
} {
|
|
98
|
+
whole = ((whole * 10.0) + (to_double d))
|
|
99
|
+
i = (i + 1)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (i < n) {
|
|
103
|
+
def dot:string (substring s i (i + 1))
|
|
104
|
+
if (dot == ".") {
|
|
105
|
+
i = (i + 1)
|
|
106
|
+
def scale:double 1.0
|
|
107
|
+
def more:boolean true
|
|
108
|
+
while ((i < n) && more) {
|
|
109
|
+
def ch2:string (substring s i (i + 1))
|
|
110
|
+
def d2:int (EvgTraceCli.digitOf(ch2))
|
|
111
|
+
if (d2 < 0) {
|
|
112
|
+
more = false
|
|
113
|
+
} {
|
|
114
|
+
scale = (scale / 10.0)
|
|
115
|
+
whole = (whole + ((to_double d2) * scale))
|
|
116
|
+
i = (i + 1)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (neg) {
|
|
122
|
+
return (0.0 - whole)
|
|
123
|
+
}
|
|
124
|
+
return whole
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
; Anything but a plain no is a yes, so `--optcurve 0` and `--optcurve false`
|
|
128
|
+
; both turn it off and a bare `--optcurve` turns it on.
|
|
129
|
+
sfn parseBool:boolean (s:string) {
|
|
130
|
+
if (s == "0") {
|
|
131
|
+
return false
|
|
132
|
+
}
|
|
133
|
+
if (s == "false") {
|
|
134
|
+
return false
|
|
135
|
+
}
|
|
136
|
+
if (s == "no") {
|
|
137
|
+
return false
|
|
138
|
+
}
|
|
139
|
+
if (s == "off") {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
return true
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
sfn splitList:[string] (s:string) {
|
|
146
|
+
def out:[string]
|
|
147
|
+
def parts:[string] (strsplit s ",")
|
|
148
|
+
def i:int 0
|
|
149
|
+
while (i < (array_length parts)) {
|
|
150
|
+
def p:string (trim (itemAt parts i))
|
|
151
|
+
if ((strlen p) > 0) {
|
|
152
|
+
push out p
|
|
153
|
+
}
|
|
154
|
+
i = (i + 1)
|
|
155
|
+
}
|
|
156
|
+
return out
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
; --- paths ------------------------------------------------------------
|
|
160
|
+
|
|
161
|
+
sfn lastSepOf:int (path:string) {
|
|
162
|
+
def a:int (lastIndexOf path "/")
|
|
163
|
+
def b:int (lastIndexOf path "\\")
|
|
164
|
+
if (b > a) {
|
|
165
|
+
return b
|
|
166
|
+
}
|
|
167
|
+
return a
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
sfn dirOf:string (path:string) {
|
|
171
|
+
def sep:int (EvgTraceCli.lastSepOf(path))
|
|
172
|
+
if (sep < 0) {
|
|
173
|
+
return "."
|
|
174
|
+
}
|
|
175
|
+
return (substring path 0 sep)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
sfn fileOf:string (path:string) {
|
|
179
|
+
def sep:int (EvgTraceCli.lastSepOf(path))
|
|
180
|
+
if (sep < 0) {
|
|
181
|
+
return path
|
|
182
|
+
}
|
|
183
|
+
return (substring path (sep + 1) (strlen path))
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
; --- options ----------------------------------------------------------
|
|
187
|
+
|
|
188
|
+
; One name per EvgTraceOptions field. Anything else is a typo, and saying so
|
|
189
|
+
; is the whole point: a silently ignored --colorcount is an hour lost to
|
|
190
|
+
; wondering why the palette will not change.
|
|
191
|
+
fn applyOption:boolean (o:EvgTraceOptions name:string value:string) {
|
|
192
|
+
if (name == "turdsize") {
|
|
193
|
+
o.turdsize = (EvgTraceCli.parseInt(value))
|
|
194
|
+
return true
|
|
195
|
+
}
|
|
196
|
+
if (name == "alphamax") {
|
|
197
|
+
o.alphamax = (EvgTraceCli.parseDouble(value))
|
|
198
|
+
return true
|
|
199
|
+
}
|
|
200
|
+
if (name == "turnpolicy") {
|
|
201
|
+
o.turnpolicy = value
|
|
202
|
+
return true
|
|
203
|
+
}
|
|
204
|
+
if (name == "optcurve") {
|
|
205
|
+
o.optcurve = (EvgTraceCli.parseBool(value))
|
|
206
|
+
return true
|
|
207
|
+
}
|
|
208
|
+
if (name == "opttolerance") {
|
|
209
|
+
o.opttolerance = (EvgTraceCli.parseDouble(value))
|
|
210
|
+
return true
|
|
211
|
+
}
|
|
212
|
+
if (name == "threshold") {
|
|
213
|
+
o.threshold = (EvgTraceCli.parseInt(value))
|
|
214
|
+
return true
|
|
215
|
+
}
|
|
216
|
+
if (name == "blackOnWhite") {
|
|
217
|
+
o.blackOnWhite = (EvgTraceCli.parseBool(value))
|
|
218
|
+
return true
|
|
219
|
+
}
|
|
220
|
+
if (name == "fillHex") {
|
|
221
|
+
o.fillHex = value
|
|
222
|
+
return true
|
|
223
|
+
}
|
|
224
|
+
if (name == "colorCount") {
|
|
225
|
+
o.colorCount = (EvgTraceCli.parseInt(value))
|
|
226
|
+
return true
|
|
227
|
+
}
|
|
228
|
+
if (name == "skipLuma") {
|
|
229
|
+
o.skipLuma = (EvgTraceCli.parseInt(value))
|
|
230
|
+
return true
|
|
231
|
+
}
|
|
232
|
+
if (name == "flatTolerance") {
|
|
233
|
+
o.flatTolerance = (EvgTraceCli.parseInt(value))
|
|
234
|
+
return true
|
|
235
|
+
}
|
|
236
|
+
if (name == "edgeSnap") {
|
|
237
|
+
o.edgeSnap = (EvgTraceCli.parseBool(value))
|
|
238
|
+
return true
|
|
239
|
+
}
|
|
240
|
+
if (name == "snapRatio") {
|
|
241
|
+
o.snapRatio = (EvgTraceCli.parseDouble(value))
|
|
242
|
+
return true
|
|
243
|
+
}
|
|
244
|
+
if (name == "lumaWeight") {
|
|
245
|
+
o.lumaWeight = (EvgTraceCli.parseInt(value))
|
|
246
|
+
return true
|
|
247
|
+
}
|
|
248
|
+
if (name == "colorSpace") {
|
|
249
|
+
o.colorSpace = value
|
|
250
|
+
return true
|
|
251
|
+
}
|
|
252
|
+
if (name == "paletteMode") {
|
|
253
|
+
o.paletteMode = value
|
|
254
|
+
return true
|
|
255
|
+
}
|
|
256
|
+
if (name == "paletteHex") {
|
|
257
|
+
o.paletteHex = (EvgTraceCli.splitList(value))
|
|
258
|
+
return true
|
|
259
|
+
}
|
|
260
|
+
if (name == "paletteBias") {
|
|
261
|
+
o.paletteBias = value
|
|
262
|
+
return true
|
|
263
|
+
}
|
|
264
|
+
if (name == "paletteChroma") {
|
|
265
|
+
o.paletteChroma = (EvgTraceCli.parseInt(value))
|
|
266
|
+
return true
|
|
267
|
+
}
|
|
268
|
+
if (name == "paletteMute") {
|
|
269
|
+
o.paletteMute = (EvgTraceCli.parseInt(value))
|
|
270
|
+
return true
|
|
271
|
+
}
|
|
272
|
+
if (name == "paletteTint") {
|
|
273
|
+
o.paletteTint = (EvgTraceCli.parseInt(value))
|
|
274
|
+
return true
|
|
275
|
+
}
|
|
276
|
+
if (name == "paletteWarm") {
|
|
277
|
+
o.paletteWarm = (EvgTraceCli.parseInt(value))
|
|
278
|
+
return true
|
|
279
|
+
}
|
|
280
|
+
if (name == "paletteContrast") {
|
|
281
|
+
o.paletteContrast = (EvgTraceCli.parseInt(value))
|
|
282
|
+
return true
|
|
283
|
+
}
|
|
284
|
+
if (name == "minColorDelta") {
|
|
285
|
+
o.minColorDelta = (EvgTraceCli.parseInt(value))
|
|
286
|
+
return true
|
|
287
|
+
}
|
|
288
|
+
if (name == "contourMode") {
|
|
289
|
+
o.contourMode = value
|
|
290
|
+
return true
|
|
291
|
+
}
|
|
292
|
+
if (name == "overlaySimilar") {
|
|
293
|
+
o.overlaySimilar = (EvgTraceCli.parseInt(value))
|
|
294
|
+
return true
|
|
295
|
+
}
|
|
296
|
+
if (name == "overlayFollowBase") {
|
|
297
|
+
o.overlayFollowBase = (EvgTraceCli.parseBool(value))
|
|
298
|
+
return true
|
|
299
|
+
}
|
|
300
|
+
if (name == "detailSwatches") {
|
|
301
|
+
o.detailSwatches = (EvgTraceCli.parseInt(value))
|
|
302
|
+
return true
|
|
303
|
+
}
|
|
304
|
+
if (name == "detailSpread") {
|
|
305
|
+
o.detailSpread = (EvgTraceCli.parseInt(value))
|
|
306
|
+
return true
|
|
307
|
+
}
|
|
308
|
+
if (name == "detailRadius") {
|
|
309
|
+
o.detailRadius = (EvgTraceCli.parseInt(value))
|
|
310
|
+
return true
|
|
311
|
+
}
|
|
312
|
+
if (name == "detailBoost") {
|
|
313
|
+
o.detailBoost = (EvgTraceCli.parseInt(value))
|
|
314
|
+
return true
|
|
315
|
+
}
|
|
316
|
+
if (name == "detailTrueColor") {
|
|
317
|
+
o.detailTrueColor = (EvgTraceCli.parseBool(value))
|
|
318
|
+
return true
|
|
319
|
+
}
|
|
320
|
+
if (name == "detailColors") {
|
|
321
|
+
o.detailColors = (EvgTraceCli.parseInt(value))
|
|
322
|
+
return true
|
|
323
|
+
}
|
|
324
|
+
if (name == "detailMinShare") {
|
|
325
|
+
o.detailMinShare = (EvgTraceCli.parseInt(value))
|
|
326
|
+
return true
|
|
327
|
+
}
|
|
328
|
+
if (name == "detailColorMerge") {
|
|
329
|
+
o.detailColorMerge = (EvgTraceCli.parseInt(value))
|
|
330
|
+
return true
|
|
331
|
+
}
|
|
332
|
+
if (name == "detailColorMax") {
|
|
333
|
+
o.detailColorMax = (EvgTraceCli.parseInt(value))
|
|
334
|
+
return true
|
|
335
|
+
}
|
|
336
|
+
if (name == "edgeMinRun") {
|
|
337
|
+
o.edgeMinRun = (EvgTraceCli.parseInt(value))
|
|
338
|
+
return true
|
|
339
|
+
}
|
|
340
|
+
if (name == "contourEdge") {
|
|
341
|
+
o.contourEdge = (EvgTraceCli.parseInt(value))
|
|
342
|
+
return true
|
|
343
|
+
}
|
|
344
|
+
if (name == "contourSpread") {
|
|
345
|
+
o.contourSpread = (EvgTraceCli.parseInt(value))
|
|
346
|
+
return true
|
|
347
|
+
}
|
|
348
|
+
if (name == "gradientFill") {
|
|
349
|
+
o.gradientFill = (EvgTraceCli.parseBool(value))
|
|
350
|
+
return true
|
|
351
|
+
}
|
|
352
|
+
if (name == "gradientGain") {
|
|
353
|
+
o.gradientGain = (EvgTraceCli.parseInt(value))
|
|
354
|
+
return true
|
|
355
|
+
}
|
|
356
|
+
if (name == "layerMode") {
|
|
357
|
+
o.layerMode = value
|
|
358
|
+
return true
|
|
359
|
+
}
|
|
360
|
+
if (name == "pathFormat") {
|
|
361
|
+
o.pathFormat = value
|
|
362
|
+
return true
|
|
363
|
+
}
|
|
364
|
+
if (name == "pathPrecision") {
|
|
365
|
+
o.pathPrecision = (EvgTraceCli.parseInt(value))
|
|
366
|
+
return true
|
|
367
|
+
}
|
|
368
|
+
if (name == "smooth") {
|
|
369
|
+
o.smooth = (EvgTraceCli.parseInt(value))
|
|
370
|
+
return true
|
|
371
|
+
}
|
|
372
|
+
if (name == "minRegion") {
|
|
373
|
+
o.minRegion = (EvgTraceCli.parseInt(value))
|
|
374
|
+
return true
|
|
375
|
+
}
|
|
376
|
+
if (name == "absorbContrast") {
|
|
377
|
+
o.absorbContrast = (EvgTraceCli.parseInt(value))
|
|
378
|
+
return true
|
|
379
|
+
}
|
|
380
|
+
if (name == "bgMode") {
|
|
381
|
+
o.bgMode = value
|
|
382
|
+
return true
|
|
383
|
+
}
|
|
384
|
+
if (name == "bgColor") {
|
|
385
|
+
o.bgColor = value
|
|
386
|
+
return true
|
|
387
|
+
}
|
|
388
|
+
if (name == "bgTolerance") {
|
|
389
|
+
o.bgTolerance = (EvgTraceCli.parseInt(value))
|
|
390
|
+
return true
|
|
391
|
+
}
|
|
392
|
+
return false
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
; Which options are switches. A switch may be written bare, so it must not
|
|
396
|
+
; swallow the token after it — and the token after it is very often the
|
|
397
|
+
; output path.
|
|
398
|
+
sfn isSwitch:boolean (name:string) {
|
|
399
|
+
if (name == "optcurve") {
|
|
400
|
+
return true
|
|
401
|
+
}
|
|
402
|
+
if (name == "blackOnWhite") {
|
|
403
|
+
return true
|
|
404
|
+
}
|
|
405
|
+
if (name == "edgeSnap") {
|
|
406
|
+
return true
|
|
407
|
+
}
|
|
408
|
+
if (name == "overlayFollowBase") {
|
|
409
|
+
return true
|
|
410
|
+
}
|
|
411
|
+
if (name == "detailTrueColor") {
|
|
412
|
+
return true
|
|
413
|
+
}
|
|
414
|
+
if (name == "gradientFill") {
|
|
415
|
+
return true
|
|
416
|
+
}
|
|
417
|
+
return false
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
; Whether a token reads as a value for a switch, as opposed to being the
|
|
421
|
+
; next thing on the line.
|
|
422
|
+
sfn looksBoolean:boolean (s:string) {
|
|
423
|
+
return ((indexOf "|0|1|true|false|yes|no|on|off|" ("|" + s + "|")) >= 0)
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
fn printUsage:void () {
|
|
427
|
+
print "evg-trace — bitmap to SVG (Ranger EvgBitmapTracer)"
|
|
428
|
+
print ""
|
|
429
|
+
print " evg-trace <input.png|.jpg> <output.svg> [options]"
|
|
430
|
+
print ""
|
|
431
|
+
print " The two paths may come anywhere among the options, and an"
|
|
432
|
+
print " option may be written --name value or --name=value."
|
|
433
|
+
print ""
|
|
434
|
+
print " --preset <name> lineart | poster | photo | print | broken"
|
|
435
|
+
print " --<option> <value>"
|
|
436
|
+
print ""
|
|
437
|
+
print "Options are the fields of EvgTraceOptions, e.g. --colorCount 12"
|
|
438
|
+
print "--paletteMute 130 --pathPrecision 1. See EvgTraceTypes.rgr for"
|
|
439
|
+
print "what each one does and what it defaults to."
|
|
440
|
+
print ""
|
|
441
|
+
print "Known options:"
|
|
442
|
+
print " turdsize alphamax turnpolicy optcurve opttolerance threshold"
|
|
443
|
+
print " blackOnWhite fillHex colorCount skipLuma flatTolerance edgeSnap"
|
|
444
|
+
print " snapRatio lumaWeight colorSpace paletteMode paletteHex"
|
|
445
|
+
print " paletteBias paletteChroma paletteMute paletteTint paletteWarm"
|
|
446
|
+
print " paletteContrast minColorDelta contourMode overlaySimilar"
|
|
447
|
+
print " overlayFollowBase detailSwatches detailSpread detailRadius"
|
|
448
|
+
print " detailBoost detailTrueColor detailColors detailMinShare"
|
|
449
|
+
print " detailColorMerge detailColorMax edgeMinRun contourEdge"
|
|
450
|
+
print " contourSpread gradientFill gradientGain layerMode pathFormat"
|
|
451
|
+
print " pathPrecision smooth minRegion absorbContrast bgMode bgColor"
|
|
452
|
+
print " bgTolerance"
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
; --- decode -----------------------------------------------------------
|
|
456
|
+
|
|
457
|
+
; A JPEG says which kind it is in its first SOF marker, which always
|
|
458
|
+
; precedes the entropy-coded data — so the first 0xFFC0 or 0xFFC2 from the
|
|
459
|
+
; start is the answer and nothing later can be mistaken for it.
|
|
460
|
+
sfn isProgressiveJpeg:boolean (bytes:buffer) {
|
|
461
|
+
def n:int (buffer_length bytes)
|
|
462
|
+
def i:int 0
|
|
463
|
+
while (i < (n - 1)) {
|
|
464
|
+
def b:int (buffer_get bytes i)
|
|
465
|
+
if (b == 255) {
|
|
466
|
+
def marker:int (buffer_get bytes (i + 1))
|
|
467
|
+
; 194 = SOF2 (progressive), 192/193 = SOF0/1 (baseline)
|
|
468
|
+
if (marker == 194) {
|
|
469
|
+
return true
|
|
470
|
+
}
|
|
471
|
+
if (marker == 192) {
|
|
472
|
+
return false
|
|
473
|
+
}
|
|
474
|
+
if (marker == 193) {
|
|
475
|
+
return false
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
i = (i + 1)
|
|
479
|
+
}
|
|
480
|
+
return false
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
; By the magic bytes rather than the extension: a .png that is really a
|
|
484
|
+
; JPEG is common enough, and the extension is the one thing about a file
|
|
485
|
+
; that nothing checks. The decoders report failure as a 1x1 image, which
|
|
486
|
+
; the caller checks for.
|
|
487
|
+
fn decodeImage:ImageBuffer (bytes:buffer dir:string file:string) {
|
|
488
|
+
def n:int (buffer_length bytes)
|
|
489
|
+
def fail (new ImageBuffer())
|
|
490
|
+
fail.init(1 1)
|
|
491
|
+
if (n < 4) {
|
|
492
|
+
return fail
|
|
493
|
+
}
|
|
494
|
+
def b0:int (buffer_get bytes 0)
|
|
495
|
+
def b1:int (buffer_get bytes 1)
|
|
496
|
+
if ((b0 == 137) && (b1 == 80)) {
|
|
497
|
+
def png (new PNGDecoder())
|
|
498
|
+
return (png.decodeBytes(bytes))
|
|
499
|
+
}
|
|
500
|
+
if ((b0 == 255) && (b1 == 216)) {
|
|
501
|
+
if (EvgTraceCli.isProgressiveJpeg(bytes)) {
|
|
502
|
+
; The progressive decoder reads the file itself; it has no
|
|
503
|
+
; in-memory entry point.
|
|
504
|
+
def prog (new ProgressiveJPEGDecoder())
|
|
505
|
+
return (prog.decode(dir file))
|
|
506
|
+
}
|
|
507
|
+
def jpg (new JPEGDecoder())
|
|
508
|
+
jpg.quiet = true
|
|
509
|
+
return (jpg.decodeBytes(bytes))
|
|
510
|
+
}
|
|
511
|
+
return fail
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
; --- run --------------------------------------------------------------
|
|
515
|
+
|
|
516
|
+
fn run:void () {
|
|
517
|
+
def argCount:int (shell_arg_cnt)
|
|
518
|
+
if (argCount < 1) {
|
|
519
|
+
this.printUsage()
|
|
520
|
+
return
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
; Positionals are taken wherever they fall. Requiring them first is the
|
|
524
|
+
; one thing about a command line nobody remembers, and
|
|
525
|
+
; `in.jpg --colorCount 4 out.svg` reading `--colorCount` as the output
|
|
526
|
+
; path is a confusing way to say so.
|
|
527
|
+
def opts:EvgTraceOptions (EvgTraceOptions.defaults())
|
|
528
|
+
def positional:[string]
|
|
529
|
+
def i:int 0
|
|
530
|
+
def bad:boolean false
|
|
531
|
+
def wantHelp:boolean false
|
|
532
|
+
while (i < argCount) {
|
|
533
|
+
def arg:string (shell_arg i)
|
|
534
|
+
if ((arg == "-h") || (arg == "--help")) {
|
|
535
|
+
wantHelp = true
|
|
536
|
+
} {
|
|
537
|
+
if ((indexOf arg "--") == 0) {
|
|
538
|
+
def body:string (substring arg 2 (strlen arg))
|
|
539
|
+
def name:string body
|
|
540
|
+
def value:string ""
|
|
541
|
+
def haveValue:boolean false
|
|
542
|
+
; --name=value is accepted as well as --name value.
|
|
543
|
+
def eq:int (indexOf body "=")
|
|
544
|
+
if (eq >= 0) {
|
|
545
|
+
name = (substring body 0 eq)
|
|
546
|
+
value = (substring body (eq + 1) (strlen body))
|
|
547
|
+
haveValue = true
|
|
548
|
+
}
|
|
549
|
+
def isFlag:boolean (EvgTraceCli.isSwitch(name))
|
|
550
|
+
if (haveValue == false) {
|
|
551
|
+
if ((i + 1) < argCount) {
|
|
552
|
+
def peek:string (shell_arg (i + 1))
|
|
553
|
+
def peekIsOption:boolean ((indexOf peek "--") == 0)
|
|
554
|
+
def take:boolean false
|
|
555
|
+
if (peekIsOption == false) {
|
|
556
|
+
take = true
|
|
557
|
+
if (isFlag) {
|
|
558
|
+
; A switch only eats what reads as a switch
|
|
559
|
+
; value; anything else is a positional.
|
|
560
|
+
take = (EvgTraceCli.looksBoolean(peek))
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (take) {
|
|
564
|
+
value = peek
|
|
565
|
+
haveValue = true
|
|
566
|
+
i = (i + 1)
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
if ((haveValue == false) && isFlag) {
|
|
571
|
+
value = "true"
|
|
572
|
+
haveValue = true
|
|
573
|
+
}
|
|
574
|
+
if (haveValue == false) {
|
|
575
|
+
print (("--" + name) + " needs a value")
|
|
576
|
+
bad = true
|
|
577
|
+
} {
|
|
578
|
+
if (name == "preset") {
|
|
579
|
+
opts = (EvgTraceOptions.preset(value))
|
|
580
|
+
} {
|
|
581
|
+
def ok:boolean (this.applyOption(opts name value))
|
|
582
|
+
if (ok == false) {
|
|
583
|
+
print ("unknown option --" + name)
|
|
584
|
+
bad = true
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
} {
|
|
589
|
+
push positional arg
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
i = (i + 1)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (wantHelp) {
|
|
596
|
+
this.printUsage()
|
|
597
|
+
return
|
|
598
|
+
}
|
|
599
|
+
def pn:int (array_length positional)
|
|
600
|
+
if (pn > 2) {
|
|
601
|
+
print (("expected an input and an output path, got " + (to_string pn)) + ":")
|
|
602
|
+
def pi:int 0
|
|
603
|
+
while (pi < pn) {
|
|
604
|
+
print (" " + (itemAt positional pi))
|
|
605
|
+
pi = (pi + 1)
|
|
606
|
+
}
|
|
607
|
+
bad = true
|
|
608
|
+
}
|
|
609
|
+
if (pn < 2) {
|
|
610
|
+
if (bad == false) {
|
|
611
|
+
print "an input path and an output path are both needed"
|
|
612
|
+
}
|
|
613
|
+
bad = true
|
|
614
|
+
}
|
|
615
|
+
if (bad) {
|
|
616
|
+
print ""
|
|
617
|
+
this.printUsage()
|
|
618
|
+
return
|
|
619
|
+
}
|
|
620
|
+
def inputPath:string (itemAt positional 0)
|
|
621
|
+
def outputPath:string (itemAt positional 1)
|
|
622
|
+
|
|
623
|
+
def inDir:string (EvgTraceCli.dirOf(inputPath))
|
|
624
|
+
def inFile:string (EvgTraceCli.fileOf(inputPath))
|
|
625
|
+
; Asked for a file that is not there, buffer_read_file raises on some
|
|
626
|
+
; targets and returns nothing on others. Neither is a message, so look
|
|
627
|
+
; first: a mistyped path is the most ordinary thing that can happen
|
|
628
|
+
; here and it should read as one line, not as a stack trace.
|
|
629
|
+
if ((file_exists inDir inFile) == false) {
|
|
630
|
+
print ("no such file: " + inputPath)
|
|
631
|
+
return
|
|
632
|
+
}
|
|
633
|
+
def bytes:buffer (buffer_read_file inDir inFile)
|
|
634
|
+
if ((buffer_length bytes) == 0) {
|
|
635
|
+
print ("cannot read " + inputPath)
|
|
636
|
+
return
|
|
637
|
+
}
|
|
638
|
+
def img:ImageBuffer (this.decodeImage(bytes inDir inFile))
|
|
639
|
+
; 1x1 is how both decoders report a failure, and writing an SVG of it
|
|
640
|
+
; would be worse than saying so: the file would look like a result.
|
|
641
|
+
if (((img.width) < 2) && ((img.height) < 2)) {
|
|
642
|
+
print ("not a PNG or JPEG this build can decode: " + inputPath)
|
|
643
|
+
return
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
def tr:EvgBitmapTracer (EvgBitmapTracer.fromImageBuffer(img opts))
|
|
647
|
+
tr.trace()
|
|
648
|
+
def svg:string (tr.toSVG())
|
|
649
|
+
|
|
650
|
+
def outDir:string (EvgTraceCli.dirOf(outputPath))
|
|
651
|
+
def outFile:string (EvgTraceCli.fileOf(outputPath))
|
|
652
|
+
write_file outDir outFile svg
|
|
653
|
+
|
|
654
|
+
def w:string (to_string (img.width))
|
|
655
|
+
def h:string (to_string (img.height))
|
|
656
|
+
def layers:string (to_string (tr.layerCount()))
|
|
657
|
+
def rings:string (to_string (tr.ringCount()))
|
|
658
|
+
def bytesOut:string (to_string (strlen svg))
|
|
659
|
+
print ((((((((outputPath + " ") + w) + "x") + h) + " layers=") + layers) + " rings=") + rings)
|
|
660
|
+
print ((" " + bytesOut) + " bytes")
|
|
661
|
+
}
|
|
662
|
+
}
|