ranger-compiler 3.5.1 → 3.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1064 -20
- package/LICENSE +3 -1
- package/README.md +123 -28
- package/dist/Lang.rgr +1188 -290
- package/dist/api.d.ts +2343 -879
- package/dist/api.js +79923 -56921
- package/dist/lib/JSON.rgr +102 -91
- package/dist/lib/Shell.rgr +4 -4
- package/dist/lib/apple/AppleToolchain.rgr +4 -4
- package/dist/lib/apple/README.md +5 -4
- package/dist/lib/apple/apple_test.rgr +1 -1
- package/dist/lib/core/README.md +1 -1
- package/dist/lib/evg/EVG.rgr +12 -0
- package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
- package/dist/lib/evg/EVGA11yTree.rgr +894 -0
- package/dist/lib/evg/EVGBox.rgr +267 -0
- package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
- package/dist/lib/evg/EVGCodepoint.rgr +316 -0
- package/dist/lib/evg/EVGColor.rgr +700 -0
- package/dist/lib/evg/EVGCommands.rgr +177 -0
- package/dist/lib/evg/EVGComponent.rgr +331 -0
- package/dist/lib/evg/EVGComponentTest.rgr +387 -0
- package/dist/lib/evg/EVGConnector.rgr +541 -0
- package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
- package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
- package/dist/lib/evg/EVGEasing.rgr +370 -0
- package/dist/lib/evg/EVGEffectTest.rgr +253 -0
- package/dist/lib/evg/EVGElement.rgr +4914 -0
- package/dist/lib/evg/EVGFixedTest.rgr +289 -0
- package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
- package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
- package/dist/lib/evg/EVGFling.rgr +244 -0
- package/dist/lib/evg/EVGFocus.rgr +400 -0
- package/dist/lib/evg/EVGFocusTest.rgr +399 -0
- package/dist/lib/evg/EVGGradient.rgr +322 -0
- package/dist/lib/evg/EVGGrapheme.rgr +190 -0
- package/dist/lib/evg/EVGGrid.rgr +975 -0
- package/dist/lib/evg/EVGHitTest.rgr +208 -0
- package/dist/lib/evg/EVGHoles.rgr +294 -0
- package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
- package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
- package/dist/lib/evg/EVGHostTree.rgr +834 -0
- package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
- package/dist/lib/evg/EVGImageDecode.rgr +117 -0
- package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
- package/dist/lib/evg/EVGInspect.rgr +883 -0
- package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
- package/dist/lib/evg/EVGJsonTest.rgr +535 -0
- package/dist/lib/evg/EVGLayout.rgr +4220 -0
- package/dist/lib/evg/EVGMeasure.rgr +1267 -0
- package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
- package/dist/lib/evg/EVGPatch.rgr +1721 -0
- package/dist/lib/evg/EVGPatchTest.rgr +692 -0
- package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
- package/dist/lib/evg/EVGReconcile.rgr +226 -0
- package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
- package/dist/lib/evg/EVGReject.rgr +126 -0
- package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
- package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
- package/dist/lib/evg/EVGRuler.rgr +232 -0
- package/dist/lib/evg/EVGRulerTest.rgr +172 -0
- package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
- package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
- package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
- package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
- package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
- package/dist/lib/evg/EVGText.rgr +105 -0
- package/dist/lib/evg/EVGTextEngine.rgr +536 -0
- package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
- package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
- package/dist/lib/evg/EVGToolbar.rgr +1369 -0
- package/dist/lib/evg/EVGTransition.rgr +728 -0
- package/dist/lib/evg/EVGTreeJson.rgr +721 -0
- package/dist/lib/evg/EVGUnit.rgr +554 -0
- package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
- package/dist/lib/evg/EvgApp.rgr +189 -0
- package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
- package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
- package/dist/lib/evg/EvgHost.rgr +451 -0
- package/dist/lib/evg/EvgTest.rgr +91 -0
- package/dist/lib/evg/EvgTraceColor.rgr +236 -0
- package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
- package/dist/lib/evg/EvgTraceFit.rgr +767 -0
- package/dist/lib/evg/EvgTracePath.rgr +435 -0
- package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
- package/dist/lib/evg/EvgViewport.rgr +313 -0
- package/dist/lib/evg/FxDemoDoc.rgr +185 -0
- package/dist/lib/evg/HOSTS.md +227 -0
- package/dist/lib/evg/ISSUES.md +835 -0
- package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
- package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
- package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
- package/dist/lib/evg/PLAN_EVG.md +518 -0
- package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
- package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
- package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
- package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
- package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
- package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
- package/dist/lib/evg/PathBuilder.rgr +333 -0
- package/dist/lib/evg/README.md +1236 -0
- package/dist/lib/evg/SPEC.md +1252 -0
- package/dist/lib/evg/SVGPathParser.rgr +1199 -0
- package/dist/lib/evg/SvgParser.rgr +1736 -0
- package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
- package/dist/lib/evg/VectorShapes.rgr +331 -0
- package/dist/lib/evg/VectorStroke.rgr +107 -0
- package/dist/lib/evg/VectorViewBox.rgr +380 -0
- package/dist/lib/evg/agent/README.md +290 -0
- package/dist/lib/evg/agent/evg_agent.rgr +899 -0
- package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
- package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
- package/dist/lib/evg/agent/fixtures/connector.css +63 -0
- package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
- package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
- package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
- package/dist/lib/evg/agent/fixtures/popover.css +99 -0
- package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
- package/dist/lib/evg/agent/roundtrip.sh +74 -0
- package/dist/lib/evg/agent/smoke.sh +230 -0
- package/dist/lib/evg/android/README.md +97 -0
- package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
- package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
- package/dist/lib/evg/android/androidstubs/App.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
- package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
- package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
- package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
- package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
- package/dist/lib/evg/android/androidstubs/View.kt +113 -0
- package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
- package/dist/lib/evg/apple/README.md +128 -0
- package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
- package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
- package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
- package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
- package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
- package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
- package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
- package/dist/lib/evg/bench/README.md +64 -0
- package/dist/lib/evg/bench/layout-bench.mjs +316 -0
- package/dist/lib/evg/bench/layout-cases.mjs +510 -0
- package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
- package/dist/lib/evg/bin/.gitignore +17 -0
- package/dist/lib/evg/evg_test.rgr +313 -0
- package/dist/lib/evg/gl/README.md +198 -0
- package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
- package/dist/lib/evg/gl/blur-check.mjs +399 -0
- package/dist/lib/evg/gl/boxmodel.json +1 -0
- package/dist/lib/evg/gl/demo.html +46 -0
- package/dist/lib/evg/gl/effect-presets.css +285 -0
- package/dist/lib/evg/gl/effect-presets.js +63 -0
- package/dist/lib/evg/gl/effect-shots.mjs +135 -0
- package/dist/lib/evg/gl/evg-a11y.js +566 -0
- package/dist/lib/evg/gl/evg-binary.js +160 -0
- package/dist/lib/evg/gl/evg-engine.js +296 -0
- package/dist/lib/evg/gl/evg-fx.js +237 -0
- package/dist/lib/evg/gl/evg-gestures.js +209 -0
- package/dist/lib/evg/gl/evg-list.js +167 -0
- package/dist/lib/evg/gl/evg-measure.js +186 -0
- package/dist/lib/evg/gl/evg-textinput.js +303 -0
- package/dist/lib/evg/gl/evg-view.js +144 -0
- package/dist/lib/evg/gl/evg-webgl.js +3942 -0
- package/dist/lib/evg/gl/fx-check.mjs +998 -0
- package/dist/lib/evg/gl/fx-demo.html +166 -0
- package/dist/lib/evg/gl/fx-demo.js +2 -0
- package/dist/lib/evg/gl/fx-serve.mjs +47 -0
- package/dist/lib/evg/gl/gestures-check.mjs +189 -0
- package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
- package/dist/lib/evg/gl/measure-check.mjs +135 -0
- package/dist/lib/evg/gl/rotation-check.mjs +207 -0
- package/dist/lib/evg/gl/shift-check.mjs +113 -0
- package/dist/lib/evg/gl/stroke-check.mjs +168 -0
- package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
- package/dist/lib/evg/gl/view-check.mjs +343 -0
- package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
- package/dist/lib/evg/html/evg-dom.js +318 -0
- package/dist/lib/evg/html/evg-html.js +600 -0
- package/dist/lib/evg/inspect/README.md +415 -0
- package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
- package/dist/lib/evg/inspect/evg-inspect.js +947 -0
- package/dist/lib/evg/inspect/shots/css.png +0 -0
- package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
- package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
- package/dist/lib/evg/inspect/shots/state.png +0 -0
- package/dist/lib/evg/inspect/shots.mjs +226 -0
- package/dist/lib/evg/oracle/css-blur.json +576 -0
- package/dist/lib/evg/oracle/css-box.json +157 -0
- package/dist/lib/evg/oracle/css-timing.json +709 -0
- package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
- package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
- package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
- package/dist/lib/evg/original/EVGColor.clj +310 -0
- package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
- package/dist/lib/evg/original/SVGPath.rgr +627 -0
- package/dist/lib/evg/original/Vec2.crgr +103 -0
- package/dist/lib/evg/ranger.json +9 -0
- package/dist/lib/evg/showcase/README.md +246 -0
- package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
- package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
- package/dist/lib/evg/showcase/build.mjs +651 -0
- package/dist/lib/evg/showcase/pages/album.tsx +30 -0
- package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
- package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
- package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
- package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
- package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
- package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
- package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
- package/dist/lib/evg/showcase/pages/more.tsx +332 -0
- package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
- package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
- package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
- package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
- package/dist/lib/evg/showcase/pages/units.tsx +35 -0
- package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
- package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
- package/dist/lib/evg/showcase/pages/views.tsx +223 -0
- package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
- package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
- package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
- package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
- package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
- package/dist/lib/evg/showcase/themes/more-default.css +128 -0
- package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
- package/dist/lib/evg/showcase/themes/showcase.css +508 -0
- package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
- package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
- package/dist/lib/evg/showcase/themes/views-default.css +15 -0
- package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
- package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
- package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
- package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
- package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
- package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
- package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
- package/dist/lib/evg/web/responsive/README.md +97 -0
- package/dist/lib/evg/web/responsive/build.mjs +90 -0
- package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
- package/dist/lib/evg/web/responsive/index.html +177 -0
- package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
- package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
- package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
- package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
- package/dist/lib/evg/web/tools/minify.mjs +60 -0
- package/dist/lib/evg/web/tracer/build.mjs +87 -0
- package/dist/lib/evg/web/tracer/index.html +2805 -0
- package/dist/lib/evg/web/tracer/sample.png +0 -0
- package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
- package/dist/lib/evgr/Cargo.lock +21 -0
- package/dist/lib/evgr/Cargo.toml +19 -0
- package/dist/lib/evgr/README.md +140 -0
- package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
- package/dist/lib/evgr/bench/compare.mjs +252 -0
- package/dist/lib/evgr/bench/speed.mjs +277 -0
- package/dist/lib/evgr/bin/.gitignore +3 -0
- package/dist/lib/evgr/src/bin/bench.rs +106 -0
- package/dist/lib/evgr/src/bin/smoke.rs +13 -0
- package/dist/lib/evgr/src/grid.rs +730 -0
- package/dist/lib/evgr/src/lib.rs +1003 -0
- package/dist/lib/evgr/src/style.rs +468 -0
- package/dist/lib/evgr/src/text.rs +83 -0
- package/dist/lib/image/BitReader.rgr +171 -0
- package/dist/lib/image/Buffer.rgr +173 -0
- package/dist/lib/image/DCT.rgr +283 -0
- package/dist/lib/image/Deflate.rgr +339 -0
- package/dist/lib/image/HuffmanDecoder.rgr +181 -0
- package/dist/lib/image/ImageBuffer.rgr +706 -0
- package/dist/lib/image/JPEGDecoder.rgr +808 -0
- package/dist/lib/image/PNGDecoder.rgr +544 -0
- package/dist/lib/image/PNGEncoder.rgr +388 -0
- package/dist/lib/image/PPMImage.rgr +224 -0
- package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
- package/dist/lib/image/README.md +33 -0
- package/dist/lib/image/RasterBuffer.rgr +294 -0
- package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
- package/dist/lib/image/WebPDecoder.rgr +433 -0
- package/dist/lib/image/WebPLossless.rgr +1035 -0
- package/dist/lib/image/WebPLossy.rgr +1929 -0
- package/dist/lib/image/ranger.json +9 -0
- package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
- package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
- package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
- package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
- package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
- package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
- package/dist/lib/image/tests/run_webp_tests.sh +39 -0
- package/dist/lib/rust/RsJson.rgr +468 -0
- package/dist/lib/rust/RsPrelude.rgr +1663 -0
- package/dist/lib/shell_test.rgr +7 -7
- package/dist/lib/stdlib.rgr +21 -5
- package/dist/lib/zip/ranger.json +6 -0
- package/dist/rgrc.js +87318 -67610
- package/package.json +1010 -1040
- package/dist/README.md +0 -117
- package/dist/package.json +0 -47
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; ==============================================================================
|
|
4
|
+
; EVGOverlayTest — surfaces that leave the flow but not the tree
|
|
5
|
+
; ==============================================================================
|
|
6
|
+
;
|
|
7
|
+
; An overlay is a menu's dropdown, a tooltip, a popover: a box that has to paint
|
|
8
|
+
; above the page and sit next to something, without becoming a child of some
|
|
9
|
+
; overlay root. Here it stays exactly where it was put — still its parent's
|
|
10
|
+
; child, still the owner of its subtree — and only layout and paint treat it
|
|
11
|
+
; differently. That is the difference between this and a portal, and the reason
|
|
12
|
+
; events, ownership and the accessibility walk keep working.
|
|
13
|
+
;
|
|
14
|
+
; What is asserted, in order of how badly each one bites when it is wrong:
|
|
15
|
+
;
|
|
16
|
+
; * an overlay takes no space in its parent's flow, so a menu is as wide as
|
|
17
|
+
; its trigger and not as wide as the panel hanging off it;
|
|
18
|
+
; * it is placed against its anchor, which it finds among its own siblings;
|
|
19
|
+
; * an overlay INSIDE another overlay anchors to the moved rectangle, which
|
|
20
|
+
; is what makes a submenu work with no submenu case anywhere;
|
|
21
|
+
; * a surface with no anchor is REPORTED. Silently at (0,0) it looks like a
|
|
22
|
+
; stylesheet mistake and is not one;
|
|
23
|
+
; * it PAINTS above the page, not merely later in the tree — a menu whose
|
|
24
|
+
; trigger comes first must still cover the menu next to it;
|
|
25
|
+
; * and a click in the area it covers HITS IT, not what is underneath, which
|
|
26
|
+
; is the same rule as painting and is therefore the same list;
|
|
27
|
+
; * near an edge it FLIPS to the other side of its anchor and SHIFTS along
|
|
28
|
+
; the edge, because a menu drawn half off the page is worse than a menu
|
|
29
|
+
; drawn above its trigger.
|
|
30
|
+
; ==============================================================================
|
|
31
|
+
|
|
32
|
+
Import "EVGElement.rgr"
|
|
33
|
+
Import "EVGUnit.rgr"
|
|
34
|
+
Import "EVGLayout.rgr"
|
|
35
|
+
Import "EVGDisplayList.rgr"
|
|
36
|
+
Import "EVGHitTest.rgr"
|
|
37
|
+
|
|
38
|
+
class OverlayCheck {
|
|
39
|
+
def passed:int 0
|
|
40
|
+
def failed:int 0
|
|
41
|
+
|
|
42
|
+
fn ok:void (name:string cond:boolean) {
|
|
43
|
+
if cond {
|
|
44
|
+
passed = (passed + 1)
|
|
45
|
+
print (" PASS " + name)
|
|
46
|
+
} {
|
|
47
|
+
failed = (failed + 1)
|
|
48
|
+
print (" FAIL " + name)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fn eqStr:void (name:string got:string want:string) {
|
|
53
|
+
def good:boolean (got == want)
|
|
54
|
+
if (good == false) {
|
|
55
|
+
print (" got '" + got + "' want '" + want + "'")
|
|
56
|
+
}
|
|
57
|
+
this.ok(name good)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
fn eqInt:void (name:string got:int want:int) {
|
|
61
|
+
def good:boolean (got == want)
|
|
62
|
+
if (good == false) {
|
|
63
|
+
print (" got " + (to_string got) + " want " + (to_string want))
|
|
64
|
+
}
|
|
65
|
+
this.ok(name good)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
class EVGOverlayTest {
|
|
70
|
+
|
|
71
|
+
sfn box:EVGElement (id:string cls:string w:double h:double) {
|
|
72
|
+
def el (EVGElement.createDiv())
|
|
73
|
+
el.id = id
|
|
74
|
+
el.className = cls
|
|
75
|
+
el.setAttribute("width" ((to_string (to_int w)) + "px"))
|
|
76
|
+
el.setAttribute("height" ((to_string (to_int h)) + "px"))
|
|
77
|
+
return el
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
sfn laidOut:EVGLayout (root:EVGElement) {
|
|
81
|
+
def lay (new EVGLayout())
|
|
82
|
+
lay.setPageSize(800.0 600.0)
|
|
83
|
+
lay.layout(root)
|
|
84
|
+
return lay
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
; A menu: a page holding a row, holding a menu, holding a trigger and the
|
|
88
|
+
; surface that hangs off it.
|
|
89
|
+
sfn buildMenu:EVGElement (withAnchor:boolean) {
|
|
90
|
+
def page:EVGElement (EVGOverlayTest.box("page" "page" 800.0 600.0))
|
|
91
|
+
def row:EVGElement (EVGOverlayTest.box("row" "row" 400.0 40.0))
|
|
92
|
+
row.setAttribute("display" "flex")
|
|
93
|
+
row.setAttribute("flex-direction" "row")
|
|
94
|
+
row.setAttribute("flex-wrap" "nowrap")
|
|
95
|
+
|
|
96
|
+
def menu:EVGElement (EVGElement.createDiv())
|
|
97
|
+
menu.id = "menu"
|
|
98
|
+
menu.setAttribute("display" "flex")
|
|
99
|
+
menu.setAttribute("flex-direction" "column")
|
|
100
|
+
menu.setAttribute("width" "fit-content")
|
|
101
|
+
|
|
102
|
+
def trigger:EVGElement (EVGOverlayTest.box("trigger" "trigger" 60.0 30.0))
|
|
103
|
+
if withAnchor {
|
|
104
|
+
trigger.setAttribute("overlay-anchor-role" "true")
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
def surface:EVGElement (EVGOverlayTest.box("surface" "surface" 200.0 120.0))
|
|
108
|
+
surface.setAttribute("overlay" "true")
|
|
109
|
+
surface.setAttribute("overlay-side" "bottom")
|
|
110
|
+
surface.setAttribute("overlay-align" "start")
|
|
111
|
+
surface.setAttribute("overlay-gap" "4")
|
|
112
|
+
|
|
113
|
+
menu.addChild(trigger)
|
|
114
|
+
menu.addChild(surface)
|
|
115
|
+
row.addChild(menu)
|
|
116
|
+
page.addChild(row)
|
|
117
|
+
return page
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
; Breadth-first over a worklist rather than a recursive search: Ranger will
|
|
121
|
+
; not resolve a static that returns an optional and calls itself, which is
|
|
122
|
+
; noted next to UiHost.findEl for the same reason.
|
|
123
|
+
; Not called `at`: that is a Ranger operator, and a static of the same
|
|
124
|
+
; name does not resolve.
|
|
125
|
+
sfn nodeById:EVGElement (root:EVGElement id:string) {
|
|
126
|
+
def work:[EVGElement]
|
|
127
|
+
push work root
|
|
128
|
+
def i:int 0
|
|
129
|
+
while (i < (array_length work)) {
|
|
130
|
+
def el:EVGElement (itemAt work i)
|
|
131
|
+
if (el.id == id) {
|
|
132
|
+
return el
|
|
133
|
+
}
|
|
134
|
+
def j:int 0
|
|
135
|
+
while (j < (array_length el.children)) {
|
|
136
|
+
push work (itemAt el.children j)
|
|
137
|
+
j = (j + 1)
|
|
138
|
+
}
|
|
139
|
+
i = (i + 1)
|
|
140
|
+
}
|
|
141
|
+
; A miss returns an empty element, so a wrong id fails an assertion
|
|
142
|
+
; rather than taking the process down.
|
|
143
|
+
return (EVGElement.createDiv())
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
sfn testOutOfFlow:void (c:OverlayCheck) {
|
|
147
|
+
print "--- an overlay takes no space in its parent's flow ---"
|
|
148
|
+
def page:EVGElement (EVGOverlayTest.buildMenu(true))
|
|
149
|
+
EVGOverlayTest.laidOut(page)
|
|
150
|
+
def menu:EVGElement (EVGOverlayTest.nodeById(page "menu"))
|
|
151
|
+
; The menu holds a 60px trigger and a 200px surface. If the surface were
|
|
152
|
+
; in the flow the menu would be 200 wide; it is the trigger's width.
|
|
153
|
+
c.eqInt("the menu is as wide as its trigger" (to_int menu.calculatedWidth) 60)
|
|
154
|
+
c.eqInt("and as tall" (to_int menu.calculatedHeight) 30)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
sfn testPlacement:void (c:OverlayCheck) {
|
|
158
|
+
print "--- a surface is placed against its anchor ---"
|
|
159
|
+
def page:EVGElement (EVGOverlayTest.buildMenu(true))
|
|
160
|
+
EVGOverlayTest.laidOut(page)
|
|
161
|
+
def trigger:EVGElement (EVGOverlayTest.nodeById(page "trigger"))
|
|
162
|
+
def surface:EVGElement (EVGOverlayTest.nodeById(page "surface"))
|
|
163
|
+
; bottom + start + a 4px gap
|
|
164
|
+
c.eqInt("left edges line up" (to_int surface.calculatedX) (to_int trigger.calculatedX))
|
|
165
|
+
c.eqInt("and it sits under the trigger, past the gap"
|
|
166
|
+
(to_int surface.calculatedY)
|
|
167
|
+
(to_int ((trigger.calculatedY + trigger.calculatedHeight) + 4.0)))
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
sfn testSubtreeTravels:void (c:OverlayCheck) {
|
|
171
|
+
print "--- the surface's children travel with it ---"
|
|
172
|
+
def page:EVGElement (EVGOverlayTest.buildMenu(true))
|
|
173
|
+
def surface:EVGElement (EVGOverlayTest.nodeById(page "surface"))
|
|
174
|
+
; To the RIGHT, so the surface moves along BOTH axes: a surface that
|
|
175
|
+
; only ever moves down would let a child that stayed behind
|
|
176
|
+
; horizontally pass this unnoticed.
|
|
177
|
+
surface.setAttribute("overlay-side" "right")
|
|
178
|
+
def kid:EVGElement (EVGOverlayTest.box("kid" "kid" 100.0 20.0))
|
|
179
|
+
surface.addChild(kid)
|
|
180
|
+
EVGOverlayTest.laidOut(page)
|
|
181
|
+
def s2:EVGElement (EVGOverlayTest.nodeById(page "surface"))
|
|
182
|
+
def k2:EVGElement (EVGOverlayTest.nodeById(page "kid"))
|
|
183
|
+
; The child was laid out inside the surface before the surface moved.
|
|
184
|
+
; If the move did not take it along it would be left behind at the top.
|
|
185
|
+
c.ok("the child is inside its surface" (k2.calculatedY >= s2.calculatedY))
|
|
186
|
+
c.eqInt("and moved sideways with it too" (to_int k2.calculatedX) (to_int s2.calculatedX))
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
; THE PASS THAT SKIPS. `placeOverlaysIn` no longer walks every element:
|
|
190
|
+
; a subtree the layout KEPT moved whole, so a surface inside it moved with
|
|
191
|
+
; the anchor it sits against, and the pass takes the answer it cached
|
|
192
|
+
; rather than descending. That saving is worth nothing if it puts a
|
|
193
|
+
; surface in the wrong place, and the way it would fail is quiet — a menu
|
|
194
|
+
; that opens where it opened last time — so it is checked directly:
|
|
195
|
+
;
|
|
196
|
+
; the same tree, laid out twice, with the kept subtree MOVED between
|
|
197
|
+
; the two, must place the surface where a tree that was never kept
|
|
198
|
+
; places it.
|
|
199
|
+
; The same menu, with a spacer of `pad` pixels before it, so the whole
|
|
200
|
+
; thing starts further down the page.
|
|
201
|
+
sfn menuBelow:EVGElement (pad:double) {
|
|
202
|
+
def page:EVGElement (EVGOverlayTest.box("page" "page" 800.0 600.0))
|
|
203
|
+
if (pad > 0.0) {
|
|
204
|
+
page.addChild((EVGOverlayTest.box("spacer" "spacer" 400.0 pad)))
|
|
205
|
+
}
|
|
206
|
+
def built:EVGElement (EVGOverlayTest.buildMenu(true))
|
|
207
|
+
def row:EVGElement (EVGOverlayTest.nodeById(built "row"))
|
|
208
|
+
page.addChild(row)
|
|
209
|
+
return page
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
sfn testKeptSubtree:void (c:OverlayCheck) {
|
|
213
|
+
print "--- a surface inside a subtree the layout kept ---"
|
|
214
|
+
def page:EVGElement (EVGOverlayTest.menuBelow(0.0))
|
|
215
|
+
def menu:EVGElement (EVGOverlayTest.nodeById(page "menu"))
|
|
216
|
+
menu.keepLayout = true
|
|
217
|
+
menu.layoutClean = true
|
|
218
|
+
EVGOverlayTest.laidOut(page)
|
|
219
|
+
; NUMBERS, not elements: the tree is the same objects on both sides of
|
|
220
|
+
; the move, so an element held across it reads the new value.
|
|
221
|
+
def s1:EVGElement (EVGOverlayTest.nodeById(page "surface"))
|
|
222
|
+
def t1:EVGElement (EVGOverlayTest.nodeById(page "trigger"))
|
|
223
|
+
def t1y:double t1.calculatedY
|
|
224
|
+
def gap1:int (to_int (s1.calculatedY - t1.calculatedY))
|
|
225
|
+
def dx1:int (to_int (s1.calculatedX - t1.calculatedX))
|
|
226
|
+
c.ok("it is placed the first time" (gap1 > 0))
|
|
227
|
+
|
|
228
|
+
; Now MOVE it: the row it sits in is pushed down and across, so the
|
|
229
|
+
; kept subtree arrives somewhere else. If the skip were wrong the
|
|
230
|
+
; surface would keep its old absolute position and the gap would open.
|
|
231
|
+
def moved:EVGElement (EVGOverlayTest.box("page" "page" 800.0 600.0))
|
|
232
|
+
moved.addChild((EVGOverlayTest.box("spacer" "spacer" 400.0 70.0)))
|
|
233
|
+
def keptRow:EVGElement (EVGOverlayTest.nodeById(page "row"))
|
|
234
|
+
moved.addChild(keptRow)
|
|
235
|
+
EVGOverlayTest.laidOut(moved)
|
|
236
|
+
def page2:EVGElement moved
|
|
237
|
+
def s2:EVGElement (EVGOverlayTest.nodeById(page2 "surface"))
|
|
238
|
+
def t2:EVGElement (EVGOverlayTest.nodeById(page2 "trigger"))
|
|
239
|
+
c.ok("the trigger moved down" (t2.calculatedY > t1y))
|
|
240
|
+
c.eqInt("and the surface kept its distance from it"
|
|
241
|
+
(to_int (s2.calculatedY - t2.calculatedY)) gap1)
|
|
242
|
+
c.eqInt("on the other axis too"
|
|
243
|
+
(to_int (s2.calculatedX - t2.calculatedX)) dx1)
|
|
244
|
+
|
|
245
|
+
; And a tree that never kept anything must agree, which is what makes
|
|
246
|
+
; the two paths one behaviour rather than two.
|
|
247
|
+
def plain:EVGElement (EVGOverlayTest.menuBelow(70.0))
|
|
248
|
+
EVGOverlayTest.laidOut(plain)
|
|
249
|
+
def s3:EVGElement (EVGOverlayTest.nodeById(plain "surface"))
|
|
250
|
+
c.eqInt("the slow path puts it in the same place"
|
|
251
|
+
(to_int s2.calculatedY) (to_int s3.calculatedY))
|
|
252
|
+
c.eqInt("and at the same x" (to_int s2.calculatedX) (to_int s3.calculatedX))
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
; The one that makes a submenu ordinary: a surface whose anchor is itself
|
|
256
|
+
; inside another surface, and therefore has already been moved.
|
|
257
|
+
sfn testNested:void (c:OverlayCheck) {
|
|
258
|
+
print "--- a surface inside a surface anchors to the moved rectangle ---"
|
|
259
|
+
def page:EVGElement (EVGOverlayTest.buildMenu(true))
|
|
260
|
+
def surface:EVGElement (EVGOverlayTest.nodeById(page "surface"))
|
|
261
|
+
|
|
262
|
+
def sub:EVGElement (EVGElement.createDiv())
|
|
263
|
+
sub.id = "submenu"
|
|
264
|
+
sub.setAttribute("display" "flex")
|
|
265
|
+
sub.setAttribute("flex-direction" "column")
|
|
266
|
+
sub.setAttribute("width" "fit-content")
|
|
267
|
+
|
|
268
|
+
def subRow:EVGElement (EVGOverlayTest.box("subrow" "subrow" 80.0 20.0))
|
|
269
|
+
subRow.setAttribute("overlay-anchor-role" "true")
|
|
270
|
+
def subSurface:EVGElement (EVGOverlayTest.box("subsurface" "subsurface" 150.0 60.0))
|
|
271
|
+
subSurface.setAttribute("overlay" "true")
|
|
272
|
+
subSurface.setAttribute("overlay-side" "right")
|
|
273
|
+
subSurface.setAttribute("overlay-align" "start")
|
|
274
|
+
subSurface.setAttribute("overlay-gap" "4")
|
|
275
|
+
sub.addChild(subRow)
|
|
276
|
+
sub.addChild(subSurface)
|
|
277
|
+
surface.addChild(sub)
|
|
278
|
+
|
|
279
|
+
EVGOverlayTest.laidOut(page)
|
|
280
|
+
def row2:EVGElement (EVGOverlayTest.nodeById(page "subrow"))
|
|
281
|
+
def surf2:EVGElement (EVGOverlayTest.nodeById(page "subsurface"))
|
|
282
|
+
c.eqInt("it opens to the right of its row, past the gap"
|
|
283
|
+
(to_int surf2.calculatedX)
|
|
284
|
+
(to_int ((row2.calculatedX + row2.calculatedWidth) + 4.0)))
|
|
285
|
+
c.eqInt("and lines up with it" (to_int surf2.calculatedY) (to_int row2.calculatedY))
|
|
286
|
+
; The outer surface moved down by the trigger's height plus the gap, so
|
|
287
|
+
; a submenu anchored to the pre-move rectangle would be 34px too high.
|
|
288
|
+
c.ok("which is BELOW the menu bar, not at the top of the page" (surf2.calculatedY > 30.0))
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
sfn testUnanchored:void (c:OverlayCheck) {
|
|
292
|
+
print "--- a surface with no anchor is reported ---"
|
|
293
|
+
def page:EVGElement (EVGOverlayTest.buildMenu(false))
|
|
294
|
+
def lay:EVGLayout (EVGOverlayTest.laidOut(page))
|
|
295
|
+
def errs:[string] (lay.getOverlayErrors())
|
|
296
|
+
c.eqInt("one error" (array_length errs) 1)
|
|
297
|
+
if ((array_length errs) > 0) {
|
|
298
|
+
def msg:string (itemAt errs 0)
|
|
299
|
+
c.ok("naming the surface" ((indexOf msg "surface") >= 0))
|
|
300
|
+
c.ok("and saying what to do" ((indexOf msg "overlay-anchor-role") >= 0))
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
sfn testCentered:void (c:OverlayCheck) {
|
|
305
|
+
print "--- a centred surface needs no anchor ---"
|
|
306
|
+
def page:EVGElement (EVGOverlayTest.box("page" "page" 800.0 600.0))
|
|
307
|
+
def modal:EVGElement (EVGOverlayTest.box("modal" "modal" 200.0 100.0))
|
|
308
|
+
modal.setAttribute("overlay" "true")
|
|
309
|
+
modal.setAttribute("overlay-side" "center")
|
|
310
|
+
page.addChild(modal)
|
|
311
|
+
def lay:EVGLayout (EVGOverlayTest.laidOut(page))
|
|
312
|
+
def m:EVGElement (EVGOverlayTest.nodeById(page "modal"))
|
|
313
|
+
c.eqInt("centred across" (to_int m.calculatedX) 300)
|
|
314
|
+
c.eqInt("and down" (to_int m.calculatedY) 250)
|
|
315
|
+
c.eqInt("with nothing reported" (array_length (lay.getOverlayErrors())) 0)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
; ---- paint order and hit testing -----------------------------------------
|
|
319
|
+
; Being placed correctly is not enough. A surface that paints in tree order
|
|
320
|
+
; is above the page only by luck of where its menu sits, and a click that
|
|
321
|
+
; walks the tree lands on whatever is UNDER the panel. Both follow from one
|
|
322
|
+
; list: the normal tree, then the surfaces, in the order they opened.
|
|
323
|
+
|
|
324
|
+
; A bar with two menus where the FIRST one is open. Its panel overhangs the
|
|
325
|
+
; second menu's trigger, so tree order paints the trigger on top of the
|
|
326
|
+
; panel and a tree-order hit test answers "trigger" for a point inside the
|
|
327
|
+
; panel. Both are wrong, and both are wrong in the same place.
|
|
328
|
+
sfn buildTwoMenus:EVGElement () {
|
|
329
|
+
def page:EVGElement (EVGOverlayTest.box("page" "page" 800.0 600.0))
|
|
330
|
+
def row:EVGElement (EVGOverlayTest.box("row" "row" 400.0 40.0))
|
|
331
|
+
row.setAttribute("display" "flex")
|
|
332
|
+
row.setAttribute("flex-direction" "row")
|
|
333
|
+
row.setAttribute("flex-wrap" "nowrap")
|
|
334
|
+
|
|
335
|
+
def first:EVGElement (EVGElement.createDiv())
|
|
336
|
+
first.id = "first"
|
|
337
|
+
first.setAttribute("display" "flex")
|
|
338
|
+
first.setAttribute("flex-direction" "column")
|
|
339
|
+
first.setAttribute("width" "fit-content")
|
|
340
|
+
def t1:EVGElement (EVGOverlayTest.box("t1" "trigger" 60.0 30.0))
|
|
341
|
+
t1.setAttribute("overlay-anchor-role" "true")
|
|
342
|
+
def panel:EVGElement (EVGOverlayTest.box("panel" "surface" 200.0 120.0))
|
|
343
|
+
panel.setAttribute("overlay" "true")
|
|
344
|
+
panel.setAttribute("overlay-side" "bottom")
|
|
345
|
+
panel.setAttribute("overlay-align" "start")
|
|
346
|
+
panel.setAttribute("overlay-gap" "4")
|
|
347
|
+
panel.setAttribute("background-color" "#ffffff")
|
|
348
|
+
first.addChild(t1)
|
|
349
|
+
first.addChild(panel)
|
|
350
|
+
|
|
351
|
+
; The second menu is closed — a trigger and nothing else — and it sits
|
|
352
|
+
; beside the first, so the open panel hangs over it.
|
|
353
|
+
def second:EVGElement (EVGElement.createDiv())
|
|
354
|
+
second.id = "second"
|
|
355
|
+
second.setAttribute("display" "flex")
|
|
356
|
+
second.setAttribute("flex-direction" "column")
|
|
357
|
+
second.setAttribute("width" "fit-content")
|
|
358
|
+
def t2:EVGElement (EVGOverlayTest.box("t2" "trigger" 60.0 30.0))
|
|
359
|
+
t2.setAttribute("background-color" "#ff0000")
|
|
360
|
+
t2.setAttribute("height" "300px")
|
|
361
|
+
second.addChild(t2)
|
|
362
|
+
|
|
363
|
+
row.addChild(first)
|
|
364
|
+
row.addChild(second)
|
|
365
|
+
page.addChild(row)
|
|
366
|
+
return page
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
; Where in the display list this element's own background was drawn, or -1.
|
|
370
|
+
sfn rectIndex:int (dl:EVGDisplayList el:EVGElement) {
|
|
371
|
+
def i:int 0
|
|
372
|
+
while (i < (array_length dl.cmds)) {
|
|
373
|
+
def c:EVGDrawCmd (itemAt dl.cmds i)
|
|
374
|
+
if (c.kind == 0) {
|
|
375
|
+
def sameX:boolean ((to_int c.x) == (to_int el.calculatedX))
|
|
376
|
+
def sameY:boolean ((to_int c.y) == (to_int el.calculatedY))
|
|
377
|
+
def sameW:boolean ((to_int c.w) == (to_int el.calculatedWidth))
|
|
378
|
+
if (sameX && (sameY && sameW)) {
|
|
379
|
+
return i
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
i = (i + 1)
|
|
383
|
+
}
|
|
384
|
+
return -1
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
sfn testPaintOrder:void (c:OverlayCheck) {
|
|
388
|
+
print "--- a surface paints above the page, not in tree order ---"
|
|
389
|
+
def page:EVGElement (EVGOverlayTest.buildTwoMenus())
|
|
390
|
+
def lay:EVGLayout (EVGOverlayTest.laidOut(page))
|
|
391
|
+
def dl (new EVGDisplayList())
|
|
392
|
+
dl.setTextEngine((lay.getTextEngine()))
|
|
393
|
+
dl.build(page)
|
|
394
|
+
def panel:EVGElement (EVGOverlayTest.nodeById(page "panel"))
|
|
395
|
+
def t2:EVGElement (EVGOverlayTest.nodeById(page "t2"))
|
|
396
|
+
def pi:int (EVGOverlayTest.rectIndex(dl panel))
|
|
397
|
+
def ti:int (EVGOverlayTest.rectIndex(dl t2))
|
|
398
|
+
c.ok("both were drawn" ((pi >= 0) && (ti >= 0)))
|
|
399
|
+
; The panel's menu comes FIRST in the bar, so tree order draws the
|
|
400
|
+
; second menu's trigger over it.
|
|
401
|
+
c.ok("the panel is drawn after the trigger it overhangs" (pi > ti))
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
sfn testHitTopmost:void (c:OverlayCheck) {
|
|
405
|
+
print "--- a click in the panel hits the panel ---"
|
|
406
|
+
def page:EVGElement (EVGOverlayTest.buildTwoMenus())
|
|
407
|
+
EVGOverlayTest.laidOut(page)
|
|
408
|
+
def panel:EVGElement (EVGOverlayTest.nodeById(page "panel"))
|
|
409
|
+
def hit (new EVGHitTest())
|
|
410
|
+
; A point inside the panel AND inside the trigger beside it: the whole
|
|
411
|
+
; question is which one answers.
|
|
412
|
+
def px:double (panel.calculatedX + 150.0)
|
|
413
|
+
def py:double (panel.calculatedY + 10.0)
|
|
414
|
+
def t2:EVGElement (EVGOverlayTest.nodeById(page "t2"))
|
|
415
|
+
c.ok("the point really is over both" ((px > t2.calculatedX) && (py < (t2.calculatedY + t2.calculatedHeight))))
|
|
416
|
+
c.ok("and the panel answers" ((hit.idAt(page px py)) == "panel"))
|
|
417
|
+
; Outside every surface, the page still answers normally.
|
|
418
|
+
c.ok("a point outside answers the element under it"
|
|
419
|
+
((hit.idAt(page (t2.calculatedX + 10.0) (t2.calculatedY + 200.0))) == "t2"))
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
; ---- collisions ----------------------------------------------------------
|
|
423
|
+
; A menu near the bottom of the page opens upwards. Every real menu does
|
|
424
|
+
; this, and the reason is not aesthetics: the part that falls off the page
|
|
425
|
+
; cannot be clicked or read, so a surface that ignores the edge silently
|
|
426
|
+
; loses rows.
|
|
427
|
+
|
|
428
|
+
; One anchor at a given spot, with a surface hanging off it. The page is
|
|
429
|
+
; 800x600, so putting the anchor near an edge is how the collision is set up.
|
|
430
|
+
sfn buildAt:EVGElement (ax:double ay:double side:string align:string sw:double sh:double) {
|
|
431
|
+
def page:EVGElement (EVGOverlayTest.box("page" "page" 800.0 600.0))
|
|
432
|
+
def holder:EVGElement (EVGElement.createDiv())
|
|
433
|
+
holder.id = "holder"
|
|
434
|
+
holder.setAttribute("position" "absolute")
|
|
435
|
+
holder.setAttribute("left" ((to_string (to_int ax)) + "px"))
|
|
436
|
+
holder.setAttribute("top" ((to_string (to_int ay)) + "px"))
|
|
437
|
+
holder.setAttribute("width" "60px")
|
|
438
|
+
holder.setAttribute("height" "30px")
|
|
439
|
+
|
|
440
|
+
def anchor:EVGElement (EVGOverlayTest.box("anchor" "anchor" 60.0 30.0))
|
|
441
|
+
anchor.setAttribute("overlay-anchor-role" "true")
|
|
442
|
+
def surface:EVGElement (EVGOverlayTest.box("surface" "surface" sw sh))
|
|
443
|
+
surface.setAttribute("overlay" "true")
|
|
444
|
+
surface.setAttribute("overlay-side" side)
|
|
445
|
+
surface.setAttribute("overlay-align" align)
|
|
446
|
+
surface.setAttribute("overlay-gap" "4")
|
|
447
|
+
|
|
448
|
+
holder.addChild(anchor)
|
|
449
|
+
holder.addChild(surface)
|
|
450
|
+
page.addChild(holder)
|
|
451
|
+
return page
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
sfn testFlip:void (c:OverlayCheck) {
|
|
455
|
+
print "--- a surface near an edge opens the other way ---"
|
|
456
|
+
; Room below: nothing moves. This one is here so the flip cannot be a
|
|
457
|
+
; test that passes because the code always flips.
|
|
458
|
+
def roomy:EVGElement (EVGOverlayTest.buildAt(100.0 100.0 "bottom" "start" 200.0 120.0))
|
|
459
|
+
EVGOverlayTest.laidOut(roomy)
|
|
460
|
+
def s1:EVGElement (EVGOverlayTest.nodeById(roomy "surface"))
|
|
461
|
+
def a1:EVGElement (EVGOverlayTest.nodeById(roomy "anchor"))
|
|
462
|
+
c.eqStr("with room, it stays where it was asked to be" s1.overlayPlacedSide "bottom")
|
|
463
|
+
c.eqInt("under the anchor" (to_int s1.calculatedY) (to_int ((a1.calculatedY + a1.calculatedHeight) + 4.0)))
|
|
464
|
+
|
|
465
|
+
; 520 + 30 + 4 + 120 = 674, which is off a 600-tall page.
|
|
466
|
+
def tight:EVGElement (EVGOverlayTest.buildAt(100.0 520.0 "bottom" "start" 200.0 120.0))
|
|
467
|
+
EVGOverlayTest.laidOut(tight)
|
|
468
|
+
def s2:EVGElement (EVGOverlayTest.nodeById(tight "surface"))
|
|
469
|
+
def a2:EVGElement (EVGOverlayTest.nodeById(tight "anchor"))
|
|
470
|
+
c.eqStr("with no room below, it opens upwards" s2.overlayPlacedSide "top")
|
|
471
|
+
c.eqInt("above the anchor, past the gap"
|
|
472
|
+
(to_int s2.calculatedY)
|
|
473
|
+
(to_int ((a2.calculatedY - 120.0) - 4.0)))
|
|
474
|
+
c.ok("and is fully on the page" ((s2.calculatedY >= 0.0) && (((s2.calculatedY + 120.0)) <= 600.0)))
|
|
475
|
+
|
|
476
|
+
; The same, sideways: a submenu at the right edge opens to the left.
|
|
477
|
+
def right:EVGElement (EVGOverlayTest.buildAt(700.0 100.0 "right" "start" 200.0 120.0))
|
|
478
|
+
EVGOverlayTest.laidOut(right)
|
|
479
|
+
def s3:EVGElement (EVGOverlayTest.nodeById(right "surface"))
|
|
480
|
+
def a3:EVGElement (EVGOverlayTest.nodeById(right "anchor"))
|
|
481
|
+
c.eqStr("a submenu at the right edge opens to the left" s3.overlayPlacedSide "left")
|
|
482
|
+
c.eqInt("beside the anchor, past the gap"
|
|
483
|
+
(to_int s3.calculatedX)
|
|
484
|
+
(to_int ((a3.calculatedX - 200.0) - 4.0)))
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
sfn testShift:void (c:OverlayCheck) {
|
|
488
|
+
print "--- and slides along the edge rather than hanging off it ---"
|
|
489
|
+
; Anchored at x=700 with a 200-wide surface aligned to its left edge:
|
|
490
|
+
; 700 + 200 = 900, off an 800-wide page. The side is fine; the CROSS
|
|
491
|
+
; axis is not, and the fix is to slide, not to flip.
|
|
492
|
+
def page:EVGElement (EVGOverlayTest.buildAt(700.0 100.0 "bottom" "start" 200.0 120.0))
|
|
493
|
+
EVGOverlayTest.laidOut(page)
|
|
494
|
+
def s:EVGElement (EVGOverlayTest.nodeById(page "surface"))
|
|
495
|
+
def a:EVGElement (EVGOverlayTest.nodeById(page "anchor"))
|
|
496
|
+
c.eqStr("it is still below" s.overlayPlacedSide "bottom")
|
|
497
|
+
c.eqInt("and its right edge is the page's" (to_int (s.calculatedX + 200.0)) 800)
|
|
498
|
+
; Sliding it back has to keep it attached to what opened it. A panel
|
|
499
|
+
; that no longer overlaps its trigger has stopped being that trigger's.
|
|
500
|
+
c.ok("while still overlapping its anchor"
|
|
501
|
+
((s.calculatedX < (a.calculatedX + a.calculatedWidth)) && ((s.calculatedX + 200.0) > a.calculatedX)))
|
|
502
|
+
; The subtree comes along, as it does for the first placement.
|
|
503
|
+
c.ok("and the move is the whole surface" (s.calculatedX < a.calculatedX))
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
sfn testNoRoomEitherWay:void (c:OverlayCheck) {
|
|
507
|
+
print "--- with no room on either side it takes the roomier one ---"
|
|
508
|
+
; A surface taller than the page cannot fit above or below. Drawing it
|
|
509
|
+
; off the top would lose the first rows, which are the ones a menu puts
|
|
510
|
+
; its most-used item in.
|
|
511
|
+
;
|
|
512
|
+
; The anchor sits at y=300 on a 600-tall page, so there are 296px above
|
|
513
|
+
; it and 266 below: neither is enough for 700, and `top` loses less. It
|
|
514
|
+
; asked for `bottom` and gets `top`, which is the rule doing its job
|
|
515
|
+
; rather than a fits/does-not-fit test.
|
|
516
|
+
def page:EVGElement (EVGOverlayTest.buildAt(100.0 300.0 "bottom" "start" 200.0 700.0))
|
|
517
|
+
EVGOverlayTest.laidOut(page)
|
|
518
|
+
def s:EVGElement (EVGOverlayTest.nodeById(page "surface"))
|
|
519
|
+
c.eqInt("it starts at the top of the page" (to_int s.calculatedY) 0)
|
|
520
|
+
c.eqStr("on the side that loses less" s.overlayPlacedSide "top")
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
; A modal's backdrop: the page itself, not the card the dialog was declared
|
|
524
|
+
; in. This is the case a percentage cannot express — `width: 100%` resolves
|
|
525
|
+
; against the PARENT, and the parent of a dialog is whatever part of the
|
|
526
|
+
; page happened to declare it.
|
|
527
|
+
sfn testCover:void (c:OverlayCheck) {
|
|
528
|
+
print "--- a backdrop covers the page, not its parent ---"
|
|
529
|
+
def page:EVGElement (EVGOverlayTest.box("page" "page" 800.0 600.0))
|
|
530
|
+
def card:EVGElement (EVGOverlayTest.box("card" "card" 200.0 100.0))
|
|
531
|
+
def backdrop:EVGElement (EVGOverlayTest.box("backdrop" "backdrop" 50.0 20.0))
|
|
532
|
+
backdrop.setAttribute("overlay" "true")
|
|
533
|
+
backdrop.setAttribute("overlay-side" "cover")
|
|
534
|
+
def dialog:EVGElement (EVGOverlayTest.box("dialog" "dialog" 300.0 200.0))
|
|
535
|
+
dialog.setAttribute("overlay" "true")
|
|
536
|
+
dialog.setAttribute("overlay-side" "center")
|
|
537
|
+
card.addChild(backdrop)
|
|
538
|
+
card.addChild(dialog)
|
|
539
|
+
page.addChild(card)
|
|
540
|
+
def lay:EVGLayout (EVGOverlayTest.laidOut(page))
|
|
541
|
+
|
|
542
|
+
def b:EVGElement (EVGOverlayTest.nodeById(page "backdrop"))
|
|
543
|
+
c.eqInt("it starts at the page's origin" (to_int (b.calculatedX + b.calculatedY)) 0)
|
|
544
|
+
c.eqInt("as wide as the page" (to_int b.calculatedWidth) 800)
|
|
545
|
+
c.eqInt("and as tall" (to_int b.calculatedHeight) 600)
|
|
546
|
+
def d:EVGElement (EVGOverlayTest.nodeById(page "dialog"))
|
|
547
|
+
c.eqInt("the dialog is centred on the page, not on the card" (to_int d.calculatedX) 250)
|
|
548
|
+
c.eqInt("and down" (to_int d.calculatedY) 200)
|
|
549
|
+
; The card it was declared in is unchanged: a modal takes no space.
|
|
550
|
+
def cd:EVGElement (EVGOverlayTest.nodeById(page "card"))
|
|
551
|
+
c.eqInt("and the card it was declared in is untouched" (to_int cd.calculatedWidth) 200)
|
|
552
|
+
; Painted after everything, and the dialog after the backdrop, so the
|
|
553
|
+
; dim never covers the dialog.
|
|
554
|
+
def hit (new EVGHitTest())
|
|
555
|
+
c.eqStr("a press in the middle hits the dialog" (hit.idAt(page 400.0 300.0)) "dialog")
|
|
556
|
+
c.eqStr("and one at the edge hits the backdrop, not the page behind it"
|
|
557
|
+
(hit.idAt(page 20.0 560.0)) "backdrop")
|
|
558
|
+
c.eqInt("with nothing reported" (array_length (lay.getOverlayErrors())) 0)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
; `fit-content` arrived for a floating panel, where what has to be measured
|
|
562
|
+
; is a column of rows. A badge is the other half of the same idea: a pill
|
|
563
|
+
; that hugs its word, where the content is TEXT and there are no children
|
|
564
|
+
; to measure at all.
|
|
565
|
+
;
|
|
566
|
+
; It already worked, and not through `contentExtent` — which sees no
|
|
567
|
+
; children and gives up — but because `fit-content` parses with `isSet`
|
|
568
|
+
; false, and a width-less box holding only text is measured from the text.
|
|
569
|
+
; That is worth a test rather than a shrug: it is load-bearing for every
|
|
570
|
+
; badge in the sortable demo, and nothing else says so.
|
|
571
|
+
sfn testFitText:void (c:OverlayCheck) {
|
|
572
|
+
print "--- fit-content measures text, not only children ---"
|
|
573
|
+
def page:EVGElement (EVGOverlayTest.box("page" "page" 800.0 600.0))
|
|
574
|
+
def badge:EVGElement (EVGElement.createDiv())
|
|
575
|
+
badge.id = "badge"
|
|
576
|
+
badge.setAttribute("width" "fit-content")
|
|
577
|
+
badge.setAttribute("padding" "4px 12px")
|
|
578
|
+
badge.setAttribute("font-size" "13px")
|
|
579
|
+
badge.textContent = "document"
|
|
580
|
+
def wide:EVGElement (EVGElement.createDiv())
|
|
581
|
+
wide.id = "wide"
|
|
582
|
+
wide.setAttribute("width" "fit-content")
|
|
583
|
+
wide.setAttribute("padding" "4px 12px")
|
|
584
|
+
wide.setAttribute("font-size" "13px")
|
|
585
|
+
wide.textContent = "a much longer label"
|
|
586
|
+
page.addChild(badge)
|
|
587
|
+
page.addChild(wide)
|
|
588
|
+
EVGOverlayTest.laidOut(page)
|
|
589
|
+
|
|
590
|
+
def b:EVGElement (EVGOverlayTest.nodeById(page "badge"))
|
|
591
|
+
def w:EVGElement (EVGOverlayTest.nodeById(page "wide"))
|
|
592
|
+
; Not the page's width, which is what a width-less box gets.
|
|
593
|
+
c.ok("a badge is narrower than the page it sits in" (b.calculatedWidth < 200.0))
|
|
594
|
+
; And wide enough for the word plus its padding: 24px of padding, and a
|
|
595
|
+
; 13px face is never wider than the string times the font size.
|
|
596
|
+
c.ok("but wide enough for its word" (b.calculatedWidth > 40.0))
|
|
597
|
+
c.ok("a longer label is wider" (w.calculatedWidth > b.calculatedWidth))
|
|
598
|
+
c.ok("and still not the whole page" (w.calculatedWidth < 400.0))
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
sfn main:void () {
|
|
602
|
+
def c (new OverlayCheck())
|
|
603
|
+
print "=== EVG overlay surfaces ==="
|
|
604
|
+
EVGOverlayTest.testOutOfFlow(c)
|
|
605
|
+
EVGOverlayTest.testPlacement(c)
|
|
606
|
+
EVGOverlayTest.testSubtreeTravels(c)
|
|
607
|
+
EVGOverlayTest.testKeptSubtree(c)
|
|
608
|
+
EVGOverlayTest.testNested(c)
|
|
609
|
+
EVGOverlayTest.testUnanchored(c)
|
|
610
|
+
EVGOverlayTest.testCentered(c)
|
|
611
|
+
EVGOverlayTest.testPaintOrder(c)
|
|
612
|
+
EVGOverlayTest.testHitTopmost(c)
|
|
613
|
+
EVGOverlayTest.testFlip(c)
|
|
614
|
+
EVGOverlayTest.testShift(c)
|
|
615
|
+
EVGOverlayTest.testNoRoomEitherWay(c)
|
|
616
|
+
EVGOverlayTest.testCover(c)
|
|
617
|
+
EVGOverlayTest.testFitText(c)
|
|
618
|
+
print ""
|
|
619
|
+
print ("passed=" + (to_string c.passed) + " failed=" + (to_string c.failed))
|
|
620
|
+
if (c.failed > 0) {
|
|
621
|
+
print "FAILURES"
|
|
622
|
+
} {
|
|
623
|
+
print "ALL PASS"
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|