Subject: bug#78621: Pixelwise display specified spaces less precise than min-width

From: Ship Mints <[email-masked]>
Date: Thu, 29 May 2025 12:41:45 -0400

On Thu, May 29, 2025 at 12:38 PM Jim Porter <[email-masked]> wrote:

> 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.