? 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 #include +#include #include @@ -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;