On 5/28/2025 11:18 PM, Eli Zaretskii wrote:
> I don't follow this argument. string-pixel-width uses the display
> code, so it should return the exact same value in pixels as what the
> actual display produces when the same characters are shown on the
> screen. So whatever rounding happens (which I don't think it does,
> since font glyphs have integer advance width), it happens the same in
> both cases and should yield the same values. Or what am I missing?
The short version is that we should pass the current buffer to
'string-pixel-width' so that we can just use the display code to compute
the string's width with all the remappings applied, rather than having
the display code compute it without remappings and then trying to guess
what the remapping would do to the width.
Here's a longer version if it helps:
The problem is that 'text-scale-increase' modifies the text size by a
particular ratio; when zooming out by one step, that defaults to 1 /
text-scale-mode-step, or 5/6.
My fixed-pitch font is 8 pixels wide at the default size, so zooming out
one step means the pixel width per char is 8 * 5/6 = 6.666. Since the
advance width is an integer, we round up to 7 pixels. The original code
works for fixed-pitch fonts since '(default-font-width)' returns 7 in
this case, so the original expression:
(ceiling (* (string-pixel-width str)
(/ (float (default-font-width)) (frame-char-width))))
is equivalent (only in this simple case) to:
(* (string-width str) (default-font-width))
Hopefully that all makes sense.
For variable-pitch fonts, this is more complex. Our zoom ratio is still
5/6, but we apply that ratio per-character, rounding each time. For the
string "hi there", the pixel widths of each character are:
Scale h i _ t h e r e Total
0 8 4 4 5 8 8 5 8 50
-1 7 3 4 4 7 7 5 7 44
Since the error introduced by rounding each character is a bit
different, we get a different result between the width from the display
engine compared to the approximation in the first expression above where
we round only once at the very end.
Yes, indeed. No more estimation. Just use the display engine directly.