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,1035 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; WebPLossless.rgr - the VP8L lossless bitstream of WebP (RFC 9649 section 3).
|
|
4
|
+
;
|
|
5
|
+
; Prefix codes (simple and normal), the color cache, backward references
|
|
6
|
+
; with the distance map, meta prefix codes and the four transforms
|
|
7
|
+
; (predictor with its 14 modes, cross-color, subtract-green, color indexing
|
|
8
|
+
; with pixel bundling). Also decodes the headerless VP8L stream that carries
|
|
9
|
+
; a compressed ALPH chunk.
|
|
10
|
+
;
|
|
11
|
+
; The decoding logic follows libwebp (src/dec/vp8l_dec.c,
|
|
12
|
+
; src/utils/huffman_utils.c, src/dsp/lossless.c), Copyright Google Inc.,
|
|
13
|
+
; BSD-3-Clause; this port is MIT like the rest of lib/image.
|
|
14
|
+
;
|
|
15
|
+
; Pixels are packed ARGB in one int each: (a << 24) | (r << 16) | (g << 8) | b,
|
|
16
|
+
; so a pixel with alpha >= 128 is negative. Every packed value is built and
|
|
17
|
+
; taken apart with bit operations only, which agree between the 32-bit
|
|
18
|
+
; integers of JavaScript and of the C++ target.
|
|
19
|
+
|
|
20
|
+
class VP8LDecoder {
|
|
21
|
+
; ---- bit reader: least significant bit first, at most 24 bits buffered
|
|
22
|
+
def data:buffer (buffer_alloc 0)
|
|
23
|
+
def dataLen:int 0
|
|
24
|
+
def pos:int 0
|
|
25
|
+
def bitBuf:int 0
|
|
26
|
+
def bitCnt:int 0
|
|
27
|
+
def padBits:int 0
|
|
28
|
+
def eos:boolean false
|
|
29
|
+
|
|
30
|
+
; ---- prefix code tables of the image level being decoded
|
|
31
|
+
; Each code is a root table of 2^rootBits entries followed by its second
|
|
32
|
+
; level tables. An entry is (length << 16) | symbol, or for a root entry
|
|
33
|
+
; that continues in a second level table ((16 + subBits) << 16) | offset.
|
|
34
|
+
def tables:int_buffer (int_buffer_alloc 4096)
|
|
35
|
+
def tablesUsed:int 0
|
|
36
|
+
def maxTableEntries:int 16777216
|
|
37
|
+
|
|
38
|
+
def error:string ""
|
|
39
|
+
def width:int 0
|
|
40
|
+
def height:int 0
|
|
41
|
+
def hasAlpha:boolean false
|
|
42
|
+
def argb:int_buffer (int_buffer_alloc 0)
|
|
43
|
+
def maxPixels:int 100000000
|
|
44
|
+
|
|
45
|
+
; ---- what the last stream used (read by the tests)
|
|
46
|
+
def statTransforms:int 0
|
|
47
|
+
def statPredModes:int 0
|
|
48
|
+
def statCacheBits:int 0
|
|
49
|
+
def statGroups:int 0
|
|
50
|
+
def statSimpleCodes:int 0
|
|
51
|
+
def statNormalCodes:int 0
|
|
52
|
+
def statBackRefs:int 0
|
|
53
|
+
def statCacheHits:int 0
|
|
54
|
+
def statBundleBits:int -1
|
|
55
|
+
|
|
56
|
+
Constructor () {
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn fail:boolean (msg:string) {
|
|
60
|
+
if ((strlen error) == 0) {
|
|
61
|
+
error = msg
|
|
62
|
+
}
|
|
63
|
+
return false
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
; ======================================================================
|
|
67
|
+
; Bit reader
|
|
68
|
+
; ======================================================================
|
|
69
|
+
|
|
70
|
+
fn initBits:void (src:buffer start:int size:int) {
|
|
71
|
+
def srcLen:int (buffer_length src)
|
|
72
|
+
def s:int start
|
|
73
|
+
if (s < 0) {
|
|
74
|
+
s = 0
|
|
75
|
+
}
|
|
76
|
+
if (s > srcLen) {
|
|
77
|
+
s = srcLen
|
|
78
|
+
}
|
|
79
|
+
def e:int (s + size)
|
|
80
|
+
if (size < 0) {
|
|
81
|
+
e = s
|
|
82
|
+
}
|
|
83
|
+
if (e > srcLen) {
|
|
84
|
+
e = srcLen
|
|
85
|
+
}
|
|
86
|
+
data = (buffer_slice src s e)
|
|
87
|
+
dataLen = (e - s)
|
|
88
|
+
pos = 0
|
|
89
|
+
bitBuf = 0
|
|
90
|
+
bitCnt = 0
|
|
91
|
+
padBits = 0
|
|
92
|
+
eos = false
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fn fill:void () {
|
|
96
|
+
while (bitCnt <= 16) {
|
|
97
|
+
def b:int 0
|
|
98
|
+
if (pos < dataLen) {
|
|
99
|
+
b = (buffer_get data pos)
|
|
100
|
+
pos = pos + 1
|
|
101
|
+
} {
|
|
102
|
+
padBits = padBits + 8
|
|
103
|
+
}
|
|
104
|
+
bitBuf = (bit_or bitBuf (bit_shl b bitCnt))
|
|
105
|
+
bitCnt = bitCnt + 8
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fn readBits16:int (n:int) {
|
|
110
|
+
if (bitCnt < n) {
|
|
111
|
+
this.fill()
|
|
112
|
+
}
|
|
113
|
+
def v:int (bit_and bitBuf ((bit_shl 1 n) - 1))
|
|
114
|
+
bitBuf = (bit_shr bitBuf n)
|
|
115
|
+
bitCnt = bitCnt - n
|
|
116
|
+
if (bitCnt < padBits) {
|
|
117
|
+
eos = true
|
|
118
|
+
}
|
|
119
|
+
return v
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
; n bits, 0 <= n <= 24
|
|
123
|
+
fn readBits:int (n:int) {
|
|
124
|
+
if (n <= 16) {
|
|
125
|
+
return (this.readBits16(n))
|
|
126
|
+
}
|
|
127
|
+
def lo:int (this.readBits16(16))
|
|
128
|
+
def hi:int (this.readBits16((n - 16)))
|
|
129
|
+
return (bit_or lo (bit_shl hi 16))
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
; ======================================================================
|
|
133
|
+
; Prefix codes
|
|
134
|
+
; ======================================================================
|
|
135
|
+
|
|
136
|
+
fn reserveTables:boolean (n:int) {
|
|
137
|
+
def need:int (tablesUsed + n)
|
|
138
|
+
if (need > maxTableEntries) {
|
|
139
|
+
return (this.fail("prefix code tables too large"))
|
|
140
|
+
}
|
|
141
|
+
def cap:int (int_buffer_length tables)
|
|
142
|
+
if (need <= cap) {
|
|
143
|
+
return true
|
|
144
|
+
}
|
|
145
|
+
def newCap:int (cap * 2)
|
|
146
|
+
while (newCap < need) {
|
|
147
|
+
newCap = newCap * 2
|
|
148
|
+
}
|
|
149
|
+
def grown:int_buffer (int_buffer_alloc newCap)
|
|
150
|
+
int_buffer_copy grown 0 tables 0 tablesUsed
|
|
151
|
+
tables = grown
|
|
152
|
+
return true
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
sfn reverseBits:int (code:int len:int) {
|
|
156
|
+
def r:int 0
|
|
157
|
+
def i:int 0
|
|
158
|
+
def c:int code
|
|
159
|
+
while (i < len) {
|
|
160
|
+
r = (bit_or (bit_shl r 1) (bit_and c 1))
|
|
161
|
+
c = (bit_shr c 1)
|
|
162
|
+
i = i + 1
|
|
163
|
+
}
|
|
164
|
+
return r
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
; Builds the decoding table for code lengths[0..n-1] and returns
|
|
168
|
+
; (offset << 4) | rootBits, or -1 when the lengths do not form a complete
|
|
169
|
+
; prefix code. A code with one used symbol reads zero bits.
|
|
170
|
+
fn buildCode:int (lengths:int_buffer n:int) {
|
|
171
|
+
def count:int_buffer (int_buffer_alloc 16)
|
|
172
|
+
def s:int 0
|
|
173
|
+
def used:int 0
|
|
174
|
+
def lastSym:int 0
|
|
175
|
+
def maxLen:int 0
|
|
176
|
+
while (s < n) {
|
|
177
|
+
def l:int (int_buffer_get lengths s)
|
|
178
|
+
if ((l < 0) || (l > 15)) {
|
|
179
|
+
return -1
|
|
180
|
+
}
|
|
181
|
+
if (l > 0) {
|
|
182
|
+
int_buffer_set count l ((int_buffer_get count l) + 1)
|
|
183
|
+
used = used + 1
|
|
184
|
+
lastSym = s
|
|
185
|
+
if (l > maxLen) {
|
|
186
|
+
maxLen = l
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
s = s + 1
|
|
190
|
+
}
|
|
191
|
+
if (used == 0) {
|
|
192
|
+
return -1
|
|
193
|
+
}
|
|
194
|
+
if (used == 1) {
|
|
195
|
+
if ((this.reserveTables(1)) == false) {
|
|
196
|
+
return -1
|
|
197
|
+
}
|
|
198
|
+
def one:int tablesUsed
|
|
199
|
+
int_buffer_set tables one lastSym
|
|
200
|
+
tablesUsed = tablesUsed + 1
|
|
201
|
+
return (bit_shl one 4)
|
|
202
|
+
}
|
|
203
|
+
; complete and not over-subscribed
|
|
204
|
+
def open:int 1
|
|
205
|
+
def len:int 1
|
|
206
|
+
while (len <= 15) {
|
|
207
|
+
open = (open * 2) - (int_buffer_get count len)
|
|
208
|
+
if (open < 0) {
|
|
209
|
+
return -1
|
|
210
|
+
}
|
|
211
|
+
len = len + 1
|
|
212
|
+
}
|
|
213
|
+
if (open != 0) {
|
|
214
|
+
return -1
|
|
215
|
+
}
|
|
216
|
+
; canonical first code of each length
|
|
217
|
+
def nextCode:int_buffer (int_buffer_alloc 16)
|
|
218
|
+
def code:int 0
|
|
219
|
+
len = 1
|
|
220
|
+
while (len <= 15) {
|
|
221
|
+
code = (bit_shl (code + (int_buffer_get count (len - 1))) 1)
|
|
222
|
+
if (len == 1) {
|
|
223
|
+
code = 0
|
|
224
|
+
}
|
|
225
|
+
int_buffer_set nextCode len code
|
|
226
|
+
len = len + 1
|
|
227
|
+
}
|
|
228
|
+
def rootBits:int maxLen
|
|
229
|
+
if (rootBits > 8) {
|
|
230
|
+
rootBits = 8
|
|
231
|
+
}
|
|
232
|
+
def rootSize:int (bit_shl 1 rootBits)
|
|
233
|
+
def rootMask:int (rootSize - 1)
|
|
234
|
+
; bit-reversed code per symbol, and the depth of each second level table
|
|
235
|
+
def rev:int_buffer (int_buffer_alloc n)
|
|
236
|
+
def subBits:int_buffer (int_buffer_alloc rootSize)
|
|
237
|
+
s = 0
|
|
238
|
+
while (s < n) {
|
|
239
|
+
def l:int (int_buffer_get lengths s)
|
|
240
|
+
if (l > 0) {
|
|
241
|
+
def c:int (int_buffer_get nextCode l)
|
|
242
|
+
int_buffer_set nextCode l (c + 1)
|
|
243
|
+
def r:int (VP8LDecoder.reverseBits(c l))
|
|
244
|
+
int_buffer_set rev s r
|
|
245
|
+
if (l > rootBits) {
|
|
246
|
+
def p:int (bit_and r rootMask)
|
|
247
|
+
if ((l - rootBits) > (int_buffer_get subBits p)) {
|
|
248
|
+
int_buffer_set subBits p (l - rootBits)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
s = s + 1
|
|
253
|
+
}
|
|
254
|
+
def total:int rootSize
|
|
255
|
+
def p:int 0
|
|
256
|
+
while (p < rootSize) {
|
|
257
|
+
def sb:int (int_buffer_get subBits p)
|
|
258
|
+
if (sb > 0) {
|
|
259
|
+
total = total + (bit_shl 1 sb)
|
|
260
|
+
}
|
|
261
|
+
p = p + 1
|
|
262
|
+
}
|
|
263
|
+
if ((this.reserveTables(total)) == false) {
|
|
264
|
+
return -1
|
|
265
|
+
}
|
|
266
|
+
def base:int tablesUsed
|
|
267
|
+
tablesUsed = tablesUsed + total
|
|
268
|
+
def subOffset:int_buffer (int_buffer_alloc rootSize)
|
|
269
|
+
def off:int rootSize
|
|
270
|
+
p = 0
|
|
271
|
+
while (p < rootSize) {
|
|
272
|
+
def sb:int (int_buffer_get subBits p)
|
|
273
|
+
if (sb > 0) {
|
|
274
|
+
int_buffer_set subOffset p off
|
|
275
|
+
int_buffer_set tables (base + p) (bit_or (bit_shl (16 + sb) 16) off)
|
|
276
|
+
off = off + (bit_shl 1 sb)
|
|
277
|
+
}
|
|
278
|
+
p = p + 1
|
|
279
|
+
}
|
|
280
|
+
s = 0
|
|
281
|
+
while (s < n) {
|
|
282
|
+
def l:int (int_buffer_get lengths s)
|
|
283
|
+
if (l > 0) {
|
|
284
|
+
def r:int (int_buffer_get rev s)
|
|
285
|
+
def entry:int (bit_or (bit_shl l 16) s)
|
|
286
|
+
if (l <= rootBits) {
|
|
287
|
+
def step:int (bit_shl 1 l)
|
|
288
|
+
def i:int r
|
|
289
|
+
while (i < rootSize) {
|
|
290
|
+
int_buffer_set tables (base + i) entry
|
|
291
|
+
i = i + step
|
|
292
|
+
}
|
|
293
|
+
} {
|
|
294
|
+
def pfx:int (bit_and r rootMask)
|
|
295
|
+
def sb:int (int_buffer_get subBits pfx)
|
|
296
|
+
def sub:int (base + (int_buffer_get subOffset pfx))
|
|
297
|
+
def step:int (bit_shl 1 (l - rootBits))
|
|
298
|
+
def subSize:int (bit_shl 1 sb)
|
|
299
|
+
def i:int (bit_shr r rootBits)
|
|
300
|
+
while (i < subSize) {
|
|
301
|
+
int_buffer_set tables (sub + i) entry
|
|
302
|
+
i = i + step
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
s = s + 1
|
|
307
|
+
}
|
|
308
|
+
return (bit_or (bit_shl base 4) rootBits)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
; Reads one symbol with the code built by buildCode.
|
|
312
|
+
fn readSymbol:int (code:int) {
|
|
313
|
+
def base:int (bit_shr code 4)
|
|
314
|
+
def rootBits:int (bit_and code 15)
|
|
315
|
+
if (rootBits == 0) {
|
|
316
|
+
return (int_buffer_get tables base)
|
|
317
|
+
}
|
|
318
|
+
if (bitCnt < 15) {
|
|
319
|
+
this.fill()
|
|
320
|
+
}
|
|
321
|
+
def e:int (int_buffer_get tables (base + (bit_and bitBuf ((bit_shl 1 rootBits) - 1))))
|
|
322
|
+
def l:int (bit_shr e 16)
|
|
323
|
+
if (l > 15) {
|
|
324
|
+
def sb:int (l - 16)
|
|
325
|
+
def idx:int (bit_and (bit_shr bitBuf rootBits) ((bit_shl 1 sb) - 1))
|
|
326
|
+
e = (int_buffer_get tables (base + (bit_and e 65535) + idx))
|
|
327
|
+
l = (bit_shr e 16)
|
|
328
|
+
}
|
|
329
|
+
bitBuf = (bit_shr bitBuf l)
|
|
330
|
+
bitCnt = bitCnt - l
|
|
331
|
+
if (bitCnt < padBits) {
|
|
332
|
+
eos = true
|
|
333
|
+
}
|
|
334
|
+
return (bit_and e 65535)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
; Reads one prefix code over an alphabet of alphabetSize symbols.
|
|
338
|
+
fn readCode:int (alphabetSize:int) {
|
|
339
|
+
def size:int alphabetSize
|
|
340
|
+
if (size < 256) {
|
|
341
|
+
size = 256
|
|
342
|
+
}
|
|
343
|
+
def lengths:int_buffer (int_buffer_alloc size)
|
|
344
|
+
def simple:int (this.readBits(1))
|
|
345
|
+
if (simple == 1) {
|
|
346
|
+
statSimpleCodes = statSimpleCodes + 1
|
|
347
|
+
def numSymbols:int ((this.readBits(1)) + 1)
|
|
348
|
+
def firstBits:int (this.readBits(1))
|
|
349
|
+
def s0:int 0
|
|
350
|
+
if (firstBits == 0) {
|
|
351
|
+
s0 = (this.readBits(1))
|
|
352
|
+
} {
|
|
353
|
+
s0 = (this.readBits(8))
|
|
354
|
+
}
|
|
355
|
+
int_buffer_set lengths s0 1
|
|
356
|
+
if (numSymbols == 2) {
|
|
357
|
+
def s1:int (this.readBits(8))
|
|
358
|
+
int_buffer_set lengths s1 1
|
|
359
|
+
}
|
|
360
|
+
} {
|
|
361
|
+
statNormalCodes = statNormalCodes + 1
|
|
362
|
+
if ((this.readCodeLengths(lengths alphabetSize)) == false) {
|
|
363
|
+
return -1
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
if eos {
|
|
367
|
+
this.fail("truncated prefix code")
|
|
368
|
+
return -1
|
|
369
|
+
}
|
|
370
|
+
def c:int (this.buildCode(lengths alphabetSize))
|
|
371
|
+
if (c < 0) {
|
|
372
|
+
this.fail("invalid prefix code")
|
|
373
|
+
}
|
|
374
|
+
return c
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
fn readCodeLengths:boolean (lengths:int_buffer numSymbols:int) {
|
|
378
|
+
def order:[int] ([] _:int (17 18 0 1 2 3 4 5 16 6 7 8 9 10 11 12 13 14 15))
|
|
379
|
+
def clen:int_buffer (int_buffer_alloc 19)
|
|
380
|
+
def numCodes:int ((this.readBits(4)) + 4)
|
|
381
|
+
def i:int 0
|
|
382
|
+
while (i < numCodes) {
|
|
383
|
+
int_buffer_set clen (itemAt order i) (this.readBits(3))
|
|
384
|
+
i = i + 1
|
|
385
|
+
}
|
|
386
|
+
def lenCode:int (this.buildCode(clen 19))
|
|
387
|
+
if (lenCode < 0) {
|
|
388
|
+
return (this.fail("invalid code length code"))
|
|
389
|
+
}
|
|
390
|
+
def maxSymbol:int numSymbols
|
|
391
|
+
if ((this.readBits(1)) == 1) {
|
|
392
|
+
def nbits:int (2 + (2 * (this.readBits(3))))
|
|
393
|
+
maxSymbol = 2 + (this.readBits(nbits))
|
|
394
|
+
if (maxSymbol > numSymbols) {
|
|
395
|
+
return (this.fail("code length count out of range"))
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
def prevLen:int 8
|
|
399
|
+
def symbol:int 0
|
|
400
|
+
while (symbol < numSymbols) {
|
|
401
|
+
if (maxSymbol == 0) {
|
|
402
|
+
break
|
|
403
|
+
}
|
|
404
|
+
maxSymbol = maxSymbol - 1
|
|
405
|
+
def codeLen:int (this.readSymbol(lenCode))
|
|
406
|
+
if eos {
|
|
407
|
+
return (this.fail("truncated code lengths"))
|
|
408
|
+
}
|
|
409
|
+
if (codeLen < 16) {
|
|
410
|
+
int_buffer_set lengths symbol codeLen
|
|
411
|
+
symbol = symbol + 1
|
|
412
|
+
if (codeLen != 0) {
|
|
413
|
+
prevLen = codeLen
|
|
414
|
+
}
|
|
415
|
+
} {
|
|
416
|
+
def repeat:int 0
|
|
417
|
+
def fillLen:int 0
|
|
418
|
+
if (codeLen == 16) {
|
|
419
|
+
repeat = (this.readBits(2)) + 3
|
|
420
|
+
fillLen = prevLen
|
|
421
|
+
}
|
|
422
|
+
if (codeLen == 17) {
|
|
423
|
+
repeat = (this.readBits(3)) + 3
|
|
424
|
+
}
|
|
425
|
+
if (codeLen == 18) {
|
|
426
|
+
repeat = (this.readBits(7)) + 11
|
|
427
|
+
}
|
|
428
|
+
if ((symbol + repeat) > numSymbols) {
|
|
429
|
+
return (this.fail("code length repeat out of range"))
|
|
430
|
+
}
|
|
431
|
+
while (repeat > 0) {
|
|
432
|
+
int_buffer_set lengths symbol fillLen
|
|
433
|
+
symbol = symbol + 1
|
|
434
|
+
repeat = repeat - 1
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return true
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
; ======================================================================
|
|
442
|
+
; Entropy-coded image
|
|
443
|
+
; ======================================================================
|
|
444
|
+
|
|
445
|
+
sfn subSampleSize:int (size:int bits:int) {
|
|
446
|
+
return (bit_shr (size + (bit_shl 1 bits) - 1) bits)
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
; (0x1e35a7bd * argb) mod 2^32 >> (32 - bits), in pieces that stay
|
|
450
|
+
; below 2^31 on a 32-bit int.
|
|
451
|
+
sfn hashPixel:int (argb:int bits:int) {
|
|
452
|
+
def lo:int (bit_and argb 65535)
|
|
453
|
+
def hi:int (bit_and (bit_ushr argb 16) 65535)
|
|
454
|
+
; K = 0x1e35a7bd: high half 7733, low half 42941 = 167 * 256 + 189
|
|
455
|
+
def carry:int (bit_shr ((lo * 167) + (bit_shr (lo * 189) 8)) 8)
|
|
456
|
+
def mid:int ((bit_and (lo * 7733) 65535) + (bit_and ((bit_shl (bit_and (hi * 167) 255) 8) + (hi * 189)) 65535))
|
|
457
|
+
def top:int (bit_and (carry + mid) 65535)
|
|
458
|
+
return (bit_shr top (16 - bits))
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
; distance / length prefix coding: symbol -> value (1-based)
|
|
462
|
+
fn copyDistance:int (sym:int) {
|
|
463
|
+
if (sym < 4) {
|
|
464
|
+
return (sym + 1)
|
|
465
|
+
}
|
|
466
|
+
def extra:int (bit_shr (sym - 2) 1)
|
|
467
|
+
def offset:int (bit_shl (2 + (bit_and sym 1)) extra)
|
|
468
|
+
return (offset + (this.readBits(extra)) + 1)
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
sfn planeCodeToDistance:int (xsize:int planeCode:int) {
|
|
472
|
+
if (planeCode > 120) {
|
|
473
|
+
return (planeCode - 120)
|
|
474
|
+
}
|
|
475
|
+
def codes:[int] ([] _:int (24 7 23 25 40 6 39 41 22 26 38 42 56 5 55 57 21 27 54 58 37 43 72 4 71 73 20 28 53 59 70 74 36 44 88 69 75 52 60 3 87 89 19 29 86 90 35 45 68 76 85 91 51 61 104 2 103 105 18 30 102 106 34 46 84 92 67 77 101 107 50 62 120 1 119 121 83 93 17 31 100 108 66 78 118 122 33 47 117 123 49 63 99 109 82 94 0 116 124 65 79 16 32 98 110 48 115 125 81 95 64 114 126 97 111 80 113 127 96 112))
|
|
476
|
+
def distCode:int (itemAt codes (planeCode - 1))
|
|
477
|
+
def yoffset:int (bit_shr distCode 4)
|
|
478
|
+
def xoffset:int (8 - (bit_and distCode 15))
|
|
479
|
+
def dist:int ((yoffset * xsize) + xoffset)
|
|
480
|
+
if (dist >= 1) {
|
|
481
|
+
return dist
|
|
482
|
+
}
|
|
483
|
+
return 1
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
; Decodes one entropy-coded image of w x h pixels. The main image (the
|
|
487
|
+
; last one of a level 0 stream) may carry meta prefix codes.
|
|
488
|
+
fn decodeImageData:int_buffer (w:int h:int isMain:boolean) {
|
|
489
|
+
def empty:int_buffer (int_buffer_alloc 0)
|
|
490
|
+
if ((w <= 0) || (h <= 0) || (((to_double w) * (to_double h)) > (to_double maxPixels))) {
|
|
491
|
+
this.fail("bad image size")
|
|
492
|
+
return empty
|
|
493
|
+
}
|
|
494
|
+
def total:int (w * h)
|
|
495
|
+
if (total <= 0) {
|
|
496
|
+
this.fail("bad image size")
|
|
497
|
+
return empty
|
|
498
|
+
}
|
|
499
|
+
; color cache
|
|
500
|
+
def cacheBits:int 0
|
|
501
|
+
def cacheSize:int 0
|
|
502
|
+
if ((this.readBits(1)) == 1) {
|
|
503
|
+
cacheBits = (this.readBits(4))
|
|
504
|
+
if ((cacheBits < 1) || (cacheBits > 11)) {
|
|
505
|
+
this.fail("bad color cache size")
|
|
506
|
+
return empty
|
|
507
|
+
}
|
|
508
|
+
cacheSize = (bit_shl 1 cacheBits)
|
|
509
|
+
if (cacheBits > statCacheBits) {
|
|
510
|
+
statCacheBits = cacheBits
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
def cache:int_buffer (int_buffer_alloc (cacheSize + 1))
|
|
514
|
+
; meta prefix codes
|
|
515
|
+
def metaBits:int 0
|
|
516
|
+
def metaW:int 0
|
|
517
|
+
def numGroups:int 1
|
|
518
|
+
def entropy:int_buffer (int_buffer_alloc 0)
|
|
519
|
+
if isMain {
|
|
520
|
+
if ((this.readBits(1)) == 1) {
|
|
521
|
+
metaBits = (this.readBits(3)) + 2
|
|
522
|
+
metaW = (VP8LDecoder.subSampleSize(w metaBits))
|
|
523
|
+
def metaH:int (VP8LDecoder.subSampleSize(h metaBits))
|
|
524
|
+
entropy = (this.decodeImageData(metaW metaH false))
|
|
525
|
+
if ((strlen error) > 0) {
|
|
526
|
+
return empty
|
|
527
|
+
}
|
|
528
|
+
def n:int (metaW * metaH)
|
|
529
|
+
def k:int 0
|
|
530
|
+
while (k < n) {
|
|
531
|
+
def g:int (bit_and (bit_shr (int_buffer_get entropy k) 8) 65535)
|
|
532
|
+
int_buffer_set entropy k g
|
|
533
|
+
if (g >= numGroups) {
|
|
534
|
+
numGroups = g + 1
|
|
535
|
+
}
|
|
536
|
+
k = k + 1
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if eos {
|
|
541
|
+
this.fail("truncated image header")
|
|
542
|
+
return empty
|
|
543
|
+
}
|
|
544
|
+
if (numGroups > statGroups) {
|
|
545
|
+
statGroups = numGroups
|
|
546
|
+
}
|
|
547
|
+
; the prefix codes of this image; earlier levels are done with theirs
|
|
548
|
+
tablesUsed = 0
|
|
549
|
+
def codes:int_buffer (int_buffer_alloc (numGroups * 5))
|
|
550
|
+
def gi:int 0
|
|
551
|
+
while (gi < numGroups) {
|
|
552
|
+
def k:int 0
|
|
553
|
+
while (k < 5) {
|
|
554
|
+
def alphabet:int 256
|
|
555
|
+
if (k == 0) {
|
|
556
|
+
alphabet = 280 + cacheSize
|
|
557
|
+
}
|
|
558
|
+
if (k == 4) {
|
|
559
|
+
alphabet = 40
|
|
560
|
+
}
|
|
561
|
+
def c:int (this.readCode(alphabet))
|
|
562
|
+
if (c < 0) {
|
|
563
|
+
return empty
|
|
564
|
+
}
|
|
565
|
+
int_buffer_set codes ((gi * 5) + k) c
|
|
566
|
+
k = k + 1
|
|
567
|
+
}
|
|
568
|
+
gi = gi + 1
|
|
569
|
+
}
|
|
570
|
+
; pixels
|
|
571
|
+
def out:int_buffer (int_buffer_alloc total)
|
|
572
|
+
def i:int 0
|
|
573
|
+
def x:int 0
|
|
574
|
+
def y:int 0
|
|
575
|
+
def gbase:int 0
|
|
576
|
+
def colorLimit:int (280 + cacheSize)
|
|
577
|
+
def hasMeta:boolean (metaBits > 0)
|
|
578
|
+
while (i < total) {
|
|
579
|
+
if hasMeta {
|
|
580
|
+
gbase = (int_buffer_get entropy (((bit_shr y metaBits) * metaW) + (bit_shr x metaBits))) * 5
|
|
581
|
+
}
|
|
582
|
+
def code:int (this.readSymbol((int_buffer_get codes gbase)))
|
|
583
|
+
if (code < 256) {
|
|
584
|
+
def r:int (this.readSymbol((int_buffer_get codes (gbase + 1))))
|
|
585
|
+
def b:int (this.readSymbol((int_buffer_get codes (gbase + 2))))
|
|
586
|
+
def a:int (this.readSymbol((int_buffer_get codes (gbase + 3))))
|
|
587
|
+
def px:int (bit_or (bit_or (bit_shl a 24) (bit_shl r 16)) (bit_or (bit_shl code 8) b))
|
|
588
|
+
int_buffer_set out i px
|
|
589
|
+
if (cacheBits > 0) {
|
|
590
|
+
int_buffer_set cache (VP8LDecoder.hashPixel(px cacheBits)) px
|
|
591
|
+
}
|
|
592
|
+
i = i + 1
|
|
593
|
+
x = x + 1
|
|
594
|
+
if (x >= w) {
|
|
595
|
+
x = 0
|
|
596
|
+
y = y + 1
|
|
597
|
+
}
|
|
598
|
+
} {
|
|
599
|
+
if (code < 280) {
|
|
600
|
+
statBackRefs = statBackRefs + 1
|
|
601
|
+
def length:int (this.copyDistance((code - 256)))
|
|
602
|
+
def distSym:int (this.readSymbol((int_buffer_get codes (gbase + 4))))
|
|
603
|
+
def distCode:int (this.copyDistance(distSym))
|
|
604
|
+
def dist:int (VP8LDecoder.planeCodeToDistance(w distCode))
|
|
605
|
+
if eos {
|
|
606
|
+
this.fail("truncated image data")
|
|
607
|
+
return empty
|
|
608
|
+
}
|
|
609
|
+
if ((i < dist) || ((total - i) < length)) {
|
|
610
|
+
this.fail("backward reference out of range")
|
|
611
|
+
return empty
|
|
612
|
+
}
|
|
613
|
+
def k:int 0
|
|
614
|
+
while (k < length) {
|
|
615
|
+
def px:int (int_buffer_get out (i - dist))
|
|
616
|
+
int_buffer_set out i px
|
|
617
|
+
if (cacheBits > 0) {
|
|
618
|
+
int_buffer_set cache (VP8LDecoder.hashPixel(px cacheBits)) px
|
|
619
|
+
}
|
|
620
|
+
i = i + 1
|
|
621
|
+
k = k + 1
|
|
622
|
+
}
|
|
623
|
+
x = x + length
|
|
624
|
+
while (x >= w) {
|
|
625
|
+
x = x - w
|
|
626
|
+
y = y + 1
|
|
627
|
+
}
|
|
628
|
+
} {
|
|
629
|
+
if (code >= colorLimit) {
|
|
630
|
+
this.fail("bad symbol")
|
|
631
|
+
return empty
|
|
632
|
+
}
|
|
633
|
+
statCacheHits = statCacheHits + 1
|
|
634
|
+
int_buffer_set out i (int_buffer_get cache (code - 280))
|
|
635
|
+
i = i + 1
|
|
636
|
+
x = x + 1
|
|
637
|
+
if (x >= w) {
|
|
638
|
+
x = 0
|
|
639
|
+
y = y + 1
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if eos {
|
|
644
|
+
this.fail("truncated image data")
|
|
645
|
+
return empty
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return out
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
; ======================================================================
|
|
652
|
+
; Transforms
|
|
653
|
+
; ======================================================================
|
|
654
|
+
|
|
655
|
+
sfn addPixels:int (a:int b:int) {
|
|
656
|
+
def ag:int ((bit_and (bit_ushr a 8) 16711935) + (bit_and (bit_ushr b 8) 16711935))
|
|
657
|
+
def rb:int ((bit_and a 16711935) + (bit_and b 16711935))
|
|
658
|
+
return (bit_or (bit_shl (bit_and ag 16711935) 8) (bit_and rb 16711935))
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
sfn average2:int (a:int b:int) {
|
|
662
|
+
def ag:int ((bit_and (bit_ushr a 8) 16711935) + (bit_and (bit_ushr b 8) 16711935))
|
|
663
|
+
def rb:int ((bit_and a 16711935) + (bit_and b 16711935))
|
|
664
|
+
return (bit_or (bit_shl (bit_and (bit_shr ag 1) 16711935) 8) (bit_and (bit_shr rb 1) 16711935))
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
sfn clip255:int (v:int) {
|
|
668
|
+
if (v < 0) {
|
|
669
|
+
return 0
|
|
670
|
+
}
|
|
671
|
+
if (v > 255) {
|
|
672
|
+
return 255
|
|
673
|
+
}
|
|
674
|
+
return v
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
sfn absInt:int (v:int) {
|
|
678
|
+
if (v < 0) {
|
|
679
|
+
return (0 - v)
|
|
680
|
+
}
|
|
681
|
+
return v
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
; the channel of packed pixel p at bit offset sh
|
|
685
|
+
sfn ch:int (p:int sh:int) {
|
|
686
|
+
return (bit_and (bit_shr p sh) 255)
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
sfn pack:int (a:int r:int g:int b:int) {
|
|
690
|
+
return (bit_or (bit_or (bit_shl a 24) (bit_shl r 16)) (bit_or (bit_shl g 8) b))
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
sfn select:int (t:int l:int tl:int) {
|
|
694
|
+
def d:int 0
|
|
695
|
+
def sh:int 0
|
|
696
|
+
while (sh < 32) {
|
|
697
|
+
def ct:int (VP8LDecoder.ch(t sh))
|
|
698
|
+
def cl:int (VP8LDecoder.ch(l sh))
|
|
699
|
+
def ctl:int (VP8LDecoder.ch(tl sh))
|
|
700
|
+
d = d + ((VP8LDecoder.absInt((cl - ctl))) - (VP8LDecoder.absInt((ct - ctl))))
|
|
701
|
+
sh = sh + 8
|
|
702
|
+
}
|
|
703
|
+
if (d <= 0) {
|
|
704
|
+
return t
|
|
705
|
+
}
|
|
706
|
+
return l
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
sfn clampAddSubtractFull:int (a:int b:int c:int) {
|
|
710
|
+
def al:int (VP8LDecoder.clip255(((VP8LDecoder.ch(a 24)) + (VP8LDecoder.ch(b 24)) - (VP8LDecoder.ch(c 24)))))
|
|
711
|
+
def r:int (VP8LDecoder.clip255(((VP8LDecoder.ch(a 16)) + (VP8LDecoder.ch(b 16)) - (VP8LDecoder.ch(c 16)))))
|
|
712
|
+
def g:int (VP8LDecoder.clip255(((VP8LDecoder.ch(a 8)) + (VP8LDecoder.ch(b 8)) - (VP8LDecoder.ch(c 8)))))
|
|
713
|
+
def bl:int (VP8LDecoder.clip255(((VP8LDecoder.ch(a 0)) + (VP8LDecoder.ch(b 0)) - (VP8LDecoder.ch(c 0)))))
|
|
714
|
+
return (VP8LDecoder.pack(al r g bl))
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
sfn halfChannel:int (a:int b:int) {
|
|
718
|
+
return (VP8LDecoder.clip255((a + (idiv (a - b) 2))))
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
sfn clampAddSubtractHalf:int (a:int b:int) {
|
|
722
|
+
def al:int (VP8LDecoder.halfChannel((VP8LDecoder.ch(a 24)) (VP8LDecoder.ch(b 24))))
|
|
723
|
+
def r:int (VP8LDecoder.halfChannel((VP8LDecoder.ch(a 16)) (VP8LDecoder.ch(b 16))))
|
|
724
|
+
def g:int (VP8LDecoder.halfChannel((VP8LDecoder.ch(a 8)) (VP8LDecoder.ch(b 8))))
|
|
725
|
+
def bl:int (VP8LDecoder.halfChannel((VP8LDecoder.ch(a 0)) (VP8LDecoder.ch(b 0))))
|
|
726
|
+
return (VP8LDecoder.pack(al r g bl))
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
; The 14 predictors of the predictor transform (14 and 15 predict black,
|
|
730
|
+
; as in libwebp).
|
|
731
|
+
sfn predict:int (mode:int l:int t:int tl:int tr:int) {
|
|
732
|
+
if (mode == 1) {
|
|
733
|
+
return l
|
|
734
|
+
}
|
|
735
|
+
if (mode == 2) {
|
|
736
|
+
return t
|
|
737
|
+
}
|
|
738
|
+
if (mode == 3) {
|
|
739
|
+
return tr
|
|
740
|
+
}
|
|
741
|
+
if (mode == 4) {
|
|
742
|
+
return tl
|
|
743
|
+
}
|
|
744
|
+
if (mode == 5) {
|
|
745
|
+
return (VP8LDecoder.average2((VP8LDecoder.average2(l tr)) t))
|
|
746
|
+
}
|
|
747
|
+
if (mode == 6) {
|
|
748
|
+
return (VP8LDecoder.average2(l tl))
|
|
749
|
+
}
|
|
750
|
+
if (mode == 7) {
|
|
751
|
+
return (VP8LDecoder.average2(l t))
|
|
752
|
+
}
|
|
753
|
+
if (mode == 8) {
|
|
754
|
+
return (VP8LDecoder.average2(tl t))
|
|
755
|
+
}
|
|
756
|
+
if (mode == 9) {
|
|
757
|
+
return (VP8LDecoder.average2(t tr))
|
|
758
|
+
}
|
|
759
|
+
if (mode == 10) {
|
|
760
|
+
return (VP8LDecoder.average2((VP8LDecoder.average2(l tl)) (VP8LDecoder.average2(t tr))))
|
|
761
|
+
}
|
|
762
|
+
if (mode == 11) {
|
|
763
|
+
return (VP8LDecoder.select(t l tl))
|
|
764
|
+
}
|
|
765
|
+
if (mode == 12) {
|
|
766
|
+
return (VP8LDecoder.clampAddSubtractFull(l t tl))
|
|
767
|
+
}
|
|
768
|
+
if (mode == 13) {
|
|
769
|
+
return (VP8LDecoder.clampAddSubtractHalf((VP8LDecoder.average2(l t)) tl))
|
|
770
|
+
}
|
|
771
|
+
return -16777216
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
fn inversePredictor:void (px:int_buffer w:int h:int bits:int modes:int_buffer) {
|
|
775
|
+
def tilesPerRow:int (VP8LDecoder.subSampleSize(w bits))
|
|
776
|
+
def y:int 0
|
|
777
|
+
while (y < h) {
|
|
778
|
+
def row:int (y * w)
|
|
779
|
+
def x:int 0
|
|
780
|
+
while (x < w) {
|
|
781
|
+
def i:int (row + x)
|
|
782
|
+
def pred:int 0
|
|
783
|
+
if (y == 0) {
|
|
784
|
+
if (x == 0) {
|
|
785
|
+
pred = -16777216
|
|
786
|
+
} {
|
|
787
|
+
pred = (int_buffer_get px (i - 1))
|
|
788
|
+
}
|
|
789
|
+
} {
|
|
790
|
+
if (x == 0) {
|
|
791
|
+
pred = (int_buffer_get px (i - w))
|
|
792
|
+
} {
|
|
793
|
+
def mode:int (bit_and (bit_shr (int_buffer_get modes (((bit_shr y bits) * tilesPerRow) + (bit_shr x bits))) 8) 15)
|
|
794
|
+
statPredModes = (bit_or statPredModes (bit_shl 1 mode))
|
|
795
|
+
pred = (VP8LDecoder.predict(mode (int_buffer_get px (i - 1)) (int_buffer_get px (i - w)) (int_buffer_get px ((i - w) - 1)) (int_buffer_get px ((i - w) + 1))))
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
int_buffer_set px i (VP8LDecoder.addPixels((int_buffer_get px i) pred))
|
|
799
|
+
x = x + 1
|
|
800
|
+
}
|
|
801
|
+
y = y + 1
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
sfn toInt8:int (v:int) {
|
|
806
|
+
if (v >= 128) {
|
|
807
|
+
return (v - 256)
|
|
808
|
+
}
|
|
809
|
+
return v
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
sfn colorDelta:int (pred:int color:int) {
|
|
813
|
+
return (bit_shr ((VP8LDecoder.toInt8(pred)) * (VP8LDecoder.toInt8(color))) 5)
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
fn inverseCrossColor:void (px:int_buffer w:int h:int bits:int mult:int_buffer) {
|
|
817
|
+
def tilesPerRow:int (VP8LDecoder.subSampleSize(w bits))
|
|
818
|
+
def y:int 0
|
|
819
|
+
while (y < h) {
|
|
820
|
+
def row:int (y * w)
|
|
821
|
+
def tileRow:int ((bit_shr y bits) * tilesPerRow)
|
|
822
|
+
def x:int 0
|
|
823
|
+
while (x < w) {
|
|
824
|
+
def m:int (int_buffer_get mult (tileRow + (bit_shr x bits)))
|
|
825
|
+
def g2r:int (bit_and m 255)
|
|
826
|
+
def g2b:int (bit_and (bit_shr m 8) 255)
|
|
827
|
+
def r2b:int (bit_and (bit_shr m 16) 255)
|
|
828
|
+
def p:int (int_buffer_get px (row + x))
|
|
829
|
+
def green:int (bit_and (bit_shr p 8) 255)
|
|
830
|
+
def red:int (bit_and ((bit_and (bit_shr p 16) 255) + (VP8LDecoder.colorDelta(g2r green))) 255)
|
|
831
|
+
def blue:int (bit_and p 255)
|
|
832
|
+
blue = (bit_and (blue + (VP8LDecoder.colorDelta(g2b green)) + (VP8LDecoder.colorDelta(r2b red))) 255)
|
|
833
|
+
int_buffer_set px (row + x) (bit_or (bit_and p -16711936) (bit_or (bit_shl red 16) blue))
|
|
834
|
+
x = x + 1
|
|
835
|
+
}
|
|
836
|
+
y = y + 1
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
fn inverseSubtractGreen:void (px:int_buffer n:int) {
|
|
841
|
+
def i:int 0
|
|
842
|
+
while (i < n) {
|
|
843
|
+
def p:int (int_buffer_get px i)
|
|
844
|
+
def green:int (bit_and (bit_shr p 8) 255)
|
|
845
|
+
def red:int (bit_and ((bit_and (bit_shr p 16) 255) + green) 255)
|
|
846
|
+
def blue:int (bit_and ((bit_and p 255) + green) 255)
|
|
847
|
+
int_buffer_set px i (bit_or (bit_and p -16711936) (bit_or (bit_shl red 16) blue))
|
|
848
|
+
i = i + 1
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
; packed indices (width packedW) -> colors (width w)
|
|
853
|
+
fn inverseColorIndex:int_buffer (px:int_buffer w:int h:int bits:int palette:int_buffer) {
|
|
854
|
+
def out:int_buffer (int_buffer_alloc (w * h))
|
|
855
|
+
def packedW:int (VP8LDecoder.subSampleSize(w bits))
|
|
856
|
+
def bitsPerPixel:int (bit_shr 8 bits)
|
|
857
|
+
def countMask:int ((bit_shl 1 bits) - 1)
|
|
858
|
+
def bitMask:int ((bit_shl 1 bitsPerPixel) - 1)
|
|
859
|
+
def y:int 0
|
|
860
|
+
while (y < h) {
|
|
861
|
+
def src:int (y * packedW)
|
|
862
|
+
def dst:int (y * w)
|
|
863
|
+
def packed:int 0
|
|
864
|
+
def x:int 0
|
|
865
|
+
while (x < w) {
|
|
866
|
+
if ((bit_and x countMask) == 0) {
|
|
867
|
+
packed = (bit_and (bit_shr (int_buffer_get px src) 8) 255)
|
|
868
|
+
src = src + 1
|
|
869
|
+
}
|
|
870
|
+
int_buffer_set out (dst + x) (int_buffer_get palette (bit_and packed bitMask))
|
|
871
|
+
packed = (bit_shr packed bitsPerPixel)
|
|
872
|
+
x = x + 1
|
|
873
|
+
}
|
|
874
|
+
y = y + 1
|
|
875
|
+
}
|
|
876
|
+
return out
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
; ======================================================================
|
|
880
|
+
; Streams
|
|
881
|
+
; ======================================================================
|
|
882
|
+
|
|
883
|
+
; A level 0 image: transforms, then the main entropy-coded image, then the
|
|
884
|
+
; transforms undone in reverse order. Returns w * h ARGB pixels.
|
|
885
|
+
fn decodeLevel0:int_buffer (w:int h:int) {
|
|
886
|
+
def empty:int_buffer (int_buffer_alloc 0)
|
|
887
|
+
def types:int_buffer (int_buffer_alloc 4)
|
|
888
|
+
def tbits:int_buffer (int_buffer_alloc 4)
|
|
889
|
+
def widths:int_buffer (int_buffer_alloc 4)
|
|
890
|
+
def data0:int_buffer (int_buffer_alloc 0)
|
|
891
|
+
def data1:int_buffer (int_buffer_alloc 0)
|
|
892
|
+
def data3:int_buffer (int_buffer_alloc 0)
|
|
893
|
+
def seen:int 0
|
|
894
|
+
def count:int 0
|
|
895
|
+
def xsize:int w
|
|
896
|
+
while ((this.readBits(1)) == 1) {
|
|
897
|
+
def t:int (this.readBits(2))
|
|
898
|
+
if ((bit_and seen (bit_shl 1 t)) != 0) {
|
|
899
|
+
this.fail("transform repeated")
|
|
900
|
+
return empty
|
|
901
|
+
}
|
|
902
|
+
seen = (bit_or seen (bit_shl 1 t))
|
|
903
|
+
statTransforms = (bit_or statTransforms (bit_shl 1 t))
|
|
904
|
+
int_buffer_set types count t
|
|
905
|
+
int_buffer_set widths count xsize
|
|
906
|
+
if ((t == 0) || (t == 1)) {
|
|
907
|
+
def b:int ((this.readBits(3)) + 2)
|
|
908
|
+
int_buffer_set tbits count b
|
|
909
|
+
def sub:int_buffer (this.decodeImageData((VP8LDecoder.subSampleSize(xsize b)) (VP8LDecoder.subSampleSize(h b)) false))
|
|
910
|
+
if ((strlen error) > 0) {
|
|
911
|
+
return empty
|
|
912
|
+
}
|
|
913
|
+
if (t == 0) {
|
|
914
|
+
data0 = sub
|
|
915
|
+
} {
|
|
916
|
+
data1 = sub
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
if (t == 3) {
|
|
920
|
+
def numColors:int ((this.readBits(8)) + 1)
|
|
921
|
+
def b:int 0
|
|
922
|
+
if (numColors <= 16) {
|
|
923
|
+
b = 1
|
|
924
|
+
}
|
|
925
|
+
if (numColors <= 4) {
|
|
926
|
+
b = 2
|
|
927
|
+
}
|
|
928
|
+
if (numColors <= 2) {
|
|
929
|
+
b = 3
|
|
930
|
+
}
|
|
931
|
+
int_buffer_set tbits count b
|
|
932
|
+
statBundleBits = b
|
|
933
|
+
def pal:int_buffer (this.decodeImageData(numColors 1 false))
|
|
934
|
+
if ((strlen error) > 0) {
|
|
935
|
+
return empty
|
|
936
|
+
}
|
|
937
|
+
; the palette is delta coded; entries past it are transparent black
|
|
938
|
+
def palSize:int (bit_shl 1 (bit_shr 8 b))
|
|
939
|
+
def full:int_buffer (int_buffer_alloc palSize)
|
|
940
|
+
def prev:int 0
|
|
941
|
+
def k:int 0
|
|
942
|
+
while (k < numColors) {
|
|
943
|
+
prev = (VP8LDecoder.addPixels(prev (int_buffer_get pal k)))
|
|
944
|
+
int_buffer_set full k prev
|
|
945
|
+
k = k + 1
|
|
946
|
+
}
|
|
947
|
+
data3 = full
|
|
948
|
+
xsize = (VP8LDecoder.subSampleSize(xsize b))
|
|
949
|
+
}
|
|
950
|
+
count = count + 1
|
|
951
|
+
}
|
|
952
|
+
if eos {
|
|
953
|
+
this.fail("truncated transforms")
|
|
954
|
+
return empty
|
|
955
|
+
}
|
|
956
|
+
def px:int_buffer (this.decodeImageData(xsize h true))
|
|
957
|
+
if ((strlen error) > 0) {
|
|
958
|
+
return empty
|
|
959
|
+
}
|
|
960
|
+
def j:int (count - 1)
|
|
961
|
+
while (j >= 0) {
|
|
962
|
+
def t:int (int_buffer_get types j)
|
|
963
|
+
def tw:int (int_buffer_get widths j)
|
|
964
|
+
if (t == 0) {
|
|
965
|
+
this.inversePredictor(px tw h (int_buffer_get tbits j) data0)
|
|
966
|
+
}
|
|
967
|
+
if (t == 1) {
|
|
968
|
+
this.inverseCrossColor(px tw h (int_buffer_get tbits j) data1)
|
|
969
|
+
}
|
|
970
|
+
if (t == 2) {
|
|
971
|
+
this.inverseSubtractGreen(px (tw * h))
|
|
972
|
+
}
|
|
973
|
+
if (t == 3) {
|
|
974
|
+
px = (this.inverseColorIndex(px tw h (int_buffer_get tbits j) data3))
|
|
975
|
+
}
|
|
976
|
+
j = j - 1
|
|
977
|
+
}
|
|
978
|
+
return px
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
fn resetStats:void () {
|
|
982
|
+
statTransforms = 0
|
|
983
|
+
statPredModes = 0
|
|
984
|
+
statCacheBits = 0
|
|
985
|
+
statGroups = 0
|
|
986
|
+
statSimpleCodes = 0
|
|
987
|
+
statNormalCodes = 0
|
|
988
|
+
statBackRefs = 0
|
|
989
|
+
statCacheHits = 0
|
|
990
|
+
statBundleBits = -1
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
; Decodes a VP8L chunk payload (signature byte and header included).
|
|
994
|
+
; On success `argb`, `width`, `height` and `hasAlpha` are set.
|
|
995
|
+
fn decode:boolean (src:buffer start:int size:int maxDim:int) {
|
|
996
|
+
error = ""
|
|
997
|
+
this.resetStats()
|
|
998
|
+
if (size < 5) {
|
|
999
|
+
return (this.fail("VP8L chunk too small"))
|
|
1000
|
+
}
|
|
1001
|
+
this.initBits(src start size)
|
|
1002
|
+
if ((this.readBits(8)) != 47) {
|
|
1003
|
+
return (this.fail("bad VP8L signature"))
|
|
1004
|
+
}
|
|
1005
|
+
width = (this.readBits(14)) + 1
|
|
1006
|
+
height = (this.readBits(14)) + 1
|
|
1007
|
+
hasAlpha = ((this.readBits(1)) == 1)
|
|
1008
|
+
if ((this.readBits(3)) != 0) {
|
|
1009
|
+
return (this.fail("unsupported VP8L version"))
|
|
1010
|
+
}
|
|
1011
|
+
if ((width > maxDim) || (height > maxDim) || (((to_double width) * (to_double height)) > (to_double maxPixels))) {
|
|
1012
|
+
return (this.fail("image too large"))
|
|
1013
|
+
}
|
|
1014
|
+
argb = (this.decodeLevel0(width height))
|
|
1015
|
+
if ((strlen error) > 0) {
|
|
1016
|
+
return false
|
|
1017
|
+
}
|
|
1018
|
+
return true
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
; Decodes the headerless VP8L stream of a compressed ALPH chunk; `argb`
|
|
1022
|
+
; then holds w * h pixels whose green channel is the alpha value.
|
|
1023
|
+
fn decodeAlphaStream:boolean (src:buffer start:int size:int w:int h:int) {
|
|
1024
|
+
error = ""
|
|
1025
|
+
this.resetStats()
|
|
1026
|
+
this.initBits(src start size)
|
|
1027
|
+
width = w
|
|
1028
|
+
height = h
|
|
1029
|
+
argb = (this.decodeLevel0(w h))
|
|
1030
|
+
if ((strlen error) > 0) {
|
|
1031
|
+
return false
|
|
1032
|
+
}
|
|
1033
|
+
return true
|
|
1034
|
+
}
|
|
1035
|
+
}
|