[patch] PangoFT2FontCache::remove



Hi,

> > b) Add some sort of callback from the internal font cache so that when
> > fonts are dropped an external glyph cache can be notified. I don'r think
> > caching glyphs when not cacheing other font information is useful, so this
> > should be enough to make it possible to use <pango_ft2_get_face(),
> > glyph_index> to index the images in the glyph cache.

OK, here's a patch that changes PangoFT2FontCache to be a GObject that 
emits a "remove" signal if a face gets unloaded from the cache. 

The problem is that the signal is never emitted since the faces are 
never removed. Although the fontcache removes faces from its MRU list 
and unrefs them as soon as there are more than 10 fonts, they are never 
really removed from the cache since pango_ft2_font_cache_unload() is 
never called, so the refcount never drops to zero.

Please use the patch if you like it, but to make it really work, the
caching in PangoFT2 will need some more changes.


Salut, Sven

Index: pangoft2-fontcache.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoft2-fontcache.c,v
retrieving revision 1.8
diff -u -r1.8 pangoft2-fontcache.c
--- pangoft2-fontcache.c	2000/12/21 09:54:01	1.8
+++ pangoft2-fontcache.c	2001/03/13 19:56:25
@@ -24,6 +24,7 @@
 
 #include <string.h>
 
+
 /* Font cache
  */
 
@@ -35,6 +36,8 @@
 
 struct _PangoFT2FontCache
 {
+  GObject     parent_instance;
+
   FT_Library  library;
   
   GHashTable *forward;
@@ -45,6 +48,11 @@
   int mru_count;
 };
 
+struct _PangoFT2FontCacheClass
+{
+  GObjectClass  parent_class;
+};
+
 struct _CacheEntry
 {
   PangoFT2OA oa;
@@ -54,79 +62,91 @@
   GList *mru;
 };
 
-static void
-free_cache_entry (PangoFT2OA        *oa,
-		  CacheEntry        *entry,
-		  PangoFT2FontCache *cache)
+
+enum
 {
-  FT_Error error;
+  REMOVE,
+  LAST_SIGNAL
+};
 
-  PING (("FT_Done_Face (%p)", entry->face));
+static GObjectClass *parent_class;
+static guint         font_cache_signals[LAST_SIGNAL] = { 0, };
 
-  error = FT_Done_Face (entry->face);
-  if (error != FT_Err_Ok)
-    g_warning ("Error from FT_Done_Face: %s",
-	       pango_ft2_ft_strerror (error));
 
-  g_free (entry);
-}
+static void  pango_ft2_font_cache_init       (PangoFT2FontCache      *cache);
+static void  pango_ft2_font_cache_class_init (PangoFT2FontCacheClass *class);
+static void  pango_ft2_font_cache_finalize   (GObject                *object);
+
+static void  free_cache_entry  (PangoFT2OA        *oa,
+                                CacheEntry        *entry,
+                                PangoFT2FontCache *cache);
+static guint oa_hash           (gconstpointer      v);
+static gint  oa_equal          (gconstpointer      v1,
+                                gconstpointer      v2);
+static void  cache_entry_unref (PangoFT2FontCache *cache,
+                                CacheEntry        *entry);
 
-/**
- * pango_ft2_font_cache_free:
- * @cache: a #PangoFT2FontCache
- * 
- * Free a #PangoFT2FontCache and all associated memory. All fonts loaded
- * through this font cache will be freed along with the cache.
- **/
-void
-pango_ft2_font_cache_free (PangoFT2FontCache *cache)
+
+GType
+pango_ft2_font_cache_get_type (void)
 {
-  g_return_if_fail (cache != NULL);
-  
-  g_hash_table_foreach (cache->forward, (GHFunc)free_cache_entry, cache);
-  
-  g_hash_table_destroy (cache->forward);
-  g_hash_table_destroy (cache->back);
+  static GType object_type = 0;
 
-  g_list_free (cache->mru);
+  if (!object_type)
+    {
+      static const GTypeInfo object_info =
+      {
+        sizeof (PangoFT2FontCacheClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) pango_ft2_font_cache_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data */
+        sizeof (PangoFT2FontCache),
+        0,              /* n_preallocs */
+        (GInstanceInitFunc) pango_ft2_font_cache_init,
+      };
+      
+      object_type = g_type_register_static (G_TYPE_OBJECT,
+                                            "PangoFT2FontCache",
+                                            &object_info, 0);
+    }
+  
+  return object_type;
 }
 
