? f
? federico
? my-pango.diff
? pango-patch-for-vektor.diff
? simple.diff
? pango/.pango-types.h.swp
? pango/.pangocairo-fcfont.c.swp
? pango/new-cache.diff
? pango/pango-easy-scripts-table.h
? pango/pangocairo-fcfont.c.federico
Index: pango/Makefile.am
===================================================================
RCS file: /cvs/gnome/pango/pango/Makefile.am,v
retrieving revision 1.121.2.2
diff -p -u -r1.121.2.2 Makefile.am
--- pango/Makefile.am	22 Sep 2005 14:58:53 -0000	1.121.2.2
+++ pango/Makefile.am	26 Oct 2005 05:27:03 -0000
@@ -52,37 +52,38 @@ endif
 pango-win32-res.o: pango.rc
 	$(WINDRES) $< $@
 
-libpango_1_0_la_SOURCES =      \
-	break.c 	       \
-	ellipsize.c     	\
-	fonts.c 	       \
-	glyphstring.c 	       \
-	mapping.c 	       \
-	modules.c 	       \
-	pango-attributes.c     \
-	pango-color.c	       \
-	pango-color-table.h    \
-	pango-context.c        \
-	pango-coverage.c       \
-	pango-engine.c	       \
-	pango-engine-private.h \
-	pango-fontmap.c	       \
-	pango-fontset.c	       \
-	pango-glyph-item.c     \
-	pango-glyph-item-private.h     \
-	pango-impl-utils.h     \
-	pango-item.c	       \
-	pango-layout.c	       \
-	pango-layout-private.h	       \
-	pango-markup.c	       \
-	pango-renderer.c       \
-	pango-script.c	       \
-	pango-script-lang-table.h \
-	pango-script-table.h   \
-	pango-tabs.c	       \
-	pango-utils.c	       \
-	reorder-items.c        \
-	shape.c	               \
+libpango_1_0_la_SOURCES =			\
+	break.c					\
+	ellipsize.c				\
+	fonts.c					\
+	glyphstring.c				\
+	mapping.c				\
+	modules.c				\
+	pango-attributes.c			\
+	pango-color.c				\
+	pango-color-table.h			\
+	pango-context.c				\
+	pango-coverage.c			\
+	pango-easy-scripts-table.h		\
+	pango-engine.c				\
+	pango-engine-private.h			\
+	pango-fontmap.c				\
+	pango-fontset.c				\
+	pango-glyph-item.c			\
+	pango-glyph-item-private.h		\
+	pango-impl-utils.h			\
+	pango-item.c				\
+	pango-layout.c				\
+	pango-layout-private.h			\
+	pango-markup.c				\
+	pango-renderer.c			\
+	pango-script.c				\
+	pango-script-lang-table.h		\
+	pango-script-table.h			\
+	pango-tabs.c				\
+	pango-utils.c				\
+	reorder-items.c				\
+	shape.c					\
 	pango-enum-types.c
 
 pango_headers =		   \
Index: pango/pango-script.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-script.c,v
retrieving revision 1.11
diff -p -u -r1.11 pango-script.c
--- pango/pango-script.c	15 Aug 2005 21:22:16 -0000	1.11
+++ pango/pango-script.c	26 Oct 2005 05:27:04 -0000
@@ -58,6 +58,7 @@
 
 #include "pango-script.h"
 #include "pango-script-table.h"
+#include "pango-easy-scripts-table.h"
 
 #define PAREN_STACK_DEPTH 128
 
@@ -80,6 +81,8 @@ struct _PangoScriptIter
 
   ParenStackEntry paren_stack[PAREN_STACK_DEPTH];
   int paren_sp;
