Re: Code freeze break request for Pango
- From: Behdad Esfahbod <behdad behdad org>
- To: Gnome Release Team <release-team gnome org>
- Subject: Re: Code freeze break request for Pango
- Date: Wed, 11 Mar 2009 08:13:49 -0400
On 03/11/2009 07:58 AM, Vincent Untz wrote:
Hi Behdad,
Le mardi 10 mars 2009, à 17:19 -0400, Behdad Esfahbod a écrit :
Hi,
I'm lazy...
So, this cycle I rewrote most of the internals of the PangoFc backend. Mostly
for optimization, also to fix bugs. This changed some of the backend-only
API. Since yesterday I've been putting the finishing touches on this work and
had to make a few changes. One of them involves a minor API addition to the
backend-only API. The others are fixes here and there. So here I am asking
for permission to push these to pango:
Nobody sent an approval so far... I guess that it's because it's hard to
know if the changes are big or not. Can we get some diff to help us
decide?
Attached. The non-trivial changes are in the first and last patch. The first
one is still quite straightforward. The last patch is a bit trickier, but
well tested. I'm hoping to get this in fedora soon to get more testing.
behdad
Vincent
From f1c43077c527595bacd0e8fe21d001be3b266582 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad behdad org>
Date: Tue, 10 Mar 2009 08:08:19 -0400
Subject: [PATCH 1/7] [pangofc] Add a "fontmap" property to PangoFcFont
Gecko uses its own PangoFcFontMap subclass with its own PangoFontSet.
Previously we were setting font->fontmap in our own private
PangoFcFontSet. Now it's up to the PangoFcFont subclass to set it
when creating the new font object.
Also adds the following backend-public symbol:
pango_fc_font_map_find_decoder()
---
docs/pango-sections.txt | 1 +
docs/tmpl/pangofc-font.sgml | 5 +++
docs/tmpl/pangofc-fontmap.sgml | 10 ++++++
pango/pangocairo-fcfont.c | 1 +
pango/pangofc-font.c | 42 ++++++++++++++++++++++--
pango/pangofc-fontmap.c | 69 +++++++++++++++++++++++----------------
pango/pangofc-fontmap.h | 2 +
pango/pangoft2.c | 1 +
pango/pangoft2.def | 1 +
pango/pangoxft-font.c | 1 +
10 files changed, 101 insertions(+), 32 deletions(-)
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt
index 7ed853c..0fbdc22 100644
--- a/docs/pango-sections.txt
+++ b/docs/pango-sections.txt
@@ -919,6 +919,7 @@ PangoFcFontMapClass
pango_fc_font_map_create_context
PangoFcDecoderFindFunc
pango_fc_font_map_add_decoder_find_func
+pango_fc_font_map_find_decoder
pango_fc_font_map_cache_clear
pango_fc_font_map_shutdown
pango_fc_font_description_from_pattern
diff --git a/docs/tmpl/pangofc-font.sgml b/docs/tmpl/pangofc-font.sgml
index 95ac1dd..a1b055c 100644
--- a/docs/tmpl/pangofc-font.sgml
+++ b/docs/tmpl/pangofc-font.sgml
@@ -40,6 +40,11 @@ Fontconfig-based backend involves deriving from both
</para>
+<!-- ##### ARG PangoFcFont:fontmap ##### -->
+<para>
+
+</para>
+
<!-- ##### ARG PangoFcFont:pattern ##### -->
<para>
diff --git a/docs/tmpl/pangofc-fontmap.sgml b/docs/tmpl/pangofc-fontmap.sgml
index bcfae81..ee6cca0 100644
--- a/docs/tmpl/pangofc-fontmap.sgml
+++ b/docs/tmpl/pangofc-fontmap.sgml
@@ -86,6 +86,16 @@ Fontconfig-based backend involves deriving from both
@dnotify:
+<!-- ##### FUNCTION pango_fc_font_map_find_decoder ##### -->
+<para>
+
+</para>
+
+ fcfontmap:
+ pattern:
+ Returns:
+
+
<!-- ##### FUNCTION pango_fc_font_map_cache_clear ##### -->
<para>
diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c
index 3039f9f..3ac166e 100644
--- a/pango/pangocairo-fcfont.c
+++ b/pango/pangocairo-fcfont.c
@@ -223,6 +223,7 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
cffont = g_object_new (PANGO_TYPE_CAIRO_FC_FONT,
"pattern", pattern,
+ "fontmap", cffontmap,
NULL);
size = get_font_size (pattern) /
diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c
index 133a4df..41fb74e 100644
--- a/pango/pangofc-font.c
+++ b/pango/pangofc-font.c
@@ -34,7 +34,8 @@
enum {
PROP_0,
- PROP_PATTERN
+ PROP_PATTERN,
+ PROP_FONTMAP
};
typedef struct _GUnicharToGlyphCacheEntry GUnicharToGlyphCacheEntry;
@@ -121,6 +122,13 @@ pango_fc_font_class_init (PangoFcFontClass *class)
"The fontconfig pattern for this font",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_FONTMAP,
+ g_param_spec_object ("fontmap",
+ "Font Map",
+ "The PangoFc font map this font is associated with",
+ PANGO_TYPE_FC_FONT_MAP,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
g_type_class_add_private (object_class, sizeof (PangoFcFontPrivate));
}
@@ -203,11 +211,12 @@ pango_fc_font_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
+ PangoFcFont *fcfont = PANGO_FC_FONT (object);
+
switch (prop_id)
{
case PROP_PATTERN:
{
- PangoFcFont *fcfont = PANGO_FC_FONT (object);
FcPattern *pattern = g_value_get_pointer (value);
g_return_if_fail (pattern != NULL);
@@ -219,11 +228,30 @@ pango_fc_font_set_property (GObject *object,
fcfont->is_hinted = pattern_is_hinted (pattern);
fcfont->is_transformed = pattern_is_transformed (pattern);
}
- break;
+ goto set_decoder;
+
+ case PROP_FONTMAP:
+ {
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (g_value_get_object (value));
+
+ g_return_if_fail (fcfont->fontmap == NULL);
+ fcfont->fontmap = (PangoFontMap *) fcfontmap;
+ if (fcfont->fontmap)
+ g_object_add_weak_pointer (G_OBJECT (fcfont->fontmap), (gpointer *) (gpointer) &fcfont->fontmap);
+ }
+ goto set_decoder;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ return;
}
+
+set_decoder:
+ /* set decoder if both pattern and fontmap are set now */
+ if (fcfont->font_pattern && fcfont->fontmap)
+ _pango_fc_font_set_decoder (fcfont,
+ pango_fc_font_map_find_decoder ((PangoFcFontMap *) fcfont->fontmap,
+ fcfont->font_pattern));
}
static void
@@ -240,6 +268,12 @@ pango_fc_font_get_property (GObject *object,
g_value_set_pointer (value, fcfont->font_pattern);
}
break;
+ case PROP_FONTMAP:
+ {
+ PangoFcFont *fcfont = PANGO_FC_FONT (object);
+ g_value_set_object (value, fcfont->fontmap);
+ }
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index 07328b6..6049046 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -1058,9 +1058,13 @@ pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap,
gpointer user_data,
GDestroyNotify dnotify)
{
- PangoFcFontMapPrivate *priv = fcfontmap->priv;
+ PangoFcFontMapPrivate *priv;
PangoFcFindFuncInfo *info;
+ g_return_val_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap), NULL);
+
+ priv = fcfontmap->priv;
+
info = g_slice_new (PangoFcFindFuncInfo);
info->findfunc = findfunc;
@@ -1070,6 +1074,41 @@ pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap,
priv->findfuncs = g_slist_append (priv->findfuncs, info);
}
+/**
+ * pango_fc_font_map_find_decoder:
+ * @fcfontmap: The #PangoFcFontMap to use.
+ * @pattern: The #FcPattern to find the decoder for.
+ *
+ * Finds the decoder to use for @pattern. Decoders can be added to
+ * a font map using pango_fc_font_map_add_decoder_find_func().
+ *
+ * Returns: a newly created #PangoFcDecoder object or %NULL if
+ * no decoder is set for @pattern.
+ *
+ * Since: 1.24.
+ **/
+PangoFcDecoder *
+pango_fc_font_map_find_decoder (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern)
+{
+ GSList *l;
+
+ g_return_val_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap), NULL);
+ g_return_val_if_fail (pattern != NULL, NULL);
+
+ for (l = fcfontmap->priv->findfuncs; l && l->data; l = l->next)
+ {
+ PangoFcFindFuncInfo *info = l->data;
+ PangoFcDecoder *decoder;
+
+ decoder = info->findfunc (pattern, info->user_data);
+ if (decoder)
+ return decoder;
+ }
+
+ return NULL;
+}
+
static void
pango_fc_font_map_finalize (GObject *object)
{
@@ -1089,13 +1128,6 @@ pango_fc_font_map_add (PangoFcFontMap *fcfontmap,
PangoFcFontMapPrivate *priv = fcfontmap->priv;
PangoFcFontKey *key_copy;
- g_assert (fcfont->fontmap == NULL);
- fcfont->fontmap = (PangoFontMap *) fcfontmap;
- /* In other fontmaps we add a weak pointer on ->fontmap so the
- * field is unset when fontmap is finalized. We don't need it
- * here though as PangoFcFontMap already cleans up fcfont->fontmap
- * as part of it's caching scheme. */
-
key_copy = pango_fc_font_key_copy (key);
_pango_fc_font_set_font_key (fcfont, key_copy);
g_hash_table_insert (priv->font_hash, key_copy, fcfont);
@@ -1109,8 +1141,6 @@ _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap,
PangoFcFontMapPrivate *priv = fcfontmap->priv;
PangoFcFontKey *key;
- fcfont->fontmap = NULL;
-
key = _pango_fc_font_get_font_key (fcfont);
if (key)
{
@@ -1411,7 +1441,6 @@ pango_fc_font_map_new_font (PangoFcFontMap *fcfontmap,
PangoFcFontMapPrivate *priv = fcfontmap->priv;
FcPattern *pattern;
PangoFcFont *fcfont;
- GSList *l;
PangoFcFontKey key;
if (priv->closed)
@@ -1462,25 +1491,9 @@ pango_fc_font_map_new_font (PangoFcFontMap *fcfontmap,
fcfont->matrix = key.matrix;
+ /* cache it on fontmap */
pango_fc_font_map_add (fcfontmap, &key, fcfont);
- /*
- * Give any custom decoders a crack at this font now that it's been
- * created.
- */
- for (l = priv->findfuncs; l && l->data; l = l->next)
- {
- PangoFcFindFuncInfo *info = l->data;
- PangoFcDecoder *decoder;
-
- decoder = info->findfunc (match, info->user_data);
- if (decoder)
- {
- _pango_fc_font_set_decoder (fcfont, decoder);
- break;
- }
- }
-
return (PangoFont *)fcfont;
}
diff --git a/pango/pangofc-fontmap.h b/pango/pangofc-fontmap.h
index d3f113a..8d496eb 100644
--- a/pango/pangofc-fontmap.h
+++ b/pango/pangofc-fontmap.h
@@ -213,6 +213,8 @@ void pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap,
PangoFcDecoderFindFunc findfunc,
gpointer user_data,
GDestroyNotify dnotify);
+PangoFcDecoder *pango_fc_font_map_find_decoder (PangoFcFontMap *fcfontmap,
+ FcPattern *pattern);
PangoFontDescription *pango_fc_font_description_from_pattern (FcPattern *pattern,
gboolean include_size);
diff --git a/pango/pangoft2.c b/pango/pangoft2.c
index d13dc69..224f6a0 100644
--- a/pango/pangoft2.c
+++ b/pango/pangoft2.c
@@ -73,6 +73,7 @@ _pango_ft2_font_new (PangoFT2FontMap *ft2fontmap,
ft2font = (PangoFT2Font *)g_object_new (PANGO_TYPE_FT2_FONT,
"pattern", pattern,
+ "fontmap", fontmap,
NULL);
if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch)
diff --git a/pango/pangoft2.def b/pango/pangoft2.def
index ba78cd4..4cfa0d1 100644
--- a/pango/pangoft2.def
+++ b/pango/pangoft2.def
@@ -17,6 +17,7 @@ EXPORTS
pango_fc_font_map_add_decoder_find_func
pango_fc_font_map_cache_clear
pango_fc_font_map_create_context
+ pango_fc_font_map_find_decoder
pango_fc_font_map_get_type
pango_fc_font_map_shutdown
pango_fc_font_unlock_face
diff --git a/pango/pangoxft-font.c b/pango/pangoxft-font.c
index ce633f7..6865490 100644
--- a/pango/pangoxft-font.c
+++ b/pango/pangoxft-font.c
@@ -92,6 +92,7 @@ _pango_xft_font_new (PangoXftFontMap *xftfontmap,
xfont = (PangoXftFont *)g_object_new (PANGO_TYPE_XFT_FONT,
"pattern", pattern,
+ "fontmap", fontmap,
NULL);
/* Hack to force hinting of vertical metrics; hinting off for
--
1.6.1.3
From 774b4b873d0702ef5cc8ea6cab6fde5a1c7e4b03 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad behdad org>
Date: Tue, 10 Mar 2009 08:26:20 -0400
Subject: [PATCH 2/7] [pango-coverage] Remove unused struct member
---
pango/pango-coverage.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c
index 73fb147..30c9209 100644
--- a/pango/pango-coverage.c
+++ b/pango/pango-coverage.c
@@ -42,7 +42,6 @@ struct _PangoCoverage
{
guint ref_count;
int n_blocks;
- int data_size;
PangoBlockInfo *blocks;
};
--
1.6.1.3
From 3a43e7d7c87f22fa940b2c6501c2aea244d27f66 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad behdad org>
Date: Tue, 10 Mar 2009 09:05:39 -0400
Subject: [PATCH 3/7] [pango-coverage] Use gslice for data arrays
---
pango/pango-coverage.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c
index 30c9209..5b7ddad 100644
--- a/pango/pango-coverage.c
+++ b/pango/pango-coverage.c
@@ -144,7 +144,7 @@ pango_coverage_unref (PangoCoverage *coverage)
if (g_atomic_int_dec_and_test ((int *) &coverage->ref_count))
{
for (i=0; i<coverage->n_blocks; i++)
- g_free (coverage->blocks[i].data);
+ g_slice_free1 (64, coverage->blocks[i].data);
g_free (coverage->blocks);
g_slice_free (PangoCoverage, coverage);
@@ -235,7 +235,7 @@ pango_coverage_set (PangoCoverage *coverage,
if (level == coverage->blocks[block_index].level)
return;
- data = g_new (guchar, 64);
+ data = g_slice_alloc (64);
coverage->blocks[block_index].data = data;
byte = coverage->blocks[block_index].level |
@@ -398,7 +398,7 @@ pango_coverage_to_bytes (PangoCoverage *coverage,
if (j == 64)
{
- g_free (data);
+ g_slice_free1 (64, data);
coverage->blocks[i].data = NULL;
coverage->blocks[i].level = first_val & 0x3;
}
--
1.6.1.3
From 70c59ecbc4230cc3f795be9edc02b60cee65b9b7 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad behdad org>
Date: Tue, 10 Mar 2009 09:38:25 -0400
Subject: [PATCH 4/7] [pangofc] Fix leak
---
pango/pangofc-fontmap.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index 6049046..f16d3ad 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -1838,9 +1838,15 @@ pango_fc_font_map_create_context (PangoFcFontMap *fcfontmap)
static void
shutdown_font (gpointer key G_GNUC_UNUSED,
- PangoFcFont *fcfont)
+ PangoFcFont *fcfont,
+ PangoFcFontMap *fcfontmap)
{
_pango_fc_font_shutdown (fcfont);
+
+ /* While _pango_fc_font_shutdown() tries to call the following
+ * function, it's too late as the fontmap weakref has already
+ * NULL'ed fcfont->fontmap, so we do it ourselves. */
+ _pango_fc_font_map_remove (fcfontmap, fcfont);
}
/**
@@ -1865,7 +1871,7 @@ pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap)
if (priv->closed)
return;
- g_hash_table_foreach (priv->font_hash, (GHFunc) shutdown_font, NULL);
+ g_hash_table_foreach (priv->font_hash, (GHFunc) shutdown_font, fcfontmap);
for (i = 0; i < priv->n_families; i++)
priv->families[i]->fontmap = NULL;
--
1.6.1.3
From 7eaebcf2e9fb5c292cc8bd070b826ca38f0f9f25 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad behdad org>
Date: Tue, 10 Mar 2009 11:42:01 -0400
Subject: [PATCH 5/7] [pango-coverage] Fix optimization bug in pango_coverage_to_bytes()
---
pango/pango-coverage.c | 19 +++++++++++--------
1 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c
index 5b7ddad..7637117 100644
--- a/pango/pango-coverage.c
+++ b/pango/pango-coverage.c
@@ -392,15 +392,18 @@ pango_coverage_to_bytes (PangoCoverage *coverage,
guchar *data = coverage->blocks[i].data;
guchar first_val = data[0];
- for (j = 1 ; j < 64; j++)
- if (data[j] != first_val)
- break;
-
- if (j == 64)
+ if (first_val == 0 || first_val == 0xff)
{
- g_slice_free1 (64, data);
- coverage->blocks[i].data = NULL;
- coverage->blocks[i].level = first_val & 0x3;
+ for (j = 1 ; j < 64; j++)
+ if (data[j] != first_val)
+ break;
+
+ if (j == 64)
+ {
+ g_slice_free1 (64, data);
+ coverage->blocks[i].data = NULL;
+ coverage->blocks[i].level = first_val & 0x3;
+ }
}
}
--
1.6.1.3
From e69cff51ff7d9ce136dc83f259415145f09b6b05 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad behdad org>
Date: Tue, 10 Mar 2009 14:00:09 -0400
Subject: [PATCH 6/7] [pangofc] Reuse filename from pattern in coverage key
---
pango/pangofc-fontmap.c | 28 ++++++++++++++++++++--------
1 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index f16d3ad..7841483 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -80,8 +80,12 @@ struct _PangoFcFontMapPrivate
struct _PangoFcCoverageKey
{
+ /* Key */
char *filename;
int id; /* needed to handle TTC files with multiple faces */
+
+ /* Data */
+ FcPattern *pattern; /* Referenced pattern that owns filename */
};
struct _PangoFcFace
@@ -191,9 +195,16 @@ pango_fc_coverage_key_hash (PangoFcCoverageKey *key)
static gboolean
pango_fc_coverage_key_equal (PangoFcCoverageKey *key1,
- PangoFcCoverageKey *key2)
+ PangoFcCoverageKey *key2)
{
- return key1->id == key2->id && strcmp (key1->filename, key2->filename) == 0;
+ return key1->id == key2->id && (key1 == key2 || 0 == strcmp (key1->filename, key2->filename));
+}
+
+static void
+pango_fc_coverage_key_free (PangoFcCoverageKey *key)
+{
+ FcPatternDestroy (key->pattern);
+ g_slice_free (PangoFcCoverageKey, key);
}
/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
@@ -983,7 +994,7 @@ pango_fc_font_map_init (PangoFcFontMap *fcfontmap)
priv->coverage_hash = g_hash_table_new_full ((GHashFunc)pango_fc_coverage_key_hash,
(GEqualFunc)pango_fc_coverage_key_equal,
- (GDestroyNotify)g_free,
+ (GDestroyNotify)pango_fc_coverage_key_free,
(GDestroyNotify)pango_coverage_unref);
priv->dpi = -1;
}
@@ -1061,7 +1072,7 @@ pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap,
PangoFcFontMapPrivate *priv;
PangoFcFindFuncInfo *info;
- g_return_val_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap), NULL);
+ g_return_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap));
priv = fcfontmap->priv;
@@ -1707,10 +1718,9 @@ pango_fc_font_map_set_coverage (PangoFcFontMap *fcfontmap,
PangoFcFontMapPrivate *priv = fcfontmap->priv;
PangoFcCoverageKey *key_dup;
- key_dup = g_malloc (sizeof (PangoFcCoverageKey) + strlen (key->filename) + 1);
- key_dup->id = key->id;
- key_dup->filename = (char *) (key_dup + 1);
- strcpy (key_dup->filename, key->filename);
+ key_dup = g_slice_new (PangoFcCoverageKey);
+ *key_dup = *key;
+ FcPatternReference (key_dup->pattern);
g_hash_table_insert (priv->coverage_hash,
key_dup, pango_coverage_ref (coverage));
@@ -1725,6 +1735,8 @@ _pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap,
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
--
1.6.1.3
From 5317893b83ee8a7270b9043d2325348cb5d03e12 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad behdad org>
Date: Tue, 10 Mar 2009 17:13:36 -0400
Subject: [PATCH 7/7] [pangofc] Share cmap cache between PangoFcFont's of the same face (#567160)
---
pango/pangofc-font.c | 41 ++++--------
pango/pangofc-fontmap.c | 172 ++++++++++++++++++++++++++++++++--------------
pango/pangofc-private.h | 26 +++++++
3 files changed, 158 insertions(+), 81 deletions(-)
diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c
index 41fb74e..976b0d8 100644
--- a/pango/pangofc-font.c
+++ b/pango/pangofc-font.c
@@ -38,33 +38,15 @@ enum {
PROP_FONTMAP
};
-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;
PangoFcFontKey *key;
- GUnicharToGlyphCacheEntry *char_to_glyph_cache;
+ PangoFcCmapCache *cmap_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,
@@ -166,7 +148,8 @@ pango_fc_font_finalize (GObject *object)
if (priv->decoder)
_pango_fc_font_set_decoder (fcfont, NULL);
- g_free (priv->char_to_glyph_cache);
+ if (priv->cmap_cache)
+ _pango_fc_cmap_cache_unref (priv->cmap_cache);
G_OBJECT_CLASS (pango_fc_font_parent_class)->finalize (object);
}
@@ -619,23 +602,25 @@ static guint
pango_fc_font_real_get_glyph (PangoFcFont *font,
gunichar wc)
{
+ PangoFcFontPrivate *priv = font->priv;
FT_Face face;
FT_UInt index;
guint idx;
- GUnicharToGlyphCacheEntry *entry;
+ PangoFcCmapCacheEntry *entry;
- PangoFcFontPrivate *priv = font->priv;
- if (G_UNLIKELY (priv->char_to_glyph_cache == NULL))
+ if (G_UNLIKELY (priv->cmap_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 */
+ priv->cmap_cache = _pango_fc_font_map_get_cmap_cache ((PangoFcFontMap *) font->fontmap,
+ font);
+
+ if (G_UNLIKELY (!priv->cmap_cache))
+ return 0;
}
- idx = wc & GLYPH_CACHE_MASK;
- entry = priv->char_to_glyph_cache + idx;
+ idx = wc & CMAP_CACHE_MASK;
+ entry = priv->cmap_cache->entries + idx;
if (entry->ch != wc)
{
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index 7841483..28acdf7 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);
}
/**
diff --git a/pango/pangofc-private.h b/pango/pangofc-private.h
index bc67ffb..0612a69 100644
--- a/pango/pangofc-private.h
+++ b/pango/pangofc-private.h
@@ -27,6 +27,7 @@
G_BEGIN_DECLS
+
typedef struct _PangoFcMetricsInfo PangoFcMetricsInfo;
struct _PangoFcMetricsInfo
@@ -35,6 +36,26 @@ struct _PangoFcMetricsInfo
PangoFontMetrics *metrics;
};
+
+typedef struct _PangoFcCmapCacheEntry PangoFcCmapCacheEntry;
+typedef struct _PangoFcCmapCache PangoFcCmapCache;
+
+#define CMAP_CACHE_NUM_ENTRIES 256 /* should be power of two */
+#define CMAP_CACHE_MASK (CMAP_CACHE_NUM_ENTRIES - 1)
+
+struct _PangoFcCmapCacheEntry
+{
+ gunichar ch;
+ PangoGlyph glyph;
+};
+
+struct _PangoFcCmapCache
+{
+ guint ref_count;
+ PangoFcCmapCacheEntry entries[CMAP_CACHE_NUM_ENTRIES];
+};
+
+
#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6))
#define PANGO_PIXELS_26_6(d) \
(((d) >= 0) ? \
@@ -46,10 +67,15 @@ void _pango_fc_font_shutdown (PangoFcFont *fcfont);
void _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap,
PangoFcFont *fcfont);
+
PangoCoverage *_pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap,
PangoFcFont *fcfont);
PangoCoverage *_pango_fc_font_map_fc_to_coverage (FcCharSet *charset);
+PangoFcCmapCache *_pango_fc_font_map_get_cmap_cache (PangoFcFontMap *fcfontmap,
+ PangoFcFont *fcfont);
+void _pango_fc_cmap_cache_unref (PangoFcCmapCache *cmap_cache);
+
PangoFcDecoder *_pango_fc_font_get_decoder (PangoFcFont *font);
void _pango_fc_font_set_decoder (PangoFcFont *font,
PangoFcDecoder *decoder);
--
1.6.1.3
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]