Index: pango/pangocairo-fcfont.c =================================================================== RCS file: /cvs/gnome/pango/pango/pangocairo-fcfont.c,v retrieving revision 1.15 diff -p -u -r1.15 pangocairo-fcfont.c --- pango/pangocairo-fcfont.c 15 Aug 2005 19:41:00 -0000 1.15 +++ pango/pangocairo-fcfont.c 26 Oct 2005 02:54:36 -0000 @@ -23,6 +23,7 @@ #include #include +#include #include @@ -44,6 +45,28 @@ typedef struct _PangoCairoFcFont Pa typedef struct _PangoCairoFcFontClass PangoCairoFcFontClass; typedef struct _PangoCairoFcGlyphInfo PangoCairoFcGlyphInfo; +#undef PROFILE_GLYPH_CACHE +#ifdef PROFILE_GLYPH_CACHE +static int num_cairo_fc_fonts; +static int max_cairo_fc_fonts; +static int num_glyph_caches; +static int max_glyph_caches; +static long num_glyph_cache_hits; +static long num_glyph_cache_misses; +#endif + +/* An entry in the fixed-size cache for the gunichar -> glyph mapping. + * The cache is indexed by the lower 8 bits of the gunichar. For scripts + * with few code points, this should provide pretty much instant lookups. + * + * The "ch" field is zero if that cache entry is invalid. + */ +typedef struct +{ + gunichar ch; + PangoGlyph glyph; +} GlyphCacheEntry; + struct _PangoCairoFcFont { PangoFcFont font; @@ -55,6 +78,9 @@ struct _PangoCairoFcFont cairo_font_options_t *options; GHashTable *glyph_info; + PangoCairoFcGlyphInfo *recent [256]; + + GlyphCacheEntry *char_to_glyph_cache; }; struct _PangoCairoFcFontClass @@ -64,6 +90,7 @@ struct _PangoCairoFcFontClass struct _PangoCairoFcGlyphInfo { + PangoGlyph glyph; PangoRectangle logical_rect; PangoRectangle ink_rect; }; @@ -161,7 +188,21 @@ pango_cairo_fc_font_finalize (GObject *o g_hash_table_destroy (cffont->glyph_info); + if (cffont->char_to_glyph_cache) + { + g_free (cffont->char_to_glyph_cache); +#ifdef PROFILE_GLYPH_CACHE + num_glyph_caches--; + g_assert (num_glyph_caches >= 0); +#endif + } + G_OBJECT_CLASS (pango_cairo_fc_font_parent_class)->finalize (object); + +#ifdef PROFILE_GLYPH_CACHE + num_cairo_fc_fonts--; + g_assert (num_cairo_fc_fonts >= 0); +#endif } static void @@ -212,10 +253,14 @@ pango_cairo_fc_font_get_glyph_info (Pang PangoCairoFcFont *cffont = (PangoCairoFcFont *)font; PangoCairoFcGlyphInfo *info; + info = cffont->recent [glyph & 0xff]; + if (info && info->glyph == glyph) return info; + info = g_hash_table_lookup (cffont->glyph_info, GUINT_TO_POINTER (glyph)); if (!info) { info = g_new0 (PangoCairoFcGlyphInfo, 1); + info->glyph = glyph; compute_glyph_extents (font, glyph, &info->ink_rect, @@ -236,11 +281,18 @@ pango_cairo_fc_font_get_glyph_extents (P PangoCairoFcGlyphInfo *info; info = pango_cairo_fc_font_get_glyph_info (font, glyph); - - if (ink_rect) - *ink_rect = info->ink_rect; - if (logical_rect) - *logical_rect = info->logical_rect; + if (ink_rect) { + ink_rect->x = info->ink_rect.x; + ink_rect->y = info->ink_rect.y; + ink_rect->width = info->ink_rect.width; + ink_rect->height = info->ink_rect.height; + } + if (logical_rect) { + logical_rect->x = info->logical_rect.x; + logical_rect->y = info->logical_rect.y; + logical_rect->width = info->logical_rect.width; + logical_rect->height = info->logical_rect.height; + } } /* This function is cut-and-pasted from pangocairo-fcfont.c - it might be @@ -313,6 +365,51 @@ pango_cairo_fc_font_unlock_face (PangoFc } static PangoGlyph +pango_cairo_fc_font_get_glyph (PangoFcFont *font, + gunichar wc) +{ + PangoCairoFcFont *cffont = (PangoCairoFcFont *)font; + guint idx; + GlyphCacheEntry *entry; + + /* We create the cache dynamically because although we'll have a lot of + * PangoCairoFcFont structures (one per font in the fontset, as many as needed + * to cover the whole Unicode space), we'll only end up using a few of them + * for the user's actual text. + */ + if (cffont->char_to_glyph_cache == NULL) { + cffont->char_to_glyph_cache = g_new0 (GlyphCacheEntry, 256); +#ifdef PROFILE_GLYPH_CACHE + num_glyph_caches++; + if (num_glyph_caches > max_glyph_caches) + max_glyph_caches = num_glyph_caches; +#endif + } + + idx = wc & 0x00ff; + entry = cffont->char_to_glyph_cache + idx; + + if (entry->ch != wc || entry->ch == 0) + { +#ifdef PROFILE_GLYPH_CACHE + num_glyph_cache_misses++; +/* printf ("cache MISS: cffont %p, gunichar %x = '%c'\n", cffont, wc, (wc < 128) ? wc : 0); */ +#endif + entry->ch = wc; + entry->glyph = ((PangoFcFontClass *) pango_cairo_fc_font_parent_class)->get_glyph (font, wc); + } + else + { +#ifdef PROFILE_GLYPH_CACHE + num_glyph_cache_hits++; +/* printf ("cache HIT: cffont %p, gunichar %x = '%c'\n", cffont, wc, (wc < 128) ? wc : 0); */ +#endif + } + + return entry->glyph; +} + +static PangoGlyph pango_cairo_fc_font_real_get_unknown_glyph (PangoFcFont *font, gunichar wc) { @@ -335,6 +432,18 @@ pango_cairo_fc_font_shutdown (PangoFcFon } } +#ifdef PROFILE_GLYPH_CACHE +static void +profile_glyph_cache_exit_cb (void) +{ + printf ("Maximum number of PangoCairoFcFont objects: %d\n", max_cairo_fc_fonts); + printf ("Maximum number of glyph caches created: %d (%d KB)\n", max_glyph_caches, (max_glyph_caches * sizeof (GlyphCacheEntry) * 256) / 1024); + printf ("Glyph cache hits: %ld\n", num_glyph_cache_hits); + printf ("Glyph cache misses: %ld\n", num_glyph_cache_misses); + printf ("Glyph cache miss rate: %f%%\n", 100.0 * (double) num_glyph_cache_misses / (num_glyph_cache_misses + num_glyph_cache_hits)); +} +#endif + static void pango_cairo_fc_font_class_init (PangoCairoFcFontClass *class) { @@ -349,8 +458,13 @@ pango_cairo_fc_font_class_init (PangoCai fc_font_class->lock_face = pango_cairo_fc_font_lock_face; fc_font_class->unlock_face = pango_cairo_fc_font_unlock_face; + fc_font_class->get_glyph = pango_cairo_fc_font_get_glyph; fc_font_class->get_unknown_glyph = pango_cairo_fc_font_real_get_unknown_glyph; fc_font_class->shutdown = pango_cairo_fc_font_shutdown; + +#ifdef PROFILE_GLYPH_CACHE + atexit (profile_glyph_cache_exit_cb); +#endif } static void @@ -360,6 +474,13 @@ pango_cairo_fc_font_init (PangoCairoFcFo NULL, NULL, (GDestroyNotify)g_free); + memset (cffont->recent, 0, 256 * 4); + +#ifdef PROFILE_GLYPH_CACHE + num_cairo_fc_fonts++; + if (num_cairo_fc_fonts > max_cairo_fc_fonts) + max_cairo_fc_fonts = num_cairo_fc_fonts; +#endif } /******************** @@ -433,6 +554,6 @@ _pango_cairo_fc_font_new (PangoCairoFcFo cairo_matrix_init_identity (&cffont->ctm); cffont->options = cairo_font_options_copy (_pango_cairo_context_get_merged_font_options (context)); - + return PANGO_FC_FONT (cffont); }