From 3882c7dcaa00c0489c4bfdd582b3fefe5e3741b9 Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Sat, 26 Jun 2010 16:05:13 +0300 Subject: [PATCH] Improve performance on Windows especially for non-Latin scripts The use of Uniscribe script caches was decidedly suboptimal. Use one persistent SCRIPT_CACHE per Win32 font and script. Patch by by David E. Hollingsworth and Fredrik Corneliusson, from bug --- modules/basic/basic-win32.c | 50 ++++++++++++++++++++++++++++++++++----------- pango/pangowin32-private.h | 7 +++---- pango/pangowin32.c | 29 ++++++++++---------------- pango/pangowin32.def | 1 + 4 files changed, 53 insertions(+), 34 deletions(-) diff --git a/modules/basic/basic-win32.c b/modules/basic/basic-win32.c index 1565a7c..22aafdb 100644 --- a/modules/basic/basic-win32.c +++ b/modules/basic/basic-win32.c @@ -31,6 +31,8 @@ #include "pangowin32.h" +extern HFONT _pango_win32_font_get_hfont (PangoFont *font); + #ifndef PANGO_MODULE_PREFIX #define PANGO_MODULE_PREFIX _pango_basic_win32 #endif @@ -500,8 +502,7 @@ itemize_shape_and_place (PangoFont *font, wchar_t *wtext, int wlen, const PangoAnalysis *analysis, - PangoGlyphString *glyphs, - SCRIPT_CACHE *script_cache) + PangoGlyphString *glyphs) { int i; int item, nitems, item_step; @@ -510,6 +511,11 @@ itemize_shape_and_place (PangoFont *font, SCRIPT_STATE state; SCRIPT_ITEM items[100]; double scale = pango_win32_font_get_metrics_factor (font); + HFONT hfont = _pango_win32_font_get_hfont (font); + static GHashTable *script_cache_hash = NULL; + + if (!script_cache_hash) + script_cache_hash = g_hash_table_new (g_int64_hash, g_int64_equal); memset (&control, 0, sizeof (control)); memset (&state, 0, sizeof (state)); @@ -556,9 +562,11 @@ itemize_shape_and_place (PangoFont *font, int advances[1000]; GOFFSET offsets[1000]; ABC abc; - int script = items[item].a.eScript; + gint32 script = items[item].a.eScript; int ng; int char_offset; + SCRIPT_CACHE *script_cache; + gint64 font_and_script_key; memset (advances, 0, sizeof (advances)); memset (offsets, 0, sizeof (offsets)); @@ -584,9 +592,33 @@ itemize_shape_and_place (PangoFont *font, items[item].a.fNoGlyphIndex ? " fNoGlyphIndex" : "", items[item].iCharPos, items[item+1].iCharPos-1, itemlen); #endif + /* Create a hash key based on hfont and script engine */ + font_and_script_key = (((gint64) ((gint32) hfont)) << 32) | script; + + /* Get the script cache for this hfont and script */ + script_cache = g_hash_table_lookup (script_cache_hash, &font_and_script_key); + if (!script_cache) + { + gint64 *key_n; + SCRIPT_CACHE *new_script_cache; + + key_n = g_new (gint64, 1); + *key_n = font_and_script_key; + + new_script_cache = g_new0 (SCRIPT_CACHE, 1); + script_cache = new_script_cache; + + /* Insert the new value */ + g_hash_table_insert (script_cache_hash, key_n, new_script_cache); + +#ifdef BASIC_WIN32_DEBUGGING + if (pango_win32_debug) + g_print (" New SCRIPT_CACHE for font %p and script %d\n", hfont, script); +#endif + } items[item].a.fRTL = analysis->level % 2; - if ((*script_shape) (hdc, &script_cache[script], + if ((*script_shape) (hdc, script_cache, wtext + items[item].iCharPos, itemlen, G_N_ELEMENTS (iglyphs), &items[item].a, @@ -616,7 +648,7 @@ itemize_shape_and_place (PangoFont *font, nglyphs, glyphs->log_clusters + ng, char_offset); - if ((*script_place) (hdc, &script_cache[script], iglyphs, nglyphs, + if ((*script_place) (hdc, script_cache, iglyphs, nglyphs, visattrs, &items[item].a, advances, offsets, &abc)) { @@ -676,9 +708,7 @@ uniscribe_shape (PangoFont *font, { wchar_t *wtext; long wlen; - int i; gboolean retval = TRUE; - SCRIPT_CACHE script_cache[100]; if (!pango_win32_font_select_font (font, hdc)) return FALSE; @@ -689,11 +719,7 @@ uniscribe_shape (PangoFont *font, if (retval) { - memset (script_cache, 0, sizeof (script_cache)); - retval = itemize_shape_and_place (font, hdc, wtext, wlen, analysis, glyphs, script_cache); - for (i = 0; i < G_N_ELEMENTS (script_cache); i++) - if (script_cache[i]) - (*script_free_cache)(&script_cache[i]); + retval = itemize_shape_and_place (font, hdc, wtext, wlen, analysis, glyphs); } if (retval) diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h index 9f35823..73df2e9 100644 --- a/pango/pangowin32-private.h +++ b/pango/pangowin32-private.h @@ -129,11 +129,8 @@ struct _PangoWin32Font PangoFontMap *fontmap; - /* Written by pango_win32_get_hfont: */ + /* Written by _pango_win32_font_get_hfont: */ HFONT hfont; - gint tm_ascent; - gint tm_descent; - gint tm_overhang; PangoWin32Face *win32face; @@ -275,6 +272,8 @@ gboolean _pango_win32_get_name_record (HDC hdc, gint i, struct name_record *record); +HFONT _pango_win32_font_get_hfont (PangoFont *font); + extern HDC _pango_win32_hdc; extern OSVERSIONINFO _pango_win32_os_version_info; extern gboolean _pango_win32_debug; diff --git a/pango/pangowin32.c b/pango/pangowin32.c index 1f8c1d2..30ec8b6 100644 --- a/pango/pangowin32.c +++ b/pango/pangowin32.c @@ -74,7 +74,6 @@ static gboolean pango_win32_font_real_select_font (PangoFont *font, static void pango_win32_font_real_done_font (PangoFont *font); static double pango_win32_font_real_get_metrics_factor (PangoFont *font); -static HFONT pango_win32_get_hfont (PangoFont *font); static void pango_win32_get_item_properties (PangoItem *item, PangoUnderline *uline, PangoAttrColor *fg_color, @@ -82,12 +81,11 @@ static void pango_win32_get_item_properties (PangoItem PangoAttrColor *bg_color, gboolean *bg_set); -static HFONT -pango_win32_get_hfont (PangoFont *font) +HFONT +_pango_win32_font_get_hfont (PangoFont *font) { PangoWin32Font *win32font = (PangoWin32Font *)font; PangoWin32FontCache *cache; - TEXTMETRIC tm; if (!win32font) return NULL; @@ -105,13 +103,6 @@ pango_win32_get_hfont (PangoFont *font) g_free (face_utf8); return NULL; } - - SelectObject (_pango_win32_hdc, win32font->hfont); - GetTextMetrics (_pango_win32_hdc, &tm); - - win32font->tm_overhang = tm.tmOverhang; - win32font->tm_descent = tm.tmDescent; - win32font->tm_ascent = tm.tmAscent; } return win32font->hfont; @@ -261,7 +252,7 @@ pango_win32_render (HDC hdc, if (glyphs->num_glyphs == 0) return; - hfont = pango_win32_get_hfont (font); + hfont = _pango_win32_font_get_hfont (font); if (!hfont) return; @@ -440,6 +431,7 @@ pango_win32_font_get_glyph_extents (PangoFont *font, PangoWin32Font *win32font = (PangoWin32Font *)font; guint16 glyph_index = glyph; GLYPHMETRICS gm; + TEXTMETRIC tm; guint32 res; HFONT hfont; MAT2 m = {{0,1}, {0,0}, {0,0}, {0,1}}; @@ -465,7 +457,7 @@ pango_win32_font_get_glyph_extents (PangoFont *font, memset (&gm, 0, sizeof (gm)); - hfont = pango_win32_get_hfont (font); + hfont = _pango_win32_font_get_hfont (font); SelectObject (_pango_win32_hdc, hfont); /* FIXME: (Alex) This constant reuse of _pango_win32_hdc is not thread-safe */ @@ -491,10 +483,11 @@ pango_win32_font_get_glyph_extents (PangoFont *font, info->ink_rect.y = - PANGO_SCALE * gm.gmptGlyphOrigin.y; info->ink_rect.height = PANGO_SCALE * gm.gmBlackBoxY; + GetTextMetrics (_pango_win32_hdc, &tm); info->logical_rect.x = 0; info->logical_rect.width = PANGO_SCALE * gm.gmCellIncX; - info->logical_rect.y = - PANGO_SCALE * win32font->tm_ascent; - info->logical_rect.height = PANGO_SCALE * (win32font->tm_ascent + win32font->tm_descent); + info->logical_rect.y = - PANGO_SCALE * tm.tmAscent; + info->logical_rect.height = PANGO_SCALE * (tm.tmAscent + tm.tmDescent); g_hash_table_insert (win32font->glyph_info, GUINT_TO_POINTER(glyph), info); } @@ -562,7 +555,7 @@ pango_win32_font_get_metrics (PangoFont *font, info->sample_str = sample_str; info->metrics = metrics = pango_font_metrics_new (); - hfont = pango_win32_get_hfont (font); + hfont = _pango_win32_font_get_hfont (font); if (hfont != NULL) { PangoCoverage *coverage; @@ -626,7 +619,7 @@ static gboolean pango_win32_font_real_select_font (PangoFont *font, HDC hdc) { - HFONT hfont = pango_win32_get_hfont (font); + HFONT hfont = _pango_win32_font_get_hfont (font); if (!hfont) return FALSE; @@ -1611,7 +1604,7 @@ font_has_name_in (PangoFont *font, if (cjkv == PANGO_WIN32_COVERAGE_UNSPEC) return TRUE; - hfont = pango_win32_get_hfont (font); + hfont = _pango_win32_font_get_hfont (font); oldhfont = SelectObject (_pango_win32_hdc, hfont); if (!_pango_win32_get_name_header (_pango_win32_hdc, &header)) diff --git a/pango/pangowin32.def b/pango/pangowin32.def index 13b6e8b..ec8e8b2 100644 --- a/pango/pangowin32.def +++ b/pango/pangowin32.def @@ -3,6 +3,7 @@ EXPORTS _pango_win32_make_matching_logfontw _pango_win32_font_get_type _pango_win32_font_map_get_type + _pango_win32_font_get_hfont pango_win32_font_cache_free pango_win32_font_cache_load pango_win32_font_cache_loadw -- 2.7.4