+  
+  int last_index_for_script_lookup;
 };
 
 /**
@@ -113,6 +116,40 @@ pango_script_for_unichar (gunichar ch)
   return PANGO_SCRIPT_COMMON;
 }
 
+PangoScript
+pango_script_for_unichar_with_last_index (gunichar ch, int *last_index)
+{
+  int lower = 0;
+  int upper = G_N_ELEMENTS (pango_script_table) - 1;
+
+  if (*last_index != -1
+      && pango_script_table[*last_index].start <= ch
+      && (ch < pango_script_table[*last_index].start + pango_script_table[*last_index].chars))
+    {
+/*       printf ("HIT: %c\n", ch); */
+      return pango_script_table[*last_index].script;
+    }
+
+/*   printf ("MISS: %c\n", ch); */
+
+  while (lower <= upper)
+    {
+      int mid = (lower + upper) / 2;
+      if (ch < pango_script_table[mid].start)
+	upper = mid - 1;
+      else if (ch >= pango_script_table[mid].start + pango_script_table[mid].chars)
+	lower = mid + 1;
+      else
+	{
+	  *last_index = mid;
+	  return pango_script_table[mid].script;
+	}
+    }
+
+  *last_index = -1;
+  return PANGO_SCRIPT_COMMON;
+}
+
 /**********************************************************************/
 
 /**
@@ -146,6 +183,7 @@ pango_script_iter_new (const char *text,
   iter->script_code = PANGO_SCRIPT_COMMON;
   
   iter->paren_sp = -1;
+  iter->last_index_for_script_lookup = -1;
 
   pango_script_iter_next (iter);
 
@@ -229,6 +267,56 @@ get_pair_index (gunichar ch)
 
   return -1;
 }
+#ifdef FMQ
+#include "pango-enum-types.h"
+
+static const char *
+get_script_name (int script)
+{
+  GEnumClass *enum_class;
+  GEnumValue *enum_value;
+
+  enum_class = g_type_class_ref (PANGO_TYPE_SCRIPT);
+  if (!enum_class)
+    g_error ("BOOM");
+
+  enum_value = g_enum_get_value (enum_class, script);
+  if (!enum_value)
+    g_error ("BING");
+
+  return enum_value->value_name;
+}
+
+#define EASY_SCRIPT_RANGE 8192
+
+static guchar easy_script_table[EASY_SCRIPT_RANGE];
+static gboolean easy_scripts_inited;
+
+static void
+easy_scripts_init (void)
+{
+  gunichar i;
+  int last_index = -1;
+  volatile GType gcc_sux_my_nutz;
+
+  easy_scripts_inited = TRUE;
+
+  gcc_sux_my_nutz = pango_script_get_type ();
+
+  puts ("{");
+
+  for (i = 0; i < EASY_SCRIPT_RANGE; i++)
+    {
+      easy_script_table[i] = pango_script_for_unichar_with_last_index (i, &last_index);
+      
+      printf ("  %s,\n", get_script_name ((int) easy_script_table[i]));
+    }
+
+  puts ("};");
+
+  fflush (stdout);
+}
+#endif
 
 #define REAL_SCRIPT(script) \
   ((script) > PANGO_SCRIPT_INHERITED)
@@ -266,8 +354,20 @@ pango_script_iter_next (PangoScriptIter 
       PangoScript sc;
       int pair_index;
 
-      sc = pango_script_for_unichar (ch);
-      pair_index = get_pair_index (ch);
+      if (ch < PANGO_EASY_SCRIPTS_RANGE)
+	{
+	  if (pango_easy_scripts_table[ch] & 0x80)
+	    pair_index = get_pair_index (ch);
+	  else
+	    pair_index = -1;
+
+	  sc = pango_easy_scripts_table[ch] & 0x7f;
+	}
+      else
+	{
+	  sc = pango_script_for_unichar_with_last_index (ch, &iter->last_index_for_script_lookup);
+	  pair_index = get_pair_index (ch);
+	}
 
       /*
        * Paired character handling:
Index: pango/pangocairo-fcfont.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangocairo-fcfont.c,v
retrieving revision 1.15
diff -p -u -r1.15 pangocairo-fcfont.c
--- pango/pangocairo-fcfont.c	15 Aug 2005 19:41:00 -0000	1.15
+++ pango/pangocairo-fcfont.c	26 Oct 2005 05:27:04 -0000
@@ -23,6 +23,7 @@
 
 #include <math.h>
 #include <stdlib.h>
+#include <stdio.h>
 
 #include <cairo-ft.h>
 
@@ -44,6 +45,29 @@ typedef struct _PangoCairoFcFont      Pa
 typedef struct _PangoCairoFcFontClass PangoCairoFcFontClass;
 typedef struct _PangoCairoFcGlyphInfo PangoCairoFcGlyphInfo;
 
+#undef PROFILE_GLYPH_CACHE
+#ifdef PROFILE_GLYPH_CACHE
+static int num_cairo_fc_fonts;
+static int max_cairo_fc_fonts;
+static int num_glyph_caches;
+static int max_glyph_caches;
+static long num_glyph_cache_hits;
+static long num_glyph_cache_misses;
+#endif
+
+/* An entry in the fixed-size cache for the gunichar -> glyph mapping.
+ * The cache is indexed by the lower 8 bits of the gunichar.  For scripts
+ * with few code points, this should provide pretty much instant lookups.
+ *
+ * The "ch" field is zero if that cache entry is invalid.
+ */
+typedef struct
+{
+  gunichar ch;
+  PangoGlyph glyph;
+} GlyphCacheEntry;
+
+#define GLYPH_INFO_SIZE 1024
 struct _PangoCairoFcFont
 {
   PangoFcFont font;
@@ -54,7 +78,9 @@ struct _PangoCairoFcFont
   cairo_matrix_t ctm;
   cairo_font_options_t *options;
 
-  GHashTable *glyph_info;
+  PangoCairoFcGlyphInfo *glyph_info [GLYPH_INFO_SIZE];
+
+  GlyphCacheEntry *char_to_glyph_cache;
 };
 
 struct _PangoCairoFcFontClass
