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,706 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; ImageBuffer.rgr - Raw RGBA pixel buffer for image manipulation
|
|
4
|
+
; Provides a simple interface for pixel operations
|
|
5
|
+
;
|
|
6
|
+
; Note: JPEG decoding/encoding requires complex algorithms (DCT, Huffman, quantization).
|
|
7
|
+
; This module works with raw pixel data and uses PPM format for I/O (simple, uncompressed).
|
|
8
|
+
|
|
9
|
+
Import "Buffer.rgr"
|
|
10
|
+
|
|
11
|
+
class Color {
|
|
12
|
+
def r:int 0
|
|
13
|
+
def g:int 0
|
|
14
|
+
def b:int 0
|
|
15
|
+
def a:int 255
|
|
16
|
+
|
|
17
|
+
Constructor () {
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fn setRGB:void (red:int green:int blue:int) {
|
|
21
|
+
r = red
|
|
22
|
+
g = green
|
|
23
|
+
b = blue
|
|
24
|
+
a = 255
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
fn setRGBA:void (red:int green:int blue:int alpha:int) {
|
|
28
|
+
r = red
|
|
29
|
+
g = green
|
|
30
|
+
b = blue
|
|
31
|
+
a = alpha
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fn clamp:int (val:int) {
|
|
35
|
+
if (val < 0) { return 0 }
|
|
36
|
+
if (val > 255) { return 255 }
|
|
37
|
+
return val
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fn set:void (red:int green:int blue:int) {
|
|
41
|
+
r = (this.clamp(red))
|
|
42
|
+
g = (this.clamp(green))
|
|
43
|
+
b = (this.clamp(blue))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fn grayscale:int () {
|
|
47
|
+
; Luminance formula: 0.299*R + 0.587*G + 0.114*B
|
|
48
|
+
; Using integer approximation: (77*R + 150*G + 29*B) >> 8
|
|
49
|
+
return (bit_shr ((r * 77) + (g * 150) + (b * 29)) 8)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fn toGrayscale:void () {
|
|
53
|
+
def gray:int (this.grayscale())
|
|
54
|
+
r = gray
|
|
55
|
+
g = gray
|
|
56
|
+
b = gray
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn invert:void () {
|
|
60
|
+
r = 255 - r
|
|
61
|
+
g = 255 - g
|
|
62
|
+
b = 255 - b
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
fn adjustBrightness:void (amount:int) {
|
|
66
|
+
r = (this.clamp(r + amount))
|
|
67
|
+
g = (this.clamp(g + amount))
|
|
68
|
+
b = (this.clamp(b + amount))
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
class ImageBuffer {
|
|
73
|
+
def width:int 0
|
|
74
|
+
def height:int 0
|
|
75
|
+
def pixels:buffer (buffer_alloc 0)
|
|
76
|
+
|
|
77
|
+
Constructor () {
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
fn init:void (w:int h:int) {
|
|
81
|
+
width = w
|
|
82
|
+
height = h
|
|
83
|
+
def size:int (w * h * 4)
|
|
84
|
+
pixels = (buffer_alloc size)
|
|
85
|
+
this.fill(255 255 255 255)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
; Allocate RGBA storage without initializing pixels (caller fills).
|
|
89
|
+
fn initClear:void (w:int h:int) {
|
|
90
|
+
width = w
|
|
91
|
+
height = h
|
|
92
|
+
pixels = (buffer_alloc (w * h * 4))
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fn fillTransparent:void () {
|
|
96
|
+
def size:int (width * height * 4)
|
|
97
|
+
buffer_fill pixels 0 0 size
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fn getPixelOffset:int (x:int y:int) {
|
|
101
|
+
return ((y * width) + x) * 4
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
fn isValidCoord:boolean (x:int y:int) {
|
|
105
|
+
if (x < 0) { return false }
|
|
106
|
+
if (y < 0) { return false }
|
|
107
|
+
if (x >= width) { return false }
|
|
108
|
+
if (y >= height) { return false }
|
|
109
|
+
return true
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
fn getPixel:Color (x:int y:int) {
|
|
113
|
+
def c (new Color())
|
|
114
|
+
if (this.isValidCoord(x y)) {
|
|
115
|
+
def off:int (this.getPixelOffset(x y))
|
|
116
|
+
c.r = (buffer_get pixels off)
|
|
117
|
+
c.g = (buffer_get pixels (off + 1))
|
|
118
|
+
c.b = (buffer_get pixels (off + 2))
|
|
119
|
+
c.a = (buffer_get pixels (off + 3))
|
|
120
|
+
}
|
|
121
|
+
return c
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
fn setPixel:void (x:int y:int c:Color) {
|
|
125
|
+
if (this.isValidCoord(x y)) {
|
|
126
|
+
def off:int (this.getPixelOffset(x y))
|
|
127
|
+
buffer_set pixels off c.r
|
|
128
|
+
buffer_set pixels (off + 1) c.g
|
|
129
|
+
buffer_set pixels (off + 2) c.b
|
|
130
|
+
buffer_set pixels (off + 3) c.a
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
fn setPixelRGB:void (x:int y:int r:int g:int b:int) {
|
|
135
|
+
if (this.isValidCoord(x y)) {
|
|
136
|
+
def off:int (this.getPixelOffset(x y))
|
|
137
|
+
buffer_set pixels off r
|
|
138
|
+
buffer_set pixels (off + 1) g
|
|
139
|
+
buffer_set pixels (off + 2) b
|
|
140
|
+
buffer_set pixels (off + 3) 255
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
fn setPixelRGBA:void (x:int y:int r:int g:int b:int a:int) {
|
|
145
|
+
if (this.isValidCoord(x y)) {
|
|
146
|
+
def off:int (this.getPixelOffset(x y))
|
|
147
|
+
buffer_set pixels off r
|
|
148
|
+
buffer_set pixels (off + 1) g
|
|
149
|
+
buffer_set pixels (off + 2) b
|
|
150
|
+
buffer_set pixels (off + 3) a
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
fn getRawBuffer:buffer () {
|
|
155
|
+
return pixels
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
fn fill:void (r:int g:int b:int a:int) {
|
|
159
|
+
def size:int (width * height * 4)
|
|
160
|
+
def i 0
|
|
161
|
+
while (i < size) {
|
|
162
|
+
buffer_set pixels i r
|
|
163
|
+
buffer_set pixels (i + 1) g
|
|
164
|
+
buffer_set pixels (i + 2) b
|
|
165
|
+
buffer_set pixels (i + 3) a
|
|
166
|
+
i = i + 4
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
fn fillRect:void (x:int y:int w:int h:int c:Color) {
|
|
171
|
+
def endX:int (x + w)
|
|
172
|
+
def endY:int (y + h)
|
|
173
|
+
def py:int y
|
|
174
|
+
while (py < endY) {
|
|
175
|
+
def px:int x
|
|
176
|
+
while (px < endX) {
|
|
177
|
+
this.setPixel(px py c)
|
|
178
|
+
px = px + 1
|
|
179
|
+
}
|
|
180
|
+
py = py + 1
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
; Image operations
|
|
185
|
+
|
|
186
|
+
fn invert:void () {
|
|
187
|
+
def size:int (width * height)
|
|
188
|
+
def i 0
|
|
189
|
+
while (i < size) {
|
|
190
|
+
def off:int (i * 4)
|
|
191
|
+
def r:int (buffer_get pixels off)
|
|
192
|
+
def g:int (buffer_get pixels (off + 1))
|
|
193
|
+
def b:int (buffer_get pixels (off + 2))
|
|
194
|
+
buffer_set pixels off (255 - r)
|
|
195
|
+
buffer_set pixels (off + 1) (255 - g)
|
|
196
|
+
buffer_set pixels (off + 2) (255 - b)
|
|
197
|
+
i = i + 1
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
fn grayscale:void () {
|
|
202
|
+
def size:int (width * height)
|
|
203
|
+
def i 0
|
|
204
|
+
while (i < size) {
|
|
205
|
+
def off:int (i * 4)
|
|
206
|
+
def r:int (buffer_get pixels off)
|
|
207
|
+
def g:int (buffer_get pixels (off + 1))
|
|
208
|
+
def b:int (buffer_get pixels (off + 2))
|
|
209
|
+
; Luminance: (77*R + 150*G + 29*B) >> 8
|
|
210
|
+
def gray:int (bit_shr ((r * 77) + (g * 150) + (b * 29)) 8)
|
|
211
|
+
buffer_set pixels off gray
|
|
212
|
+
buffer_set pixels (off + 1) gray
|
|
213
|
+
buffer_set pixels (off + 2) gray
|
|
214
|
+
i = i + 1
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
fn adjustBrightness:void (amount:int) {
|
|
219
|
+
def size:int (width * height)
|
|
220
|
+
def i 0
|
|
221
|
+
while (i < size) {
|
|
222
|
+
def off:int (i * 4)
|
|
223
|
+
def r:int (buffer_get pixels off)
|
|
224
|
+
def g:int (buffer_get pixels (off + 1))
|
|
225
|
+
def b:int (buffer_get pixels (off + 2))
|
|
226
|
+
r = r + amount
|
|
227
|
+
g = g + amount
|
|
228
|
+
b = b + amount
|
|
229
|
+
if (r < 0) { r = 0 }
|
|
230
|
+
if (r > 255) { r = 255 }
|
|
231
|
+
if (g < 0) { g = 0 }
|
|
232
|
+
if (g > 255) { g = 255 }
|
|
233
|
+
if (b < 0) { b = 0 }
|
|
234
|
+
if (b > 255) { b = 255 }
|
|
235
|
+
buffer_set pixels off r
|
|
236
|
+
buffer_set pixels (off + 1) g
|
|
237
|
+
buffer_set pixels (off + 2) b
|
|
238
|
+
i = i + 1
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
fn threshold:void (level:int) {
|
|
243
|
+
; Convert to black and white based on threshold
|
|
244
|
+
def size:int (width * height)
|
|
245
|
+
def i 0
|
|
246
|
+
while (i < size) {
|
|
247
|
+
def off:int (i * 4)
|
|
248
|
+
def r:int (buffer_get pixels off)
|
|
249
|
+
def g:int (buffer_get pixels (off + 1))
|
|
250
|
+
def b:int (buffer_get pixels (off + 2))
|
|
251
|
+
def gray:int (bit_shr ((r * 77) + (g * 150) + (b * 29)) 8)
|
|
252
|
+
def val:int 0
|
|
253
|
+
if (gray >= level) {
|
|
254
|
+
val = 255
|
|
255
|
+
}
|
|
256
|
+
buffer_set pixels off val
|
|
257
|
+
buffer_set pixels (off + 1) val
|
|
258
|
+
buffer_set pixels (off + 2) val
|
|
259
|
+
i = i + 1
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
fn sepia:void () {
|
|
264
|
+
; Sepia tone effect
|
|
265
|
+
def size:int (width * height)
|
|
266
|
+
def i 0
|
|
267
|
+
while (i < size) {
|
|
268
|
+
def off:int (i * 4)
|
|
269
|
+
def r:int (buffer_get pixels off)
|
|
270
|
+
def g:int (buffer_get pixels (off + 1))
|
|
271
|
+
def b:int (buffer_get pixels (off + 2))
|
|
272
|
+
; Sepia formula (integer approximation)
|
|
273
|
+
def newR:int (bit_shr ((r * 101) + (g * 197) + (b * 48)) 8)
|
|
274
|
+
def newG:int (bit_shr ((r * 89) + (g * 175) + (b * 43)) 8)
|
|
275
|
+
def newB:int (bit_shr ((r * 70) + (g * 137) + (b * 33)) 8)
|
|
276
|
+
if (newR > 255) { newR = 255 }
|
|
277
|
+
if (newG > 255) { newG = 255 }
|
|
278
|
+
if (newB > 255) { newB = 255 }
|
|
279
|
+
buffer_set pixels off newR
|
|
280
|
+
buffer_set pixels (off + 1) newG
|
|
281
|
+
buffer_set pixels (off + 2) newB
|
|
282
|
+
i = i + 1
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
fn flipHorizontal:void () {
|
|
287
|
+
def y 0
|
|
288
|
+
while (y < height) {
|
|
289
|
+
def x 0
|
|
290
|
+
def halfW:int (bit_shr width 1)
|
|
291
|
+
while (x < halfW) {
|
|
292
|
+
def x2:int ((width - 1) - x)
|
|
293
|
+
def off1:int (this.getPixelOffset(x y))
|
|
294
|
+
def off2:int (this.getPixelOffset(x2 y))
|
|
295
|
+
; Swap pixels
|
|
296
|
+
def r1:int (buffer_get pixels off1)
|
|
297
|
+
def g1:int (buffer_get pixels (off1 + 1))
|
|
298
|
+
def b1:int (buffer_get pixels (off1 + 2))
|
|
299
|
+
def a1:int (buffer_get pixels (off1 + 3))
|
|
300
|
+
def r2:int (buffer_get pixels off2)
|
|
301
|
+
def g2:int (buffer_get pixels (off2 + 1))
|
|
302
|
+
def b2:int (buffer_get pixels (off2 + 2))
|
|
303
|
+
def a2:int (buffer_get pixels (off2 + 3))
|
|
304
|
+
buffer_set pixels off1 r2
|
|
305
|
+
buffer_set pixels (off1 + 1) g2
|
|
306
|
+
buffer_set pixels (off1 + 2) b2
|
|
307
|
+
buffer_set pixels (off1 + 3) a2
|
|
308
|
+
buffer_set pixels off2 r1
|
|
309
|
+
buffer_set pixels (off2 + 1) g1
|
|
310
|
+
buffer_set pixels (off2 + 2) b1
|
|
311
|
+
buffer_set pixels (off2 + 3) a1
|
|
312
|
+
x = x + 1
|
|
313
|
+
}
|
|
314
|
+
y = y + 1
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
fn flipVertical:void () {
|
|
319
|
+
def y 0
|
|
320
|
+
def halfH:int (bit_shr height 1)
|
|
321
|
+
while (y < halfH) {
|
|
322
|
+
def y2:int ((height - 1) - y)
|
|
323
|
+
def x 0
|
|
324
|
+
while (x < width) {
|
|
325
|
+
def off1:int (this.getPixelOffset(x y))
|
|
326
|
+
def off2:int (this.getPixelOffset(x y2))
|
|
327
|
+
; Swap pixels
|
|
328
|
+
def r1:int (buffer_get pixels off1)
|
|
329
|
+
def g1:int (buffer_get pixels (off1 + 1))
|
|
330
|
+
def b1:int (buffer_get pixels (off1 + 2))
|
|
331
|
+
def a1:int (buffer_get pixels (off1 + 3))
|
|
332
|
+
def r2:int (buffer_get pixels off2)
|
|
333
|
+
def g2:int (buffer_get pixels (off2 + 1))
|
|
334
|
+
def b2:int (buffer_get pixels (off2 + 2))
|
|
335
|
+
def a2:int (buffer_get pixels (off2 + 3))
|
|
336
|
+
buffer_set pixels off1 r2
|
|
337
|
+
buffer_set pixels (off1 + 1) g2
|
|
338
|
+
buffer_set pixels (off1 + 2) b2
|
|
339
|
+
buffer_set pixels (off1 + 3) a2
|
|
340
|
+
buffer_set pixels off2 r1
|
|
341
|
+
buffer_set pixels (off2 + 1) g1
|
|
342
|
+
buffer_set pixels (off2 + 2) b1
|
|
343
|
+
buffer_set pixels (off2 + 3) a1
|
|
344
|
+
x = x + 1
|
|
345
|
+
}
|
|
346
|
+
y = y + 1
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
; Drawing primitives
|
|
351
|
+
|
|
352
|
+
fn drawLine:void (x1:int y1:int x2:int y2:int c:Color) {
|
|
353
|
+
; Bresenham's line algorithm
|
|
354
|
+
def dx:int (x2 - x1)
|
|
355
|
+
def dy:int (y2 - y1)
|
|
356
|
+
if (dx < 0) { dx = 0 - dx }
|
|
357
|
+
if (dy < 0) { dy = 0 - dy }
|
|
358
|
+
|
|
359
|
+
def sx:int 1
|
|
360
|
+
if (x1 > x2) { sx = -1 }
|
|
361
|
+
def sy:int 1
|
|
362
|
+
if (y1 > y2) { sy = -1 }
|
|
363
|
+
|
|
364
|
+
def err:int (dx - dy)
|
|
365
|
+
def x:int x1
|
|
366
|
+
def y:int y1
|
|
367
|
+
|
|
368
|
+
def done:boolean false
|
|
369
|
+
while (done == false) {
|
|
370
|
+
this.setPixel(x y c)
|
|
371
|
+
if ((x == x2) && (y == y2)) {
|
|
372
|
+
done = true
|
|
373
|
+
} {
|
|
374
|
+
def e2:int (err * 2)
|
|
375
|
+
if (e2 > (0 - dy)) {
|
|
376
|
+
err = err - dy
|
|
377
|
+
x = x + sx
|
|
378
|
+
}
|
|
379
|
+
if (e2 < dx) {
|
|
380
|
+
err = err + dx
|
|
381
|
+
y = y + sy
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
fn drawRect:void (x:int y:int w:int h:int c:Color) {
|
|
388
|
+
this.drawLine(x y (x + w - 1) y c)
|
|
389
|
+
this.drawLine((x + w - 1) y (x + w - 1) (y + h - 1) c)
|
|
390
|
+
this.drawLine((x + w - 1) (y + h - 1) x (y + h - 1) c)
|
|
391
|
+
this.drawLine(x (y + h - 1) x y c)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
fn scale:ImageBuffer (factor:int) {
|
|
395
|
+
; Scale image by integer factor (nearest neighbor)
|
|
396
|
+
def newW:int (width * factor)
|
|
397
|
+
def newH:int (height * factor)
|
|
398
|
+
return (this.scaleToSize(newW newH))
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
fn scaleToSize:ImageBuffer (newW:int newH:int) {
|
|
402
|
+
; Scale image to specific size using bilinear interpolation
|
|
403
|
+
def result (new ImageBuffer())
|
|
404
|
+
result.init(newW newH)
|
|
405
|
+
|
|
406
|
+
def scaleX:double ((to_double width) / (to_double newW))
|
|
407
|
+
def scaleY:double ((to_double height) / (to_double newH))
|
|
408
|
+
|
|
409
|
+
def destY 0
|
|
410
|
+
while (destY < newH) {
|
|
411
|
+
def srcYf:double ((to_double destY) * scaleY)
|
|
412
|
+
def srcY0:int (to_int srcYf)
|
|
413
|
+
def srcY1:int (srcY0 + 1)
|
|
414
|
+
if (srcY1 >= height) { srcY1 = (height - 1) }
|
|
415
|
+
def fy:double (srcYf - (to_double srcY0))
|
|
416
|
+
|
|
417
|
+
def destX 0
|
|
418
|
+
while (destX < newW) {
|
|
419
|
+
def srcXf:double ((to_double destX) * scaleX)
|
|
420
|
+
def srcX0:int (to_int srcXf)
|
|
421
|
+
def srcX1:int (srcX0 + 1)
|
|
422
|
+
if (srcX1 >= width) { srcX1 = (width - 1) }
|
|
423
|
+
def fx:double (srcXf - (to_double srcX0))
|
|
424
|
+
|
|
425
|
+
; Bilinear interpolation
|
|
426
|
+
def off00:int (((srcY0 * width) + srcX0) * 4)
|
|
427
|
+
def off01:int (((srcY0 * width) + srcX1) * 4)
|
|
428
|
+
def off10:int (((srcY1 * width) + srcX0) * 4)
|
|
429
|
+
def off11:int (((srcY1 * width) + srcX1) * 4)
|
|
430
|
+
|
|
431
|
+
; Interpolate each channel
|
|
432
|
+
def r:int (this.bilinear(
|
|
433
|
+
(buffer_get pixels off00)
|
|
434
|
+
(buffer_get pixels off01)
|
|
435
|
+
(buffer_get pixels off10)
|
|
436
|
+
(buffer_get pixels off11)
|
|
437
|
+
fx fy))
|
|
438
|
+
def g:int (this.bilinear(
|
|
439
|
+
(buffer_get pixels (off00 + 1))
|
|
440
|
+
(buffer_get pixels (off01 + 1))
|
|
441
|
+
(buffer_get pixels (off10 + 1))
|
|
442
|
+
(buffer_get pixels (off11 + 1))
|
|
443
|
+
fx fy))
|
|
444
|
+
def b:int (this.bilinear(
|
|
445
|
+
(buffer_get pixels (off00 + 2))
|
|
446
|
+
(buffer_get pixels (off01 + 2))
|
|
447
|
+
(buffer_get pixels (off10 + 2))
|
|
448
|
+
(buffer_get pixels (off11 + 2))
|
|
449
|
+
fx fy))
|
|
450
|
+
def a:int (this.bilinear(
|
|
451
|
+
(buffer_get pixels (off00 + 3))
|
|
452
|
+
(buffer_get pixels (off01 + 3))
|
|
453
|
+
(buffer_get pixels (off10 + 3))
|
|
454
|
+
(buffer_get pixels (off11 + 3))
|
|
455
|
+
fx fy))
|
|
456
|
+
|
|
457
|
+
; Write to destination
|
|
458
|
+
def destOff:int (((destY * newW) + destX) * 4)
|
|
459
|
+
buffer_set result.pixels destOff r
|
|
460
|
+
buffer_set result.pixels (destOff + 1) g
|
|
461
|
+
buffer_set result.pixels (destOff + 2) b
|
|
462
|
+
buffer_set result.pixels (destOff + 3) a
|
|
463
|
+
destX = destX + 1
|
|
464
|
+
}
|
|
465
|
+
destY = destY + 1
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return result
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
fn bilinear:int (v00:int v01:int v10:int v11:int fx:double fy:double) {
|
|
472
|
+
; Bilinear interpolation helper
|
|
473
|
+
def top:double ((to_double v00) * (1.0 - fx) + (to_double v01) * fx)
|
|
474
|
+
def bottom:double ((to_double v10) * (1.0 - fx) + (to_double v11) * fx)
|
|
475
|
+
def result:double (top * (1.0 - fy) + bottom * fy)
|
|
476
|
+
return (to_int result)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
fn rotate90CW:ImageBuffer () {
|
|
480
|
+
; Rotate 90 degrees clockwise
|
|
481
|
+
; New dimensions: width becomes height, height becomes width
|
|
482
|
+
def result (new ImageBuffer())
|
|
483
|
+
result.init(height width)
|
|
484
|
+
|
|
485
|
+
def y 0
|
|
486
|
+
while (y < height) {
|
|
487
|
+
def x 0
|
|
488
|
+
while (x < width) {
|
|
489
|
+
; Source pixel at (x, y) goes to (height-1-y, x) in destination
|
|
490
|
+
; After 90 CW: newX = height - 1 - y, newY = x
|
|
491
|
+
def newX:int (height - 1 - y)
|
|
492
|
+
def newY:int x
|
|
493
|
+
|
|
494
|
+
def srcOff:int (((y * width) + x) * 4)
|
|
495
|
+
def destOff:int (((newY * height) + newX) * 4)
|
|
496
|
+
|
|
497
|
+
buffer_set result.pixels destOff (buffer_get pixels srcOff)
|
|
498
|
+
buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
|
|
499
|
+
buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
|
|
500
|
+
buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
|
|
501
|
+
|
|
502
|
+
x = x + 1
|
|
503
|
+
}
|
|
504
|
+
y = y + 1
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return result
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
fn rotate180:ImageBuffer () {
|
|
511
|
+
; Rotate 180 degrees
|
|
512
|
+
def result (new ImageBuffer())
|
|
513
|
+
result.init(width height)
|
|
514
|
+
|
|
515
|
+
def y 0
|
|
516
|
+
while (y < height) {
|
|
517
|
+
def x 0
|
|
518
|
+
while (x < width) {
|
|
519
|
+
def newX:int (width - 1 - x)
|
|
520
|
+
def newY:int (height - 1 - y)
|
|
521
|
+
|
|
522
|
+
def srcOff:int (((y * width) + x) * 4)
|
|
523
|
+
def destOff:int (((newY * width) + newX) * 4)
|
|
524
|
+
|
|
525
|
+
buffer_set result.pixels destOff (buffer_get pixels srcOff)
|
|
526
|
+
buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
|
|
527
|
+
buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
|
|
528
|
+
buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
|
|
529
|
+
|
|
530
|
+
x = x + 1
|
|
531
|
+
}
|
|
532
|
+
y = y + 1
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return result
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
fn rotate270CW:ImageBuffer () {
|
|
539
|
+
; Rotate 270 degrees clockwise (= 90 counter-clockwise)
|
|
540
|
+
def result (new ImageBuffer())
|
|
541
|
+
result.init(height width)
|
|
542
|
+
|
|
543
|
+
def y 0
|
|
544
|
+
while (y < height) {
|
|
545
|
+
def x 0
|
|
546
|
+
while (x < width) {
|
|
547
|
+
; After 270 CW (90 CCW): newX = y, newY = width - 1 - x
|
|
548
|
+
def newX:int y
|
|
549
|
+
def newY:int (width - 1 - x)
|
|
550
|
+
|
|
551
|
+
def srcOff:int (((y * width) + x) * 4)
|
|
552
|
+
def destOff:int (((newY * height) + newX) * 4)
|
|
553
|
+
|
|
554
|
+
buffer_set result.pixels destOff (buffer_get pixels srcOff)
|
|
555
|
+
buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
|
|
556
|
+
buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
|
|
557
|
+
buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
|
|
558
|
+
|
|
559
|
+
x = x + 1
|
|
560
|
+
}
|
|
561
|
+
y = y + 1
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return result
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
fn transpose:ImageBuffer () {
|
|
568
|
+
; Transpose: swap x and y (mirror along diagonal)
|
|
569
|
+
def result (new ImageBuffer())
|
|
570
|
+
result.init(height width)
|
|
571
|
+
|
|
572
|
+
def y 0
|
|
573
|
+
while (y < height) {
|
|
574
|
+
def x 0
|
|
575
|
+
while (x < width) {
|
|
576
|
+
def srcOff:int (((y * width) + x) * 4)
|
|
577
|
+
def destOff:int (((x * height) + y) * 4)
|
|
578
|
+
|
|
579
|
+
buffer_set result.pixels destOff (buffer_get pixels srcOff)
|
|
580
|
+
buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
|
|
581
|
+
buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
|
|
582
|
+
buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
|
|
583
|
+
|
|
584
|
+
x = x + 1
|
|
585
|
+
}
|
|
586
|
+
y = y + 1
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
return result
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
fn transverse:ImageBuffer () {
|
|
593
|
+
; Transverse: rotate 90 CW then flip horizontal (or flip vertical then rotate 90 CW)
|
|
594
|
+
def result (new ImageBuffer())
|
|
595
|
+
result.init(height width)
|
|
596
|
+
|
|
597
|
+
def y 0
|
|
598
|
+
while (y < height) {
|
|
599
|
+
def x 0
|
|
600
|
+
while (x < width) {
|
|
601
|
+
; Transverse: newX = height - 1 - y, newY = width - 1 - x... wait
|
|
602
|
+
; Actually: transpose + rotate 180 = newX = y, newY = width - 1 - x
|
|
603
|
+
; No: transverse is anti-diagonal reflection
|
|
604
|
+
; pixel(x,y) -> pixel(height-1-y, width-1-x) in transposed space
|
|
605
|
+
def newX:int (height - 1 - y)
|
|
606
|
+
def newY:int (width - 1 - x)
|
|
607
|
+
|
|
608
|
+
def srcOff:int (((y * width) + x) * 4)
|
|
609
|
+
def destOff:int (((newY * height) + newX) * 4)
|
|
610
|
+
|
|
611
|
+
buffer_set result.pixels destOff (buffer_get pixels srcOff)
|
|
612
|
+
buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
|
|
613
|
+
buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
|
|
614
|
+
buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
|
|
615
|
+
|
|
616
|
+
x = x + 1
|
|
617
|
+
}
|
|
618
|
+
y = y + 1
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
return result
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
fn applyExifOrientation:ImageBuffer (orientation:int) {
|
|
625
|
+
; Apply EXIF orientation correction
|
|
626
|
+
; Orientation values:
|
|
627
|
+
; 1 = Normal (no transform needed)
|
|
628
|
+
; 2 = Flip horizontal
|
|
629
|
+
; 3 = Rotate 180
|
|
630
|
+
; 4 = Flip vertical
|
|
631
|
+
; 5 = Transpose (flip horizontal + rotate 270)
|
|
632
|
+
; 6 = Rotate 90 CW
|
|
633
|
+
; 7 = Transverse (flip horizontal + rotate 90)
|
|
634
|
+
; 8 = Rotate 270 CW (= rotate 90 CCW)
|
|
635
|
+
|
|
636
|
+
if (orientation == 1) {
|
|
637
|
+
; Normal - return copy
|
|
638
|
+
return (this.scale(1))
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
if (orientation == 2) {
|
|
642
|
+
; Flip horizontal
|
|
643
|
+
def result (new ImageBuffer())
|
|
644
|
+
result.init(width height)
|
|
645
|
+
def y 0
|
|
646
|
+
while (y < height) {
|
|
647
|
+
def x 0
|
|
648
|
+
while (x < width) {
|
|
649
|
+
def srcOff:int (((y * width) + x) * 4)
|
|
650
|
+
def destOff:int (((y * width) + (width - 1 - x)) * 4)
|
|
651
|
+
buffer_set result.pixels destOff (buffer_get pixels srcOff)
|
|
652
|
+
buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
|
|
653
|
+
buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
|
|
654
|
+
buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
|
|
655
|
+
x = x + 1
|
|
656
|
+
}
|
|
657
|
+
y = y + 1
|
|
658
|
+
}
|
|
659
|
+
return result
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
if (orientation == 3) {
|
|
663
|
+
return (this.rotate180())
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (orientation == 4) {
|
|
667
|
+
; Flip vertical
|
|
668
|
+
def result (new ImageBuffer())
|
|
669
|
+
result.init(width height)
|
|
670
|
+
def y 0
|
|
671
|
+
while (y < height) {
|
|
672
|
+
def x 0
|
|
673
|
+
while (x < width) {
|
|
674
|
+
def srcOff:int (((y * width) + x) * 4)
|
|
675
|
+
def destOff:int ((((height - 1 - y) * width) + x) * 4)
|
|
676
|
+
buffer_set result.pixels destOff (buffer_get pixels srcOff)
|
|
677
|
+
buffer_set result.pixels (destOff + 1) (buffer_get pixels (srcOff + 1))
|
|
678
|
+
buffer_set result.pixels (destOff + 2) (buffer_get pixels (srcOff + 2))
|
|
679
|
+
buffer_set result.pixels (destOff + 3) (buffer_get pixels (srcOff + 3))
|
|
680
|
+
x = x + 1
|
|
681
|
+
}
|
|
682
|
+
y = y + 1
|
|
683
|
+
}
|
|
684
|
+
return result
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
if (orientation == 5) {
|
|
688
|
+
return (this.transpose())
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
if (orientation == 6) {
|
|
692
|
+
return (this.rotate90CW())
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (orientation == 7) {
|
|
696
|
+
return (this.transverse())
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
if (orientation == 8) {
|
|
700
|
+
return (this.rotate270CW())
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
; Unknown orientation - return copy
|
|
704
|
+
return (this.scale(1))
|
|
705
|
+
}
|
|
706
|
+
}
|