Re: Code freeze break request for Pango



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]