Behdad and I have a longstanding discussion about better apis for font enumeration.
Looking at https://gitlab.gnome.org/GNOME/pango/-/issues/53, it appears to go back
as far as 2006. I've revisited fontconfig performance last summer. Some of the results
from that work are mentioned in the last comments in that Pango issue.
To summarize the performance problem:
- Sorting all the system fonts is too expensive to it multiple times per paragraph, when
the goal is to render text at 60fps. As a datapoint, after installing all the Noto fonts, my
system has ~4000 fonts, and even after the aforementioned performance fixes, a
single FcFontSort call averages 7ms - half of a frame.
- Most of the sorting work is wasted, since we only access the first few members of
the returned list (in the vast majority of cases, Pango only ever uses the first one or
two members of the sorted list).
- In the case where we do access more than the first few members, the exact order
of fonts in 'the long tail' hardly matters - all of these are fonts that have little relation
to the pattern we are interested in, and we might just as well have a generic fallback.
Our thoughts on improving this generally revolve around doing less work up front.
Basically, switch to an incremental sorting approach, where Pango can ask for the
"next best" font, one at a time.
As very rough api sketch could be something like this:
/* Create a sorted fontset that is sorted by matching against p */
FcSortedFontSet *FcSortedFontSetCreate (FcFontSet *s, FcPattern *p);
/* Return the n-th element of the sorted fontset s */
FcPattern *FcSortedFontSetGet (FcSortedFontSet *s, int n);
With this api, FcFontSetMatch could be implemented like this:
FcFontSetMatch (FcFontSet *s, FcPattern *p)
sorted = FcSortedFontSetCreate (s, p);
match = FcSortedFontSet (sorted, 0);
In a recent call, Behdad pointed out a related, but distinct issue with the current
pipeline approach to font rendering, as implemented in pango:
First, pick fonts for all characters ("itemize")
Second, select glyphs for the resulting runs ("Shape")
The first step is where we use fontconfig to find candidate fonts, and then we
check their coverage for each character to make a choice. fontconfig currently uses
freetype to determine coverage information for fonts.
But what characters are reasonably 'covered' by font very much depends on what use
the second step makes of the font. The harfbuzz shaper can decompose and compose
glyphs and thereby extend coverage in ways that freetype has no idea about.
There are different ways in which this could be improved. One would be to give up
on the approach of making all font selection choices up-front, and instead use a recursive
approach in which the shaper can ask for more fonts if it can make do with the ones it
was given initially.
Another, maybe simpler approach would be to make fontconfig use harfbuzz instead
of freetype for finding font coverage.
_______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/fontconfig