[HarfBuzz] harfbuzz: Branch 'master'

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue May 28 10:14:05 PDT 2013


 configure.ac        |   14 --
 src/hb-uniscribe.cc |  322 +++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 271 insertions(+), 65 deletions(-)

New commits:
commit 2a17f9568d9724e045d2c1d660e007f3acd747d9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 28 13:10:51 2013 -0400

    Bug 55494 - ScriptItemizeOpenType doesn't exists under Windows XP
    
    Fallback to older API if OpenType variants are not available.

diff --git a/configure.ac b/configure.ac
index f3898c9..3f1add9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -291,19 +291,7 @@ AC_ARG_WITH(uniscribe,
 	[with_uniscribe=no])
 have_uniscribe=false
 if test "x$with_uniscribe" = "xyes" -o "x$with_uniscribe" = "xauto"; then
-	AC_MSG_CHECKING([for ScriptShapeOpenType in usp10])
-	saved_LIBS=$LIBS
-	LIBS="$LIBS -lusp10 -lgdi32"
-	AC_LINK_IFELSE([AC_LANG_PROGRAM(
-		[[
-		 #define _WIN32_WINNT 0x0600
-		 #include <windows.h>
-		 #include <usp10.h>
-		 ]],
-		ScriptShapeOpenType)],
-		[have_uniscribe=true; AC_MSG_RESULT(yes)],
-		[AC_MSG_RESULT(no)])
-	LIBS=$saved_LIBS
+	AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true)
 fi
 if test "x$with_uniscribe" = "xyes" -a "x$have_uniscribe" != "xtrue"; then
 	AC_MSG_ERROR([uniscribe support requested but not found])
diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc
index 2f01c28..4a77fc0 100644
--- a/src/hb-uniscribe.cc
+++ b/src/hb-uniscribe.cc
@@ -44,15 +44,215 @@
 #endif
 
 
-/*
-DWORD GetFontData(
-  __in   HDC hdc,
-  __in   DWORD dwTable,
-  __in   DWORD dwOffset,
-  __out  LPVOID lpvBuffer,
-  __in   DWORD cbData
+typedef HRESULT WINAPI (*SIOT) /*ScriptItemizeOpenType*/(
+  const WCHAR *pwcInChars,
+  int cInChars,
+  int cMaxItems,
+  const SCRIPT_CONTROL *psControl,
+  const SCRIPT_STATE *psState,
+  SCRIPT_ITEM *pItems,
+  OPENTYPE_TAG *pScriptTags,
+  int *pcItems
+);
+
+typedef HRESULT WINAPI (*SSOT) /*ScriptShapeOpenType*/(
+  HDC hdc,
+  SCRIPT_CACHE *psc,
+  SCRIPT_ANALYSIS *psa,
+  OPENTYPE_TAG tagScript,
+  OPENTYPE_TAG tagLangSys,
+  int *rcRangeChars,
+  TEXTRANGE_PROPERTIES **rpRangeProperties,
+  int cRanges,
+  const WCHAR *pwcChars,
+  int cChars,
+  int cMaxGlyphs,
+  WORD *pwLogClust,
+  SCRIPT_CHARPROP *pCharProps,
+  WORD *pwOutGlyphs,
+  SCRIPT_GLYPHPROP *pOutGlyphProps,
+  int *pcGlyphs
 );
-*/
+
+typedef HRESULT WINAPI (*SPOT) /*ScriptPlaceOpenType*/(
+  HDC hdc,
+  SCRIPT_CACHE *psc,
+  SCRIPT_ANALYSIS *psa,
+  OPENTYPE_TAG tagScript,
+  OPENTYPE_TAG tagLangSys,
+  int *rcRangeChars,
+  TEXTRANGE_PROPERTIES **rpRangeProperties,
+  int cRanges,
+  const WCHAR *pwcChars,
+  WORD *pwLogClust,
+  SCRIPT_CHARPROP *pCharProps,
+  int cChars,
+  const WORD *pwGlyphs,
+  const SCRIPT_GLYPHPROP *pGlyphProps,
+  int cGlyphs,
+  int *piAdvance,
+  GOFFSET *pGoffset,
+  ABC *pABC
+);
+
+
+/* Fallback implementations. */
+
+static HRESULT WINAPI
+hb_ScriptItemizeOpenType(
+  const WCHAR *pwcInChars,
+  int cInChars,
+  int cMaxItems,
+  const SCRIPT_CONTROL *psControl,
+  const SCRIPT_STATE *psState,
+  SCRIPT_ITEM *pItems,
+  OPENTYPE_TAG *pScriptTags,
+  int *pcItems
+)
+{
+{
+  return ScriptItemize (pwcInChars,
+			cInChars,
+			cMaxItems,
+			psControl,
+			psState,
+			pItems,
+			pcItems);
+}
+}
+
+static HRESULT WINAPI
+hb_ScriptShapeOpenType(
+  HDC hdc,
+  SCRIPT_CACHE *psc,
+  SCRIPT_ANALYSIS *psa,
+  OPENTYPE_TAG tagScript,
+  OPENTYPE_TAG tagLangSys,
+  int *rcRangeChars,
+  TEXTRANGE_PROPERTIES **rpRangeProperties,
+  int cRanges,
+  const WCHAR *pwcChars,
+  int cChars,
+  int cMaxGlyphs,
+  WORD *pwLogClust,
+  SCRIPT_CHARPROP *pCharProps,
+  WORD *pwOutGlyphs,
+  SCRIPT_GLYPHPROP *pOutGlyphProps,
+  int *pcGlyphs
+)
+{
+  SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pOutGlyphProps;
+  return ScriptShape (hdc,
+		      psc,
+		      pwcChars,
+		      cChars,
+		      cMaxGlyphs,
+		      psa,
+		      pwOutGlyphs,
+		      pwLogClust,
+		      psva,
+		      pcGlyphs);
+}
+
+static HRESULT WINAPI
+hb_ScriptPlaceOpenType(
+  HDC hdc,
+  SCRIPT_CACHE *psc,
+  SCRIPT_ANALYSIS *psa,
+  OPENTYPE_TAG tagScript,
+  OPENTYPE_TAG tagLangSys,
+  int *rcRangeChars,
+  TEXTRANGE_PROPERTIES **rpRangeProperties,
+  int cRanges,
+  const WCHAR *pwcChars,
+  WORD *pwLogClust,
+  SCRIPT_CHARPROP *pCharProps,
+  int cChars,
+  const WORD *pwGlyphs,
+  const SCRIPT_GLYPHPROP *pGlyphProps,
+  int cGlyphs,
+  int *piAdvance,
+  GOFFSET *pGoffset,
+  ABC *pABC
+)
+{
+  SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pGlyphProps;
+  return ScriptPlace (hdc,
+		      psc,
+		      pwGlyphs,
+		      cGlyphs,
+		      psva,
+		      psa,
+		      piAdvance,
+		      pGoffset,
+		      pABC);
+}
+
+
+struct hb_uniscribe_shaper_funcs_t {
+  SIOT ScriptItemizeOpenType;
+  SSOT ScriptShapeOpenType;
+  SPOT ScriptPlaceOpenType;
+
+  inline void init (void)
+  {
+    this->ScriptItemizeOpenType = NULL;
+    this->ScriptShapeOpenType   = NULL;
+    this->ScriptPlaceOpenType   = NULL;
+
+    HMODULE hinstLib = GetModuleHandle("usp10.dll");
+    if (hinstLib)
+    {
+      this->ScriptItemizeOpenType = (SIOT) GetProcAddress (hinstLib, "ScriptItemizeOpenType");
+      this->ScriptShapeOpenType   = (SSOT) GetProcAddress (hinstLib, "ScriptShapeOpenType");
+      this->ScriptPlaceOpenType   = (SPOT) GetProcAddress (hinstLib, "ScriptPlaceOpenType");
+    }
+    if (!this->ScriptItemizeOpenType ||
+	!this->ScriptShapeOpenType   ||
+	!this->ScriptPlaceOpenType)
+    {
+      DEBUG_MSG (UNISCRIBE, NULL, "OpenType versions of functions not found; falling back.");
+      this->ScriptItemizeOpenType = hb_ScriptItemizeOpenType;
+      this->ScriptShapeOpenType   = hb_ScriptShapeOpenType;
+      this->ScriptPlaceOpenType   = hb_ScriptPlaceOpenType;
+    }
+  }
+};
+static hb_uniscribe_shaper_funcs_t *uniscribe_funcs;
+
+static inline void
+free_uniscribe_funcs (void)
+{
+  free (uniscribe_funcs);
+}
+
+
+static hb_uniscribe_shaper_funcs_t *
+hb_uniscribe_shaper_get_funcs (void)
+{
+retry:
+  hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
+
+  if (unlikely (!funcs))
+  {
+    funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
+    if (unlikely (!funcs))
+      return NULL;
+
+    funcs->init ();
+
+    if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, NULL, funcs)) {
+      free (funcs);
+      goto retry;
+    }
+
+#ifdef HAVE_ATEXIT
+    atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */
+#endif
+  }
+
+  return funcs;
+}
 
 
 HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face)
@@ -65,6 +265,7 @@ HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font)
 
 struct hb_uniscribe_shaper_face_data_t {
   HANDLE fh;
+  hb_uniscribe_shaper_funcs_t *funcs;
 };
 
 hb_uniscribe_shaper_face_data_t *
