feat: real text metrics for label layout (DasherCore v0.2.4) - #16
Merged
Merged
Conversation
… #56) Bumps third_party/DasherCore to v0.2.4 and wires the text-size callback: the engine measures labels with the same Paint (typeface + size transform) the canvas draws opcode-5 text with, replacing the codepoints x size/2 estimate whose error compounds down the label chain and jumbles deep-zoom text. - jni_bridge: textSizeCallback marshals into Kotlin NativeBridge.onTextSize (same cached-methodID pattern as the other engine callbacks); nativeSetTextSizeCallback / nativeTextMetricsChanged bindings. - DasherCanvasView.measureGlyphText applies the canvas's exact opcode-5 size transform (x2.5, floored at 8) so measurement and drawing agree; glyphFontName changes fire textMetricsChanged. - MainActivity and the IME both install their own measurement (the NativeBridge listener is static, so the IME must not inherit the Activity's canvas). Signed-off-by: will wade <willwade@gmail.com>
willwade
added a commit
that referenced
this pull request
Aug 22, 2026
Supersedes #16 (squash-merged into its stacked base by mistake) and #18 (auto-closed by the same). One PR, two commits, net diff identical to those two combined. ## 1. Real text metrics for label layout ([DasherCore #56](dasher-project/DasherCore#56) / v0.2.4) The engine laid out node labels using a `codepoints × fontSize/2` estimate whose error compounds down the label shunting chain — deep-zoom text degenerates into jumbles (user-visible on Windows; same engine path here). Wires `dasher_set_text_size_callback` end to end: - JNI `textSizeCallback` marshals into `NativeBridge.onTextSize` (same cached-methodID pattern as the other callbacks); new `nativeSetTextSizeCallback` / `nativeTextMetricsChanged`. - `DasherCanvasView.measureGlyphText` measures with the same Paint + size transform (`×2.5, floor 8`) the canvas draws opcode-5 text with, so layout and drawing agree; font changes invalidate cached metrics. - MainActivity **and** the IME install their own measurement (static listeners — the IME must not inherit the Activity's canvas). - Submodule → DasherCore v0.2.4. ## 2. App version line in Settings → Privacy ([RFC 0016](https://github.com/dasher-project/governance/blob/main/rfcs/0016-version-in-settings.md), fixes #17) Quiet `Dasher <version>` line reading `AnalyticsService.appVersion` (`BuildConfig.VERSION_NAME`) — same value analytics reports; UI and telemetry cannot disagree. ## Testing `:app:compileDebugKotlin`, `:app:testDebugUnitTest`, `:app:assembleDebug` (native vs v0.2.4, arm64-v8a + x86_64) green locally; CI green on the superseded PRs (same code). DCO signed (both commits carried it). --------- Signed-off-by: will wade <willwade@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #14 (branches from it; merge #14 first). Implements the Android side of DasherCore #56 / v0.2.4.
What
The engine laid out node labels using a
codepoints × fontSize/2width estimate; the error compounds down the label shunting chain and deep-zoom text degenerates into jumbles (reported making long sentences untypeable on Windows; Android shares the engine path).Wires the new
dasher_set_text_size_callbackend to end:jni_bridge.cpp):textSizeCallbackmarshals into a cachedNativeBridge.onTextSize(String, int, float[]) → booleanmethod — the same pattern as clipboard/speak/message/parameter callbacks. New bindings:nativeSetTextSizeCallback,nativeTextMetricsChanged.DasherCanvasView):measureGlyphTextmeasures with the same Paint the canvas draws opcode-5 text with, including its size transform (engineSize × 2.5, floored at 8) — measuring with the raw font size would desync layout from drawing.glyphFontNamechanges now firenativeTextMetricsChangedso a font switch re-measures.NativeBridgelisteners are static, so the IME must reinstall on everycreateEngine()— otherwise it would inherit the (possibly destroyed) Activity's canvas.Caveat documented in code: the canvas's emergency normalize transform (off-screen/huge-span frames) scales geometry per-frame and can't be known at measurement time; measurement matches the normal (non-normalized) path, which is the steady state.
Submodule: DasherCore → v0.2.4.
Testing
:app:compileDebugKotlin+:app:testDebugUnitTest+:app:assembleDebug(native build vs v0.2.4, arm64-v8a + x86_64) green locally.Sibling wiring: Dasher-GTK #53; Dasher-Windows tracked in #28.
DCO signed.