summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@iki.fi>2010-09-11 15:17:19 +0300
committerTor Lillqvist <tml@iki.fi>2010-09-11 15:18:41 +0300
commited4732969da2219e36c5c74193886637439bb2e9 (patch)
tree81e12030fc82dfc4803d23b5f10bbeb923bee004
parent9daa110ccb5adc48a0f01a1a637a9134b6d46892 (diff)
downloadpango-ed4732969da2219e36c5c74193886637439bb2e9.tar.gz
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 #621869.
-rw-r--r--modules/basic/basic-win32.c50
-rw-r--r--pango/pangowin32-private.h7
-rw-r--r--pango/pangowin32.c29
-rw-r--r--pango/pangowin32.def1
4 files changed, 53 insertions, 34 deletions
diff --git a/modules/basic/basic-win32.c b/modules/basic/basic-win32.c
index ecb139e0..e1ef3766 100644
--- a/modules/basic/basic-win32.c
+++ b/modules/basic/basic-win32.c
@@ -33,6 +33,8 @@
#include "pango-engine.h"
#include "pango-utils.h"
+extern HFONT _pango_win32_font_get_hfont (PangoFont *font);
+
/* No extra fields needed */
typedef PangoEngineShape BasicEngineWin32;
typedef PangoEngineShapeClass BasicEngineWin32Class ;
@@ -495,8 +497,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;
@@ -505,6 +506,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));
@@ -551,9 +557,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));
@@ -579,9 +587,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,
@@ -611,7 +643,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))
{
@@ -671,9 +703,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;
@@ -684,11 +714,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 9f358230..73df2e99 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 1f8c1d25..30ec8b6f 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 13b6e8b1..ec8e8b2d 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