Subject: bug#73752: 29.4; Ligatures are randomly rendered with extra spaces

From: Tim Ruffing <[email-masked]>
Date: Tue, 05 Nov 2024 00:33:17 +0100

On Mon, 2024-11-04 at 19:45 +0200, Eli Zaretskii wrote:
> > From: Tim Ruffing <[email-masked]>
> > Cc: [email-masked], [email-masked], [email-masked]
> > Date: Mon, 04 Nov 2024 01:11:39 +0100
> > 
> > This fixes the problem:  
> 
> Thanks.  But do you understand why?
> 
> And how did you arrive to the conclusion that this is the change
> which
> might help?

I was trying to understand why hb_shape_full() gives different results
at different times. All the other inputs (e.g., text direction) to hb
seemed harmless and fixed for the reproducing script. The only thing
that is constantly changing in the script is the font, so this was the
obvious candidate.

Then I searched harfbuzz's bug tracker for relevant issues, and I found
this one, which is rather similar to what we observe (e.g., advance
wrong): https://github.com/harfbuzz/harfbuzz/issues/1620 

> That code was written by a leading HarfBuzz developer, so it's hard
> for me to believe that it is so incorrect.
> 

Perhaps it was simply written before harfbuzz implemented caching, so
the code was correct for older versions of harfbuzz. The root cause of
the aforementioned issue is exactly this.  

> OTOH, I see that ftcrhbfont is the _only_ HarfBuzz-based font backend
> which implements the end_hb_font method, and I think you both told me
> that only the Cairo build has this problem?  

The Cairo build has this problem, and yeah, I've just checked, I can't
reproduce with the the Xft backend. 

> If so, I think the code
> to look at is the end_hb_font method and what it does to the hb_font
> object.  The end_hb_font method is called each time the shaper is
> called, so whatever it does to the hb_font object is inherited by the
> next call to the shaper.

This sounds like a plausible cause, but as far as I can tell,
end_hb_font doesn't do anything to hb_font. The end function is simply
necessary to call cairo_ft_scaled_font_unlock_face().

What I don't understand is whether or how the underlying FT_Face or
FT_Size is supposed to change at all. I assume it's not supposed to
change?