[Fonts]Re: Notes on Pango Xft backend



Around 20 o'clock on May 27, Owen Taylor wrote:

> I'm not particularly happy with the way the Xft backend for Pango
> works at the moment ... it's complex, memory hungry, and relatively
> slow. (Pango shaping with Xft is about twice as slow as Pango shaping
> with the old X backend.)

That's really sad -- let's make it faster than the old X stuff if at all 
possible.

> The fundamental font operation in the Pango XFT backend (or any Pango
> backend) is to map from a unicode codepoint and a PangoFontDescription
> (family, style, weight, stretch, variant) to a particular PangoXftFont.

Are you thinking of doing sequences of codepoints at some point to avoid 
ransom note results?

> Operation A) is far too slow to implement into its entirety for each
> small segment of text, so the bulk of the operation is cached -
> a "infinite sized" map from PangoFontDescription to a list of patterns
> is kept. (So, basically, everything but actually creating the PangoXftFont
> objects and adding them to the fontset is cached.))

There's a new call you might like -- FcFontSetSort takes a pattern and 
returns the *whole* set of available fonts in sorted order, along with the 
union of all of their coverages.  It's not significantly slower than 
matching a single font.  Take all of the family names you want and stick 
them into the pattern, then hand the whole mess to FcFontSetSort and
you'll get back the matches you're interested in.

If you ask it to, it will only return the fonts which increase the global 
coverage of the list; that makes the list a *lot* shorter.  When doing 
that, I can make it faster by stopping when the global list is full, but 
the implementation doesn't currently bother.

Note that you needn't *open* fonts to determine their coverage; the result 
of any match contains the coverage for the target font.

> A second cache is kept of PangoXftFont; when creating a PangoXftFont
> for a pattern, instead of always creating it from scratch, we instead 
> check to see if there is already an outstanding font for the pattern,
> and, if so, return it. We also keep a small number of fonts around
> after the last refcount is dropped (MAX_FREED_FONTS, currently 16.)

You don't have to do this; Xft caches at this level as well.  It doesn't 
keep previously opened fonts around, but it could if you think that would 
be useful.

>  * The PangoFontDescription => [list of patterns] map really can
>    grow without bond, because each size is stored independently
>    (and Pango allows very fine-grained sizes.) So, an app that
>    allowed arbitrary zooming could easily end with a huge amount
>    of cached lists of patterns.

If you use FcFontSetSort, you can keep only the pattern around and 
regenerate it as needed.  That operation is (relatively) quick.

>   (So, first Pango does an hash lookup to make sure that 
>   the no PangoXftFont is already open; if none is, then Xft will
>   do a linear lookup to the same effect.)

If you find it necessary to avoid the linear search, it's obvious that Xft 
needs to use a hash as well.  I avoided the complexity because I couldn't 
see it in my performance data (which is obviously limited at this point).

Using Xft's cache instead of Pango's avoids the duplication of effort and 
allows faster operations as Xft can use the internal structures.  I assume
that the pattern equality tests have been of some use here already; I did 
convert the internal pattern representation to sort the pattern elements 
which avoided a quadratic comparison operation.

>   [ One problem with dropping the pattern => PangoXftFont cache, is 
>     that you will end up creating many PangoXftFont objects for the
>     same font at the same size, even though Xft will only create
>     one XftFont object. ]

We could allow you to store the PangoXftFont object from the XftFont; that 
way successive open operations could look for that and return it if it 
existed, saving the memory.

>  * Xft could export the idea of the "core" of a pattern ... an opaque
>    structure holding:
> 
>     file/minspace/char_width/size/spacing/rgba/antialias/load_flags/render/matrix



>   a) XftFont is fairly large. (It stores the complete pattern, for one thing)

Note that the Unicode coverage is not duplicated; that structure is ref 
counted to avoid copying it.  Your idea of further sub-caching leaves of 
that structure would serve to really reduce storage of these objects.

I could attempt to reduce the pattern size further by sharing strings 
across different patterns and perhaps finding a small representation for 
the lists of values that are present today; embedding the initial value 
within the object header would save quite a bit of malloc overhead in this 
case.

>   b) When you open an XftFont, it immediately opens the FT_Face
>      for the font. We'd really like to avoid having to ever open the FT_Face
>      for fonts that are in our patterns but not used.

I don't know why you're opening the font then; everything you need to know 
about the font is available from the pattern, including the Unicode 
coverage.  The only thing not available are the glyph metrics; I assume 
you don't need those until you draw the glyphs.

>  * If the solution we take results in a large number of open XftFonts, it
>    might be necessary to replace the linear lookup in XftFontOpenPattern
>    with something smarter.

Yes, that needs doing in any case; I left it linear just because it was 
easier.  If there's a performance problem here, it's always easy to add a 
new hash table.  I already have a hash function for patterns.

Hmm. The return value from FcFontSetSort references the patterns of the 
original fonts; taking that value and opening a font requires a call to 
FcFontRenderPrepare; that makes the storage of this list *very* small,
it's just an array of pointers, and a fairly short list at that.  Let's 
see if we can't make this operation work for Pango, that seems like it 
will solve the pattern storage and matching performance problems.  Fixing 
the XftFont opening to be sub-linear should solve the other end of the 
puzzle.

-keith


_______________________________________________
Fonts mailing list
Fonts XFree86 Org
http://XFree86.Org/mailman/listinfo/fonts



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]