-static guint
-oa_hash (gconstpointer v)
+static void
+pango_ft2_font_cache_class_init (PangoFT2FontCacheClass *class)
 {
-  PangoFT2OA *oa = (PangoFT2OA *) v;
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GType param_types[1] = { G_TYPE_POINTER };
 
-  if (oa->open_args->flags & ft_open_memory)
-    return (guint) oa->open_args->memory_base;
-  else if (oa->open_args->flags == ft_open_pathname)
-    return g_str_hash (oa->open_args->pathname);
-  else if (oa->open_args->flags & ft_open_stream)
-    return (guint) oa->open_args->stream;
-  else
-    return 0;
+  parent_class = g_type_class_peek_parent (class);
+
+  font_cache_signals[REMOVE] =
+    g_signal_newv ("remove",
+                   G_TYPE_FROM_CLASS (class),
+                   G_SIGNAL_RUN_FIRST,
+                   NULL,        /*  class closure  */
+                   NULL, NULL,  /*  accumulator    */
+                   g_cclosure_marshal_VOID__POINTER,
+                   G_TYPE_NONE,
+                   1, param_types);
+
+  object_class->finalize = pango_ft2_font_cache_finalize;
 }
 
-static gint
-oa_equal (gconstpointer v1,
-	  gconstpointer v2)
+static void
+pango_ft2_font_cache_init (PangoFT2FontCache *cache)
 {
-  PangoFT2OA *oa1 = (PangoFT2OA *) v1;
-  PangoFT2OA *oa2 = (PangoFT2OA *) v2;
+  cache->library   = NULL;
 
-  if (oa1->open_args->flags != oa2->open_args->flags)
-    return 0;
-  else if (oa1->open_args->flags & ft_open_memory)
-    return (oa1->open_args->memory_base == oa2->open_args->memory_base &&
-	    oa1->face_index == oa2->face_index);
-  else if (oa1->open_args->flags == ft_open_pathname)
-    return (strcmp (oa1->open_args->pathname,
-		    oa2->open_args->pathname) == 0 &&
-	    oa1->face_index == oa2->face_index);
-  else if (oa1->open_args->flags & ft_open_stream)
-    return (oa1->open_args->stream == oa2->open_args->stream &&
-	    oa1->face_index == oa2->face_index);
-  else
-    return 0;
+  cache->forward   = g_hash_table_new (oa_hash, oa_equal);
+  cache->back      = g_hash_table_new (g_direct_hash, g_direct_equal);
+      
+  cache->mru       = NULL;
+  cache->mru_tail  = NULL;
+  cache->mru_count = 0;
 }
 
 /**
@@ -135,41 +155,40 @@
  * 
  * Create a font cache.
  * 
- * Return value: The new font cache. This must be freed with
- * pango_ft2_font_cache_free().
+ * Return value: The new font cache object. All fonts loaded
+ * through this font cache will be freed if the object gets
+ * destroyed.
  **/
 PangoFT2FontCache *
 pango_ft2_font_cache_new (FT_Library library)
 {
   PangoFT2FontCache *cache;
 
-  cache = g_new (PangoFT2FontCache, 1);
+  g_return_val_if_fail (library != NULL, NULL);
 
-  cache->library = library;
-  
-  cache->forward = g_hash_table_new (oa_hash, oa_equal);
-  cache->back = g_hash_table_new (g_direct_hash, g_direct_equal);
-      
-  cache->mru = NULL;
-  cache->mru_tail = NULL;
-  cache->mru_count = 0;
+  cache = g_object_new (pango_ft2_font_cache_get_type (), NULL);
+
+  cache->library   = library;
   
-  return cache;
+  return PANGO_FT2_FONT_CACHE (cache);
 }
 
 static void
