Subject: Re: bug#20628: 25.0.50; Incorrect line height for some fonts

From: Eli Zaretskii <[email-masked]>
Date: Wed, 03 Jun 2015 17:53:18 +0300

> Date: Wed, 03 Jun 2015 11:44:17 +0200 (CEST)
> Cc: [email-masked], [email-masked], [email-masked]
> From: Werner LEMBERG <[email-masked]>
> 
> > The relevant place in the display engine where these factors are
> > taken into consideration is around line 26388 in xdisp.c, [...]
> 
> I'm completely lost in this huuuge file.

Which is why I mentioned the line number explicitly...

> > The change we look for should:
> > 
> >   . set the initial values for it->ascent and it->descent using some
> >     heuristics based on pixel_size of the default face's font;
> 
> Where are the initial values set?

They are not set anywhere in the original display engine, because it
was not needed.  The values were set to the ascent and descent of each
produced glyph in x_produce_glyphs and its subroutines.  For character
glyphs, these were taken from the font-global values, since the
assumption was that those global values are reasonable.

But I was somewhat wrong in the above description: the important
values are not it->ascent and it->descent, but rather it->max_ascent
and it->max_descent.  These accumulate the maximum values seen while
producing a single screen line, and when the screen line ends, they
determine the line's height (see compute_line_metrics):

	  row->height = it->max_ascent + it->max_descent;

> >   . update it->ascent and it->descent based on ascent/descent values
> >     returned by get_per_char_metric in the per-character metrics
> >     data

> I think this already happens, right?  At least the line height
> increases on my GNU/Linux version of Emacs if I use a font with larger
> ascent/descent values...  So no additional action is needed for this,
> it seems.

Actually, since I wrote the message to which you respond, I think I
already solved the problem, you can see the solution in the
scratch/large-fonts branch of the Emacs Git repository.  If you have
time, I'd appreciate your opinion about the heuristics I use there.
Specifically, the following macro is used to detect fonts that claim
preposterously large ascent/descent values:

 #define FONT_TOO_HIGH(ft) ((ft)->ascent + (ft)->descent > 3*(ft)->pixel_size)

The pixel_size member of the struct font object is the pixel size with
which we opened the font, see the 'open' method of the font drivers
(e.g., 'xftfont_open' in xftfont.c).  The number 3 above is the
heuristics.

The other part of the heuristics is in how I compute "reasonable"
values of ascent and descent to be used instead of font's global
values.  The code is in the function 'normal_char_ascent_descent'
defined in xdisp.c.  This is necessary because, as I expected, the
font's global values are used all over the place in display-related
code, and so just computing line height from character metrics was not
enough to countermand all the negative effects of such preposterously
large font height values.  As just 2 examples, the font height was
used to allocate pixel screen estate for the mode line, and for
calculating line height when a 'display' property or a line-height
property specifies height as a fraction of the "normal" text height.

Thanks.