Re: Notes on Pango Xft backend



Around 14 o'clock on May 28, Owen Taylor wrote:

> The reason that Pango does it is that Pango does not keep font objects
> around persistantly; it looks them up from PangoFontDescription 
> as needed; so you could get bad thrashing effects without keeping
> some up.

I've added a hash table to match existing fonts and also changed the code 
to leave unreferenced fonts in the table for a while.  There's a 
configurable limit to the unreferenced fonts to leave around.  They're 
pretty cheap as the glyph cache code will prune glyph and metric storage 
for these fonts automatically.

I also have a XftFontInfo structure which contains the information needed 
to uniquely identify a font; each font holds one of these structures and 
users can create them from patterns on the fly and then open the related 
font.  From our discussions, I'm not sure this is a useful abstraction 
anymore; please let me know if it would be useful to leave this exposed to 
applications.

Here's how I think things could be structured:

	/*
	 * A physical font capable of rendering some unicode codepoints,
	 * could be cached to limit the total number of XftFont tables
	 * loaded, but Xft already limits memory pretty aggressively
	 */
	typedef struct _PangoXftFont {
		XftFont		*xftfont;
		/* extra pango tables */
	} PangoXftFont;

	/*
	 * A logical font, the physical font is not realized until needed
	 */
	typedef struct _PangoXftFontElt {
		FcPattern	*pattern;
		FcCharSet	*charset;
		PangoXftFont	*font;
	} PangoXftFontElt;

	/*
	 * A list of logical fonts in the order used to render particular
	 * glyphs
	 */
	typedef struct _PangoXftFontSet {
		FcPattern	*pattern;
		FcCharSet	*charset;
		int		nelt;
		PangoXftFontElt	*elts;
	} PangoXftFontSet;

	void PangoRealizeXftFont (PangoXftFontElt *elt, FcPattern *pattern)
	{
		if (!elt->font)
		{
			FcPattern	*pat;
			elt->font = malloc ();
			pat = FcFontRenderPrepare (0, pattern, elt->pattern);
			elt->font->xftfont = XftFontOpenPattern (dpy, pat);
			if (!elt->font->xftfont) 
			{
				XftPatternDestroy (pat);
				free (elt->font);
				elt->font = 0;
				return;
			}
			/* prepare additional pango tables from face */
			/* discard any faces desired to limit memory usage */
		}
	}
	/*
	 * Return a font which can draw the specified unicode codepoint,
	 * or zero if no font exists for that codepoint
	 */
	PangoXftFont *PangoFindXftFont (PangoXftFontSet *set, long ucs4)
	{
		int	n;

		for (n = 0; n < set->nelt; n++)
			if (FcCharSetHasChar (set->elts[n].charset, ucs4))
			{
				if (!set->elts[n].font)
					PangoRealizeXftFont (&set->elts[n],
							     set->pattern);
				return set->elts[n].font;
			}
		return 0;
	}

	/*
	 * Return a font set for the specified pattern
	 */
	PangoXftFontSet *PangoCreateXftFontSet (FcPattern *pattern)
	{
		FcCharSet	*cs;
		FcResult	result;
		FcFontSet	*set = FcFontSort (0, pattern, FcTrue, 
						   &cs, &result);
		PangoXftFontSet	*fs;
		int		i;

		if (!set)
			return 0;
		fs = malloc ();
		fs->elts = (PangoXftFontElt *) (fs + 1);
		fs->nelt = set->nfont;
		fs->pattern = pattern;
		fs->charset = cs;
		for (i = 0; i < set->nfont)
		{
			fs->elts[i].pattern = set->fonts[i];
			fs->elts[i].charset = 0;
			FcPatternGetCharSet (set->fonts[i], FC_CHARSET,
					     &fs->elts[i].charset);
			fs->elts[i].font = 0;
		}
	}

In this structure, I don't see a place for the XftFontInfo.  One place for 
caching is in the pattern->fontset mapping; that should be pretty 
straightforward, perhaps give a few additional APIs in fontconfig to 
generate hash values for patterns.  Other than that, I think most
of the code here should run fast enough to be left uncached.

Keith Packard        XFree86 Core Team        HP Cambridge Research Lab





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