fix(functional): centre text vertically in buttons and form fields (S14)
Both renderers placed the baseline at box_top + height/2 + descent/2. Centring glyphs of visual height ascent+descent in a box of height H puts the baseline at box_top + H/2 + (ascent-descent)/2; the two agree only when ascent is exactly twice descent. DejaVu is nearer 4:1, so labels sat high against the top edge - measured at 5px above and 11px below for a 14px button. ButtonText also sized itself from the nominal font size, which is smaller than the text's visual height (17px of ink for a 14px DejaVu font), leaving the button too short to centre its label in. It now measures ascent+descent, with a fallback for font objects that cannot report metrics. docs/images/example_07_pressed_state.png was stale - no example writes it, the demo emits demo_07_pressed.png at the repo root and the docs copy had been placed by hand in November. Refreshed here; the demo should write straight to docs/images/ so it cannot drift again.
This commit is contained in:
@@ -28,6 +28,7 @@ It is independent of every other spec here.
|
||||
| [S11](#s11--partial-block-progress-is-discarded) | Partial-block progress is discarded | 0 |
|
||||
| [S12](#s12--background-rendering) | Background rendering | 4 |
|
||||
| [S13](#s13--word-spacing-and-alignment) | Word spacing and alignment | 0 |
|
||||
| [S14](#s14--vertical-centring-in-buttons-and-fields) | Vertical centring in buttons and fields | 0 |
|
||||
|
||||
## Design invariants
|
||||
|
||||
@@ -1158,6 +1159,58 @@ Three defects, all visible as a right edge that wobbles from line to line.
|
||||
|
||||
---
|
||||
|
||||
## S14 — Vertical centring in buttons and fields
|
||||
|
||||
### Problem
|
||||
|
||||
`ButtonText.render` and `FormFieldText.render` both placed the text baseline at
|
||||
`box_top + box_height / 2 + descent / 2`. Centring glyphs whose visual height is
|
||||
`ascent + descent` inside a box of height `H` puts the baseline at
|
||||
`box_top + H/2 + (ascent - descent)/2`. The two agree only when
|
||||
`ascent == 2 * descent`; DejaVu is nearer 4:1, so labels rode high against the
|
||||
top edge of the control.
|
||||
|
||||
`ButtonText` also sized itself as `font_size + padding`, but the text's visual
|
||||
height exceeds the nominal size — DejaVu at 14px measures 17 — so the button was
|
||||
too short to centre its own label in.
|
||||
|
||||
### Evidence
|
||||
|
||||
A 14px "Save Document" button with 6px vertical padding, measuring the label's
|
||||
ink against the button rectangle:
|
||||
|
||||
```
|
||||
gap above text: 5px
|
||||
gap below text: 11px
|
||||
```
|
||||
|
||||
### Design
|
||||
|
||||
- `baseline = area_top + (area_height - (ascent + descent)) / 2 + ascent` in both
|
||||
renderers.
|
||||
- `ButtonText._padded_height` derives from `ascent + descent`, guarded so a mock
|
||||
or unusual font object falls back to the nominal size.
|
||||
|
||||
### Acceptance criteria
|
||||
|
||||
- Label ink is centred within ±2px at font sizes 10, 14 and 20.
|
||||
- Label ink stays inside the button rectangle.
|
||||
- Button height is at least `ascent + descent + vertical padding`.
|
||||
- A form field's value is centred within its input box (±3px).
|
||||
|
||||
### Files
|
||||
|
||||
`pyWebLayout/concrete/functional.py`
|
||||
|
||||
### Note
|
||||
|
||||
`docs/images/example_07_pressed_state.png` was stale — no example regenerates it;
|
||||
`07_pressed_state_demo.py` writes `demo_07_pressed.png` at the repository root
|
||||
and the docs copy had been placed by hand. It has been refreshed. Worth wiring
|
||||
the demo to write straight to `docs/images/` so it cannot drift again.
|
||||
|
||||
---
|
||||
|
||||
## Test plan
|
||||
|
||||
Findings were reproduced with four probe scripts; each becomes a regression test
|
||||
|
||||
Reference in New Issue
Block a user