Digit height must be content-width-aware: HERO1 clips on emery/basalt, QUAD clips on basalt #121
Labels
No labels
area:companion
area:docs
area:shared
area:tooling
area:watchapp
blocker
kind:chore
kind:feature
kind:spike
kind:test
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
robert/PedalPebble#121
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Surfaced by #59's PR #120 (HERO1/GRID6 Phase 1b work), not introduced by it — this is a pre-existing limitation of the whole digit-rendering mechanism from Phase 1 (#59/PR #87) that nobody had checked against real screen widths until PR #120's own basalt/HERO1 verification looked.
page_render_digit_height(template, slot)returns a fixed pixel height per template/slot, independent of the cell's actual width.page_render_glyph_width()'s fixed ratio (digit = 0.6x height, dot = 0.2x, gap = 0.1x —page_render_geometry.c) means a value's on-screen width scales linearly with digit height regardless of how wide the cell actually is. Nothing currently checks that the resulting run fits.Verified by direct arithmetic against the shipped constants (
DIGIT_WIDTH_NUM/DEN=6/10,DOT_WIDTH_NUM/DEN=2/10,GLYPH_GAP_NUM/DEN=1/10), independent of the PR's own screenshots: a "28.4"-shaped value (3 digits + 1 dot + 3 gaps) needs3(0.6h) + 0.2h + 3(0.1h) = 2.3hpixels of run width.Finding 1 — HERO1 clips on both emery and basalt
HERO1's digit height is DESIGN.md's literal "~140px" figure. At h=140, "28.4" needs
2.3 x 140 = 322px. Emery's content is 200px wide; basalt's is 144px. Both clip. The largest height that keeps "28.4" on-screen on emery is200 / 2.3 ~= 87px— smaller than HERO2's own 96px hero, which would make HERO1 the smaller of the two "one dominant number" shapes, contradicting the physical-size table the 140px figure came from in the first place. Confirmed via real emery/basalt emulator screenshots in PR #120 (last digit sliced off on emery; unusable on basalt).Finding 2 — QUAD (unchanged, shipped since Phase 1/PR #87) clips on basalt
QUAD's digit heights (56px ordinary / 76px emphasised, D29) were sized against emery's 100x104 cell. Basalt's real QUAD cell is only 72x74 (half its 144x148 content). A 3-digit-plus-dot value visibly overlaps the neighbouring cell. This affects every QUAD page on basalt today, including both default pages (Effort, Progress) already shipping. DESIGN.md rule 7 ("GRID6 drops to QUAD on basalt") does not currently deliver "degrades without clipping" as a result, since the fallback target itself isn't basalt-safe. Confirmed via a real basalt emulator screenshot in PR #120.
Acceptance criteria
page_render_digit_height()(or a new sizing function alongside it) becomes aware of the cell/content width it will actually be drawn into, not just(template, slot)FIELD_SPEED's "28.4", or a longer field) without clipping on emery, gabbro and basaltwatchapp/tests/test_page_render_geometry.c) gain a real "does this text fit this cell at this height" assertion, not just a tiling/no-gap checkFiles
watchapp/src/c/page_render_geometry.c(page_render_digit_height(), the glyph-width ratio constants)watchapp/src/c/page_render.c(call sites)Notes
This is a mechanism change affecting every template already shipped (HERO2/QUAD from Phase 1, HERO1/GRID6 from Phase 1b) — explicitly why PR #120 flagged rather than silently patched it (per D48: a checked fact reported for a decision, not resolved unilaterally). #59 depends on this issue since its own "degrades without clipping on basalt" acceptance criterion is not met until this lands.
Closed by PR #123 (
area/digit-height-content-aware). Newpage_render_fit_digit_height(text, max_width, requested_height)— a second function alongside the unchangedpage_render_digit_height(), called frompage_render.c'sprv_draw_cell()(the one place with both the live formatted text and the cell width in hand). Binary-searches the realpage_render_text_width()rather than a closed-form estimate of it, so it can never disagree with what that function itself says fits; only clamps downward, never raises a height that already fit.A genuinely important discovery along the way: checking HERO1/QUAD-on-basalt surfaced that HERO2's 96px hero and QUAD's 56/76px ceilings were also already overflowing on emery itself for realistic values (
FIELD_SPEED's "28.4" needs 217px against HERO2's 200px hero; HR/POWER_3S/AVG_POWER's 3-digit values need 109-149px against QUAD's 100px cell) — nobody had actually measured this since PR #87 picked its glyph-width ratio "by eye" rather than D55's own recommended ≤0.50. I independently re-verified the headline case by hand with the actual integer-truncated arithmetic the C code uses (3×(96×6/10) + (96×2/10) + 3×(96×1/10) = 3×57+19+27 = 217) before trusting it — exact match. The fix corrects these as a side effect of the same general mechanism, not a separate patch, and every already-fitting value (QUAD's two-digit cadence, HERO2's lower-cell decimals) is asserted unchanged.HERO1's own 140px figure is kept as a ceiling, not lowered — a genuinely short value still draws at the full size; D55 gets an append-only correction (per D48, same treatment D24's DPI correction got) rather than a rewritten number, and DESIGN.md section 3 gets a one-line footnote pointing to it.
Honestly left open: gabbro's round bezel overshoot (HERO1's "28.4" now fits the rectangular content rect correctly, but that rect itself is ~16px too wide for the physical round screen) — a pre-existing gap affecting every template on round, correctly scoped to #62, not patched here.
Real verification:
pebble buildclean on all three targets, all 47 tests intest_page_render_geometryplus 126 across the other three host suites (173 total) hand-compiled with gcc and run directly — zero regressions.