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,433 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; WebPDecoder.rgr - WebP (RFC 9649) -> RGBA ImageBuffer, no third-party code.
|
|
4
|
+
;
|
|
5
|
+
; def dec (new WebPDecoder())
|
|
6
|
+
; def img:ImageBuffer (dec.decodeBytes(bytes))
|
|
7
|
+
; if dec.ok { ... img.width, img.height, img.pixels (RGBA, 4 bytes a pixel) }
|
|
8
|
+
;
|
|
9
|
+
; Supported: the simple lossy ('VP8 ') and lossless ('VP8L') formats, and the
|
|
10
|
+
; extended format ('VP8X') with an ALPH chunk (uncompressed or VP8L
|
|
11
|
+
; compressed, all four filters, the pre-processing flag accepted) beside a
|
|
12
|
+
; 'VP8 ' frame, or a 'VP8L' frame. Unknown chunks (ICCP, EXIF, XMP, ...) are
|
|
13
|
+
; skipped. An animation ('ANIM' / 'ANMF') decodes to its first frame, placed
|
|
14
|
+
; at its offset on a transparent canvas of the animation's size, which is
|
|
15
|
+
; what libwebp's animation decoder returns for frame one.
|
|
16
|
+
;
|
|
17
|
+
; A malformed, truncated or oversized file never throws or reads out of
|
|
18
|
+
; bounds: decodeBytes returns a 1x1 image with `ok` false and the reason in
|
|
19
|
+
; `error`. Each side is capped by maxDimension (16384) and the area by
|
|
20
|
+
; maxPixels.
|
|
21
|
+
;
|
|
22
|
+
; The decoding logic follows libwebp (Copyright Google Inc., BSD-3-Clause);
|
|
23
|
+
; see WebPLossy.rgr and WebPLossless.rgr. The output matches libwebp's RGBA
|
|
24
|
+
; (and simplewebp's) byte for byte. This port is MIT like the rest of lib/image.
|
|
25
|
+
|
|
26
|
+
Import "Buffer.rgr"
|
|
27
|
+
Import "ImageBuffer.rgr"
|
|
28
|
+
Import "VP8BoolDecoder.rgr"
|
|
29
|
+
Import "WebPLossless.rgr"
|
|
30
|
+
Import "WebPLossy.rgr"
|
|
31
|
+
|
|
32
|
+
class WebPDecoder {
|
|
33
|
+
def ok:boolean false
|
|
34
|
+
def error:string ""
|
|
35
|
+
def quiet:boolean true
|
|
36
|
+
|
|
37
|
+
; what the last decode found
|
|
38
|
+
def width:int 0
|
|
39
|
+
def height:int 0
|
|
40
|
+
def hasAlpha:boolean false
|
|
41
|
+
def isLossless:boolean false
|
|
42
|
+
def isAnimated:boolean false
|
|
43
|
+
def frameCount:int 0
|
|
44
|
+
def alphaMethod:int -1
|
|
45
|
+
def alphaFilter:int -1
|
|
46
|
+
def alphaPreprocessing:int -1
|
|
47
|
+
|
|
48
|
+
def maxDimension:int 16384
|
|
49
|
+
def maxPixels:int 100000000
|
|
50
|
+
|
|
51
|
+
def lossless:VP8LDecoder (new VP8LDecoder())
|
|
52
|
+
def lossy:VP8Decoder (new VP8Decoder())
|
|
53
|
+
|
|
54
|
+
; the frame decoded by decodeFrameChunks
|
|
55
|
+
def frame:ImageBuffer (new ImageBuffer())
|
|
56
|
+
|
|
57
|
+
Constructor () {
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
sfn u16le:int (b:buffer p:int) {
|
|
61
|
+
return (bit_or (buffer_get b p) (bit_shl (buffer_get b (p + 1)) 8))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
sfn u24le:int (b:buffer p:int) {
|
|
65
|
+
return (bit_or (WebPDecoder.u16le(b p)) (bit_shl (buffer_get b (p + 2)) 16))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
; a chunk size; sizes of 2^31 and more come out negative and are rejected
|
|
69
|
+
sfn u32le:int (b:buffer p:int) {
|
|
70
|
+
return (bit_or (WebPDecoder.u24le(b p)) (bit_shl (buffer_get b (p + 3)) 24))
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
sfn tagIs:boolean (b:buffer p:int tag:string) {
|
|
74
|
+
def i:int 0
|
|
75
|
+
while (i < 4) {
|
|
76
|
+
if ((buffer_get b (p + i)) != (charAt tag i)) {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
i = i + 1
|
|
80
|
+
}
|
|
81
|
+
return true
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
; True when the bytes start like a WebP file (RIFF....WEBP).
|
|
85
|
+
sfn isWebP:boolean (b:buffer) {
|
|
86
|
+
if ((buffer_length b) < 12) {
|
|
87
|
+
return false
|
|
88
|
+
}
|
|
89
|
+
if ((WebPDecoder.tagIs(b 0 "RIFF")) == false) {
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
return (WebPDecoder.tagIs(b 8 "WEBP"))
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fn fail:boolean (msg:string) {
|
|
96
|
+
if ((strlen error) == 0) {
|
|
97
|
+
error = msg
|
|
98
|
+
}
|
|
99
|
+
return false
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
fn decode:ImageBuffer (dir:string fileName:string) {
|
|
103
|
+
def bytes:buffer (buffer_read_file dir fileName)
|
|
104
|
+
return (this.decodeBytes(bytes))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
; Decodes a WebP file held in memory. Check `ok` afterwards.
|
|
108
|
+
fn decodeBytes:ImageBuffer (bytes:buffer) {
|
|
109
|
+
ok = false
|
|
110
|
+
error = ""
|
|
111
|
+
width = 0
|
|
112
|
+
height = 0
|
|
113
|
+
hasAlpha = false
|
|
114
|
+
isLossless = false
|
|
115
|
+
isAnimated = false
|
|
116
|
+
frameCount = 0
|
|
117
|
+
alphaMethod = -1
|
|
118
|
+
alphaFilter = -1
|
|
119
|
+
alphaPreprocessing = -1
|
|
120
|
+
lossless.maxPixels = maxPixels
|
|
121
|
+
lossy.maxPixels = maxPixels
|
|
122
|
+
def img:ImageBuffer (new ImageBuffer())
|
|
123
|
+
if (this.parse(bytes)) {
|
|
124
|
+
img = frame
|
|
125
|
+
ok = true
|
|
126
|
+
} {
|
|
127
|
+
img.init(1 1)
|
|
128
|
+
if (quiet == false) {
|
|
129
|
+
print ("[webp_decoder] " + error)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
frame = (new ImageBuffer())
|
|
133
|
+
return img
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
fn parse:boolean (b:buffer) {
|
|
137
|
+
def len:int (buffer_length b)
|
|
138
|
+
if (len < 12) {
|
|
139
|
+
return (this.fail("not a WebP file: too small"))
|
|
140
|
+
}
|
|
141
|
+
if (((WebPDecoder.tagIs(b 0 "RIFF")) == false) || ((WebPDecoder.tagIs(b 8 "WEBP")) == false)) {
|
|
142
|
+
return (this.fail("not a WebP file: bad RIFF header"))
|
|
143
|
+
}
|
|
144
|
+
def riffSize:int (WebPDecoder.u32le(b 4))
|
|
145
|
+
if (riffSize < 12) {
|
|
146
|
+
return (this.fail("bad RIFF size"))
|
|
147
|
+
}
|
|
148
|
+
if (riffSize > (len - 8)) {
|
|
149
|
+
return (this.fail("truncated file"))
|
|
150
|
+
}
|
|
151
|
+
def end:int (8 + riffSize)
|
|
152
|
+
if ((12 + 8) > end) {
|
|
153
|
+
return (this.fail("no chunks"))
|
|
154
|
+
}
|
|
155
|
+
if (WebPDecoder.tagIs(b 12 "VP8X")) {
|
|
156
|
+
return (this.parseExtended(b end))
|
|
157
|
+
}
|
|
158
|
+
return (this.decodeFrameChunks(b 12 end 0 0))
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
; the bounds of the chunk at p inside [p, end): payload size, or -1
|
|
162
|
+
fn chunkSize:int (b:buffer p:int end:int) {
|
|
163
|
+
if ((p + 8) > end) {
|
|
164
|
+
this.fail("truncated chunk header")
|
|
165
|
+
return -1
|
|
166
|
+
}
|
|
167
|
+
def size:int (WebPDecoder.u32le(b (p + 4)))
|
|
168
|
+
if ((size < 0) || (size > ((end - p) - 8))) {
|
|
169
|
+
this.fail("truncated chunk")
|
|
170
|
+
return -1
|
|
171
|
+
}
|
|
172
|
+
return size
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
sfn nextChunk:int (p:int size:int) {
|
|
176
|
+
return (((p + 8) + size) + (bit_and size 1))
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
fn parseExtended:boolean (b:buffer end:int) {
|
|
180
|
+
def size:int (this.chunkSize(b 12 end))
|
|
181
|
+
if (size < 0) {
|
|
182
|
+
return false
|
|
183
|
+
}
|
|
184
|
+
if (size != 10) {
|
|
185
|
+
return (this.fail("bad VP8X chunk size"))
|
|
186
|
+
}
|
|
187
|
+
def flags:int (buffer_get b 20)
|
|
188
|
+
def canvasW:int ((WebPDecoder.u24le(b 24)) + 1)
|
|
189
|
+
def canvasH:int ((WebPDecoder.u24le(b 27)) + 1)
|
|
190
|
+
if ((canvasW > maxDimension) || (canvasH > maxDimension) || (((to_double canvasW) * (to_double canvasH)) > (to_double maxPixels))) {
|
|
191
|
+
return (this.fail("image too large"))
|
|
192
|
+
}
|
|
193
|
+
def p:int (WebPDecoder.nextChunk(12 size))
|
|
194
|
+
if ((bit_and flags 2) == 0) {
|
|
195
|
+
if ((this.decodeFrameChunks(b p end canvasW canvasH)) == false) {
|
|
196
|
+
return false
|
|
197
|
+
}
|
|
198
|
+
return true
|
|
199
|
+
}
|
|
200
|
+
; animation: the first ANMF frame on a transparent canvas
|
|
201
|
+
isAnimated = true
|
|
202
|
+
def firstFrame:int -1
|
|
203
|
+
def firstSize:int 0
|
|
204
|
+
while (p < end) {
|
|
205
|
+
def cs:int (this.chunkSize(b p end))
|
|
206
|
+
if (cs < 0) {
|
|
207
|
+
return false
|
|
208
|
+
}
|
|
209
|
+
if (WebPDecoder.tagIs(b p "ANMF")) {
|
|
210
|
+
frameCount = frameCount + 1
|
|
211
|
+
if (firstFrame < 0) {
|
|
212
|
+
firstFrame = p
|
|
213
|
+
firstSize = cs
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
p = (WebPDecoder.nextChunk(p cs))
|
|
217
|
+
}
|
|
218
|
+
if (firstFrame < 0) {
|
|
219
|
+
return (this.fail("animation without frames"))
|
|
220
|
+
}
|
|
221
|
+
if (firstSize < 16) {
|
|
222
|
+
return (this.fail("bad ANMF chunk"))
|
|
223
|
+
}
|
|
224
|
+
def fp:int (firstFrame + 8)
|
|
225
|
+
def fx:int ((WebPDecoder.u24le(b fp)) * 2)
|
|
226
|
+
def fy:int ((WebPDecoder.u24le(b (fp + 3))) * 2)
|
|
227
|
+
def fw:int ((WebPDecoder.u24le(b (fp + 6))) + 1)
|
|
228
|
+
def fh:int ((WebPDecoder.u24le(b (fp + 9))) + 1)
|
|
229
|
+
if (((fx + fw) > canvasW) || ((fy + fh) > canvasH)) {
|
|
230
|
+
return (this.fail("frame outside the canvas"))
|
|
231
|
+
}
|
|
232
|
+
if ((this.decodeFrameChunks(b (fp + 16) ((fp + firstSize)) fw fh)) == false) {
|
|
233
|
+
return false
|
|
234
|
+
}
|
|
235
|
+
def canvas:ImageBuffer (new ImageBuffer())
|
|
236
|
+
canvas.initClear(canvasW canvasH)
|
|
237
|
+
canvas.fillTransparent()
|
|
238
|
+
def row:int 0
|
|
239
|
+
while (row < fh) {
|
|
240
|
+
buffer_copy canvas.pixels ((((fy + row) * canvasW) + fx) * 4) frame.pixels ((row * fw) * 4) (fw * 4)
|
|
241
|
+
row = row + 1
|
|
242
|
+
}
|
|
243
|
+
frame = canvas
|
|
244
|
+
width = canvasW
|
|
245
|
+
height = canvasH
|
|
246
|
+
hasAlpha = true
|
|
247
|
+
return true
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
; Walks the chunks in [p, end) up to the first 'VP8 ' or 'VP8L' and decodes
|
|
251
|
+
; that frame into `frame`, with the ALPH chunk before it. expectW / expectH,
|
|
252
|
+
; when not 0, is the size the container announced.
|
|
253
|
+
fn decodeFrameChunks:boolean (b:buffer start:int end:int expectW:int expectH:int) {
|
|
254
|
+
def alphStart:int -1
|
|
255
|
+
def alphSize:int 0
|
|
256
|
+
def p:int start
|
|
257
|
+
while (p < end) {
|
|
258
|
+
def cs:int (this.chunkSize(b p end))
|
|
259
|
+
if (cs < 0) {
|
|
260
|
+
return false
|
|
261
|
+
}
|
|
262
|
+
if (WebPDecoder.tagIs(b p "ALPH")) {
|
|
263
|
+
alphStart = p + 8
|
|
264
|
+
alphSize = cs
|
|
265
|
+
}
|
|
266
|
+
if (WebPDecoder.tagIs(b p "VP8L")) {
|
|
267
|
+
return (this.decodeLossless(b (p + 8) cs expectW expectH))
|
|
268
|
+
}
|
|
269
|
+
if (WebPDecoder.tagIs(b p "VP8 ")) {
|
|
270
|
+
return (this.decodeLossy(b (p + 8) cs expectW expectH alphStart alphSize))
|
|
271
|
+
}
|
|
272
|
+
p = (WebPDecoder.nextChunk(p cs))
|
|
273
|
+
}
|
|
274
|
+
return (this.fail("no image data"))
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
fn checkSize:boolean (w:int h:int expectW:int expectH:int) {
|
|
278
|
+
if ((expectW > 0) && ((w != expectW) || (h != expectH))) {
|
|
279
|
+
return (this.fail("frame size does not match the canvas"))
|
|
280
|
+
}
|
|
281
|
+
return true
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
fn decodeLossless:boolean (b:buffer start:int size:int expectW:int expectH:int) {
|
|
285
|
+
isLossless = true
|
|
286
|
+
if ((lossless.decode(b start size maxDimension)) == false) {
|
|
287
|
+
return (this.fail(lossless.error))
|
|
288
|
+
}
|
|
289
|
+
def w:int lossless.width
|
|
290
|
+
def h:int lossless.height
|
|
291
|
+
if ((this.checkSize(w h expectW expectH)) == false) {
|
|
292
|
+
return false
|
|
293
|
+
}
|
|
294
|
+
width = w
|
|
295
|
+
height = h
|
|
296
|
+
hasAlpha = lossless.hasAlpha
|
|
297
|
+
frame = (new ImageBuffer())
|
|
298
|
+
frame.initClear(w h)
|
|
299
|
+
def n:int (w * h)
|
|
300
|
+
def i:int 0
|
|
301
|
+
while (i < n) {
|
|
302
|
+
def p:int (int_buffer_get lossless.argb i)
|
|
303
|
+
def o:int (i * 4)
|
|
304
|
+
buffer_set frame.pixels o (bit_and (bit_shr p 16) 255)
|
|
305
|
+
buffer_set frame.pixels (o + 1) (bit_and (bit_shr p 8) 255)
|
|
306
|
+
buffer_set frame.pixels (o + 2) (bit_and p 255)
|
|
307
|
+
buffer_set frame.pixels (o + 3) (bit_and (bit_shr p 24) 255)
|
|
308
|
+
i = i + 1
|
|
309
|
+
}
|
|
310
|
+
lossless.argb = (int_buffer_alloc 0)
|
|
311
|
+
return true
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
fn decodeLossy:boolean (b:buffer start:int size:int expectW:int expectH:int alphStart:int alphSize:int) {
|
|
315
|
+
if ((lossy.decodeHeader(b start size maxDimension)) == false) {
|
|
316
|
+
return (this.fail(lossy.error))
|
|
317
|
+
}
|
|
318
|
+
def w:int lossy.width
|
|
319
|
+
def h:int lossy.height
|
|
320
|
+
if ((this.checkSize(w h expectW expectH)) == false) {
|
|
321
|
+
return false
|
|
322
|
+
}
|
|
323
|
+
if ((lossy.decodeFrame()) == false) {
|
|
324
|
+
return (this.fail(lossy.error))
|
|
325
|
+
}
|
|
326
|
+
width = w
|
|
327
|
+
height = h
|
|
328
|
+
def alpha:buffer (buffer_alloc 0)
|
|
329
|
+
def withAlpha:boolean false
|
|
330
|
+
if (alphStart >= 0) {
|
|
331
|
+
alpha = (this.decodeAlpha(b alphStart alphSize w h))
|
|
332
|
+
if ((strlen error) > 0) {
|
|
333
|
+
return false
|
|
334
|
+
}
|
|
335
|
+
withAlpha = true
|
|
336
|
+
}
|
|
337
|
+
hasAlpha = withAlpha
|
|
338
|
+
frame = (new ImageBuffer())
|
|
339
|
+
lossy.toRGBA(frame alpha withAlpha)
|
|
340
|
+
lossy.yPlane = (buffer_alloc 0)
|
|
341
|
+
lossy.uPlane = (buffer_alloc 0)
|
|
342
|
+
lossy.vPlane = (buffer_alloc 0)
|
|
343
|
+
return true
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
; The alpha plane of an ALPH chunk (RFC 9649 section 2.7.1.2).
|
|
347
|
+
fn decodeAlpha:buffer (b:buffer start:int size:int w:int h:int) {
|
|
348
|
+
def empty:buffer (buffer_alloc 0)
|
|
349
|
+
if (size <= 1) {
|
|
350
|
+
this.fail("ALPH chunk too small")
|
|
351
|
+
return empty
|
|
352
|
+
}
|
|
353
|
+
def hdr:int (buffer_get b start)
|
|
354
|
+
def method:int (bit_and hdr 3)
|
|
355
|
+
def filter:int (bit_and (bit_shr hdr 2) 3)
|
|
356
|
+
def pre:int (bit_and (bit_shr hdr 4) 3)
|
|
357
|
+
alphaMethod = method
|
|
358
|
+
alphaFilter = filter
|
|
359
|
+
alphaPreprocessing = pre
|
|
360
|
+
if ((method > 1) || (pre > 1) || ((bit_shr hdr 6) != 0)) {
|
|
361
|
+
this.fail("bad ALPH header")
|
|
362
|
+
return empty
|
|
363
|
+
}
|
|
364
|
+
def n:int (w * h)
|
|
365
|
+
def a:buffer (buffer_alloc n)
|
|
366
|
+
if (method == 0) {
|
|
367
|
+
if ((size - 1) < n) {
|
|
368
|
+
this.fail("ALPH data too short")
|
|
369
|
+
return empty
|
|
370
|
+
}
|
|
371
|
+
buffer_copy a 0 b (start + 1) n
|
|
372
|
+
} {
|
|
373
|
+
if ((lossless.decodeAlphaStream(b (start + 1) (size - 1) w h)) == false) {
|
|
374
|
+
this.fail(("alpha: " + lossless.error))
|
|
375
|
+
return empty
|
|
376
|
+
}
|
|
377
|
+
def i:int 0
|
|
378
|
+
while (i < n) {
|
|
379
|
+
buffer_set a i (bit_and (bit_shr (int_buffer_get lossless.argb i) 8) 255)
|
|
380
|
+
i = i + 1
|
|
381
|
+
}
|
|
382
|
+
lossless.argb = (int_buffer_alloc 0)
|
|
383
|
+
}
|
|
384
|
+
WebPDecoder.unfilterAlpha(a w h filter)
|
|
385
|
+
return a
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
; Undoes the alpha filtering in place: 1 horizontal, 2 vertical, 3 gradient.
|
|
389
|
+
; The first row always predicts from the left, the first column from above.
|
|
390
|
+
sfn unfilterAlpha:void (a:buffer w:int h:int filter:int) {
|
|
391
|
+
if (filter == 0) {
|
|
392
|
+
return
|
|
393
|
+
}
|
|
394
|
+
def y:int 0
|
|
395
|
+
while (y < h) {
|
|
396
|
+
def row:int (y * w)
|
|
397
|
+
def x:int 0
|
|
398
|
+
while (x < w) {
|
|
399
|
+
def i:int (row + x)
|
|
400
|
+
def pred:int 0
|
|
401
|
+
if (y == 0) {
|
|
402
|
+
if (x > 0) {
|
|
403
|
+
pred = (buffer_get a (i - 1))
|
|
404
|
+
}
|
|
405
|
+
} {
|
|
406
|
+
if (x == 0) {
|
|
407
|
+
pred = (buffer_get a (i - w))
|
|
408
|
+
} {
|
|
409
|
+
if (filter == 1) {
|
|
410
|
+
pred = (buffer_get a (i - 1))
|
|
411
|
+
}
|
|
412
|
+
if (filter == 2) {
|
|
413
|
+
pred = (buffer_get a (i - w))
|
|
414
|
+
}
|
|
415
|
+
if (filter == 3) {
|
|
416
|
+
def g:int (((buffer_get a (i - 1)) + (buffer_get a (i - w))) - (buffer_get a ((i - w) - 1)))
|
|
417
|
+
if (g < 0) {
|
|
418
|
+
g = 0
|
|
419
|
+
}
|
|
420
|
+
if (g > 255) {
|
|
421
|
+
g = 255
|
|
422
|
+
}
|
|
423
|
+
pred = g
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
buffer_set a i (bit_and ((buffer_get a i) + pred) 255)
|
|
428
|
+
x = x + 1
|
|
429
|
+
}
|
|
430
|
+
y = y + 1
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|