Skip to content

feat: real text metrics for label layout (DasherCore v0.2.4) - #16

Merged
willwade merged 1 commit into
fix/speed-range-from-enginefrom
feat/text-size-callback
Aug 22, 2026
Merged

feat: real text metrics for label layout (DasherCore v0.2.4)#16
willwade merged 1 commit into
fix/speed-range-from-enginefrom
feat/text-size-callback

Conversation

@willwade

Copy link
Copy Markdown
Contributor

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/2 width 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_callback end to end:

  • JNI (jni_bridge.cpp): textSizeCallback marshals into a cached NativeBridge.onTextSize(String, int, float[]) → boolean method — the same pattern as clipboard/speak/message/parameter callbacks. New bindings: nativeSetTextSizeCallback, nativeTextMetricsChanged.
  • Canvas (DasherCanvasView): measureGlyphText measures 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. glyphFontName changes now fire nativeTextMetricsChanged so a font switch re-measures.
  • Both engines: MainActivity and the IME install their own measurement. NativeBridge listeners are static, so the IME must reinstall on every createEngine() — 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.
  • Manual check recommended: long sentence; frontier labels no longer crowd/overlap; toggle canvas font in Settings → letters re-space.

Sibling wiring: Dasher-GTK #53; Dasher-Windows tracked in #28.

DCO signed.

… #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
willwade merged commit 96179c8 into fix/speed-range-from-engine Aug 22, 2026
1 check passed
@willwade
willwade deleted the feat/text-size-callback branch August 22, 2026 09:16
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant