# This is a shell script that calls functions and scripts from
# tml@iki.fi's personal work environment. It is not expected to be
# usable unmodified by others, and is included only for reference.

MOD=pango
VER=1.28.1
REV=2
ARCH=win32

THIS=${MOD}_${VER}-${REV}_${ARCH}

RUNZIP=${MOD}_${VER}-${REV}_${ARCH}.zip
DEVZIP=${MOD}-dev_${VER}-${REV}_${ARCH}.zip

HEX=`echo $THIS | md5sum | cut -d' ' -f1`
TARGET=c:/devel/target/$HEX

usedev
usemsvs6

(

set -x

patch --verbose --fuzz=0 -p1 <<'EOF'
commit ed4732969da2219e36c5c74193886637439bb2e9
Author: Tor Lillqvist <tml@iki.fi>
Date:   Sat Sep 11 15:17:19 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 #621869.

diff --git a/modules/basic/basic-win32.c b/modules/basic/basic-win32.c
index ecb139e..e1ef376 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 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

commit 75f0db89f7a4d0bd2948d27134913b9f2af02533
Author: Tor Lillqvist <tml@iki.fi>
Date:   Sat Sep 11 14:52:28 2010 +0300

    Reduce DLL hijack risk and simplify code in basic-win32 module
    
    Dont load usp10.dll dynamically with LoadLibrary(). Just link to the
    Uniscribe API directly. MinGW comes with an import library so no
    problem with that either. The Uniscribe DLL is present on all versions
    of Windows we care for.

diff --git a/modules/basic/Makefile.am b/modules/basic/Makefile.am
index acd0c4d..93604c9 100644
--- a/modules/basic/Makefile.am
+++ b/modules/basic/Makefile.am
@@ -47,7 +47,8 @@ endif
 endif
 
 pango_basic_win32_la_LDFLAGS = -module $(MODULE_LIBTOOL_OPTIONS)
-pango_basic_win32_la_LIBADD = $(pangowin32libs) -lgdi32
+pango_basic_win32_la_LIBADD = $(pangowin32libs) -lgdi32 -lusp10
+libpango_basic_win32_la_LIBADD = -lgdi32 -lusp10
 pango_basic_win32_la_SOURCES = basic-win32.c
 libpango_basic_win32_la_SOURCES = basic-win32.c
 libpango_basic_win32_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_win32
diff --git a/modules/basic/basic-win32.c b/modules/basic/basic-win32.c
index e1ef376..a7f1c90 100644
--- a/modules/basic/basic-win32.c
+++ b/modules/basic/basic-win32.c
@@ -45,55 +45,8 @@ static gboolean pango_win32_debug = FALSE;
 
 #include <usp10.h>
 
-static gboolean have_uniscribe = FALSE;
-
 static HDC hdc;
 
-typedef HRESULT (WINAPI *pScriptGetProperties) (const SCRIPT_PROPERTIES ***,
-						int *);
-
-typedef HRESULT (WINAPI *pScriptItemize) (const WCHAR *,
-					  int,
-					  int,
-					  const SCRIPT_CONTROL *,
-					  const SCRIPT_STATE *,
-					  SCRIPT_ITEM *,
-					  int *);
-
-typedef HRESULT (WINAPI *pScriptShape) (HDC,
-					SCRIPT_CACHE *,
-					const WCHAR *,
-					int,
-					int,
-					SCRIPT_ANALYSIS *,
-					WORD *,
-					WORD *,
-					SCRIPT_VISATTR *,
-					int *);
-
-typedef HRESULT (WINAPI *pScriptPlace) (HDC,
-					SCRIPT_CACHE *,
-					const WORD *,
-					int,
-					const SCRIPT_VISATTR *,
-					SCRIPT_ANALYSIS *,
-					int *,
-					GOFFSET *,
-					ABC *);
-
-typedef HRESULT (WINAPI *pScriptFreeCache) (SCRIPT_CACHE *);
-
-typedef HRESULT (WINAPI *pScriptIsComplex) (WCHAR *,
-					    int,
-					    DWORD);
-
-static pScriptGetProperties script_get_properties;
-static pScriptItemize script_itemize;
-static pScriptShape script_shape;
-static pScriptPlace script_place;
-static pScriptFreeCache script_free_cache;
-static pScriptIsComplex script_is_complex;
-
 #ifdef BASIC_WIN32_DEBUGGING
 static const SCRIPT_PROPERTIES **scripts;
 static int nscripts;
@@ -523,8 +476,8 @@ itemize_shape_and_place (PangoFont           *font,
     g_print (G_STRLOC ": ScriptItemize: uDefaultLanguage:%04x uBidiLevel:%d\n",
 	     control.uDefaultLanguage, state.uBidiLevel);
 #endif
-  if ((*script_itemize) (wtext, wlen, G_N_ELEMENTS (items), &control, NULL,
-			 items, &nitems))
+  if (ScriptItemize (wtext, wlen, G_N_ELEMENTS (items), &control, NULL,
+		     items, &nitems))
     {
 #ifdef BASIC_WIN32_DEBUGGING
       if (pango_win32_debug)
@@ -613,14 +566,14 @@ itemize_shape_and_place (PangoFont           *font,
 	}
 
       items[item].a.fRTL = analysis->level % 2;
-      if ((*script_shape) (hdc, script_cache,
-			   wtext + items[item].iCharPos, itemlen,
-			   G_N_ELEMENTS (iglyphs),
-			   &items[item].a,
-			   iglyphs,
-			   log_clusters,
-			   visattrs,
-			   &nglyphs))
+      if (ScriptShape (hdc, script_cache,
+		       wtext + items[item].iCharPos, itemlen,
+		       G_N_ELEMENTS (iglyphs),
+		       &items[item].a,
+		       iglyphs,
+		       log_clusters,
+		       visattrs,
+		       &nglyphs))
 	{
 #ifdef BASIC_WIN32_DEBUGGING
 	  if (pango_win32_debug)
@@ -643,9 +596,9 @@ itemize_shape_and_place (PangoFont           *font,
 				 nglyphs, glyphs->log_clusters + ng,
 				 char_offset);
 
-      if ((*script_place) (hdc, script_cache, iglyphs, nglyphs,
-			   visattrs, &items[item].a,
-			   advances, offsets, &abc))
+      if (ScriptPlace (hdc, script_cache, iglyphs, nglyphs,
+		       visattrs, &items[item].a,
+		       advances, offsets, &abc))
 	{
 #ifdef BASIC_WIN32_DEBUGGING
 	  if (pango_win32_debug)
@@ -752,7 +705,7 @@ text_is_simple (const char *text,
   if (wtext == NULL)
     return TRUE;
 
-  retval = ((*script_is_complex) (wtext, wlen, SIC_COMPLEX) == S_FALSE);
+  retval = (ScriptIsComplex (wtext, wlen, SIC_COMPLEX) == S_FALSE);
 
   g_free (wtext);
 
@@ -782,8 +735,7 @@ basic_engine_shape (PangoEngineShape 	*engine,
   g_return_if_fail (length >= 0);
   g_return_if_fail (analysis != NULL);
 
-  if (have_uniscribe &&
-      !text_is_simple (text, length) &&
+  if (!text_is_simple (text, length) &&
       uniscribe_shape (font, text, length, analysis, glyphs))
     return;
 
@@ -872,33 +824,10 @@ basic_engine_shape (PangoEngineShape 	*engine,
 static void
 init_uniscribe (void)
 {
-  HMODULE usp10_dll;
-
-  have_uniscribe = FALSE;
-
-  if ((usp10_dll = LoadLibrary ("usp10.dll")) != NULL)
-    {
-      (script_get_properties = (pScriptGetProperties)
-       GetProcAddress (usp10_dll, "ScriptGetProperties")) &&
-      (script_itemize = (pScriptItemize)
-       GetProcAddress (usp10_dll, "ScriptItemize")) &&
-      (script_shape = (pScriptShape)
-       GetProcAddress (usp10_dll, "ScriptShape")) &&
-      (script_place = (pScriptPlace)
-       GetProcAddress (usp10_dll, "ScriptPlace")) &&
-      (script_free_cache = (pScriptFreeCache)
-       GetProcAddress (usp10_dll, "ScriptFreeCache")) &&
-      (script_is_complex = (pScriptIsComplex)
-       GetProcAddress (usp10_dll, "ScriptIsComplex")) &&
-      (have_uniscribe = TRUE);
-    }
-  if (have_uniscribe)
-    {
 #ifdef BASIC_WIN32_DEBUGGING
-      (*script_get_properties) (&scripts, &nscripts);
+  ScriptGetProperties (&scripts, &nscripts);
 #endif
-      hdc = pango_win32_get_dc ();
-    }
+  hdc = pango_win32_get_dc ();
 }
 
 static void
@@ -935,28 +864,25 @@ PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
   script_engines[0].scripts = basic_scripts;
   script_engines[0].n_scripts = G_N_ELEMENTS (basic_scripts);
 
-  if (have_uniscribe)
-    {
 #if 0
-      int i;
-      GArray *ranges = g_array_new (FALSE, FALSE, sizeof (PangoEngineRange));
+  int i;
+  GArray *ranges = g_array_new (FALSE, FALSE, sizeof (PangoEngineRange));
 
-      /* Walk through scripts supported by the Uniscribe implementation on this
-       * machine, and mark corresponding Unicode ranges.
-       */
-      for (i = 0; i < nscripts; i++)
-	{
-	}
+  /* Walk through scripts supported by the Uniscribe implementation on this
+   * machine, and mark corresponding Unicode ranges.
+   */
+  for (i = 0; i < nscripts; i++)
+    {
+    }
 
-      /* Sort range array */
-      g_array_sort (ranges, compare_range);
-      script_engines[0].ranges = ranges;
-      script_engines[0].n_ranges = ranges->len;
+  /* Sort range array */
+  g_array_sort (ranges, compare_range);
+  script_engines[0].ranges = ranges;
+  script_engines[0].n_ranges = ranges->len;
 #else
-      script_engines[0].scripts = uniscribe_scripts;
-      script_engines[0].n_scripts = G_N_ELEMENTS (uniscribe_scripts);
+  script_engines[0].scripts = uniscribe_scripts;
+  script_engines[0].n_scripts = G_N_ELEMENTS (uniscribe_scripts);
 #endif
-    }
 
   *engines = script_engines;
   *n_engines = G_N_ELEMENTS (script_engines);
EOF

patch -p0 --verbose <<'EOF'
--- modules/basic/Makefile.in
+++ modules/basic/Makefile.in
@@ -101,7 +101,7 @@
 	$(libpango_basic_fc_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
 	$(LDFLAGS) -o $@
 @HAVE_FREETYPE_TRUE@@INCLUDE_BASIC_FC_TRUE@am_libpango_basic_fc_la_rpath =
-libpango_basic_win32_la_LIBADD =
+libpango_basic_win32_la_LIBADD = -lgdi32 -lusp10
 am_libpango_basic_win32_la_OBJECTS =  \
 	libpango_basic_win32_la-basic-win32.lo
 libpango_basic_win32_la_OBJECTS =  \
EOF

DEPS=`latest --arch=${ARCH} glib pkg-config zlib libpng pixman cairo expat fontconfig freetype`
PROXY_LIBINTL=`latest --arch=${ARCH} proxy-libintl`

PKG_CONFIG_PATH=/dummy
for D in $DEPS; do
    PKG_CONFIG_PATH=/devel/dist/${ARCH}/$D/lib/pkgconfig:$PKG_CONFIG_PATH
    PATH=/devel/dist/${ARCH}/$D/bin:$PATH
done

patch -p0 <<\EOF
EOF

lt_cv_deplibs_check_method='pass_all' \
CC='gcc -mtune=pentium3 -mthreads' \
LDFLAGS="-L/devel/dist/${ARCH}/${PROXY_LIBINTL}/lib -Wl,--exclude-libs=libintl.a -Wl,--enable-auto-image-base" \
CFLAGS=-O2 \
./configure --enable-debug=yes --disable-gtk-doc --without-x --prefix=c:/devel/target/$HEX --enable-explicit-deps=no --with-included-modules=yes &&

PATH=/devel/target/$HEX/bin:.libs:$PATH make install &&

./pango-zip.sh &&

cd $TARGET

zip /tmp/${MOD}-dev-${VER}.zip bin/pango-view.exe
zip /tmp/${MOD}-dev-${VER}.zip share/man/man1/*.1

mv /tmp/${MOD}-${VER}.zip /tmp/$RUNZIP &&
mv /tmp/${MOD}-dev-${VER}.zip /tmp/$DEVZIP

) 2>&1 | tee /devel/src/tml/packaging/$THIS.log

(cd /devel && zip /tmp/$DEVZIP src/tml/packaging/$THIS.{sh,log}) &&
manifestify /tmp/$RUNZIP /tmp/$DEVZIP
