ranger-compiler 3.5.0 → 3.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1160 -19
- package/LICENSE +3 -1
- package/README.md +124 -29
- package/dist/Lang.rgr +1188 -290
- package/dist/api.d.ts +2343 -879
- package/dist/api.js +79924 -56922
- package/dist/lib/JSON.rgr +102 -91
- package/dist/lib/Shell.rgr +4 -4
- package/dist/lib/apple/AppleToolchain.rgr +4 -4
- package/dist/lib/apple/README.md +5 -4
- package/dist/lib/apple/apple_test.rgr +1 -1
- package/dist/lib/core/README.md +1 -1
- package/dist/lib/evg/EVG.rgr +12 -0
- package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
- package/dist/lib/evg/EVGA11yTree.rgr +894 -0
- package/dist/lib/evg/EVGBox.rgr +267 -0
- package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
- package/dist/lib/evg/EVGCodepoint.rgr +316 -0
- package/dist/lib/evg/EVGColor.rgr +700 -0
- package/dist/lib/evg/EVGCommands.rgr +177 -0
- package/dist/lib/evg/EVGComponent.rgr +331 -0
- package/dist/lib/evg/EVGComponentTest.rgr +387 -0
- package/dist/lib/evg/EVGConnector.rgr +541 -0
- package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
- package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
- package/dist/lib/evg/EVGEasing.rgr +370 -0
- package/dist/lib/evg/EVGEffectTest.rgr +253 -0
- package/dist/lib/evg/EVGElement.rgr +4914 -0
- package/dist/lib/evg/EVGFixedTest.rgr +289 -0
- package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
- package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
- package/dist/lib/evg/EVGFling.rgr +244 -0
- package/dist/lib/evg/EVGFocus.rgr +400 -0
- package/dist/lib/evg/EVGFocusTest.rgr +399 -0
- package/dist/lib/evg/EVGGradient.rgr +322 -0
- package/dist/lib/evg/EVGGrapheme.rgr +190 -0
- package/dist/lib/evg/EVGGrid.rgr +975 -0
- package/dist/lib/evg/EVGHitTest.rgr +208 -0
- package/dist/lib/evg/EVGHoles.rgr +294 -0
- package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
- package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
- package/dist/lib/evg/EVGHostTree.rgr +834 -0
- package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
- package/dist/lib/evg/EVGImageDecode.rgr +117 -0
- package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
- package/dist/lib/evg/EVGInspect.rgr +883 -0
- package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
- package/dist/lib/evg/EVGJsonTest.rgr +535 -0
- package/dist/lib/evg/EVGLayout.rgr +4220 -0
- package/dist/lib/evg/EVGMeasure.rgr +1267 -0
- package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
- package/dist/lib/evg/EVGPatch.rgr +1721 -0
- package/dist/lib/evg/EVGPatchTest.rgr +692 -0
- package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
- package/dist/lib/evg/EVGReconcile.rgr +226 -0
- package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
- package/dist/lib/evg/EVGReject.rgr +126 -0
- package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
- package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
- package/dist/lib/evg/EVGRuler.rgr +232 -0
- package/dist/lib/evg/EVGRulerTest.rgr +172 -0
- package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
- package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
- package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
- package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
- package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
- package/dist/lib/evg/EVGText.rgr +105 -0
- package/dist/lib/evg/EVGTextEngine.rgr +536 -0
- package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
- package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
- package/dist/lib/evg/EVGToolbar.rgr +1369 -0
- package/dist/lib/evg/EVGTransition.rgr +728 -0
- package/dist/lib/evg/EVGTreeJson.rgr +721 -0
- package/dist/lib/evg/EVGUnit.rgr +554 -0
- package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
- package/dist/lib/evg/EvgApp.rgr +189 -0
- package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
- package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
- package/dist/lib/evg/EvgHost.rgr +451 -0
- package/dist/lib/evg/EvgTest.rgr +91 -0
- package/dist/lib/evg/EvgTraceColor.rgr +236 -0
- package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
- package/dist/lib/evg/EvgTraceFit.rgr +767 -0
- package/dist/lib/evg/EvgTracePath.rgr +435 -0
- package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
- package/dist/lib/evg/EvgViewport.rgr +313 -0
- package/dist/lib/evg/FxDemoDoc.rgr +185 -0
- package/dist/lib/evg/HOSTS.md +227 -0
- package/dist/lib/evg/ISSUES.md +835 -0
- package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
- package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
- package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
- package/dist/lib/evg/PLAN_EVG.md +518 -0
- package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
- package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
- package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
- package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
- package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
- package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
- package/dist/lib/evg/PathBuilder.rgr +333 -0
- package/dist/lib/evg/README.md +1236 -0
- package/dist/lib/evg/SPEC.md +1252 -0
- package/dist/lib/evg/SVGPathParser.rgr +1199 -0
- package/dist/lib/evg/SvgParser.rgr +1736 -0
- package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
- package/dist/lib/evg/VectorShapes.rgr +331 -0
- package/dist/lib/evg/VectorStroke.rgr +107 -0
- package/dist/lib/evg/VectorViewBox.rgr +380 -0
- package/dist/lib/evg/agent/README.md +290 -0
- package/dist/lib/evg/agent/evg_agent.rgr +899 -0
- package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
- package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
- package/dist/lib/evg/agent/fixtures/connector.css +63 -0
- package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
- package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
- package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
- package/dist/lib/evg/agent/fixtures/popover.css +99 -0
- package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
- package/dist/lib/evg/agent/roundtrip.sh +74 -0
- package/dist/lib/evg/agent/smoke.sh +230 -0
- package/dist/lib/evg/android/README.md +97 -0
- package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
- package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
- package/dist/lib/evg/android/androidstubs/App.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
- package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
- package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
- package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
- package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
- package/dist/lib/evg/android/androidstubs/View.kt +113 -0
- package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
- package/dist/lib/evg/apple/README.md +128 -0
- package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
- package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
- package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
- package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
- package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
- package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
- package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
- package/dist/lib/evg/bench/README.md +64 -0
- package/dist/lib/evg/bench/layout-bench.mjs +316 -0
- package/dist/lib/evg/bench/layout-cases.mjs +510 -0
- package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
- package/dist/lib/evg/bin/.gitignore +17 -0
- package/dist/lib/evg/evg_test.rgr +313 -0
- package/dist/lib/evg/gl/README.md +198 -0
- package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
- package/dist/lib/evg/gl/blur-check.mjs +399 -0
- package/dist/lib/evg/gl/boxmodel.json +1 -0
- package/dist/lib/evg/gl/demo.html +46 -0
- package/dist/lib/evg/gl/effect-presets.css +285 -0
- package/dist/lib/evg/gl/effect-presets.js +63 -0
- package/dist/lib/evg/gl/effect-shots.mjs +135 -0
- package/dist/lib/evg/gl/evg-a11y.js +566 -0
- package/dist/lib/evg/gl/evg-binary.js +160 -0
- package/dist/lib/evg/gl/evg-engine.js +296 -0
- package/dist/lib/evg/gl/evg-fx.js +237 -0
- package/dist/lib/evg/gl/evg-gestures.js +209 -0
- package/dist/lib/evg/gl/evg-list.js +167 -0
- package/dist/lib/evg/gl/evg-measure.js +186 -0
- package/dist/lib/evg/gl/evg-textinput.js +303 -0
- package/dist/lib/evg/gl/evg-view.js +144 -0
- package/dist/lib/evg/gl/evg-webgl.js +3942 -0
- package/dist/lib/evg/gl/fx-check.mjs +998 -0
- package/dist/lib/evg/gl/fx-demo.html +166 -0
- package/dist/lib/evg/gl/fx-demo.js +2 -0
- package/dist/lib/evg/gl/fx-serve.mjs +47 -0
- package/dist/lib/evg/gl/gestures-check.mjs +189 -0
- package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
- package/dist/lib/evg/gl/measure-check.mjs +135 -0
- package/dist/lib/evg/gl/rotation-check.mjs +207 -0
- package/dist/lib/evg/gl/shift-check.mjs +113 -0
- package/dist/lib/evg/gl/stroke-check.mjs +168 -0
- package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
- package/dist/lib/evg/gl/view-check.mjs +343 -0
- package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
- package/dist/lib/evg/html/evg-dom.js +318 -0
- package/dist/lib/evg/html/evg-html.js +600 -0
- package/dist/lib/evg/inspect/README.md +415 -0
- package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
- package/dist/lib/evg/inspect/evg-inspect.js +947 -0
- package/dist/lib/evg/inspect/shots/css.png +0 -0
- package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
- package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
- package/dist/lib/evg/inspect/shots/state.png +0 -0
- package/dist/lib/evg/inspect/shots.mjs +226 -0
- package/dist/lib/evg/oracle/css-blur.json +576 -0
- package/dist/lib/evg/oracle/css-box.json +157 -0
- package/dist/lib/evg/oracle/css-timing.json +709 -0
- package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
- package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
- package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
- package/dist/lib/evg/original/EVGColor.clj +310 -0
- package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
- package/dist/lib/evg/original/SVGPath.rgr +627 -0
- package/dist/lib/evg/original/Vec2.crgr +103 -0
- package/dist/lib/evg/ranger.json +9 -0
- package/dist/lib/evg/showcase/README.md +246 -0
- package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
- package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
- package/dist/lib/evg/showcase/build.mjs +651 -0
- package/dist/lib/evg/showcase/pages/album.tsx +30 -0
- package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
- package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
- package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
- package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
- package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
- package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
- package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
- package/dist/lib/evg/showcase/pages/more.tsx +332 -0
- package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
- package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
- package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
- package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
- package/dist/lib/evg/showcase/pages/units.tsx +35 -0
- package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
- package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
- package/dist/lib/evg/showcase/pages/views.tsx +223 -0
- package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
- package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
- package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
- package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
- package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
- package/dist/lib/evg/showcase/themes/more-default.css +128 -0
- package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
- package/dist/lib/evg/showcase/themes/showcase.css +508 -0
- package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
- package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
- package/dist/lib/evg/showcase/themes/views-default.css +15 -0
- package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
- package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
- package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
- package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
- package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
- package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
- package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
- package/dist/lib/evg/web/responsive/README.md +97 -0
- package/dist/lib/evg/web/responsive/build.mjs +90 -0
- package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
- package/dist/lib/evg/web/responsive/index.html +177 -0
- package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
- package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
- package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
- package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
- package/dist/lib/evg/web/tools/minify.mjs +60 -0
- package/dist/lib/evg/web/tracer/build.mjs +87 -0
- package/dist/lib/evg/web/tracer/index.html +2805 -0
- package/dist/lib/evg/web/tracer/sample.png +0 -0
- package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
- package/dist/lib/evgr/Cargo.lock +21 -0
- package/dist/lib/evgr/Cargo.toml +19 -0
- package/dist/lib/evgr/README.md +140 -0
- package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
- package/dist/lib/evgr/bench/compare.mjs +252 -0
- package/dist/lib/evgr/bench/speed.mjs +277 -0
- package/dist/lib/evgr/bin/.gitignore +3 -0
- package/dist/lib/evgr/src/bin/bench.rs +106 -0
- package/dist/lib/evgr/src/bin/smoke.rs +13 -0
- package/dist/lib/evgr/src/grid.rs +730 -0
- package/dist/lib/evgr/src/lib.rs +1003 -0
- package/dist/lib/evgr/src/style.rs +468 -0
- package/dist/lib/evgr/src/text.rs +83 -0
- package/dist/lib/image/BitReader.rgr +171 -0
- package/dist/lib/image/Buffer.rgr +173 -0
- package/dist/lib/image/DCT.rgr +283 -0
- package/dist/lib/image/Deflate.rgr +339 -0
- package/dist/lib/image/HuffmanDecoder.rgr +181 -0
- package/dist/lib/image/ImageBuffer.rgr +706 -0
- package/dist/lib/image/JPEGDecoder.rgr +808 -0
- package/dist/lib/image/PNGDecoder.rgr +544 -0
- package/dist/lib/image/PNGEncoder.rgr +388 -0
- package/dist/lib/image/PPMImage.rgr +224 -0
- package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
- package/dist/lib/image/README.md +33 -0
- package/dist/lib/image/RasterBuffer.rgr +294 -0
- package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
- package/dist/lib/image/WebPDecoder.rgr +433 -0
- package/dist/lib/image/WebPLossless.rgr +1035 -0
- package/dist/lib/image/WebPLossy.rgr +1929 -0
- package/dist/lib/image/ranger.json +9 -0
- package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
- package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
- package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
- package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
- package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
- package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
- package/dist/lib/image/tests/run_webp_tests.sh +39 -0
- package/dist/lib/rust/RsJson.rgr +468 -0
- package/dist/lib/rust/RsPrelude.rgr +1663 -0
- package/dist/lib/shell_test.rgr +7 -7
- package/dist/lib/stdlib.rgr +21 -5
- package/dist/lib/zip/ranger.json +6 -0
- package/dist/rgrc.js +87318 -67610
- package/package.json +1010 -1040
- package/dist/README.md +0 -117
- package/dist/package.json +0 -47
|
@@ -0,0 +1,720 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; EVGTextMeasurer.rgr - Abstract text measurement interface for EVG layout
|
|
4
|
+
|
|
5
|
+
Import "EVGCodepoint.rgr"
|
|
6
|
+
|
|
7
|
+
class EVGTextMetrics {
|
|
8
|
+
def width:double 0.0
|
|
9
|
+
def height:double 0.0
|
|
10
|
+
def ascent:double 0.0
|
|
11
|
+
def descent:double 0.0
|
|
12
|
+
def lineHeight:double 0.0
|
|
13
|
+
|
|
14
|
+
Constructor () {
|
|
15
|
+
width = 0.0
|
|
16
|
+
height = 0.0
|
|
17
|
+
ascent = 0.0
|
|
18
|
+
descent = 0.0
|
|
19
|
+
lineHeight = 0.0
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
sfn create:EVGTextMetrics (w:double h:double) {
|
|
23
|
+
def m (new EVGTextMetrics())
|
|
24
|
+
m.width = w
|
|
25
|
+
m.height = h
|
|
26
|
+
return m
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
; Abstract interface - implementations must override
|
|
31
|
+
class EVGTextMeasurer {
|
|
32
|
+
|
|
33
|
+
; --- WHAT `measureChar` IS NOT ALLOWED TO DO AGAIN PER CHARACTER ----------
|
|
34
|
+
;
|
|
35
|
+
; `measureChar` is called once per character of every string the layout
|
|
36
|
+
; measures, and a wrap measures the same string many times over, so
|
|
37
|
+
; anything it does is done millions of times in a frame. It used to do two
|
|
38
|
+
; things there that had no business being in that loop:
|
|
39
|
+
;
|
|
40
|
+
; `isMono(fontFamily)` — six substring searches over the family name,
|
|
41
|
+
; for an answer that is the same for every character of the run. It was
|
|
42
|
+
; 38% of the whole profile of a scroll in `gallery/realtrainer`: the
|
|
43
|
+
; single most expensive function in the frame, computing one boolean
|
|
44
|
+
; over and over.
|
|
45
|
+
;
|
|
46
|
+
; `advanceEm()` — a NINETY-FIVE ELEMENT ARRAY LITERAL, freshly allocated
|
|
47
|
+
; for each character, to read one slot out of it. That is what put minor
|
|
48
|
+
; GC and the collector's `drop` next in the same profile.
|
|
49
|
+
;
|
|
50
|
+
; Both are constants of the run, so they are held here instead: the tables
|
|
51
|
+
; materialised once per measurer, and the family's monospace-ness
|
|
52
|
+
; remembered for the last family asked about — which, inside a run, is
|
|
53
|
+
; every character after the first.
|
|
54
|
+
def advTable:[double]
|
|
55
|
+
def monoTable:[double]
|
|
56
|
+
def latinTable:[double]
|
|
57
|
+
def punctTable:[double]
|
|
58
|
+
def tablesReady:boolean false
|
|
59
|
+
; The last family `monoFor` was asked about and the answer it gave.
|
|
60
|
+
; `monoKnown` is what distinguishes "not asked yet" from "asked about the
|
|
61
|
+
; empty family", which `monoFamily` alone cannot.
|
|
62
|
+
def monoFamily:string ""
|
|
63
|
+
def monoKnown:boolean false
|
|
64
|
+
def monoCached:boolean false
|
|
65
|
+
; …and whether it is the bold cut, remembered with it. The layout asks
|
|
66
|
+
; for `Arial-Bold` when the element is bold (`EVGElement.effectiveFontFamily`),
|
|
67
|
+
; and a bold face is measured with the bold tables below.
|
|
68
|
+
def boldCached:boolean false
|
|
69
|
+
def boldTable:[double]
|
|
70
|
+
def boldLatinTable:[double]
|
|
71
|
+
def boldPunctTable:[double]
|
|
72
|
+
|
|
73
|
+
; --- THE FACE'S VERTICAL METRICS, MEASURED ---------------------------------
|
|
74
|
+
;
|
|
75
|
+
; These used to be 0.80 and 0.20, which sum to exactly 1.00em — and no real
|
|
76
|
+
; face does. Measured at 1000px in Chromium, the sans fallback is 0.905 and
|
|
77
|
+
; 0.212, summing to 1.117em; see `oracle/textbox.json`, which records the
|
|
78
|
+
; serif and monospace faces too.
|
|
79
|
+
;
|
|
80
|
+
; The ASCENT is what puts the baseline inside the line box, so an ascent
|
|
81
|
+
; that is a tenth of an em short draws every run of text that much high. It
|
|
82
|
+
; is not a rounding error, it is the difference between text sitting in a
|
|
83
|
+
; row and text sitting above one.
|
|
84
|
+
;
|
|
85
|
+
; They are still an ESTIMATE — a measurer with no font file cannot know the
|
|
86
|
+
; face — but an estimate taken from a real fallback rather than from a
|
|
87
|
+
; round number. A measurer that opens fonts overrides `measureText` and
|
|
88
|
+
; reports the truth.
|
|
89
|
+
sfn fallbackAscentEm:double () {
|
|
90
|
+
return 0.905
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
sfn fallbackDescentEm:double () {
|
|
94
|
+
return 0.212
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
; `line-height: normal`, which is NOT 1.2. It is the face's own line box —
|
|
98
|
+
; ascent plus descent plus the line gap — and it is 1.15em for the sans
|
|
99
|
+
; fallback, 1.164 for monospace. 1.2 is a number people type, not a number
|
|
100
|
+
; a browser computes.
|
|
101
|
+
sfn normalLineHeightEm:double () {
|
|
102
|
+
return 1.15
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
; Does this measurer report real metrics from the font file that will be
|
|
106
|
+
; painted? The default implementation below does NOT — it guesses from the
|
|
107
|
+
; font size and never opens a font — so it must not silently drive print
|
|
108
|
+
; layout. EVGTextEngine consults this to decide whether a document that
|
|
109
|
+
; names custom fonts can be measured honestly.
|
|
110
|
+
fn isFontAccurate:boolean () {
|
|
111
|
+
return false
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
; Is a concrete face available for this family? A measurer with no font
|
|
115
|
+
; files has none, whatever the family is called.
|
|
116
|
+
fn hasFace:boolean (fontFamily:string) {
|
|
117
|
+
return false
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
; --- WHAT WOULD MAKE THIS MEASURER ANSWER DIFFERENTLY --------------------
|
|
121
|
+
;
|
|
122
|
+
; `EVGTextEngine` caches wraps and metrics, and this string goes in the
|
|
123
|
+
; key. A measurer whose answers depend on nothing but its arguments — this
|
|
124
|
+
; one, whose tables are constants — has nothing to report and returns the
|
|
125
|
+
; empty string.
|
|
126
|
+
;
|
|
127
|
+
; A measurer that can CHANGE ITS MIND must override it: one that loads
|
|
128
|
+
; faces answers differently once a face is loaded, and one that is told a
|
|
129
|
+
; weight before each run answers differently for bold. Without the change
|
|
130
|
+
; showing up here, the engine would hand back a width measured before it.
|
|
131
|
+
; The rule is simply that anything read by `measureText` and not passed to
|
|
132
|
+
; it belongs in this string.
|
|
133
|
+
fn measureKey:string () {
|
|
134
|
+
return ""
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
fn measureText:EVGTextMetrics (text:string fontFamily:string fontSize:double) {
|
|
138
|
+
; Default implementation - estimate based on font size
|
|
139
|
+
; Average character width is approximately 0.5-0.6 of font size
|
|
140
|
+
def avgCharWidth:double (fontSize * 0.55)
|
|
141
|
+
def textLen:int (strlen text)
|
|
142
|
+
def width:double ((to_double textLen) * avgCharWidth)
|
|
143
|
+
def lineHeight:double (fontSize * (EVGTextMeasurer.normalLineHeightEm()))
|
|
144
|
+
|
|
145
|
+
def metrics (new EVGTextMetrics())
|
|
146
|
+
metrics.width = width
|
|
147
|
+
metrics.height = lineHeight
|
|
148
|
+
metrics.ascent = (fontSize * (EVGTextMeasurer.fallbackAscentEm()))
|
|
149
|
+
metrics.descent = (fontSize * (EVGTextMeasurer.fallbackDescentEm()))
|
|
150
|
+
metrics.lineHeight = lineHeight
|
|
151
|
+
return metrics
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
fn measureTextWidth:double (text:string fontFamily:string fontSize:double) {
|
|
155
|
+
def metrics:EVGTextMetrics (this.measureText(text fontFamily fontSize))
|
|
156
|
+
return metrics.width
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
fn getLineHeight:double (fontFamily:string fontSize:double) {
|
|
160
|
+
return (fontSize * (EVGTextMeasurer.normalLineHeightEm()))
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
; --- how wide a character really is ---------------------------------------
|
|
165
|
+
;
|
|
166
|
+
; MEASURED, one advance per printable character, as a fraction of the em.
|
|
167
|
+
; `advance_oracle.mjs` asks a browser for each one with canvas
|
|
168
|
+
; `measureText` at a 100px reference and this is what it said.
|
|
169
|
+
;
|
|
170
|
+
; What it replaces was a handful of buckets — space and `i l j t f` at 0.3
|
|
171
|
+
; of the size, `m w` at 0.8, `M W` at 0.9, everything else in between — and
|
|
172
|
+
; those buckets put "At least 8 characters." 12.4 pixels wide of the truth
|
|
173
|
+
; at 13px, and "ada.example.com" 7.9 wide. That second number is the bug
|
|
174
|
+
; this was written for: a caret is drawn at the measured width of the text
|
|
175
|
+
; before it, so the caret sat eight pixels past the end of the text.
|
|
176
|
+
;
|
|
177
|
+
; It is worse than a caret being untidy. The RENDERER does not estimate —
|
|
178
|
+
; the GL backend builds its glyph atlas with the browser's own
|
|
179
|
+
; `measureText` — so the text was DRAWN at its true width while the layout
|
|
180
|
+
; believed the buckets. Two measurements of one string, and everything
|
|
181
|
+
; placed from the wrong one: the caret, the selection band, the index a
|
|
182
|
+
; click maps to, the width of a box meant to fit its label.
|
|
183
|
+
;
|
|
184
|
+
; WHAT THIS TABLE IS NOT. It is a sum of single advances, and a browser
|
|
185
|
+
; kerns pairs, which no per-character table can express. Measured over
|
|
186
|
+
; fifteen strings the sum is EXACT for twelve and drifts at most 3.9px on
|
|
187
|
+
; the all-caps pairs that kern hardest — "AVATAR", "To Wave". So the table
|
|
188
|
+
; is right for text and slightly wide for capitals, which is a different
|
|
189
|
+
; and much smaller error than the one it replaces, and the check reports it
|
|
190
|
+
; rather than hiding it.
|
|
191
|
+
;
|
|
192
|
+
; AND IT IS ONE FACE. Arial, Helvetica and `sans-serif` all measured
|
|
193
|
+
; identically here because they resolve to the same substitute; a machine
|
|
194
|
+
; with a different Arial will differ slightly. The honest fix for that is
|
|
195
|
+
; to measure with the face actually in use, which the browser can do
|
|
196
|
+
; through `setMeasurer` — this table is what every target can carry.
|
|
197
|
+
; The same, for the BOLD cut. Bold Arial is not the regular face drawn
|
|
198
|
+
; thicker: `i`, `l`, `r`, `t` and `s` are a twentieth of an em wider each,
|
|
199
|
+
; and "Päivitä suunnitelma" at 14px is 131px bold against 121px regular.
|
|
200
|
+
; A button whose label was measured regular and drawn bold had its text
|
|
201
|
+
; against its right edge — the padding the sheet gave it went to the
|
|
202
|
+
; ten pixels the measurement was short. Measured as `advanceEm` was.
|
|
203
|
+
sfn boldAdvanceEm:[double] () {
|
|
204
|
+
return ([] _:double (
|
|
205
|
+
0.27783 0.33301 0.47412 0.55615 0.55615 0.88916 0.72217 0.23779
|
|
206
|
+
0.33301 0.33301 0.38916 0.58398 0.27783 0.33301 0.27783 0.27783
|
|
207
|
+
0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615
|
|
208
|
+
0.55615 0.55615 0.33301 0.33301 0.58398 0.58398 0.58398 0.61084
|
|
209
|
+
0.97510 0.72217 0.72217 0.72217 0.72217 0.66699 0.61084 0.77783
|
|
210
|
+
0.72217 0.27783 0.55615 0.72217 0.61084 0.83301 0.72217 0.77783
|
|
211
|
+
0.66699 0.77783 0.72217 0.66699 0.61084 0.72217 0.66699 0.94385
|
|
212
|
+
0.66699 0.66699 0.61084 0.33301 0.27783 0.33301 0.58398 0.55615
|
|
213
|
+
0.33301 0.55615 0.61084 0.55615 0.61084 0.55615 0.33301 0.61084
|
|
214
|
+
0.61084 0.27783 0.27783 0.55615 0.27783 0.88916 0.61084 0.61084
|
|
215
|
+
0.61084 0.61084 0.38916 0.55615 0.33301 0.61084 0.55615 0.77783
|
|
216
|
+
0.55615 0.55615 0.50000 0.38916 0.27979 0.38916 0.58398
|
|
217
|
+
))
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
sfn boldLatin1Em:[double] () {
|
|
221
|
+
return ([] _:double (
|
|
222
|
+
0.27783 0.33301 0.55615 0.55615 0.55615 0.55615 0.27979 0.55615
|
|
223
|
+
0.33301 0.73682 0.37012 0.55615 0.58398 0.00000 0.73682 0.55225
|
|
224
|
+
0.39990 0.54883 0.33301 0.33301 0.33301 0.57617 0.55615 0.33301
|
|
225
|
+
0.33301 0.33301 0.36523 0.55615 0.83398 0.83398 0.83398 0.61084
|
|
226
|
+
0.72217 0.72217 0.72217 0.72217 0.72217 0.72217 1.00000 0.72217
|
|
227
|
+
0.66699 0.66699 0.66699 0.66699 0.27783 0.27783 0.27783 0.27783
|
|
228
|
+
0.72217 0.72217 0.77783 0.77783 0.77783 0.77783 0.77783 0.58398
|
|
229
|
+
0.77783 0.72217 0.72217 0.72217 0.72217 0.66699 0.66699 0.61084
|
|
230
|
+
0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.88916 0.55615
|
|
231
|
+
0.55615 0.55615 0.55615 0.55615 0.27783 0.27783 0.27783 0.27783
|
|
232
|
+
0.61084 0.61084 0.61084 0.61084 0.61084 0.61084 0.61084 0.54883
|
|
233
|
+
0.61084 0.61084 0.61084 0.61084 0.61084 0.55615 0.61084 0.55615
|
|
234
|
+
))
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
sfn boldPunctEm:[double] () {
|
|
238
|
+
return ([] _:double (
|
|
239
|
+
0.33301 0.33301 0.55615 0.55615 1.00000 1.00000 0.49756 0.55225
|
|
240
|
+
0.27783 0.27783 0.27783 0.27783 0.50000 0.50000 0.50000 0.50000
|
|
241
|
+
0.55615 0.55615 0.35010 0.58984 0.33447 0.66748 1.00000
|
|
242
|
+
))
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
sfn advanceEm:[double] () {
|
|
246
|
+
return ([] _:double (
|
|
247
|
+
0.27783 0.27783 0.35498 0.55615 0.55615 0.88916 0.66699 0.19092
|
|
248
|
+
0.33301 0.33301 0.38916 0.58398 0.27783 0.33301 0.27783 0.27783
|
|
249
|
+
0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615
|
|
250
|
+
0.55615 0.55615 0.27783 0.27783 0.58398 0.58398 0.58398 0.55615
|
|
251
|
+
1.01514 0.66699 0.66699 0.72217 0.72217 0.66699 0.61084 0.77783
|
|
252
|
+
0.72217 0.27783 0.50000 0.66699 0.55615 0.83301 0.72217 0.77783
|
|
253
|
+
0.66699 0.77783 0.72217 0.66699 0.61084 0.72217 0.66699 0.94385
|
|
254
|
+
0.66699 0.66699 0.61084 0.27783 0.27783 0.27783 0.46924 0.55615
|
|
255
|
+
0.33301 0.55615 0.55615 0.50000 0.55615 0.55615 0.27783 0.55615
|
|
256
|
+
0.55615 0.22217 0.22217 0.50000 0.22217 0.83301 0.55615 0.55615
|
|
257
|
+
0.55615 0.55615 0.33301 0.50000 0.27783 0.55615 0.50000 0.72217
|
|
258
|
+
0.50000 0.50000 0.50000 0.33398 0.25977 0.33398 0.58398
|
|
259
|
+
))
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
; The same for a monospace face, where every advance is the same number and
|
|
263
|
+
; the sum is exact by construction.
|
|
264
|
+
sfn monoAdvanceEm:[double] () {
|
|
265
|
+
return ([] _:double (
|
|
266
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
267
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
268
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
269
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
270
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
271
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
272
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
273
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
274
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
275
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
276
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
277
|
+
0.60205 0.60205 0.60205 0.60205 0.60205 0.60205 0.60205
|
|
278
|
+
))
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
; Latin-1 Supplement, U+00A0 … U+00FF, measured the same way at the same
|
|
282
|
+
; reference: the umlauts every Finnish string has, the degree, the
|
|
283
|
+
; multiplication sign, and the soft hyphen at zero. Before this table
|
|
284
|
+
; an a-umlaut was the half-em guess below — 0.5 where the face has
|
|
285
|
+
; 0.55615 — and a caret after "Päiväkirja" was two pixels short.
|
|
286
|
+
sfn latin1Em:[double] () {
|
|
287
|
+
return ([] _:double (
|
|
288
|
+
0.27783 0.33301 0.55615 0.55615 0.55615 0.55615 0.25977 0.55615
|
|
289
|
+
0.33301 0.73682 0.37012 0.55615 0.58398 0.00000 0.73682 0.55225
|
|
290
|
+
0.39990 0.54883 0.33301 0.33301 0.33301 0.57617 0.53711 0.33301
|
|
291
|
+
0.33301 0.33301 0.36523 0.55615 0.83398 0.83398 0.83398 0.61084
|
|
292
|
+
0.66699 0.66699 0.66699 0.66699 0.66699 0.66699 1.00000 0.72217
|
|
293
|
+
0.66699 0.66699 0.66699 0.66699 0.27783 0.27783 0.27783 0.27783
|
|
294
|
+
0.72217 0.72217 0.77783 0.77783 0.77783 0.77783 0.77783 0.58398
|
|
295
|
+
0.77783 0.72217 0.72217 0.72217 0.72217 0.66699 0.66699 0.61084
|
|
296
|
+
0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.88916 0.50000
|
|
297
|
+
0.55615 0.55615 0.55615 0.55615 0.27783 0.27783 0.27783 0.27783
|
|
298
|
+
0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.55615 0.54883
|
|
299
|
+
0.61084 0.55615 0.55615 0.55615 0.55615 0.50000 0.55615 0.50000
|
|
300
|
+
))
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
; General Punctuation, U+2010 … U+2026: the dashes, the curly quotes,
|
|
304
|
+
; the daggers, the bullet and the ellipsis. The bullet is the one that
|
|
305
|
+
; was seen wrong: a password field draws one per character and the caret
|
|
306
|
+
; sat at the guessed 0.5 em each where the face draws 0.3501 — nine
|
|
307
|
+
; characters in, the caret was fifteen pixels past the last bullet.
|
|
308
|
+
sfn punctEm:[double] () {
|
|
309
|
+
return ([] _:double (
|
|
310
|
+
0.33301 0.33301 0.55615 0.55615 1.00000 1.00000 0.41309 0.55225
|
|
311
|
+
0.22217 0.22217 0.22217 0.22217 0.33301 0.33301 0.33301 0.33301
|
|
312
|
+
0.55615 0.55615 0.35010 0.59000 0.33000 0.67000 1.00000
|
|
313
|
+
))
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
; A few beyond those ranges the gallery draws: the single guillemets,
|
|
317
|
+
; the trade mark, the check mark.
|
|
318
|
+
sfn extraEm:double (ch:int) {
|
|
319
|
+
if (ch == 8249) { return 0.33301 }
|
|
320
|
+
if (ch == 8250) { return 0.33301 }
|
|
321
|
+
if (ch == 8482) { return 1.0 }
|
|
322
|
+
if (ch == 10003) { return 0.84 }
|
|
323
|
+
if (ch == 10004) { return 0.84 }
|
|
324
|
+
if (ch == 8242) { return 0.1875 }
|
|
325
|
+
if (ch == 8243) { return 0.354 }
|
|
326
|
+
return -1.0
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
; The euro, which the invoice demo puts in front of an amount and which
|
|
330
|
+
; was, before the two tables above, the one character outside printable
|
|
331
|
+
; ASCII the gallery asked for.
|
|
332
|
+
sfn euroEm:double () {
|
|
333
|
+
return 0.55615
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
sfn monoEuroEm:double () {
|
|
337
|
+
return 0.60205
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
; Is this family drawn with one advance for every character?
|
|
341
|
+
; Is this family drawn with one advance for every character?
|
|
342
|
+
;
|
|
343
|
+
; By name, and in both spellings, because Ranger has no case folding to
|
|
344
|
+
; reach for here. The families the gallery actually names are `monospace`,
|
|
345
|
+
; `Courier New` and `Consolas`; anything else is measured with the
|
|
346
|
+
; proportional table, which is the safer way to be wrong — a proportional
|
|
347
|
+
; table on a monospace face is a little narrow, a monospace table on a
|
|
348
|
+
; proportional face is wrong for every character.
|
|
349
|
+
sfn isMono:boolean (fontFamily:string) {
|
|
350
|
+
if ((indexOf fontFamily "mono") >= 0) {
|
|
351
|
+
return true
|
|
352
|
+
}
|
|
353
|
+
if ((indexOf fontFamily "Mono") >= 0) {
|
|
354
|
+
return true
|
|
355
|
+
}
|
|
356
|
+
if ((indexOf fontFamily "courier") >= 0) {
|
|
357
|
+
return true
|
|
358
|
+
}
|
|
359
|
+
if ((indexOf fontFamily "Courier") >= 0) {
|
|
360
|
+
return true
|
|
361
|
+
}
|
|
362
|
+
if ((indexOf fontFamily "Consol") >= 0) {
|
|
363
|
+
return true
|
|
364
|
+
}
|
|
365
|
+
if ((indexOf fontFamily "consol") >= 0) {
|
|
366
|
+
return true
|
|
367
|
+
}
|
|
368
|
+
return false
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
; `isMono` for a family, asked once and remembered. A run is measured one
|
|
372
|
+
; character at a time and every one of them names the same family, so the
|
|
373
|
+
; answer after the first is a pointer comparison rather than six searches.
|
|
374
|
+
fn monoFor:boolean (fontFamily:string) {
|
|
375
|
+
if monoKnown {
|
|
376
|
+
if (monoFamily == fontFamily) {
|
|
377
|
+
return monoCached
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
monoFamily = fontFamily
|
|
381
|
+
monoCached = (EVGTextMeasurer.isMono(fontFamily))
|
|
382
|
+
boldCached = (EVGTextMeasurer.isBold(fontFamily))
|
|
383
|
+
monoKnown = true
|
|
384
|
+
return monoCached
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
; The bold cut, as the layout names it: the family with `-Bold` on it.
|
|
388
|
+
sfn isBold:boolean (fontFamily:string) {
|
|
389
|
+
return ((indexOf fontFamily "-Bold") >= 0)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
; The advance tables, built once per measurer rather than once per
|
|
393
|
+
; character. Lazily, because a measurer that overrides `measureText` and
|
|
394
|
+
; never reaches `measureChar` should not pay for four arrays it will not
|
|
395
|
+
; read.
|
|
396
|
+
fn prepareTables:void () {
|
|
397
|
+
advTable = (EVGTextMeasurer.advanceEm())
|
|
398
|
+
monoTable = (EVGTextMeasurer.monoAdvanceEm())
|
|
399
|
+
latinTable = (EVGTextMeasurer.latin1Em())
|
|
400
|
+
punctTable = (EVGTextMeasurer.punctEm())
|
|
401
|
+
boldTable = (EVGTextMeasurer.boldAdvanceEm())
|
|
402
|
+
boldLatinTable = (EVGTextMeasurer.boldLatin1Em())
|
|
403
|
+
boldPunctTable = (EVGTextMeasurer.boldPunctEm())
|
|
404
|
+
tablesReady = true
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
fn measureChar:double (ch:int fontFamily:string fontSize:double) {
|
|
408
|
+
if (tablesReady == false) {
|
|
409
|
+
this.prepareTables()
|
|
410
|
+
}
|
|
411
|
+
def mono:boolean (this.monoFor(fontFamily))
|
|
412
|
+
def bold:boolean boldCached
|
|
413
|
+
if (ch == 8364) {
|
|
414
|
+
if mono {
|
|
415
|
+
return ((EVGTextMeasurer.monoEuroEm()) * fontSize)
|
|
416
|
+
}
|
|
417
|
+
return ((EVGTextMeasurer.euroEm()) * fontSize)
|
|
418
|
+
}
|
|
419
|
+
if ((ch >= 32) && (ch <= 126)) {
|
|
420
|
+
def t:[double] advTable
|
|
421
|
+
if mono {
|
|
422
|
+
t = monoTable
|
|
423
|
+
} {
|
|
424
|
+
if bold {
|
|
425
|
+
t = boldTable
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return ((itemAt t (ch - 32)) * fontSize)
|
|
429
|
+
}
|
|
430
|
+
; The soft hyphen takes no space in either kind of face.
|
|
431
|
+
if (ch == 173) {
|
|
432
|
+
return 0.0
|
|
433
|
+
}
|
|
434
|
+
; A monospace face has one advance for everything it holds, and it
|
|
435
|
+
; holds all of these — measured: every code below came back 0.60205.
|
|
436
|
+
if mono {
|
|
437
|
+
if (((ch >= 160) && (ch <= 255)) || ((ch >= 8208) && (ch <= 8230))) {
|
|
438
|
+
return ((EVGTextMeasurer.monoEuroEm()) * fontSize)
|
|
439
|
+
}
|
|
440
|
+
if ((EVGTextMeasurer.extraEm(ch)) >= 0.0) {
|
|
441
|
+
return ((EVGTextMeasurer.monoEuroEm()) * fontSize)
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
if ((ch >= 160) && (ch <= 255)) {
|
|
445
|
+
if bold {
|
|
446
|
+
return ((itemAt boldLatinTable (ch - 160)) * fontSize)
|
|
447
|
+
}
|
|
448
|
+
return ((itemAt latinTable (ch - 160)) * fontSize)
|
|
449
|
+
}
|
|
450
|
+
if ((ch >= 8208) && (ch <= 8230)) {
|
|
451
|
+
if bold {
|
|
452
|
+
return ((itemAt boldPunctTable (ch - 8208)) * fontSize)
|
|
453
|
+
}
|
|
454
|
+
return ((itemAt punctTable (ch - 8208)) * fontSize)
|
|
455
|
+
}
|
|
456
|
+
def extra:double (EVGTextMeasurer.extraEm(ch))
|
|
457
|
+
if (extra >= 0.0) {
|
|
458
|
+
return (extra * fontSize)
|
|
459
|
+
}
|
|
460
|
+
; --- surrogate pairs, which is to say emoji -------------------------
|
|
461
|
+
;
|
|
462
|
+
; A code point above the BMP arrives as TWO code units, and half an em
|
|
463
|
+
; each made an emoji exactly one em wide. Measured in Chromium at
|
|
464
|
+
; 13px and 16px — the fractions are identical at both, so they really
|
|
465
|
+
; are per-em:
|
|
466
|
+
;
|
|
467
|
+
; thumbs up 1.2477 em crying face 1.1685 em eye 1.0 em
|
|
468
|
+
;
|
|
469
|
+
; So the pair was under-measured by a factor of about 1.2, and a chat
|
|
470
|
+
; bubble sized from that wrapped its emoji onto a second line and
|
|
471
|
+
; spilled it out of the box. That is what this fixes.
|
|
472
|
+
;
|
|
473
|
+
; The HIGH surrogate carries the whole width and the low one carries
|
|
474
|
+
; none, so a caret index still lands between characters rather than
|
|
475
|
+
; inside one.
|
|
476
|
+
;
|
|
477
|
+
; 1.25 em for an emoji this does not know individually, and that
|
|
478
|
+
; number is deliberately the WIDEST measured rather than the average.
|
|
479
|
+
; The two failure modes are not symmetric: over-measuring leaves a box
|
|
480
|
+
; a few pixels wide, and under-measuring wraps a line that was meant
|
|
481
|
+
; to fit and pushes it out of its container.
|
|
482
|
+
if ((ch >= 55296) && (ch <= 56319)) {
|
|
483
|
+
if (ch == 55357) {
|
|
484
|
+
return (fontSize * 1.25)
|
|
485
|
+
}
|
|
486
|
+
return (fontSize * 1.25)
|
|
487
|
+
}
|
|
488
|
+
if ((ch >= 56320) && (ch <= 57343)) {
|
|
489
|
+
return 0.0
|
|
490
|
+
}
|
|
491
|
+
; A zero-width joiner and a variation selector take no space of their
|
|
492
|
+
; own — they modify the run around them. Counting them as half an em
|
|
493
|
+
; each is how a family of four ends up measured as seven characters.
|
|
494
|
+
if (ch == 8205) {
|
|
495
|
+
return 0.0
|
|
496
|
+
}
|
|
497
|
+
if (ch == 65039) {
|
|
498
|
+
return 0.0
|
|
499
|
+
}
|
|
500
|
+
; Outside the table — anything beyond printable ASCII and the euro.
|
|
501
|
+
; Half an em, which is the middle of the measured range rather than a
|
|
502
|
+
; number picked by feel, and it is a GUESS: the honest fix for a
|
|
503
|
+
; character this table does not hold is to measure with the face that
|
|
504
|
+
; will draw it, through `EVGTextEngine.setMeasurer`.
|
|
505
|
+
;
|
|
506
|
+
; Latin-1 and the general punctuation block are in the tables above
|
|
507
|
+
; now; this is what is left — other scripts, symbols, arrows. A left
|
|
508
|
+
; arrow measured 1.0 em and an up arrow 0.5, so half an em is the
|
|
509
|
+
; middle of the range rather than a number picked by feel, and it is
|
|
510
|
+
; a GUESS: fine for a glyph alone in a box, not for a sentence.
|
|
511
|
+
return (fontSize * 0.5)
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
fn wrapText:[string] (text:string fontFamily:string fontSize:double maxWidth:double) {
|
|
515
|
+
; Wrap text to fit within maxWidth
|
|
516
|
+
; Returns array of lines
|
|
517
|
+
def lines:[string]
|
|
518
|
+
def currentLine:string ""
|
|
519
|
+
def currentWidth:double 0.0
|
|
520
|
+
def wordStart:int 0
|
|
521
|
+
; What goes between this word and the next: a space, or nothing when
|
|
522
|
+
; the break was a hyphen the word already carries.
|
|
523
|
+
def joiner:string " "
|
|
524
|
+
def textLen:int (strlen text)
|
|
525
|
+
def i:int 0
|
|
526
|
+
|
|
527
|
+
while (i <= textLen) {
|
|
528
|
+
def ch:int 0
|
|
529
|
+
def isEnd:boolean (i == textLen)
|
|
530
|
+
if (isEnd == false) {
|
|
531
|
+
ch = (charAt text i)
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
; Where a line may be broken: a space, a newline, the end — and
|
|
535
|
+
; after a hyphen. The last one was missing, so a hyphenated
|
|
536
|
+
; compound was one unbreakable word: a box too narrow for the whole
|
|
537
|
+
; of "Liiketoiminta-logiikka" had nowhere to break it. The rule is
|
|
538
|
+
; `EVGCodepoint.breaksAfter`, shared with the .pptx wrapper so the
|
|
539
|
+
; two cannot disagree.
|
|
540
|
+
def isWordEnd:boolean false
|
|
541
|
+
if isEnd {
|
|
542
|
+
isWordEnd = true
|
|
543
|
+
}
|
|
544
|
+
if (ch == 32) { ; space
|
|
545
|
+
isWordEnd = true
|
|
546
|
+
}
|
|
547
|
+
if (ch == 10) { ; newline
|
|
548
|
+
isWordEnd = true
|
|
549
|
+
}
|
|
550
|
+
def hyphen:boolean false
|
|
551
|
+
if (isEnd == false) {
|
|
552
|
+
if (EVGCodepoint.breaksAfter(ch)) {
|
|
553
|
+
; …but not on the first character of a word: "-5" is not a
|
|
554
|
+
; place to break, and an empty word would loop.
|
|
555
|
+
if (i > wordStart) {
|
|
556
|
+
isWordEnd = true
|
|
557
|
+
hyphen = true
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
if isWordEnd {
|
|
563
|
+
; Extract word. A hyphen belongs to the word BEFORE it and
|
|
564
|
+
; stays on that line — which is the whole point of breaking
|
|
565
|
+
; there rather than one character earlier.
|
|
566
|
+
def wordEnd:int i
|
|
567
|
+
if hyphen {
|
|
568
|
+
wordEnd = (i + 1)
|
|
569
|
+
}
|
|
570
|
+
def word:string ""
|
|
571
|
+
if (wordEnd > wordStart) {
|
|
572
|
+
word = (substring text wordStart wordEnd)
|
|
573
|
+
}
|
|
574
|
+
def wordWidth:double (this.measureTextWidth(word fontFamily fontSize))
|
|
575
|
+
|
|
576
|
+
; What joins this word to the one before it: a space normally,
|
|
577
|
+
; nothing when the line before ended in a hyphen.
|
|
578
|
+
def spaceWidth:double 0.0
|
|
579
|
+
if ((strlen currentLine) > 0) {
|
|
580
|
+
if ((strlen joiner) > 0) {
|
|
581
|
+
spaceWidth = (this.measureTextWidth(joiner fontFamily fontSize))
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
if ((currentWidth + spaceWidth + wordWidth) <= maxWidth) {
|
|
586
|
+
; Word fits
|
|
587
|
+
if ((strlen currentLine) > 0) {
|
|
588
|
+
currentLine = (currentLine + joiner)
|
|
589
|
+
currentWidth = currentWidth + spaceWidth
|
|
590
|
+
}
|
|
591
|
+
currentLine = (currentLine + word)
|
|
592
|
+
currentWidth = currentWidth + wordWidth
|
|
593
|
+
} {
|
|
594
|
+
; Word doesn't fit - start new line. A word wider than the
|
|
595
|
+
; box goes on one anyway and overflows, which is what every
|
|
596
|
+
; office program does; none of them hyphenates on its own.
|
|
597
|
+
if ((strlen currentLine) > 0) {
|
|
598
|
+
push lines currentLine
|
|
599
|
+
}
|
|
600
|
+
currentLine = word
|
|
601
|
+
currentWidth = wordWidth
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
; Handle explicit newline
|
|
605
|
+
if (ch == 10) {
|
|
606
|
+
push lines currentLine
|
|
607
|
+
currentLine = ""
|
|
608
|
+
currentWidth = 0.0
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
joiner = " "
|
|
612
|
+
if hyphen {
|
|
613
|
+
joiner = ""
|
|
614
|
+
}
|
|
615
|
+
wordStart = i + 1
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
i = i + 1
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
; Add final line
|
|
622
|
+
if ((strlen currentLine) > 0) {
|
|
623
|
+
push lines currentLine
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
return lines
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
; Simple measurer that uses fixed-width approximation
|
|
631
|
+
class SimpleTextMeasurer {
|
|
632
|
+
Extends(EVGTextMeasurer)
|
|
633
|
+
|
|
634
|
+
; Character width ratios for common fonts
|
|
635
|
+
def charWidthRatio:double 0.55
|
|
636
|
+
|
|
637
|
+
fn setCharWidthRatio:void (ratio:double) {
|
|
638
|
+
charWidthRatio = ratio
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
fn measureText:EVGTextMetrics (text:string fontFamily:string fontSize:double) {
|
|
642
|
+
def textLen:int (strlen text)
|
|
643
|
+
def width:double 0.0
|
|
644
|
+
|
|
645
|
+
; Sum up character widths
|
|
646
|
+
def i:int 0
|
|
647
|
+
while (i < textLen) {
|
|
648
|
+
def ch:int (charAt text i)
|
|
649
|
+
width = width + (this.measureChar(ch fontFamily fontSize))
|
|
650
|
+
i = i + 1
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
def lineHeight:double (fontSize * (EVGTextMeasurer.normalLineHeightEm()))
|
|
654
|
+
|
|
655
|
+
def metrics (new EVGTextMetrics())
|
|
656
|
+
metrics.width = width
|
|
657
|
+
metrics.height = lineHeight
|
|
658
|
+
metrics.ascent = (fontSize * (EVGTextMeasurer.fallbackAscentEm()))
|
|
659
|
+
metrics.descent = (fontSize * (EVGTextMeasurer.fallbackDescentEm()))
|
|
660
|
+
metrics.lineHeight = lineHeight
|
|
661
|
+
return metrics
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
; ==============================================================================
|
|
666
|
+
; EVGDefaultMeasurer — the measurer a layout gets when nobody handed it one
|
|
667
|
+
; ==============================================================================
|
|
668
|
+
;
|
|
669
|
+
; Twenty-five places in the gallery say `new EVGLayout()` and never call
|
|
670
|
+
; `setMeasurer`: every demo, the RealTrainer page, the pptx chrome. Each of
|
|
671
|
+
; them measured with a fresh `SimpleTextMeasurer`, which is the table. For a
|
|
672
|
+
; platform to measure for ALL of them — PLAN_NATIVE_HOSTS.md S0 — there has
|
|
673
|
+
; to be one place a host can put the measurer it made, and this is it: a
|
|
674
|
+
; process-wide default that `EVGLayout` and `EVGTextEngine` consult in their
|
|
675
|
+
; constructors. An app that installs a measurer explicitly (`setMeasurer`,
|
|
676
|
+
; the TTF one for print) is unaffected; it overrides the default the way it
|
|
677
|
+
; always did.
|
|
678
|
+
;
|
|
679
|
+
; It is a singleton per compiled module, which is what a host wants: a page
|
|
680
|
+
; that bundles several generated modules installs into each, because two
|
|
681
|
+
; copies of a class are two classes (`gallery/ui/demo/main.js` says so).
|
|
682
|
+
;
|
|
683
|
+
; The default is read at CONSTRUCTION. A layout built before the host
|
|
684
|
+
; installed keeps the table; that is why a host installs before `start` —
|
|
685
|
+
; and why `EVGHostTextMeasurer` can be installed unattached and attached
|
|
686
|
+
; later, so the order of "install" and "the platform is ready" does not
|
|
687
|
+
; matter, only the order of "install" and "build the first layout".
|
|
688
|
+
class EVGDefaultMeasurer @singleton(true) {
|
|
689
|
+
def current@(optional):EVGTextMeasurer
|
|
690
|
+
def installs:int 0
|
|
691
|
+
|
|
692
|
+
sfn install:void (m:EVGTextMeasurer) {
|
|
693
|
+
def r:EVGDefaultMeasurer (EVGDefaultMeasurer.__singleton())
|
|
694
|
+
r.current = m
|
|
695
|
+
r.installs = (r.installs + 1)
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
sfn uninstall:void () {
|
|
699
|
+
def r:EVGDefaultMeasurer (EVGDefaultMeasurer.__singleton())
|
|
700
|
+
def none@(optional):EVGTextMeasurer
|
|
701
|
+
r.current = none
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
sfn isInstalled:boolean () {
|
|
705
|
+
def r:EVGDefaultMeasurer (EVGDefaultMeasurer.__singleton())
|
|
706
|
+
return (!null? r.current)
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
; What a new layout or engine measures with: the installed measurer, or a
|
|
710
|
+
; fresh table when there is none — exactly what the constructors made
|
|
711
|
+
; before this existed.
|
|
712
|
+
sfn measurer:EVGTextMeasurer () {
|
|
713
|
+
def r:EVGDefaultMeasurer (EVGDefaultMeasurer.__singleton())
|
|
714
|
+
if (!null? r.current) {
|
|
715
|
+
return (unwrap r.current)
|
|
716
|
+
}
|
|
717
|
+
def m (new SimpleTextMeasurer())
|
|
718
|
+
return m
|
|
719
|
+
}
|
|
720
|
+
}
|