[pango] Improve performance on Windows especially for non-Latin scripts



commit 3882c7dcaa00c0489c4bfdd582b3fefe5e3741b9
Author: Tor Lillqvist <tml iki fi>
Date:   Sat Jun 26 16:05:13 2010 +0300

    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



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