diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2009-03-10 17:13:36 -0400 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2009-03-13 18:03:50 -0400 |
commit | 03a13541fbf3f49c21d73490570ca217f559acbb (patch) | |
tree | 98edb70be04557bb169a4cf56601d9169ecd28ff /pango/pangofc-fontmap.c | |
parent | c84d4e6e068d802cd0fe2b23bee4c611ae9ef89f (diff) | |
download | pango-03a13541fbf3f49c21d73490570ca217f559acbb.tar.gz |
[pangofc] Share cmap cache between PangoFcFont's of the same face (#567160)
Diffstat (limited to 'pango/pangofc-fontmap.c')
-rw-r--r-- | pango/pangofc-fontmap.c | 172 |
1 files changed, 119 insertions, 53 deletions
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index 1cd934a9..e6ff945e 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -31,7 +31,7 @@ #include "modules.h" #include "pango-enum-types.h" -typedef struct _PangoFcCoverageKey PangoFcCoverageKey; +typedef struct _PangoFcFontFaceData PangoFcFontFaceData; typedef struct _PangoFcFace PangoFcFace; typedef struct _PangoFcFamily PangoFcFamily; typedef struct _PangoFcFindFuncInfo PangoFcFindFuncInfo; @@ -64,7 +64,7 @@ struct _PangoFcFontMapPrivate */ GHashTable *pattern_hash; - GHashTable *coverage_hash; /* Maps font file name/id -> PangoCoverage */ + GHashTable *font_face_data_hash; /* Maps font file name/id -> data */ /* List of all families availible */ PangoFcFamily **families; @@ -78,7 +78,7 @@ struct _PangoFcFontMapPrivate guint closed : 1; }; -struct _PangoFcCoverageKey +struct _PangoFcFontFaceData { /* Key */ char *filename; @@ -86,6 +86,8 @@ struct _PangoFcCoverageKey /* Data */ FcPattern *pattern; /* Referenced pattern that owns filename */ + PangoCoverage *coverage; + PangoFcCmapCache *cmap_cache; }; struct _PangoFcFace @@ -141,9 +143,9 @@ static PangoFont *pango_fc_font_map_new_font (PangoFcFontMap *fontmap, PangoFcFontsetKey *fontset_key, FcPattern *match); -static guint pango_fc_coverage_key_hash (PangoFcCoverageKey *key); -static gboolean pango_fc_coverage_key_equal (PangoFcCoverageKey *key1, - PangoFcCoverageKey *key2); +static guint pango_fc_font_face_data_hash (PangoFcFontFaceData *key); +static gboolean pango_fc_font_face_data_equal (PangoFcFontFaceData *key1, + PangoFcFontFaceData *key2); static void pango_fc_fontset_key_init (PangoFcFontsetKey *key, PangoFcFontMap *fcfontmap, @@ -188,23 +190,31 @@ get_gravity_class (void) } static guint -pango_fc_coverage_key_hash (PangoFcCoverageKey *key) +pango_fc_font_face_data_hash (PangoFcFontFaceData *key) { return g_str_hash (key->filename) ^ key->id; } static gboolean -pango_fc_coverage_key_equal (PangoFcCoverageKey *key1, - PangoFcCoverageKey *key2) +pango_fc_font_face_data_equal (PangoFcFontFaceData *key1, + PangoFcFontFaceData *key2) { - return key1->id == key2->id && (key1 == key2 || 0 == strcmp (key1->filename, key2->filename)); + return key1->id == key2->id && + (key1 == key2 || 0 == strcmp (key1->filename, key2->filename)); } static void -pango_fc_coverage_key_free (PangoFcCoverageKey *key) +pango_fc_font_face_data_free (PangoFcFontFaceData *data) { - FcPatternDestroy (key->pattern); - g_slice_free (PangoFcCoverageKey, key); + FcPatternDestroy (data->pattern); + + if (data->coverage) + pango_coverage_unref (data->coverage); + + if (data->cmap_cache) + _pango_fc_cmap_cache_unref (data->cmap_cache); + + g_slice_free (PangoFcFontFaceData, data); } /* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) @@ -992,10 +1002,10 @@ pango_fc_font_map_init (PangoFcFontMap *fcfontmap) (GDestroyNotify) FcPatternDestroy, NULL); - priv->coverage_hash = g_hash_table_new_full ((GHashFunc)pango_fc_coverage_key_hash, - (GEqualFunc)pango_fc_coverage_key_equal, - (GDestroyNotify)pango_fc_coverage_key_free, - (GDestroyNotify)pango_coverage_unref); + priv->font_face_data_hash = g_hash_table_new_full ((GHashFunc)pango_fc_font_face_data_hash, + (GEqualFunc)pango_fc_font_face_data_equal, + (GDestroyNotify)pango_fc_font_face_data_free, + NULL); priv->dpi = -1; } @@ -1017,8 +1027,8 @@ pango_fc_font_map_fini (PangoFcFontMap *fcfontmap) g_hash_table_destroy (priv->font_hash); priv->font_hash = NULL; - g_hash_table_destroy (priv->coverage_hash); - priv->coverage_hash = NULL; + g_hash_table_destroy (priv->font_face_data_hash); + priv->font_face_data_hash = NULL; g_hash_table_destroy (priv->pattern_hash); priv->pattern_hash = NULL; @@ -1710,20 +1720,85 @@ pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap) pango_fc_font_map_init (fcfontmap); } -static void -pango_fc_font_map_set_coverage (PangoFcFontMap *fcfontmap, - PangoFcCoverageKey *key, - PangoCoverage *coverage) +static PangoFcFontFaceData * +pango_fc_font_map_get_font_face_data (PangoFcFontMap *fcfontmap, + FcPattern *font_pattern) { PangoFcFontMapPrivate *priv = fcfontmap->priv; - PangoFcCoverageKey *key_dup; + PangoFcFontFaceData key; + PangoFcFontFaceData *data; + + if (FcPatternGetString (font_pattern, FC_FILE, 0, (FcChar8 **)(void*)&key.filename) != FcResultMatch) + return NULL; - key_dup = g_slice_new (PangoFcCoverageKey); - *key_dup = *key; - FcPatternReference (key_dup->pattern); + if (FcPatternGetInteger (font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch) + return NULL; + + data = g_hash_table_lookup (priv->font_face_data_hash, &key); + if (G_LIKELY (data)) + return data; + + data = g_slice_new0 (PangoFcFontFaceData); + data->filename = key.filename; + data->id = key.id; + + data->pattern = font_pattern; + FcPatternReference (data->pattern); - g_hash_table_insert (priv->coverage_hash, - key_dup, pango_coverage_ref (coverage)); + g_hash_table_insert (priv->font_face_data_hash, data, data); + + return data; +} + +PangoFcCmapCache * +_pango_fc_cmap_cache_ref (PangoFcCmapCache *cmap_cache) +{ + g_atomic_int_inc ((int *) &cmap_cache->ref_count); + + return cmap_cache; +} + +void +_pango_fc_cmap_cache_unref (PangoFcCmapCache *cmap_cache) +{ + g_return_if_fail (cmap_cache->ref_count > 0); + + if (g_atomic_int_dec_and_test ((int *) &cmap_cache->ref_count)) + { + g_free (cmap_cache); + } +} + +PangoFcCmapCache * +_pango_fc_font_map_get_cmap_cache (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont) +{ + PangoFcFontMapPrivate *priv; + PangoFcFontFaceData *data; + PangoFcCmapCache *cmap_cache; + + if (G_UNLIKELY (fcfontmap == NULL)) + return NULL; + + if (G_UNLIKELY (!fcfont->font_pattern)) + return NULL; + + priv = fcfontmap->priv; + + data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern); + if (G_UNLIKELY (!data)) + return NULL; + + if (G_UNLIKELY (data->cmap_cache == NULL)) + { + data->cmap_cache = g_new0 (PangoFcCmapCache, 1); + data->cmap_cache->ref_count = 1; + + /* Make sure all cache entries are invalid initially */ + data->cmap_cache->entries[0].ch = 1; /* char 1 cannot happen in bucket 0 */ + } + + return _pango_fc_cmap_cache_ref (data->cmap_cache); } PangoCoverage * @@ -1731,39 +1806,30 @@ _pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, PangoFcFont *fcfont) { PangoFcFontMapPrivate *priv = fcfontmap->priv; - PangoFcCoverageKey key; + PangoFcFontFaceData *data; PangoCoverage *coverage; FcCharSet *charset; - key.pattern = fcfont->font_pattern; - - /* - * Assume that coverage information is identified by - * a filename/index pair; there shouldn't be any reason - * this isn't true, but it's not specified anywhere - */ - if (FcPatternGetString (fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)(void*)&key.filename) != FcResultMatch) + if (G_UNLIKELY (!fcfont->font_pattern)) return NULL; - if (FcPatternGetInteger (fcfont->font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch) + data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern); + if (G_UNLIKELY (!data)) return NULL; - coverage = g_hash_table_lookup (priv->coverage_hash, &key); - if (G_LIKELY (coverage)) - return pango_coverage_ref (coverage); - - /* - * Pull the coverage out of the pattern, this - * doesn't require loading the font - */ - if (FcPatternGetCharSet (fcfont->font_pattern, FC_CHARSET, 0, &charset) != FcResultMatch) - return NULL; - - coverage = _pango_fc_font_map_fc_to_coverage (charset); + if (G_UNLIKELY (data->coverage == NULL)) + { + /* + * Pull the coverage out of the pattern, this + * doesn't require loading the font + */ + if (FcPatternGetCharSet (fcfont->font_pattern, FC_CHARSET, 0, &charset) != FcResultMatch) + return NULL; - pango_fc_font_map_set_coverage (fcfontmap, &key, coverage); + data->coverage = _pango_fc_font_map_fc_to_coverage (charset); + } - return coverage; + return pango_coverage_ref (data->coverage); } /** |