summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@gnome.org>2006-04-29 20:03:17 +0000
committerBehdad Esfahbod <behdad@src.gnome.org>2006-04-29 20:03:17 +0000
commitd52296311614adf06c07389e34fa2bd69dbc343a (patch)
tree7959cd742bb2b6b4bd6fac9175a6858304c22ac6
parentdd69229f4e5bea613aec846d9964edc7d2683825 (diff)
downloadpango-d52296311614adf06c07389e34fa2bd69dbc343a.tar.gz
Bug 329664 – Move gunichar_to_glyph cache from PangoCairoFcFont to
2006-04-29 Behdad Esfahbod <behdad@gnome.org> Bug 329664 – Move gunichar_to_glyph cache from PangoCairoFcFont to PangoFcFont Patch from LingNing Zhang. * pango/pangocairo-fcfont.c (pango_cairo_fc_font_finalize), (pango_cairo_fc_font_glyph_extents_cache_init), (pango_cairo_fc_font_get_glyph_extents_cache_entry), (pango_cairo_fc_font_class_init), (pango_cairo_fc_font_init): * pango/pangofc-font.c (pango_fc_font_finalize), (pango_fc_font_real_get_glyph): Move gunichar->glyph cache to pangofc-font.c
-rw-r--r--ChangeLog14
-rw-r--r--pango/pangocairo-fcfont.c150
-rw-r--r--pango/pangofc-font.c59
3 files changed, 66 insertions, 157 deletions
diff --git a/ChangeLog b/ChangeLog
index 8c020efc..49a710de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
2006-04-29 Behdad Esfahbod <behdad@gnome.org>
+ Bug 329664 – Move gunichar_to_glyph cache from PangoCairoFcFont to
+ PangoFcFont
+ Patch from LingNing Zhang.
+
+ * pango/pangocairo-fcfont.c (pango_cairo_fc_font_finalize),
+ (pango_cairo_fc_font_glyph_extents_cache_init),
+ (pango_cairo_fc_font_get_glyph_extents_cache_entry),
+ (pango_cairo_fc_font_class_init), (pango_cairo_fc_font_init):
+ * pango/pangofc-font.c (pango_fc_font_finalize),
+ (pango_fc_font_real_get_glyph): Move gunichar->glyph cache to
+ pangofc-font.c
+
+2006-04-29 Behdad Esfahbod <behdad@gnome.org>
+
Bug 329547 – pango_layout_get_pixel_extents and
pango_layout_get_pixel_size cause off-by-one metrics
diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c
index 43882c83..10be3c36 100644
--- a/pango/pangocairo-fcfont.c
+++ b/pango/pangocairo-fcfont.c
@@ -42,53 +42,11 @@ typedef struct _PangoCairoFcFont PangoCairoFcFont;
typedef struct _PangoCairoFcFontClass PangoCairoFcFontClass;
typedef struct _GlyphExtentsCacheEntry GlyphExtentsCacheEntry;
-typedef struct _GUnicharToGlyphCacheEntry GUnicharToGlyphCacheEntry;
-
-
-
-
-#define PANGO_UNITS(Double) ((int)((Double) * PANGO_SCALE + 0.49999))
-
-
-
-
-/* define one of these to profile one of the caches */
-#undef PROFILE_GLYPH_EXTENTS_CACHE
-#undef PROFILE_CHAR_TO_GLYPH_CACHE
-
-#undef PROFILE_GLYPH_CACHE
-#ifdef PROFILE_GLYPH_EXTENTS_CACHE
-# define PROFILE_GLYPH_CACHE GlyphExtentsCacheEntry
-#endif
-#ifdef PROFILE_CHAR_TO_GLYPH_CACHE
-# define PROFILE_GLYPH_CACHE GUnicharToGlyphCacheEntry
-#endif
-#ifdef PROFILE_GLYPH_CACHE
-static long num_cairo_fc_fonts;
-static long max_cairo_fc_fonts;
-static long num_glyph_caches;
-static long max_glyph_caches;
-static long num_glyph_cache_hits;
-static long num_glyph_cache_misses;
-#endif
-
-
#define GLYPH_CACHE_NUM_ENTRIES 256 /* should be power of two */
#define GLYPH_CACHE_MASK (GLYPH_CACHE_NUM_ENTRIES - 1)
-/* An entry in the fixed-size cache for the gunichar -> glyph mapping.
- * The cache is indexed by the lower N bits of the gunichar (see
- * GLYPH_CACHE_NUM_ENTRIES). For scripts with few code points,
- * this should provide pretty much instant lookups.
- *
- * The "ch" field is zero if that cache entry is invalid.
- */
-struct _GUnicharToGlyphCacheEntry
-{
- gunichar ch;
- PangoGlyph glyph;
-};
+#define PANGO_UNITS(Double) ((int)((Double) * PANGO_SCALE + 0.49999))
/* An entry in the fixed-size cache for the glyph -> ink_rect mapping.
* The cache is indexed by the lower N bits of the glyph (see
@@ -113,8 +71,7 @@ struct _PangoCairoFcFont
cairo_font_options_t *options;
PangoRectangle font_extents;
- GlyphExtentsCacheEntry *glyph_extents_cache;
- GUnicharToGlyphCacheEntry *char_to_glyph_cache;
+ GlyphExtentsCacheEntry *glyph_extents_cache;
};
struct _PangoCairoFcFontClass
@@ -225,27 +182,9 @@ pango_cairo_fc_font_finalize (GObject *object)
if (cffont->glyph_extents_cache)
{
g_free (cffont->glyph_extents_cache);
-#ifdef PROFILE_GLYPH_EXTENTS_CACHE
- num_glyph_caches--;
- g_assert (num_glyph_caches >= 0);
-#endif
- }
-
- if (cffont->char_to_glyph_cache)
- {
- g_free (cffont->char_to_glyph_cache);
-#ifdef PROFILE_CHAR_TO_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
}
/* This function is cut-and-pasted from pangocairo-fcfont.c - it might be
@@ -320,49 +259,6 @@ pango_cairo_fc_font_unlock_face (PangoFcFont *font)
cairo_ft_scaled_font_unlock_face (scaled_font);
}
-static PangoGlyph
-pango_cairo_fc_font_get_glyph (PangoFcFont *font,
- gunichar wc)
-{
- PangoCairoFcFont *cffont = (PangoCairoFcFont *)font;
- guint idx;
- GUnicharToGlyphCacheEntry *entry;
-
- if (cffont->char_to_glyph_cache == NULL)
- {
- cffont->char_to_glyph_cache = g_new0 (GUnicharToGlyphCacheEntry, GLYPH_CACHE_NUM_ENTRIES);
- /* Make sure all cache entries are invalid initially */
- cffont->char_to_glyph_cache[0].ch = 1; /* char 1 cannot happen in bucket 0 */
-#ifdef PROFILE_CHAR_TO_GLYPH_CACHE
- num_glyph_caches++;
- if (num_glyph_caches > max_glyph_caches)
- max_glyph_caches = num_glyph_caches;
-#endif
- }
-
- idx = wc & GLYPH_CACHE_MASK;
- entry = cffont->char_to_glyph_cache + idx;
-
- if (entry->ch != wc)
- {
-#ifdef PROFILE_CHAR_TO_GLYPH_CACHE
- num_glyph_cache_misses++;
- /*g_message ("cache MISS: cffont %p, gunichar %x = '%c'", cffont, wc, (wc < 128) ? wc : 0);*/
-#endif
- entry->ch = wc;
- entry->glyph = ((PangoFcFontClass *) pango_cairo_fc_font_parent_class)->get_glyph (font, wc);
- }
-#ifdef PROFILE_CHAR_TO_GLYPH_CACHE
- else
- {
- num_glyph_cache_hits++;
- /*g_message ("cache HIT: cffont %p, gunichar %x = '%c'", cffont, wc, (wc < 128) ? wc : 0);*/
- }
-#endif
-
- return entry->glyph;
-}
-
static void
pango_cairo_fc_font_glyph_extents_cache_init (PangoCairoFcFont *cffont)
{
@@ -380,12 +276,6 @@ pango_cairo_fc_font_glyph_extents_cache_init (PangoCairoFcFont *cffont)
cffont->glyph_extents_cache = g_new0 (GlyphExtentsCacheEntry, GLYPH_CACHE_NUM_ENTRIES);
/* Make sure all cache entries are invalid initially */
cffont->glyph_extents_cache[0].glyph = 1; /* glyph 1 cannot happen in bucket 0 */
-
-#ifdef PROFILE_GLYPH_EXTENTS_CACHE
- num_glyph_caches++;
- if (num_glyph_caches > max_glyph_caches)
- max_glyph_caches = num_glyph_caches;
-#endif
}
/* Fills in the glyph extents cache entry
@@ -425,19 +315,8 @@ pango_cairo_fc_font_get_glyph_extents_cache_entry (PangoCairoFcFont *cffon
if (entry->glyph != glyph)
{
-#ifdef PROFILE_GLYPH_EXTENTS_CACHE
- num_glyph_cache_misses++;
- /*g_message ("cache MISS: cffont %p, glyph %x", cffont, glyph);*/
-#endif
compute_glyph_extents (cffont, glyph, entry);
}
-#ifdef PROFILE_GLYPH_EXTENTS_CACHE
- else
- {
- num_glyph_cache_hits++;
- /*g_message ("cache HIT: cffont %p, glyph %x = '%c'", cffont, glyph);*/
- }
-#endif
return entry;
}
@@ -504,19 +383,6 @@ pango_cairo_fc_font_shutdown (PangoFcFont *fcfont)
}
}
-#ifdef PROFILE_GLYPH_CACHE
-static void
-profile_glyph_cache_exit_cb (void)
-{
- g_message ("Profiled %s cache", G_STRINGIFY (PROFILE_GLYPH_CACHE));
- g_message ("Maximum number of PangoCairoFcFont objects: %ld", max_cairo_fc_fonts);
- g_message ("Maximum number of glyph caches created: %ld (%ld KB)", max_glyph_caches, (max_glyph_caches * sizeof (PROFILE_GLYPH_CACHE) * GLYPH_CACHE_NUM_ENTRIES) / 1024);
- g_message ("Glyph cache hits: %ld", num_glyph_cache_hits);
- g_message ("Glyph cache misses: %ld", num_glyph_cache_misses);
- g_message ("Glyph cache miss rate: %f%%", 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)
{
@@ -531,22 +397,12 @@ pango_cairo_fc_font_class_init (PangoCairoFcFontClass *class)
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->shutdown = pango_cairo_fc_font_shutdown;
-
-#ifdef PROFILE_GLYPH_CACHE
- atexit (profile_glyph_cache_exit_cb);
-#endif
}
static void
pango_cairo_fc_font_init (PangoCairoFcFont *cffont)
{
-#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
}
/********************
diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c
index e3585acf..2c0968d4 100644
--- a/pango/pangofc-font.c
+++ b/pango/pangofc-font.c
@@ -37,14 +37,33 @@ enum {
PROP_PATTERN
};
+typedef struct _GUnicharToGlyphCacheEntry GUnicharToGlyphCacheEntry;
+
+/* An entry in the fixed-size cache for the gunichar -> glyph mapping.
+ * The cache is indexed by the lower N bits of the gunichar (see
+ * GLYPH_CACHE_NUM_ENTRIES). For scripts with few code points,
+ * this should provide pretty much instant lookups.
+ *
+ * The "ch" field is zero if that cache entry is invalid.
+ */
+struct _GUnicharToGlyphCacheEntry
+{
+ gunichar ch;
+ PangoGlyph glyph;
+};
+
typedef struct _PangoFcFontPrivate PangoFcFontPrivate;
struct _PangoFcFontPrivate
{
PangoFcDecoder *decoder;
gpointer context_key;
+ GUnicharToGlyphCacheEntry *char_to_glyph_cache;
};
+#define GLYPH_CACHE_NUM_ENTRIES 256 /* should be power of two */
+#define GLYPH_CACHE_MASK (GLYPH_CACHE_NUM_ENTRIES - 1)
+
static gboolean pango_fc_font_real_has_char (PangoFcFont *font,
gunichar wc);
static guint pango_fc_font_real_get_glyph (PangoFcFont *font,
@@ -69,9 +88,6 @@ static PangoFontDescription *pango_fc_font_describe (PangoFont *font)
#define PANGO_FC_FONT_LOCK_FACE(font) (PANGO_FC_FONT_GET_CLASS (font)->lock_face (font))
#define PANGO_FC_FONT_UNLOCK_FACE(font) (PANGO_FC_FONT_GET_CLASS (font)->unlock_face (font))
-
-
-
G_DEFINE_TYPE (PangoFcFont, pango_fc_font, PANGO_TYPE_FONT)
static void
@@ -134,6 +150,9 @@ pango_fc_font_finalize (GObject *object)
if (priv->decoder)
_pango_fc_font_set_decoder (fcfont, NULL);
+ if (priv->char_to_glyph_cache)
+ g_free (priv->char_to_glyph_cache);
+
G_OBJECT_CLASS (pango_fc_font_parent_class)->finalize (object);
}
@@ -505,15 +524,35 @@ pango_fc_font_real_get_glyph (PangoFcFont *font,
FT_Face face;
FT_UInt index;
- face = PANGO_FC_FONT_LOCK_FACE (font);
-
- index = FcFreeTypeCharIndex (face, wc);
- if (index > (FT_UInt)face->num_glyphs)
- index = 0;
+ guint idx;
+ GUnicharToGlyphCacheEntry *entry;
- PANGO_FC_FONT_UNLOCK_FACE (font);
+ PangoFcFontPrivate *priv = font->priv;
+
+ if (G_UNLIKELY (priv->char_to_glyph_cache == NULL))
+ {
+ priv->char_to_glyph_cache = g_new0 (GUnicharToGlyphCacheEntry, GLYPH_CACHE_NUM_ENTRIES);
+ /* Make sure all cache entries are invalid initially */
+ priv->char_to_glyph_cache[0].ch = 1; /* char 1 cannot happen in bucket 0 */
+ }
+
+ idx = wc & GLYPH_CACHE_MASK;
+ entry = priv->char_to_glyph_cache + idx;
+
+ if (entry->ch != wc)
+ {
+ face = PANGO_FC_FONT_LOCK_FACE (font);
+ index = FcFreeTypeCharIndex (face, wc);
+ if (index > (FT_UInt)face->num_glyphs)
+ index = 0;
+
+ entry->ch = wc;
+ entry->glyph = index;
+
+ PANGO_FC_FONT_UNLOCK_FACE (font);
+ }
- return index;
+ return entry->glyph;
}
/**