Skip to content

toolkit: the face follows the metric scale - #452

Merged
tannevaled merged 2 commits into
mainfrom
text-follows-scale
Sep 5, 2026
Merged

toolkit: the face follows the metric scale#452
tannevaled merged 2 commits into
mainfrom
text-follows-scale

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Every pixel constant in this toolkit is multiplied by MetricScale. The OpenType face was not — so on a display with two device pixels to the point, an application got bitmap chrome at the right size around type at half of it, and had to notice and re-render the face itself. Per-application work for a toolkit-wide fact.

  • UseOpenTypeTextSize now takes logical pixels, like every other metric here: the face is rendered at sizePx × MetricScale and re-rendered whenever that scale changes;
  • SetFont(nil) forgets the requested size as well as the face — back to the bitmap means back to the bitmap, otherwise the next SetMetricScale quietly re-installs a face nobody wants. That is what broke a neighbouring test, and how this was caught;
  • a failed re-render leaves the working face in place: dropping the text because a resize could not re-render it would be worse than text briefly the wrong size.

The bitmap default already followed the scale — its metrics go through scaled() like everything else. That is what made the face the odd one out.

🤖 Generated with Claude Code

tannevaled and others added 2 commits September 5, 2026 21:56
Every pixel constant in this toolkit is multiplied by MetricScale. The
OpenType face was not — so on a display with two device pixels to the point,
an application got bitmap chrome at the right size around type at half of it,
and had to notice and re-render the face itself. That is per-application work
for a toolkit-wide fact, and it was reported as "small but readable", which is
a polite way of saying wrong.

UseOpenTypeTextSize now takes LOGICAL pixels, like every other metric here: the
face is rendered at sizePx × MetricScale, and re-rendered whenever that scale
changes. A caller asking for 16 gets type that reads the same size on every
display, which is the point of having a scale at all.

SetFont(nil) forgets the requested size as well as the face. Back to the bitmap
means back to the bitmap — otherwise the next SetMetricScale would quietly
re-install a face nobody wants, which is exactly what broke a neighbouring test
and is how this was caught.

A failed re-render leaves the working face in place: a toolkit that dropped its
text because a resize could not re-render it would be worse than one whose text
is briefly the wrong size.

The bitmap default already followed the scale — its metrics go through
scaled() like everything else. That is what made the face the odd one out.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A scale small enough to round the size to nothing gives one pixel, not
zero: type of size zero is not small type, it is no text at all. And a
face that cannot be built leaves the working one in place — dropping the
text because a resize could not re-render it would be worse than text
briefly the wrong size.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit d9da11e into main Sep 5, 2026
2 checks passed
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