-cache_entry_unref (PangoFT2FontCache *cache,
-		   CacheEntry        *entry)
+pango_ft2_font_cache_finalize (GObject *object)
 {
-  entry->ref_count--;
-  PING (("face:%p ref_count:%d", entry->face, entry->ref_count));
-  if (entry->ref_count == 0)
-    {
-      g_hash_table_remove (cache->forward, &entry->oa);
-      g_hash_table_remove (cache->back, entry->face);
+  PangoFT2FontCache *cache;
 
-      free_cache_entry (NULL, entry, cache);
-    }
+  cache = PANGO_FT2_FONT_CACHE (object);
+  
+  g_hash_table_foreach (cache->forward, (GHFunc)free_cache_entry, cache);
+  
+  g_hash_table_destroy (cache->forward);
+  g_hash_table_destroy (cache->back);
+
+  g_list_free (cache->mru);
+
+  if (G_OBJECT_CLASS (parent_class)->finalize)
+    G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 /**
@@ -194,7 +213,7 @@
   CacheEntry *entry;
   PangoFT2OA oa;
 
-  g_return_val_if_fail (cache != NULL, NULL);
+  g_return_val_if_fail (PANGO_FT2_IS_FONT_CACHE (cache), NULL);
   g_return_val_if_fail (args != NULL, NULL);
 
   oa.open_args = args;
@@ -299,7 +318,7 @@
 {
   CacheEntry *entry;
 
-  g_return_if_fail (cache != NULL);
+  g_return_if_fail (PANGO_FT2_IS_FONT_CACHE (cache));
   g_return_if_fail (face != NULL);
 
   entry = g_hash_table_lookup (cache->back, face);
@@ -307,4 +326,77 @@
 
   PING (("pango_ft2_font_cache_unload"));
   cache_entry_unref (cache, entry);  
+}
+
+static guint
+oa_hash (gconstpointer v)
+{
+  PangoFT2OA *oa = (PangoFT2OA *) v;
+
+  if (oa->open_args->flags & ft_open_memory)
+    return (guint) oa->open_args->memory_base;
+  else if (oa->open_args->flags == ft_open_pathname)
+    return g_str_hash (oa->open_args->pathname);
+  else if (oa->open_args->flags & ft_open_stream)
+    return (guint) oa->open_args->stream;
+  else
+    return 0;
+}
+
+static gint
+oa_equal (gconstpointer v1,
+	  gconstpointer v2)
+{
+  PangoFT2OA *oa1 = (PangoFT2OA *) v1;
+  PangoFT2OA *oa2 = (PangoFT2OA *) v2;
+
+  if (oa1->open_args->flags != oa2->open_args->flags)
+    return 0;
+  else if (oa1->open_args->flags & ft_open_memory)
+    return (oa1->open_args->memory_base == oa2->open_args->memory_base &&
+	    oa1->face_index == oa2->face_index);
+  else if (oa1->open_args->flags == ft_open_pathname)
+    return (strcmp (oa1->open_args->pathname,
+		    oa2->open_args->pathname) == 0 &&
+	    oa1->face_index == oa2->face_index);
+  else if (oa1->open_args->flags & ft_open_stream)
+    return (oa1->open_args->stream == oa2->open_args->stream &&
+	    oa1->face_index == oa2->face_index);
+  else
+    return 0;
+}
+
+static void
+free_cache_entry (PangoFT2OA        *oa,
+		  CacheEntry        *entry,
+		  PangoFT2FontCache *cache)
+{
+  FT_Error error;
+
+  PING (("FT_Done_Face (%p)", entry->face));
+  g_signal_emit (G_OBJECT (cache), 
+                 font_cache_signals[REMOVE], 0,
+                 entry->face);
+
+  error = FT_Done_Face (entry->face);
+  if (error != FT_Err_Ok)
+    g_warning ("Error from FT_Done_Face: %s",
+	       pango_ft2_ft_strerror (error));
+
+  g_free (entry);
+}
+
+static void
+cache_entry_unref (PangoFT2FontCache *cache,
+		   CacheEntry        *entry)
+{
+  entry->ref_count--;
+  PING (("face:%p ref_count:%d", entry->face, entry->ref_count));
+  if (entry->ref_count == 0)
+    {
+      g_hash_table_remove (cache->forward, &entry->oa);
+      g_hash_table_remove (cache->back, entry->face);
+
+      free_cache_entry (NULL, entry, cache);
+    }
 }
Index: pangoft2-fontmap.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoft2-fontmap.c,v
retrieving revision 1.10
diff -u -r1.10 pangoft2-fontmap.c
--- pangoft2-fontmap.c	2001/02/04 07:04:06	1.10
+++ pangoft2-fontmap.c	2001/03/13 19:56:26
@@ -360,7 +360,7 @@
   g_list_foreach (ft2fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
   g_queue_free (ft2fontmap->freed_fonts);
   
-  pango_ft2_font_cache_free (ft2fontmap->font_cache);
+  g_object_unref (G_OBJECT (ft2fontmap->font_cache));
 
   FT_Done_FreeType (ft2fontmap->library);
 
Index: pangoft2.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoft2.h,v
retrieving revision 1.5
diff -u -r1.5 pangoft2.h
--- pangoft2.h	2001/01/07 04:54:28	1.5
+++ pangoft2.h	2001/03/13 19:56:28
@@ -78,8 +78,17 @@
 /* API for libraries that want to use PangoFT2 mixed with classic
  * FT2 fonts.
  */
-typedef struct _PangoFT2FontCache PangoFT2FontCache;
 
+#define PANGO_TYPE_FT2_FONT_CACHE              (pango_ft2_font_cache_get_type ())
+#define PANGO_FT2_FONT_CACHE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_FONT_CACHE, PangoFT2FontCache))
+#define PANGO_FT2_FONT_CACHE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_FONT_CACHE, PangoFT2FontCacheClass))
+#define PANGO_FT2_IS_FONT_CACHE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_FONT_CACHE))
+#define PANGO_FT2_IS_FONT_CACHE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_FONT_CACHE))
+
+typedef struct _PangoFT2FontCache      PangoFT2FontCache;
+typedef struct _PangoFT2FontCacheClass PangoFT2FontCacheClass;
+
+GType              pango_ft2_font_cache_get_type     (void);
 PangoFT2FontCache *pango_ft2_font_cache_new          (FT_Library         library);
 void               pango_ft2_font_cache_free         (PangoFT2FontCache *cache);
 FT_Face            pango_ft2_font_cache_load         (PangoFT2FontCache *cache,
@@ -87,6 +96,7 @@
 						      FT_Long            face_index);
 void               pango_ft2_font_cache_unload       (PangoFT2FontCache *cache,
 						      FT_Face            face);
+
 PangoFontMap      *pango_ft2_font_map_for_display    (void);
 void               pango_ft2_shutdown_display        (void);
 PangoFT2FontCache *pango_ft2_font_map_get_font_cache (PangoFontMap      *font_map);




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]