@@ -64,8 +90,10 @@ struct _PangoCairoFcFontClass
 
 struct _PangoCairoFcGlyphInfo
 {
+  PangoGlyph glyph;
   PangoRectangle logical_rect;
   PangoRectangle ink_rect;
+  PangoCairoFcGlyphInfo *next;
 };
 
 GType pango_cairo_fc_font_get_type (void);
@@ -151,6 +179,7 @@ static void
 pango_cairo_fc_font_finalize (GObject *object)
 {
   PangoCairoFcFont *cffont = PANGO_CAIRO_FC_FONT (object);
+  int i;
 
   if (cffont->font_face)
     cairo_font_face_destroy (cffont->font_face);
@@ -159,9 +188,34 @@ pango_cairo_fc_font_finalize (GObject *o
   if (cffont->options)
     cairo_font_options_destroy (cffont->options);
 
-  g_hash_table_destroy (cffont->glyph_info);
+  for (i = 0; i < GLYPH_INFO_SIZE; i++)
+    {
+      PangoCairoFcGlyphInfo *info;
+      info = cffont->glyph_info [i];
+      while (info)
+        {
+          PangoCairoFcGlyphInfo *temp;
+          temp = info->next;
+          g_free (info);
+          info = temp;
+        }
+    }
+
+  if (cffont->char_to_glyph_cache)
+    {
+      g_free (cffont->char_to_glyph_cache);
+#ifdef PROFILE_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
 }
 
 static void
@@ -211,17 +265,21 @@ pango_cairo_fc_font_get_glyph_info (Pang
 {
   PangoCairoFcFont *cffont = (PangoCairoFcFont *)font;
   PangoCairoFcGlyphInfo *info;
+  guint cur = glyph & (GLYPH_INFO_SIZE - 1);
 
-  info = g_hash_table_lookup (cffont->glyph_info, GUINT_TO_POINTER (glyph));
+  info = cffont->glyph_info [cur];
+  while (info && info->glyph != glyph) info = info->next;
   if (!info)
     {
       info = g_new0 (PangoCairoFcGlyphInfo, 1);
+      info->glyph = glyph;
       
       compute_glyph_extents (font, glyph,
 			     &info->ink_rect,
 			     &info->logical_rect);
-      
-      g_hash_table_insert (cffont->glyph_info, GUINT_TO_POINTER (glyph), info);
+
+      info->next = cffont->glyph_info [cur];
+      cffont->glyph_info [cur] = info;
     }
 
   return info;
@@ -236,11 +294,18 @@ pango_cairo_fc_font_get_glyph_extents (P
   PangoCairoFcGlyphInfo *info;
 
   info = pango_cairo_fc_font_get_glyph_info (font, glyph);
-  
-  if (ink_rect)
-    *ink_rect = info->ink_rect;
-  if (logical_rect)
-    *logical_rect = info->logical_rect;
+  if (ink_rect) {
+    ink_rect->x = info->ink_rect.x;
+    ink_rect->y = info->ink_rect.y;
+    ink_rect->width = info->ink_rect.width;
+    ink_rect->height = info->ink_rect.height;
+  }
+  if (logical_rect) {
+    logical_rect->x = info->logical_rect.x;
+    logical_rect->y = info->logical_rect.y;
+    logical_rect->width = info->logical_rect.width;
+    logical_rect->height = info->logical_rect.height;
+  }
 }
 
 /* This function is cut-and-pasted from pangocairo-fcfont.c - it might be
@@ -313,6 +378,51 @@ pango_cairo_fc_font_unlock_face (PangoFc
 }
 
 static PangoGlyph
+pango_cairo_fc_font_get_glyph (PangoFcFont *font,
+			       gunichar     wc)
+{
+  PangoCairoFcFont *cffont = (PangoCairoFcFont *)font;
+  guint idx;
+  GlyphCacheEntry *entry;
+
+  /* We create the cache dynamically because although we'll have a lot of
+   * PangoCairoFcFont structures (one per font in the fontset, as many as needed
+   * to cover the whole Unicode space), we'll only end up using a few of them
+   * for the user's actual text.
+   */
+  if (cffont->char_to_glyph_cache == NULL) {
+    cffont->char_to_glyph_cache = g_new0 (GlyphCacheEntry, 256);
+#ifdef PROFILE_GLYPH_CACHE
+    num_glyph_caches++;
+    if (num_glyph_caches > max_glyph_caches)
+      max_glyph_caches = num_glyph_caches;
+#endif
+  }
+
+  idx = wc & 0x00ff;
+  entry = cffont->char_to_glyph_cache + idx;
+
+  if (entry->ch != wc || entry->ch == 0)
+    {
+#ifdef PROFILE_GLYPH_CACHE
+      num_glyph_cache_misses++;
+/*       printf ("cache MISS: cffont %p, gunichar %x = '%c'\n", cffont, wc, (wc < 128) ? wc : 0); */
+#endif
+      entry->ch = wc;
+      entry->glyph = ((PangoFcFontClass *) pango_cairo_fc_font_parent_class)->get_glyph (font, wc);
+    }
+  else
+    {
+#ifdef PROFILE_GLYPH_CACHE
+      num_glyph_cache_hits++;
+/*       printf ("cache HIT: cffont %p, gunichar %x = '%c'\n", cffont, wc, (wc < 128) ? wc : 0); */
+#endif
+    }
+
+  return entry->glyph;
+}
+
+static PangoGlyph
 pango_cairo_fc_font_real_get_unknown_glyph (PangoFcFont *font,
 					    gunichar     wc)
 {
@@ -335,6 +445,18 @@ pango_cairo_fc_font_shutdown (PangoFcFon
     }
 }
 
+#ifdef PROFILE_GLYPH_CACHE
+static void
+profile_glyph_cache_exit_cb (void)
+{
+  printf ("Maximum number of PangoCairoFcFont objects: %d\n", max_cairo_fc_fonts);
+  printf ("Maximum number of glyph caches created: %d (%d KB)\n", max_glyph_caches, (max_glyph_caches * sizeof (GlyphCacheEntry) * 256) / 1024);
+  printf ("Glyph cache hits: %ld\n", num_glyph_cache_hits);
+  printf ("Glyph cache misses: %ld\n", num_glyph_cache_misses);
+  printf ("Glyph cache miss rate: %f%%\n", 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)
 {
@@ -349,17 +471,25 @@ pango_cairo_fc_font_class_init (PangoCai
 
   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->get_unknown_glyph = pango_cairo_fc_font_real_get_unknown_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)
 {
-  cffont->glyph_info = g_hash_table_new_full (g_direct_hash,
-					      NULL,
-					      NULL,
-					      (GDestroyNotify)g_free);
+  memset (cffont->glyph_info, 0, GLYPH_INFO_SIZE * sizeof (PangoCairoFcGlyphInfo *));
+
+#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
 }
 
 /********************
@@ -433,6 +563,6 @@ _pango_cairo_fc_font_new (PangoCairoFcFo
     cairo_matrix_init_identity (&cffont->ctm);
 
   cffont->options = cairo_font_options_copy (_pango_cairo_context_get_merged_font_options (context));
-  
+
   return PANGO_FC_FONT (cffont);
 }
Index: pango/pangocairo-fontmap.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangocairo-fontmap.c,v
retrieving revision 1.8.2.1
diff -p -u -r1.8.2.1 pangocairo-fontmap.c
--- pango/pangocairo-fontmap.c	11 Sep 2005 02:46:38 -0000	1.8.2.1
+++ pango/pangocairo-fontmap.c	26 Oct 2005 05:27:04 -0000
@@ -220,8 +220,14 @@ static PangoCairoContextInfo *
 get_context_info (PangoContext *context,
 		  gboolean      create)
 {
-  PangoCairoContextInfo *info = g_object_get_data (G_OBJECT (context),
-						   "pango-cairo-context-info");
+  static GQuark context_info_quark;
+  PangoCairoContextInfo *info;
+
+  if (!context_info_quark)
+    context_info_quark = g_quark_from_static_string ("pango-cairo-context-info");
+
+  info = g_object_get_qdata (G_OBJECT (context), context_info_quark);
+
   if (!info && create)
     {
       info = g_new (PangoCairoContextInfo, 1);
@@ -230,8 +236,8 @@ get_context_info (PangoContext *context,
       info->surface_options = NULL;
       info->merged_options = NULL;
 
-      g_object_set_data_full (G_OBJECT (context), "pango-cairo-context-info", 
-			      info, (GDestroyNotify)free_context_info);
+      g_object_set_qdata_full (G_OBJECT (context), context_info_quark, 
+			       info, (GDestroyNotify)free_context_info);
     }
 
   return info;
