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,1003 @@
|
|
|
1
|
+
//! EVGr: the layout of EVG documents as a strict Rust module
|
|
2
|
+
//! (docs/plans/PLAN_RUST_SYNTAX.md), beside the Ranger engine in `lib/evg`.
|
|
3
|
+
//!
|
|
4
|
+
//! An experiment: the same kind of document -- boxes styled with CSS
|
|
5
|
+
//! declarations, laid out as flexbox with EVG's box model and initial values
|
|
6
|
+
//! -- written once in Rust, built by cargo for native code and by `rgrc` for
|
|
7
|
+
//! every Ranger target. `bench/compare.mjs` lays out the cases of
|
|
8
|
+
//! `lib/evg/bench/layout-cases.mjs` with EVG, EVGr and Chromium;
|
|
9
|
+
//! `bench/speed.mjs` and `src/bin/bench.rs` time the fixtures of
|
|
10
|
+
//! `lib/evg/bench/layout-bench.mjs`.
|
|
11
|
+
//!
|
|
12
|
+
//! What is laid out: `display` block / flex / none, `flex-direction` (with
|
|
13
|
+
//! the reverse forms), `flex-wrap`, width / height and their min / max (px,
|
|
14
|
+
//! %), padding, margin (px), gap, `flex-grow` / `flex-shrink` /
|
|
15
|
+
//! `flex-basis` / `flex`, `justify-content`, `align-items`, `align-self`,
|
|
16
|
+
//! `align-content`, `position: absolute` with top / right / bottom / left,
|
|
17
|
+
//! `aspect-ratio`, `calc()` of px and %, grid (src/grid.rs), and text
|
|
18
|
+
//! measured with EVG's default advance table.
|
|
19
|
+
//!
|
|
20
|
+
//! The tree is an arena: a node is an index, its children a list of
|
|
21
|
+
//! indices. Layout writes `x`, `y` (page coordinates), `w` and `h`
|
|
22
|
+
//! (border box: padding is inside, as in EVG).
|
|
23
|
+
|
|
24
|
+
use ranger::prelude::*;
|
|
25
|
+
|
|
26
|
+
mod grid;
|
|
27
|
+
mod style;
|
|
28
|
+
mod text;
|
|
29
|
+
|
|
30
|
+
use style::Len;
|
|
31
|
+
|
|
32
|
+
const INF: double = 1000000000000000000.0;
|
|
33
|
+
|
|
34
|
+
pub struct EvgrNode {
|
|
35
|
+
/// 0 block, 1 flex, 2 none, 3 grid
|
|
36
|
+
pub display: int,
|
|
37
|
+
pub row: bool,
|
|
38
|
+
pub reverse: bool,
|
|
39
|
+
pub wrap: bool,
|
|
40
|
+
pub width: Len,
|
|
41
|
+
pub height: Len,
|
|
42
|
+
pub min_w: Len,
|
|
43
|
+
pub max_w: Len,
|
|
44
|
+
pub min_h: Len,
|
|
45
|
+
pub max_h: Len,
|
|
46
|
+
pub basis: Len,
|
|
47
|
+
pub grow: double,
|
|
48
|
+
pub shrink: double,
|
|
49
|
+
pub pad_t_len: Len,
|
|
50
|
+
pub pad_r_len: Len,
|
|
51
|
+
pub pad_b_len: Len,
|
|
52
|
+
pub pad_l_len: Len,
|
|
53
|
+
/// the padding in pixels, resolved against the containing block
|
|
54
|
+
pub pad_t: double,
|
|
55
|
+
pub pad_r: double,
|
|
56
|
+
pub pad_b: double,
|
|
57
|
+
pub pad_l: double,
|
|
58
|
+
/// `aspect-ratio` as width / height, 0.0 when none
|
|
59
|
+
pub ratio: double,
|
|
60
|
+
// grid: the container's templates, the item's placement
|
|
61
|
+
pub grid_cols: String,
|
|
62
|
+
pub grid_rows: String,
|
|
63
|
+
pub grid_areas: String,
|
|
64
|
+
pub grid_auto_rows: String,
|
|
65
|
+
pub grid_dense: bool,
|
|
66
|
+
pub grid_column: String,
|
|
67
|
+
pub grid_row: String,
|
|
68
|
+
pub grid_area: String,
|
|
69
|
+
pub mar_t: double,
|
|
70
|
+
pub mar_r: double,
|
|
71
|
+
pub mar_b: double,
|
|
72
|
+
pub mar_l: double,
|
|
73
|
+
pub row_gap: double,
|
|
74
|
+
pub col_gap: double,
|
|
75
|
+
pub justify: int,
|
|
76
|
+
pub align_items: int,
|
|
77
|
+
pub align_self: int,
|
|
78
|
+
pub align_content: int,
|
|
79
|
+
pub absolute: bool,
|
|
80
|
+
pub top: Len,
|
|
81
|
+
pub right: Len,
|
|
82
|
+
pub bottom: Len,
|
|
83
|
+
pub left: Len,
|
|
84
|
+
/// the declared font size, -1.0 when inherited
|
|
85
|
+
pub font_size: double,
|
|
86
|
+
pub text: String,
|
|
87
|
+
pub children: Vec<int>,
|
|
88
|
+
pub parent: int,
|
|
89
|
+
// the result
|
|
90
|
+
pub x: double,
|
|
91
|
+
pub y: double,
|
|
92
|
+
pub w: double,
|
|
93
|
+
pub h: double,
|
|
94
|
+
// this pass: the font size in effect, the width it was laid out at and
|
|
95
|
+
// the height it was given (-1.0 auto), the max-content width
|
|
96
|
+
fs: double,
|
|
97
|
+
// the text measured at `text_fs`: its width and its widest word
|
|
98
|
+
text_fs: double,
|
|
99
|
+
text_w: double,
|
|
100
|
+
text_min: double,
|
|
101
|
+
laid: bool,
|
|
102
|
+
lay_w: double,
|
|
103
|
+
max_cw: double,
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
impl EvgrNode {
|
|
107
|
+
pub fn new(parent: int) -> EvgrNode {
|
|
108
|
+
EvgrNode {
|
|
109
|
+
display: 0,
|
|
110
|
+
row: false,
|
|
111
|
+
reverse: false,
|
|
112
|
+
// EVG's initial values: column, wrap, align-items flex-start
|
|
113
|
+
wrap: true,
|
|
114
|
+
width: Len::auto(),
|
|
115
|
+
height: Len::auto(),
|
|
116
|
+
min_w: Len::auto(),
|
|
117
|
+
max_w: Len::auto(),
|
|
118
|
+
min_h: Len::auto(),
|
|
119
|
+
max_h: Len::auto(),
|
|
120
|
+
basis: Len::auto(),
|
|
121
|
+
grow: 0.0,
|
|
122
|
+
shrink: 1.0,
|
|
123
|
+
pad_t_len: Len::px(0.0),
|
|
124
|
+
pad_r_len: Len::px(0.0),
|
|
125
|
+
pad_b_len: Len::px(0.0),
|
|
126
|
+
pad_l_len: Len::px(0.0),
|
|
127
|
+
pad_t: 0.0,
|
|
128
|
+
pad_r: 0.0,
|
|
129
|
+
pad_b: 0.0,
|
|
130
|
+
pad_l: 0.0,
|
|
131
|
+
ratio: 0.0,
|
|
132
|
+
grid_cols: String::new(),
|
|
133
|
+
grid_rows: String::new(),
|
|
134
|
+
grid_areas: String::new(),
|
|
135
|
+
grid_auto_rows: String::new(),
|
|
136
|
+
grid_dense: false,
|
|
137
|
+
grid_column: String::new(),
|
|
138
|
+
grid_row: String::new(),
|
|
139
|
+
grid_area: String::new(),
|
|
140
|
+
mar_t: 0.0,
|
|
141
|
+
mar_r: 0.0,
|
|
142
|
+
mar_b: 0.0,
|
|
143
|
+
mar_l: 0.0,
|
|
144
|
+
row_gap: 0.0,
|
|
145
|
+
col_gap: 0.0,
|
|
146
|
+
justify: style::START,
|
|
147
|
+
align_items: style::UNSET,
|
|
148
|
+
align_self: style::UNSET,
|
|
149
|
+
align_content: style::START,
|
|
150
|
+
absolute: false,
|
|
151
|
+
top: Len::auto(),
|
|
152
|
+
right: Len::auto(),
|
|
153
|
+
bottom: Len::auto(),
|
|
154
|
+
left: Len::auto(),
|
|
155
|
+
font_size: -1.0,
|
|
156
|
+
text: String::new(),
|
|
157
|
+
children: Vec::new(),
|
|
158
|
+
parent,
|
|
159
|
+
x: 0.0,
|
|
160
|
+
y: 0.0,
|
|
161
|
+
w: 0.0,
|
|
162
|
+
h: 0.0,
|
|
163
|
+
fs: 14.0,
|
|
164
|
+
text_fs: -1.0,
|
|
165
|
+
text_w: 0.0,
|
|
166
|
+
text_min: 0.0,
|
|
167
|
+
laid: false,
|
|
168
|
+
lay_w: -1.0,
|
|
169
|
+
max_cw: -1.0,
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/// Padding in pixels; a percentage is of `cb_w`, the width of the
|
|
174
|
+
/// containing block, on all four sides.
|
|
175
|
+
pub fn resolve_pads(&mut self, cb_w: double) {
|
|
176
|
+
self.pad_t = self.pad_t_len.resolve(cb_w).max(0.0);
|
|
177
|
+
self.pad_r = self.pad_r_len.resolve(cb_w).max(0.0);
|
|
178
|
+
self.pad_b = self.pad_b_len.resolve(cb_w).max(0.0);
|
|
179
|
+
self.pad_l = self.pad_l_len.resolve(cb_w).max(0.0);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
pub struct EvgrTree {
|
|
184
|
+
pub nodes: Vec<EvgrNode>,
|
|
185
|
+
table: Vec<double>,
|
|
186
|
+
/// `property:value` declarations that were not laid out
|
|
187
|
+
pub unsupported: Vec<String>,
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
impl EvgrTree {
|
|
191
|
+
pub fn new() -> EvgrTree {
|
|
192
|
+
EvgrTree { nodes: Vec::new(), table: text::advance_table(), unsupported: Vec::new() }
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/// A box styled by `css`, under `parent` (-1 for the root). Answers its
|
|
196
|
+
/// index.
|
|
197
|
+
pub fn add(&mut self, parent: int, css: &str) -> int {
|
|
198
|
+
let i = self.nodes.len() as int;
|
|
199
|
+
self.nodes.push(EvgrNode::new(parent));
|
|
200
|
+
if parent >= 0 {
|
|
201
|
+
self.nodes[parent as usize].children.push(i);
|
|
202
|
+
}
|
|
203
|
+
self.apply_css(i, css);
|
|
204
|
+
i
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/// A text leaf.
|
|
208
|
+
pub fn add_text(&mut self, parent: int, css: &str, text: &str) -> int {
|
|
209
|
+
let i = self.add(parent, css);
|
|
210
|
+
self.nodes[i as usize].text = text.to_string();
|
|
211
|
+
i
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
pub fn count(&self) -> int {
|
|
215
|
+
self.nodes.len() as int
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
pub fn x(&self, i: int) -> double {
|
|
219
|
+
self.nodes[i as usize].x
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
pub fn y(&self, i: int) -> double {
|
|
223
|
+
self.nodes[i as usize].y
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
pub fn w(&self, i: int) -> double {
|
|
227
|
+
self.nodes[i as usize].w
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
pub fn h(&self, i: int) -> double {
|
|
231
|
+
self.nodes[i as usize].h
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
pub fn unsupported_count(&self) -> int {
|
|
235
|
+
self.unsupported.len() as int
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
pub fn unsupported_at(&self, k: int) -> String {
|
|
239
|
+
self.unsupported[k as usize].clone()
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
fn apply_css(&mut self, i: int, css: &str) {
|
|
243
|
+
for part in css.split(';') {
|
|
244
|
+
let decl = part.trim();
|
|
245
|
+
if decl.is_empty() {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if let Some(colon) = decl.find(':') {
|
|
249
|
+
let name = decl[..colon].trim().to_string();
|
|
250
|
+
let value = decl[colon + 1..].trim().to_string();
|
|
251
|
+
let known = style::apply(&mut self.nodes[i as usize], &name, &value);
|
|
252
|
+
if !known {
|
|
253
|
+
self.unsupported.push(format!("{}:{}", name, value));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// ------------------------------------------------------------ layout
|
|
260
|
+
|
|
261
|
+
/// Lays the tree out from its root (node 0) in a viewport of `width` x
|
|
262
|
+
/// `height`.
|
|
263
|
+
pub fn layout(&mut self, width: double, height: double) {
|
|
264
|
+
if self.nodes.is_empty() {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
let mut k = 0;
|
|
268
|
+
while k < self.nodes.len() {
|
|
269
|
+
self.nodes[k].laid = false;
|
|
270
|
+
self.nodes[k].max_cw = -1.0;
|
|
271
|
+
k += 1;
|
|
272
|
+
}
|
|
273
|
+
self.inherit_fonts(0, 14.0);
|
|
274
|
+
self.nodes[0].resolve_pads(width);
|
|
275
|
+
let mut w = self.nodes[0].width.resolve(width);
|
|
276
|
+
if w < 0.0 {
|
|
277
|
+
w = width;
|
|
278
|
+
}
|
|
279
|
+
w = self.clamp_w(0, w, width);
|
|
280
|
+
// EVG: a root without a height is as tall as the viewport
|
|
281
|
+
let mut h = self.nodes[0].height.resolve(height);
|
|
282
|
+
if h < 0.0 {
|
|
283
|
+
h = height;
|
|
284
|
+
}
|
|
285
|
+
self.place(0, 0.0, 0.0, w, h);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
fn inherit_fonts(&mut self, i: int, from: double) {
|
|
289
|
+
let own = self.nodes[i as usize].font_size;
|
|
290
|
+
let fs = if own > 0.0 { own } else { from };
|
|
291
|
+
self.nodes[i as usize].fs = fs;
|
|
292
|
+
let kids = self.nodes[i as usize].children.clone();
|
|
293
|
+
for k in &kids {
|
|
294
|
+
self.inherit_fonts(*k, fs);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/// Measures a text leaf once per font size.
|
|
299
|
+
fn measure_text(&mut self, i: int) {
|
|
300
|
+
let iu = i as usize;
|
|
301
|
+
let fs = self.nodes[iu].fs;
|
|
302
|
+
if self.nodes[iu].text_fs == fs {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
let t = self.nodes[iu].text.clone();
|
|
306
|
+
self.nodes[iu].text_w = text::measure(&self.table, &t, fs);
|
|
307
|
+
self.nodes[iu].text_min = text::min_width(&self.table, &t, fs);
|
|
308
|
+
self.nodes[iu].text_fs = fs;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
fn is_text(&self, i: int) -> bool {
|
|
312
|
+
let n = &self.nodes[i as usize];
|
|
313
|
+
!n.text.is_empty() && n.children.is_empty()
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
fn pad_x(&self, i: int) -> double {
|
|
317
|
+
self.nodes[i as usize].pad_l + self.nodes[i as usize].pad_r
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
fn pad_y(&self, i: int) -> double {
|
|
321
|
+
self.nodes[i as usize].pad_t + self.nodes[i as usize].pad_b
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
fn clamp_w(&self, i: int, w: double, base: double) -> double {
|
|
325
|
+
let mut r = w;
|
|
326
|
+
let mx = self.nodes[i as usize].max_w.resolve(base);
|
|
327
|
+
if mx >= 0.0 && r > mx {
|
|
328
|
+
r = mx;
|
|
329
|
+
}
|
|
330
|
+
// min last: it wins over max
|
|
331
|
+
let mn = self.nodes[i as usize].min_w.resolve(base);
|
|
332
|
+
if mn >= 0.0 && r < mn {
|
|
333
|
+
r = mn;
|
|
334
|
+
}
|
|
335
|
+
r
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
fn clamp_h(&self, i: int, h: double, base: double) -> double {
|
|
339
|
+
let mut r = h;
|
|
340
|
+
let mx = self.nodes[i as usize].max_h.resolve(base);
|
|
341
|
+
if mx >= 0.0 && r > mx {
|
|
342
|
+
r = mx;
|
|
343
|
+
}
|
|
344
|
+
let mn = self.nodes[i as usize].min_h.resolve(base);
|
|
345
|
+
if mn >= 0.0 && r < mn {
|
|
346
|
+
r = mn;
|
|
347
|
+
}
|
|
348
|
+
r
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
fn is_row(&self, i: int) -> bool {
|
|
352
|
+
self.nodes[i as usize].display == 1 && self.nodes[i as usize].row
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
fn in_flow(&self, k: int) -> bool {
|
|
356
|
+
self.nodes[k as usize].display != 2 && !self.nodes[k as usize].absolute
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/// The width the box takes when nothing limits it (border box).
|
|
360
|
+
fn max_content_w(&mut self, i: int) -> double {
|
|
361
|
+
let cached = self.nodes[i as usize].max_cw;
|
|
362
|
+
if cached >= 0.0 {
|
|
363
|
+
return cached;
|
|
364
|
+
}
|
|
365
|
+
let r = self.content_w(i, false, false);
|
|
366
|
+
self.nodes[i as usize].max_cw = r;
|
|
367
|
+
r
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/// The narrowest the box can be without overflowing (border box).
|
|
371
|
+
fn min_content_w(&mut self, i: int) -> double {
|
|
372
|
+
self.content_w(i, true, false)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/// The content-based minimum of a flex item: its min-content width,
|
|
376
|
+
/// whatever width it declares (CSS's automatic minimum size).
|
|
377
|
+
fn min_content_own(&mut self, i: int) -> double {
|
|
378
|
+
self.content_w(i, true, true)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
fn content_w(&mut self, i: int, want_min: bool, ignore_width: bool) -> double {
|
|
382
|
+
if self.nodes[i as usize].display == 2 {
|
|
383
|
+
return 0.0;
|
|
384
|
+
}
|
|
385
|
+
let fixed = self.nodes[i as usize].width.resolve(-1.0);
|
|
386
|
+
if fixed >= 0.0 && !ignore_width {
|
|
387
|
+
return fixed;
|
|
388
|
+
}
|
|
389
|
+
let pads = self.pad_x(i);
|
|
390
|
+
if self.is_text(i) {
|
|
391
|
+
self.measure_text(i);
|
|
392
|
+
let tw = if want_min { self.nodes[i as usize].text_min } else { self.nodes[i as usize].text_w };
|
|
393
|
+
return self.clamp_w(i, tw + pads, -1.0);
|
|
394
|
+
}
|
|
395
|
+
let row = self.is_row(i);
|
|
396
|
+
let kids = self.nodes[i as usize].children.clone();
|
|
397
|
+
let mut total = 0.0;
|
|
398
|
+
let mut count = 0;
|
|
399
|
+
for k in &kids {
|
|
400
|
+
if !self.in_flow(*k) {
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
let kw = if want_min { self.min_content_w(*k) } else { self.max_content_w(*k) };
|
|
404
|
+
let outer = kw + self.nodes[*k as usize].mar_l + self.nodes[*k as usize].mar_r;
|
|
405
|
+
if row && !want_min {
|
|
406
|
+
total += outer;
|
|
407
|
+
} else if row && want_min && !self.nodes[i as usize].wrap {
|
|
408
|
+
total += outer;
|
|
409
|
+
} else if outer > total {
|
|
410
|
+
total = outer;
|
|
411
|
+
}
|
|
412
|
+
count += 1;
|
|
413
|
+
}
|
|
414
|
+
if row && count > 1 && (!want_min || !self.nodes[i as usize].wrap) {
|
|
415
|
+
total += self.nodes[i as usize].col_gap * ((count - 1) as double);
|
|
416
|
+
}
|
|
417
|
+
self.clamp_w(i, total + pads, -1.0)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/// The height of `i` laid out at width `w`.
|
|
421
|
+
fn height_for(&mut self, i: int, w: double) -> double {
|
|
422
|
+
let fixed = self.nodes[i as usize].height.resolve(-1.0);
|
|
423
|
+
if fixed >= 0.0 {
|
|
424
|
+
return self.clamp_h(i, fixed, -1.0);
|
|
425
|
+
}
|
|
426
|
+
let ratio = self.nodes[i as usize].ratio;
|
|
427
|
+
if ratio > 0.0 {
|
|
428
|
+
return self.clamp_h(i, w / ratio, -1.0);
|
|
429
|
+
}
|
|
430
|
+
self.place(i, 0.0, 0.0, w, -1.0);
|
|
431
|
+
self.nodes[i as usize].h
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
fn translate(&mut self, i: int, dx: double, dy: double) {
|
|
435
|
+
self.nodes[i as usize].x += dx;
|
|
436
|
+
self.nodes[i as usize].y += dy;
|
|
437
|
+
let kids = self.nodes[i as usize].children.clone();
|
|
438
|
+
for k in &kids {
|
|
439
|
+
self.translate(*k, dx, dy);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/// Puts the box at (x, y) with width `w` and height `h` (-1.0: from
|
|
444
|
+
/// its content), and lays out what is inside.
|
|
445
|
+
fn place(&mut self, i: int, x: double, y: double, w: double, h: double) {
|
|
446
|
+
let iu = i as usize;
|
|
447
|
+
// laid out at this width already this pass: the same boxes, moved
|
|
448
|
+
if self.nodes[iu].laid && self.nodes[iu].lay_w == w && (h < 0.0 || (h - self.nodes[iu].h).abs() < 0.0000001) {
|
|
449
|
+
let dx = x - self.nodes[iu].x;
|
|
450
|
+
let dy = y - self.nodes[iu].y;
|
|
451
|
+
if dx != 0.0 || dy != 0.0 {
|
|
452
|
+
self.translate(i, dx, dy);
|
|
453
|
+
}
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
self.nodes[iu].x = x;
|
|
457
|
+
self.nodes[iu].y = y;
|
|
458
|
+
self.nodes[iu].w = w;
|
|
459
|
+
self.nodes[iu].laid = true;
|
|
460
|
+
self.nodes[iu].lay_w = w;
|
|
461
|
+
if self.nodes[iu].display == 2 {
|
|
462
|
+
self.nodes[iu].w = 0.0;
|
|
463
|
+
self.nodes[iu].h = 0.0;
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
let iw = (w - self.pad_x(i)).max(0.0);
|
|
467
|
+
let mut hh = h;
|
|
468
|
+
if hh < 0.0 && self.nodes[iu].ratio > 0.0 {
|
|
469
|
+
hh = w / self.nodes[iu].ratio;
|
|
470
|
+
}
|
|
471
|
+
if self.is_text(i) {
|
|
472
|
+
let fs = self.nodes[iu].fs;
|
|
473
|
+
self.measure_text(i);
|
|
474
|
+
// one line when it fits, else wrapped at spaces
|
|
475
|
+
let mut lines = 1;
|
|
476
|
+
if self.nodes[iu].text_w > iw + 0.001 {
|
|
477
|
+
let t = self.nodes[iu].text.clone();
|
|
478
|
+
let (wrapped, _widest) = text::wrap(&self.table, &t, fs, iw);
|
|
479
|
+
lines = wrapped;
|
|
480
|
+
}
|
|
481
|
+
if hh < 0.0 {
|
|
482
|
+
hh = (lines as double) * text::line_height(fs) + self.pad_y(i);
|
|
483
|
+
}
|
|
484
|
+
} else {
|
|
485
|
+
let ih = if hh >= 0.0 { (hh - self.pad_y(i)).max(0.0) } else { -1.0 };
|
|
486
|
+
let content = if self.nodes[iu].display == 3 { self.layout_grid(i, iw, ih) } else { self.layout_box(i, iw, ih) };
|
|
487
|
+
if hh < 0.0 {
|
|
488
|
+
hh = content + self.pad_y(i);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
hh = self.clamp_h(i, hh, -1.0);
|
|
492
|
+
self.nodes[iu].h = hh;
|
|
493
|
+
self.place_absolutes(i);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
fn place_absolutes(&mut self, i: int) {
|
|
497
|
+
let kids = self.nodes[i as usize].children.clone();
|
|
498
|
+
let x0 = self.nodes[i as usize].x + self.nodes[i as usize].pad_l;
|
|
499
|
+
let y0 = self.nodes[i as usize].y + self.nodes[i as usize].pad_t;
|
|
500
|
+
let cw = (self.nodes[i as usize].w - self.pad_x(i)).max(0.0);
|
|
501
|
+
let ch = (self.nodes[i as usize].h - self.pad_y(i)).max(0.0);
|
|
502
|
+
for k in &kids {
|
|
503
|
+
let ku = *k as usize;
|
|
504
|
+
if !self.nodes[ku].absolute || self.nodes[ku].display == 2 {
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
let l = self.nodes[ku].left.resolve(cw);
|
|
508
|
+
let r = self.nodes[ku].right.resolve(cw);
|
|
509
|
+
let t = self.nodes[ku].top.resolve(ch);
|
|
510
|
+
let b = self.nodes[ku].bottom.resolve(ch);
|
|
511
|
+
let mut w = self.nodes[ku].width.resolve(cw);
|
|
512
|
+
if w < 0.0 && l >= 0.0 && r >= 0.0 {
|
|
513
|
+
w = cw - l - r - self.nodes[ku].mar_l - self.nodes[ku].mar_r;
|
|
514
|
+
}
|
|
515
|
+
if w < 0.0 {
|
|
516
|
+
w = self.max_content_w(*k);
|
|
517
|
+
}
|
|
518
|
+
w = self.clamp_w(*k, w, cw);
|
|
519
|
+
let mut h = self.nodes[ku].height.resolve(ch);
|
|
520
|
+
if h < 0.0 && t >= 0.0 && b >= 0.0 {
|
|
521
|
+
h = ch - t - b - self.nodes[ku].mar_t - self.nodes[ku].mar_b;
|
|
522
|
+
}
|
|
523
|
+
if h < 0.0 {
|
|
524
|
+
h = self.height_for(*k, w);
|
|
525
|
+
}
|
|
526
|
+
h = self.clamp_h(*k, h, ch);
|
|
527
|
+
let mut x = x0;
|
|
528
|
+
if l >= 0.0 {
|
|
529
|
+
x = x0 + l;
|
|
530
|
+
} else if r >= 0.0 {
|
|
531
|
+
x = x0 + cw - r - w - self.nodes[ku].mar_r - self.nodes[ku].mar_l;
|
|
532
|
+
}
|
|
533
|
+
let mut y = y0;
|
|
534
|
+
if t >= 0.0 {
|
|
535
|
+
y = y0 + t;
|
|
536
|
+
} else if b >= 0.0 {
|
|
537
|
+
y = y0 + ch - b - h - self.nodes[ku].mar_b - self.nodes[ku].mar_t;
|
|
538
|
+
}
|
|
539
|
+
self.place(*k, x + self.nodes[ku].mar_l, y + self.nodes[ku].mar_t, w, h);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/// The alignment of item `k` in container `c` on the cross axis.
|
|
544
|
+
fn align_of(&self, c: int, k: int) -> int {
|
|
545
|
+
let own = self.nodes[k as usize].align_self;
|
|
546
|
+
if own != style::UNSET {
|
|
547
|
+
return own;
|
|
548
|
+
}
|
|
549
|
+
let items = self.nodes[c as usize].align_items;
|
|
550
|
+
if items != style::UNSET {
|
|
551
|
+
// EVG: a text leaf without a width fits its text even where the
|
|
552
|
+
// column stretches its boxes
|
|
553
|
+
if items == style::STRETCH && !self.is_row(c) && self.is_text(k) {
|
|
554
|
+
return style::START;
|
|
555
|
+
}
|
|
556
|
+
return items;
|
|
557
|
+
}
|
|
558
|
+
// EVG: a box in a column fills the width, a text leaf fits its text;
|
|
559
|
+
// in a row nothing stretches
|
|
560
|
+
if !self.is_row(c) && !self.is_text(k) {
|
|
561
|
+
return style::STRETCH;
|
|
562
|
+
}
|
|
563
|
+
style::START
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/// Lays out the children of `c` inside its content box (`iw` wide, `ih`
|
|
567
|
+
/// high or -1.0 when that is to come from the content). Answers the
|
|
568
|
+
/// content height.
|
|
569
|
+
fn layout_box(&mut self, c: int, iw: double, ih: double) -> double {
|
|
570
|
+
let cu = c as usize;
|
|
571
|
+
let row = self.is_row(c);
|
|
572
|
+
let wrap = self.nodes[cu].display == 1 && self.nodes[cu].wrap;
|
|
573
|
+
let main_size = if row { iw } else { ih };
|
|
574
|
+
let cross_size = if row { ih } else { iw };
|
|
575
|
+
let main_gap = if row { self.nodes[cu].col_gap } else { self.nodes[cu].row_gap };
|
|
576
|
+
let cross_gap = if row { self.nodes[cu].row_gap } else { self.nodes[cu].col_gap };
|
|
577
|
+
let kids = self.nodes[cu].children.clone();
|
|
578
|
+
let mut items: Vec<int> = Vec::new();
|
|
579
|
+
for k in &kids {
|
|
580
|
+
self.nodes[*k as usize].resolve_pads(iw);
|
|
581
|
+
if self.in_flow(*k) {
|
|
582
|
+
items.push(*k);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
let n = items.len();
|
|
586
|
+
if n == 0 {
|
|
587
|
+
return 0.0;
|
|
588
|
+
}
|
|
589
|
+
// flex base sizes and their limits
|
|
590
|
+
let mut base: Vec<double> = Vec::new();
|
|
591
|
+
let mut hypo: Vec<double> = Vec::new();
|
|
592
|
+
let mut min_m: Vec<double> = Vec::new();
|
|
593
|
+
let mut max_m: Vec<double> = Vec::new();
|
|
594
|
+
let mut main_mar: Vec<double> = Vec::new();
|
|
595
|
+
let mut cross_mar: Vec<double> = Vec::new();
|
|
596
|
+
let mut j = 0;
|
|
597
|
+
while j < n {
|
|
598
|
+
let k = items[j];
|
|
599
|
+
let ku = k as usize;
|
|
600
|
+
let mm = if row { self.nodes[ku].mar_l + self.nodes[ku].mar_r } else { self.nodes[ku].mar_t + self.nodes[ku].mar_b };
|
|
601
|
+
let cm = if row { self.nodes[ku].mar_t + self.nodes[ku].mar_b } else { self.nodes[ku].mar_l + self.nodes[ku].mar_r };
|
|
602
|
+
main_mar.push(mm);
|
|
603
|
+
cross_mar.push(cm);
|
|
604
|
+
let spec = if row { self.nodes[ku].width.resolve(main_size) } else { self.nodes[ku].height.resolve(main_size) };
|
|
605
|
+
let mut b = self.nodes[ku].basis.resolve(main_size);
|
|
606
|
+
if b < 0.0 {
|
|
607
|
+
b = spec;
|
|
608
|
+
}
|
|
609
|
+
if b < 0.0 {
|
|
610
|
+
if row {
|
|
611
|
+
b = self.max_content_w(k);
|
|
612
|
+
} else {
|
|
613
|
+
let cw = self.item_cross_w(c, k, cross_size, cm);
|
|
614
|
+
b = self.height_for(k, cw);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
let mut lo = if row { self.nodes[ku].min_w.resolve(main_size) } else { self.nodes[ku].min_h.resolve(main_size) };
|
|
618
|
+
if lo < 0.0 {
|
|
619
|
+
// the automatic minimum: no narrower than the content
|
|
620
|
+
if row {
|
|
621
|
+
lo = self.min_content_own(k);
|
|
622
|
+
if spec >= 0.0 && spec < lo {
|
|
623
|
+
lo = spec;
|
|
624
|
+
}
|
|
625
|
+
} else if !self.nodes[ku].children.is_empty() || self.is_text(k) {
|
|
626
|
+
if spec < 0.0 {
|
|
627
|
+
let cw2 = self.item_cross_w(c, k, cross_size, cm);
|
|
628
|
+
lo = self.content_height(k, cw2);
|
|
629
|
+
} else {
|
|
630
|
+
lo = 0.0;
|
|
631
|
+
}
|
|
632
|
+
} else {
|
|
633
|
+
lo = 0.0;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
let mut hi = if row { self.nodes[ku].max_w.resolve(main_size) } else { self.nodes[ku].max_h.resolve(main_size) };
|
|
637
|
+
if hi < 0.0 {
|
|
638
|
+
hi = INF;
|
|
639
|
+
}
|
|
640
|
+
base.push(b);
|
|
641
|
+
// min wins over max when they conflict
|
|
642
|
+
hypo.push(b.min(hi).max(lo));
|
|
643
|
+
min_m.push(lo);
|
|
644
|
+
max_m.push(hi);
|
|
645
|
+
j += 1;
|
|
646
|
+
}
|
|
647
|
+
// lines
|
|
648
|
+
let mut line_start: Vec<int> = Vec::new();
|
|
649
|
+
let mut line_end: Vec<int> = Vec::new();
|
|
650
|
+
let mut cur_start = 0;
|
|
651
|
+
let mut used = 0.0;
|
|
652
|
+
j = 0;
|
|
653
|
+
while j < n {
|
|
654
|
+
let outer = hypo[j] + main_mar[j];
|
|
655
|
+
if wrap && main_size >= 0.0 && j > cur_start && used + main_gap + outer > main_size + 0.0001 {
|
|
656
|
+
line_start.push(cur_start as int);
|
|
657
|
+
line_end.push(j as int);
|
|
658
|
+
cur_start = j;
|
|
659
|
+
used = outer;
|
|
660
|
+
} else if j == cur_start {
|
|
661
|
+
used = outer;
|
|
662
|
+
} else {
|
|
663
|
+
used = used + main_gap + outer;
|
|
664
|
+
}
|
|
665
|
+
j += 1;
|
|
666
|
+
}
|
|
667
|
+
line_start.push(cur_start as int);
|
|
668
|
+
line_end.push(n as int);
|
|
669
|
+
// main sizes: grow or shrink each line into the container
|
|
670
|
+
let mut main_final: Vec<double> = hypo.clone();
|
|
671
|
+
let lines = line_start.len();
|
|
672
|
+
let mut li = 0;
|
|
673
|
+
while li < lines {
|
|
674
|
+
let a = line_start[li] as usize;
|
|
675
|
+
let e = line_end[li] as usize;
|
|
676
|
+
// grow and shrink are for flex items; a block's children keep
|
|
677
|
+
// their sizes
|
|
678
|
+
if main_size >= 0.0 && self.nodes[cu].display == 1 {
|
|
679
|
+
self.resolve_flex(&items, a, e, main_size, main_gap, &base, &hypo, &min_m, &max_m, &main_mar, &mut main_final);
|
|
680
|
+
}
|
|
681
|
+
li += 1;
|
|
682
|
+
}
|
|
683
|
+
// cross sizes, and each line's
|
|
684
|
+
let mut cross: Vec<double> = Vec::new();
|
|
685
|
+
let mut stretch: Vec<bool> = Vec::new();
|
|
686
|
+
j = 0;
|
|
687
|
+
while j < n {
|
|
688
|
+
let k = items[j];
|
|
689
|
+
let ku = k as usize;
|
|
690
|
+
let al = self.align_of(c, k);
|
|
691
|
+
let spec = if row { self.nodes[ku].height.resolve(cross_size) } else { self.nodes[ku].width.resolve(cross_size) };
|
|
692
|
+
let st = spec < 0.0 && al == style::STRETCH;
|
|
693
|
+
let cs = if spec >= 0.0 {
|
|
694
|
+
if row { self.clamp_h(k, spec, cross_size) } else { self.clamp_w(k, spec, cross_size) }
|
|
695
|
+
} else if row {
|
|
696
|
+
self.height_for(k, main_final[j])
|
|
697
|
+
} else {
|
|
698
|
+
self.item_cross_w(c, k, cross_size, cross_mar[j])
|
|
699
|
+
};
|
|
700
|
+
cross.push(cs);
|
|
701
|
+
stretch.push(st);
|
|
702
|
+
j += 1;
|
|
703
|
+
}
|
|
704
|
+
// baseline alignment (rows): each item's first baseline, from its top
|
|
705
|
+
let mut bl: Vec<double> = Vec::new();
|
|
706
|
+
j = 0;
|
|
707
|
+
while j < n {
|
|
708
|
+
let k = items[j];
|
|
709
|
+
if row && self.align_of(c, k) == style::BASELINE {
|
|
710
|
+
bl.push(self.baseline_of(k, cross[j]));
|
|
711
|
+
} else {
|
|
712
|
+
bl.push(-1.0);
|
|
713
|
+
}
|
|
714
|
+
j += 1;
|
|
715
|
+
}
|
|
716
|
+
let mut line_cross: Vec<double> = Vec::new();
|
|
717
|
+
let mut line_base: Vec<double> = Vec::new();
|
|
718
|
+
li = 0;
|
|
719
|
+
while li < lines {
|
|
720
|
+
let a = line_start[li] as usize;
|
|
721
|
+
let e = line_end[li] as usize;
|
|
722
|
+
let mut m = 0.0;
|
|
723
|
+
let mut above = 0.0;
|
|
724
|
+
let mut below = 0.0;
|
|
725
|
+
let mut q = a;
|
|
726
|
+
while q < e {
|
|
727
|
+
let o = cross[q] + cross_mar[q];
|
|
728
|
+
if o > m {
|
|
729
|
+
m = o;
|
|
730
|
+
}
|
|
731
|
+
if bl[q] >= 0.0 {
|
|
732
|
+
let up = self.nodes[items[q] as usize].mar_t + bl[q];
|
|
733
|
+
if up > above {
|
|
734
|
+
above = up;
|
|
735
|
+
}
|
|
736
|
+
if o - up > below {
|
|
737
|
+
below = o - up;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
q += 1;
|
|
741
|
+
}
|
|
742
|
+
if above + below > m {
|
|
743
|
+
m = above + below;
|
|
744
|
+
}
|
|
745
|
+
line_cross.push(m);
|
|
746
|
+
line_base.push(above);
|
|
747
|
+
li += 1;
|
|
748
|
+
}
|
|
749
|
+
if !wrap && cross_size >= 0.0 {
|
|
750
|
+
line_cross[0] = cross_size;
|
|
751
|
+
}
|
|
752
|
+
// align-content: the lines in the container's cross size
|
|
753
|
+
let mut total_cross = 0.0;
|
|
754
|
+
li = 0;
|
|
755
|
+
while li < lines {
|
|
756
|
+
total_cross += line_cross[li];
|
|
757
|
+
li += 1;
|
|
758
|
+
}
|
|
759
|
+
total_cross += cross_gap * ((lines - 1) as double);
|
|
760
|
+
let mut cross_pos = 0.0;
|
|
761
|
+
let mut line_space = cross_gap;
|
|
762
|
+
if wrap && cross_size >= 0.0 {
|
|
763
|
+
let free = cross_size - total_cross;
|
|
764
|
+
let ac = self.nodes[cu].align_content;
|
|
765
|
+
if ac == style::STRETCH && free > 0.0 {
|
|
766
|
+
let add = free / (lines as double);
|
|
767
|
+
li = 0;
|
|
768
|
+
while li < lines {
|
|
769
|
+
line_cross[li] += add;
|
|
770
|
+
li += 1;
|
|
771
|
+
}
|
|
772
|
+
} else if ac == style::END {
|
|
773
|
+
cross_pos = free;
|
|
774
|
+
} else if ac == style::CENTER {
|
|
775
|
+
cross_pos = free / 2.0;
|
|
776
|
+
} else if ac == style::BETWEEN && lines > 1 && free > 0.0 {
|
|
777
|
+
line_space = cross_gap + free / ((lines - 1) as double);
|
|
778
|
+
} else if ac == style::AROUND && free > 0.0 {
|
|
779
|
+
cross_pos = free / (2.0 * (lines as double));
|
|
780
|
+
line_space = cross_gap + free / (lines as double);
|
|
781
|
+
} else if ac == style::EVENLY && free > 0.0 {
|
|
782
|
+
cross_pos = free / ((lines + 1) as double);
|
|
783
|
+
line_space = cross_gap + free / ((lines + 1) as double);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
// place each line
|
|
787
|
+
let x0 = self.nodes[cu].x + self.nodes[cu].pad_l;
|
|
788
|
+
let y0 = self.nodes[cu].y + self.nodes[cu].pad_t;
|
|
789
|
+
let reverse = self.nodes[cu].reverse;
|
|
790
|
+
let mut content_main = 0.0;
|
|
791
|
+
li = 0;
|
|
792
|
+
while li < lines {
|
|
793
|
+
let a = line_start[li] as usize;
|
|
794
|
+
let e = line_end[li] as usize;
|
|
795
|
+
let count = e - a;
|
|
796
|
+
let mut line_used = main_gap * ((count - 1) as double);
|
|
797
|
+
let mut q = a;
|
|
798
|
+
while q < e {
|
|
799
|
+
line_used += main_final[q] + main_mar[q];
|
|
800
|
+
q += 1;
|
|
801
|
+
}
|
|
802
|
+
if line_used > content_main {
|
|
803
|
+
content_main = line_used;
|
|
804
|
+
}
|
|
805
|
+
let avail = if main_size >= 0.0 { main_size } else { line_used };
|
|
806
|
+
let free = avail - line_used;
|
|
807
|
+
let mut pos = 0.0;
|
|
808
|
+
let mut space = main_gap;
|
|
809
|
+
let jc = self.nodes[cu].justify;
|
|
810
|
+
if free > 0.0 {
|
|
811
|
+
if jc == style::END {
|
|
812
|
+
pos = free;
|
|
813
|
+
} else if jc == style::CENTER {
|
|
814
|
+
pos = free / 2.0;
|
|
815
|
+
} else if jc == style::BETWEEN && count > 1 {
|
|
816
|
+
space = main_gap + free / ((count - 1) as double);
|
|
817
|
+
} else if jc == style::AROUND {
|
|
818
|
+
pos = free / (2.0 * (count as double));
|
|
819
|
+
space = main_gap + free / (count as double);
|
|
820
|
+
} else if jc == style::EVENLY {
|
|
821
|
+
pos = free / ((count + 1) as double);
|
|
822
|
+
space = main_gap + free / ((count + 1) as double);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
let lc = line_cross[li];
|
|
826
|
+
q = a;
|
|
827
|
+
while q < e {
|
|
828
|
+
let k = items[q];
|
|
829
|
+
let ku = k as usize;
|
|
830
|
+
let size_m = main_final[q];
|
|
831
|
+
let mut size_c = cross[q];
|
|
832
|
+
if stretch[q] {
|
|
833
|
+
size_c = lc - cross_mar[q];
|
|
834
|
+
size_c = if row { self.clamp_h(k, size_c, cross_size) } else { self.clamp_w(k, size_c, cross_size) };
|
|
835
|
+
}
|
|
836
|
+
let al = self.align_of(c, k);
|
|
837
|
+
let outer_c = size_c + cross_mar[q];
|
|
838
|
+
let mut off_c = 0.0;
|
|
839
|
+
if al == style::END {
|
|
840
|
+
off_c = lc - outer_c;
|
|
841
|
+
} else if al == style::CENTER {
|
|
842
|
+
off_c = (lc - outer_c) / 2.0;
|
|
843
|
+
} else if bl[q] >= 0.0 {
|
|
844
|
+
off_c = line_base[li] - bl[q] - self.nodes[ku].mar_t;
|
|
845
|
+
}
|
|
846
|
+
let mut main_at = pos;
|
|
847
|
+
if reverse {
|
|
848
|
+
main_at = avail - pos - size_m - main_mar[q];
|
|
849
|
+
}
|
|
850
|
+
if row {
|
|
851
|
+
let px = x0 + main_at + self.nodes[ku].mar_l;
|
|
852
|
+
let py = y0 + cross_pos + off_c + self.nodes[ku].mar_t;
|
|
853
|
+
self.place(k, px, py, size_m, size_c);
|
|
854
|
+
} else {
|
|
855
|
+
let px2 = x0 + cross_pos + off_c + self.nodes[ku].mar_l;
|
|
856
|
+
let py2 = y0 + main_at + self.nodes[ku].mar_t;
|
|
857
|
+
self.place(k, px2, py2, size_c, size_m);
|
|
858
|
+
}
|
|
859
|
+
pos = pos + size_m + main_mar[q] + space;
|
|
860
|
+
q += 1;
|
|
861
|
+
}
|
|
862
|
+
cross_pos = cross_pos + lc + line_space;
|
|
863
|
+
li += 1;
|
|
864
|
+
}
|
|
865
|
+
if row {
|
|
866
|
+
total_cross = 0.0;
|
|
867
|
+
li = 0;
|
|
868
|
+
while li < lines {
|
|
869
|
+
total_cross += line_cross[li];
|
|
870
|
+
li += 1;
|
|
871
|
+
}
|
|
872
|
+
total_cross += cross_gap * ((lines - 1) as double);
|
|
873
|
+
return total_cross;
|
|
874
|
+
}
|
|
875
|
+
content_main
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/// The first baseline of `k`, from the top of its border box, when it is
|
|
879
|
+
/// `h` high: a text leaf's first line (the half-leading model, with the
|
|
880
|
+
/// measurer's ascent and descent), a box's first child's, or else the
|
|
881
|
+
/// bottom edge.
|
|
882
|
+
fn baseline_of(&mut self, k: int, h: double) -> double {
|
|
883
|
+
let ku = k as usize;
|
|
884
|
+
if self.is_text(k) {
|
|
885
|
+
let fs = self.nodes[ku].fs;
|
|
886
|
+
let lh = text::line_height(fs);
|
|
887
|
+
return self.nodes[ku].pad_t + (lh - (0.905 + 0.212) * fs) / 2.0 + 0.905 * fs;
|
|
888
|
+
}
|
|
889
|
+
let kids = self.nodes[ku].children.clone();
|
|
890
|
+
for c in &kids {
|
|
891
|
+
if self.in_flow(*c) {
|
|
892
|
+
let ch = self.nodes[*c as usize].h;
|
|
893
|
+
return self.nodes[ku].pad_t + self.nodes[*c as usize].mar_t + self.baseline_of(*c, ch);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
h
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/// The width a column item takes on its cross axis before stretching.
|
|
900
|
+
fn item_cross_w(&mut self, c: int, k: int, cross_size: double, cross_mar: double) -> double {
|
|
901
|
+
let spec = self.nodes[k as usize].width.resolve(cross_size);
|
|
902
|
+
if spec >= 0.0 {
|
|
903
|
+
return self.clamp_w(k, spec, cross_size);
|
|
904
|
+
}
|
|
905
|
+
let avail = if cross_size >= 0.0 { cross_size - cross_mar } else { INF };
|
|
906
|
+
if self.align_of(c, k) == style::STRETCH && cross_size >= 0.0 {
|
|
907
|
+
return self.clamp_w(k, avail.max(0.0), cross_size);
|
|
908
|
+
}
|
|
909
|
+
let fit = self.max_content_w(k);
|
|
910
|
+
self.clamp_w(k, fit.min(avail), cross_size)
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/// The height of the content of `k` at width `w`, without its declared
|
|
914
|
+
/// height: the automatic minimum of a column item.
|
|
915
|
+
fn content_height(&mut self, k: int, w: double) -> double {
|
|
916
|
+
if self.nodes[k as usize].height.is_auto() {
|
|
917
|
+
return self.height_for(k, w);
|
|
918
|
+
}
|
|
919
|
+
0.0
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/// Grows or shrinks the items `a..e` of one line into `main_size`,
|
|
923
|
+
/// freezing an item at its min or max and sharing the rest again, as the
|
|
924
|
+
/// CSS algorithm does.
|
|
925
|
+
fn resolve_flex(&self, items: &Vec<int>, a: usize, e: usize, main_size: double, gap: double, base: &Vec<double>, hypo: &Vec<double>, min_m: &Vec<double>, max_m: &Vec<double>, mar: &Vec<double>, out: &mut Vec<double>) {
|
|
926
|
+
let count = e - a;
|
|
927
|
+
let mut used = gap * ((count - 1) as double);
|
|
928
|
+
let mut q = a;
|
|
929
|
+
while q < e {
|
|
930
|
+
used += hypo[q] + mar[q];
|
|
931
|
+
q += 1;
|
|
932
|
+
}
|
|
933
|
+
let growing = used < main_size;
|
|
934
|
+
let mut frozen: Vec<bool> = Vec::new();
|
|
935
|
+
q = a;
|
|
936
|
+
while q < e {
|
|
937
|
+
let ku = items[q] as usize;
|
|
938
|
+
let f = if growing { self.nodes[ku].grow <= 0.0 || base[q] > hypo[q] } else { self.nodes[ku].shrink <= 0.0 || base[q] < hypo[q] };
|
|
939
|
+
frozen.push(f);
|
|
940
|
+
out[q] = hypo[q];
|
|
941
|
+
q += 1;
|
|
942
|
+
}
|
|
943
|
+
let mut rounds = 0;
|
|
944
|
+
while rounds <= count {
|
|
945
|
+
rounds += 1;
|
|
946
|
+
let mut free = main_size - gap * ((count - 1) as double);
|
|
947
|
+
let mut weight = 0.0;
|
|
948
|
+
let mut grow_sum = 0.0;
|
|
949
|
+
q = a;
|
|
950
|
+
while q < e {
|
|
951
|
+
let ku = items[q] as usize;
|
|
952
|
+
if frozen[q - a] {
|
|
953
|
+
free -= out[q] + mar[q];
|
|
954
|
+
} else {
|
|
955
|
+
free -= base[q] + mar[q];
|
|
956
|
+
if growing {
|
|
957
|
+
weight += self.nodes[ku].grow;
|
|
958
|
+
grow_sum += self.nodes[ku].grow;
|
|
959
|
+
} else {
|
|
960
|
+
weight += self.nodes[ku].shrink * base[q];
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
q += 1;
|
|
964
|
+
}
|
|
965
|
+
if weight <= 0.0 {
|
|
966
|
+
break;
|
|
967
|
+
}
|
|
968
|
+
// a total grow under 1 hands out only that share of the space
|
|
969
|
+
if growing && grow_sum < 1.0 {
|
|
970
|
+
free = free * grow_sum;
|
|
971
|
+
}
|
|
972
|
+
let mut violation = 0.0;
|
|
973
|
+
q = a;
|
|
974
|
+
while q < e {
|
|
975
|
+
if !frozen[q - a] {
|
|
976
|
+
let ku = items[q] as usize;
|
|
977
|
+
let share = if growing { self.nodes[ku].grow / weight } else { self.nodes[ku].shrink * base[q] / weight };
|
|
978
|
+
let want = base[q] + free * share;
|
|
979
|
+
let clamped = want.min(max_m[q]).max(min_m[q]).max(0.0);
|
|
980
|
+
violation += clamped - want;
|
|
981
|
+
out[q] = clamped;
|
|
982
|
+
}
|
|
983
|
+
q += 1;
|
|
984
|
+
}
|
|
985
|
+
if violation.abs() < 0.0000001 {
|
|
986
|
+
break;
|
|
987
|
+
}
|
|
988
|
+
// freeze the items the clamp moved the way the total moved
|
|
989
|
+
q = a;
|
|
990
|
+
while q < e {
|
|
991
|
+
if !frozen[q - a] {
|
|
992
|
+
let ku = items[q] as usize;
|
|
993
|
+
let share2 = if growing { self.nodes[ku].grow / weight } else { self.nodes[ku].shrink * base[q] / weight };
|
|
994
|
+
let want2 = base[q] + free * share2;
|
|
995
|
+
if (violation > 0.0 && out[q] > want2 + 0.0000001) || (violation < 0.0 && out[q] < want2 - 0.0000001) {
|
|
996
|
+
frozen[q - a] = true;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
q += 1;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|