Subject: Re: bug#52493: 29.0.50; Setting Inconsolata up in init.el makes default face rendered wrong

From: martin rudalics <[email-masked]>
Date: Mon, 9 Jan 2023 11:07:24 +0100

> Here's a few more complex ones that seem off:
 >
 > ;;; Scenario 1
 > ;; 1.
 > (set-face-attribute 'default nil :height 110 :family "InconsolataLGC")
 > ;; to get the frame sized right
 > ;; call (set-frame-size nil 80 36)
 > ;; or (set-frame-size nil 160 36)
 > ;; or don't if the frame is at that size already (which it should be)
 > ;; (frame-text-lines) returns 36

Note that a frame with the "right height" is only one where

(= (* (frame-char-height) (frame-text-lines)) (frame-text-height))

holds.  Here, for example, a maximized frame does not have the "right
height".

 > ;; 2. !important
 > ;; manually resize the frame using the mouse to have one line less
 > ;; (frame-text-lines) will continue to return 36

Manually resizing a frame with a scaling factor of 2 will be off by one
pixel when the font has impair height.  There is nothing we can do about
that - the height increment we send to the WM must be an integer.  The
result is that while the frame's pixel height changes and so does the
height of the frame on the display, the height in lines stays the same.

 > ;; 3.
 > (set-face-attribute 'default nil :height 110 :family "InconsolataLGC")
 > ;; The frame will get resized to the previous dimensions.
 > ;; Note that the return value of (frame-text-lines) doesn't change.

Hopefully so.  It's crucial that all executions of

(set-face-attribute 'default nil :height 110 :family "InconsolataLGC")

starting with the same number of text lines result in the same pixel and
text heights.

 > ;;; Scenario 2
 > ;; Do the same steps, except for the width instead of height.
 > ;; Optionally, use different dimensions:
 > ;; (set-frame-size nil 160 36)
 > ;; These are the only ones I found to have this effect for both dimensions.
 > ;; I'm guessing 160x72 will work as well, but that's bigger than my screen.

IIUC this scenario is just a variation of the first one - with a
character size of 17x37 you will lose one pixel in both dimensions.

 > ;;; Scenario 3
 > ;; 1. From Scenario 1.
 > ;; 2. Resize with the mouse both width and height, to have 1 less.
 > ;; 3. Eval the set-frame-attribute form. Nothing happens, the frame size stays the same.
 > ;; Step 2 still doesn't change the return values of frame-text-cols/lines.

IIUC these steps

xg_frame_resized old native pixels 1424x1368 new native pixels 1408x1368
adjust_frame_size old native pixels 1424x1368 new native pixels 1408x1368 old text pixels 1376x1368 new text pixels 1360x1368 old text chars 80x36 new text chars 80x36
xg_frame_resized old native pixels 1408x1368 new native pixels 1408x1332
adjust_frame_size old native pixels 1408x1368 new native pixels 1408x1332 old text pixels 1360x1368 new text pixels 1360x1332 old text chars 80x36 new text chars 80x36

represent two mouse operations that resize the frame by 16 pixels, first
the width, then the height.  Both are less that the character size so
while again the size of the frame should have changed, the numbers of
text characters didn't.

x_new_font old char size 17x37 new char size 17x37 text chars 80x36 old text pixels 1360x1332 new text pixels 1360x1332

x_new_font old char size 17x37 new char size 17x37 text chars 80x36 old text pixels 1360x1332 new text pixels 1360x1332

Here we have (= (* 80 17) 1360) and (= (* 36 37) 1332) so
adjust_frame_size triggered by x_new_font correctly decides that the
frame size should stay the same.

martin