@@ -74,6 +275,13 @@ _hb_uniscribe_shaper_face_data_create (hb_face_t *face)
   if (unlikely (!data))
     return NULL;
 
+  data->funcs = hb_uniscribe_shaper_get_funcs ();
+  if (unlikely (!data->funcs))
+  {
+    free (data);
+    return NULL;
+  }
+
   hb_blob_t *blob = hb_face_reference_blob (face);
   unsigned int blob_length;
   const char *blob_data = hb_blob_get_data (blob, &blob_length);
@@ -240,6 +448,7 @@ _hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
   hb_face_t *face = font->face;
   hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
   hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+  hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
 
 #define FAIL(...) \
   HB_STMT_START { \
@@ -291,10 +500,19 @@ retry:
 
   ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
   ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
+  ALLOCATE_ARRAY (SCRIPT_VISATTR, vis_attr, glyphs_size);
   ALLOCATE_ARRAY (int, advances, glyphs_size);
   ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
   ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
 
+  /* Note:
+   * We can't touch the contents of glyph_props.  Our fallback
+   * implementations of Shape and Place functions use that buffer
+   * by casting it to a different type.  It works because they
+   * both agree about it, but if we want to access it here we
+   * need address that issue first.
+   */
+
 #undef ALLOCATE_ARRAY
 
 #define MAX_ITEMS 256
@@ -312,14 +530,14 @@ retry:
   bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
   bidi_state.fOverrideDirection = 1;
 
-  hr = ScriptItemizeOpenType (wchars,
-			      chars_len,
-			      MAX_ITEMS,
-			      &bidi_control,
-			      &bidi_state,
-			      items,
-			      script_tags,
-			      &item_count);
+  hr = funcs->ScriptItemizeOpenType (wchars,
+				     chars_len,
+				     MAX_ITEMS,
+				     &bidi_control,
+				     &bidi_state,
+				     items,
+				     script_tags,
+				     &item_count);
   if (unlikely (FAILED (hr)))
     FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
 
@@ -344,23 +562,23 @@ retry:
     unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
 
   retry_shape:
-    hr = ScriptShapeOpenType (font_data->hdc,
-			      &font_data->script_cache,
-			      &items[i].a,
-			      script_tags[i],
-			      language_tag,
-			      range_char_counts,
-			      range_properties,
-			      range_count,
-			      wchars + chars_offset,
-			      item_chars_len,
-			      glyphs_size - glyphs_offset,
-			      /* out */
-			      log_clusters + chars_offset,
-			      char_props + chars_offset,
-			      glyphs + glyphs_offset,
-			      glyph_props + glyphs_offset,
-			      (int *) &glyphs_len);
+    hr = funcs->ScriptShapeOpenType (font_data->hdc,
+				     &font_data->script_cache,
+				     &items[i].a,
+				     script_tags[i],
+				     language_tag,
+				     range_char_counts,
+				     range_properties,
+				     range_count,
+				     wchars + chars_offset,
+				     item_chars_len,
+				     glyphs_size - glyphs_offset,
+				     /* out */
+				     log_clusters + chars_offset,
+				     char_props + chars_offset,
+				     glyphs + glyphs_offset,
+				     glyph_props + glyphs_offset,
+				     (int *) &glyphs_len);
 
     if (unlikely (items[i].a.fNoGlyphIndex))
       FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
@@ -386,25 +604,25 @@ retry:
     for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
       log_clusters[j] += glyphs_offset;
 
-    hr = ScriptPlaceOpenType (font_data->hdc,
-			      &font_data->script_cache,
-			      &items[i].a,
-			      script_tags[i],
-			      language_tag,
-			      range_char_counts,
-			      range_properties,
-			      range_count,
-			      wchars + chars_offset,
-			      log_clusters + chars_offset,
-			      char_props + chars_offset,
-			      item_chars_len,
-			      glyphs + glyphs_offset,
-			      glyph_props + glyphs_offset,
-			      glyphs_len,
-			      /* out */
-			      advances + glyphs_offset,
-			      offsets + glyphs_offset,
-			      NULL);
+    hr = funcs->ScriptPlaceOpenType (font_data->hdc,
+				     &font_data->script_cache,
+				     &items[i].a,
+				     script_tags[i],
+				     language_tag,
+				     range_char_counts,
+				     range_properties,
+				     range_count,
+				     wchars + chars_offset,
+				     log_clusters + chars_offset,
+				     char_props + chars_offset,
+				     item_chars_len,
+				     glyphs + glyphs_offset,
+				     glyph_props + glyphs_offset,
+				     glyphs_len,
+				     /* out */
+				     advances + glyphs_offset,
+				     offsets + glyphs_offset,
+				     NULL);
     if (unlikely (FAILED (hr)))
       FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
 



More information about the HarfBuzz mailing list