changeset 97025:e72be8a4fdb8

(uniscribe_shape): Pass NULL for control arg to ScriptItemize. Clean up return value checking. Remove unused variables. (uniscribe_encode_char): Encode non-BMP characters with uniscribe shaping engine.
author Jason Rumney <jasonr@gnu.org>
date Fri, 25 Jul 2008 21:53:21 +0000
parents c46e4c1d8339
children aebbea50eef4
files src/ChangeLog src/w32uniscribe.c
diffstat 2 files changed, 66 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Jul 25 21:44:37 2008 +0000
+++ b/src/ChangeLog	Fri Jul 25 21:53:21 2008 +0000
@@ -1,3 +1,14 @@
+2008-07-25  Jason Rumney  <jasonr@gnu.org>
+
+        * w32uniscribe.c (uniscribe_shape): Pass NULL for control arg to
+        ScriptItemize. Clean up return value checking. Remove unused
+        variables.
+        (uniscribe_encode_char): Encode non-BMP characters with uniscribe
+        shaping engine.
+
+        * w32font.c (w32font_has_char): Handle the case where we can't
+        determine the script for a character.
+
 2008-07-25  Chong Yidong  <cyd@stupidchicken.com>
 
 	* term.c (syms_of_term): Initialize default_orig_pair,
--- a/src/w32uniscribe.c	Fri Jul 25 21:44:37 2008 +0000
+++ b/src/w32uniscribe.c	Fri Jul 25 21:53:21 2008 +0000
@@ -134,6 +134,7 @@
 
   /* Initialize the cache for this font.  */
   uniscribe_font->cache = NULL;
+
   /* Mark the format as opentype  */
   uniscribe_font->w32_font.font.props[FONT_FORMAT_INDEX] = Qopentype;
   uniscribe_font->w32_font.font.driver = &uniscribe_font_driver;
@@ -150,7 +151,7 @@
     = (struct uniscribe_font_info *) font;
 
   if (uniscribe_font->cache)
-    ScriptFreeCache (&uniscribe_font->cache);
+    ScriptFreeCache (&(uniscribe_font->cache));
 
   w32font_close (f, font);
 }
@@ -206,12 +207,10 @@
   wchar_t *chars;
   WORD *glyphs, *clusters;
   SCRIPT_ITEM *items;
-  SCRIPT_CONTROL control;
   SCRIPT_VISATTR *attributes;
   int *advances;
   GOFFSET *offsets;
   ABC overall_metrics;
-  MAT2 transform;
   HDC context;
   HFONT old_font;
   HRESULT result;
@@ -239,9 +238,8 @@
      can be treated together.  First try a single run.  */
   max_items = 2;
   items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1);
-  bzero (&control, sizeof (control));
 
-  while ((result = ScriptItemize (chars, nchars, max_items, &control, NULL,
+  while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL,
 				  items, &nitems)) == E_OUTOFMEMORY)
     {
       /* If that wasn't enough, keep trying with one more run.  */
@@ -250,8 +248,7 @@
 					sizeof (SCRIPT_ITEM) * max_items + 1);
     }
 
-  /* 0 = success in Microsoft's backwards world.  */
-  if (result)
+  if (!SUCCEEDED (result))
     {
       xfree (items);
       return Qnil;
@@ -269,9 +266,6 @@
   attributes = alloca (max_glyphs * sizeof (SCRIPT_VISATTR));
   advances = alloca (max_glyphs * sizeof (int));
   offsets = alloca (max_glyphs * sizeof (GOFFSET));
-  bzero (&transform, sizeof (transform));
-  transform.eM11.value = 1;
-  transform.eM22.value = 1;
 
   for (i = 0; i < nitems; i++)
     {
@@ -304,7 +298,7 @@
 	  result = ScriptPlace (context, &(uniscribe_font->cache),
 				glyphs, nglyphs, attributes, &(items[i].a),
 				advances, offsets, &overall_metrics);
-	  if (result == 0) /* Success.  */
+	  if (SUCCEEDED (result))
 	    {
 	      int j, nclusters, from, to;
 
@@ -364,7 +358,7 @@
 						   &(uniscribe_font->cache),
 						   glyphs[j], &char_metric);
 
-		  if (result == 0) /* Success.  */
+		  if (SUCCEEDED (result))
 		    {
 		      LGLYPH_SET_LBEARING (lglyph, char_metric.abcA);
 		      LGLYPH_SET_RBEARING (lglyph, (char_metric.abcA
@@ -411,45 +405,68 @@
      struct font *font;
      int c;
 {
-  wchar_t chars[2];
-  int len;
-  WORD indices[1];
   HDC context;
   struct frame *f;
   HFONT old_font;
-  DWORD retval;
-
-  if (c > 0xFFFF)
-    {
-      DWORD surrogate = c - 0x10000;
-
-      /* High surrogate: U+D800 - U+DBFF.  */
-      chars[0] = 0xD800 + ((surrogate >> 10) & 0x03FF);
-      /* Low surrogate: U+DC00 - U+DFFF.  */
-      chars[1] = 0xDC00 + (surrogate & 0x03FF);
-      len = 2;
-    }
-  else
-    {
-      chars[0] = (wchar_t) c;
-      len = 1;
-    }
+  unsigned code = FONT_INVALID_CODE;
 
   /* Use selected frame until API is updated to pass the frame.  */
   f = XFRAME (selected_frame);
   context = get_frame_dc (f);
   old_font = SelectObject (context, FONT_HANDLE(font));
 
-  retval = GetGlyphIndicesW (context, chars, len, indices,
-			     GGI_MARK_NONEXISTING_GLYPHS);
+  /* There are a number of ways to get glyph indices for BMP characters.
+     The GetGlyphIndices GDI function seems to work best for detecting
+     non-existing glyphs.  */
+  if (c < 0x10000)
+    {
+      wchar_t ch = (wchar_t) c;
+      WORD index;
+      DWORD retval = GetGlyphIndicesW (context, &ch, 1, &index,
+                                       GGI_MARK_NONEXISTING_GLYPHS);
+      if (retval == 1 && index != 0xFFFF)
+        code = index;
+    }
+
+  /* Non BMP characters must be handled by the uniscribe shaping
+     engine as GDI functions (except blindly displaying lines of
+     unicode text) and the promising looking ScriptGetCMap do not
+     convert surrogate pairs to glyph indexes correctly.  */
+  else
+    {
+      wchar_t ch[2];
+      SCRIPT_ITEM* items;
+      int nitems;
+      struct uniscribe_font_info *uniscribe_font
+        = (struct uniscribe_font_info *)font;
+      DWORD surrogate = c - 0x10000;
+
+      /* High surrogate: U+D800 - U+DBFF.  */
+      ch[0] = 0xD800 + ((surrogate >> 10) & 0x03FF);
+      /* Low surrogate: U+DC00 - U+DFFF.  */
+      ch[1] = 0xDC00 + (surrogate & 0x03FF);
+
+      items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1);
+      if (SUCCEEDED (ScriptItemize (ch, 2, 2, NULL, NULL, items, &nitems)))
+        {
+          WORD glyphs[2], clusters[2];
+          SCRIPT_VISATTR attrs[2];
+          int nglyphs;
+
+          if (SUCCEEDED (ScriptShape (context, &(uniscribe_font->cache),
+                                      ch, 2, 2, &(items[0].a),
+                                      glyphs, clusters, attrs, &nglyphs))
+              && nglyphs == 1)
+            {
+              code = glyphs[0];
+            }
+        }
+    }
 
   SelectObject (context, old_font);
   release_frame_dc (f, context);
 
-  if (retval == 1)
-    return indices[0] == 0xFFFF ? FONT_INVALID_CODE : indices[0];
-  else
-    return FONT_INVALID_CODE;
+  return code;
 }
 
 /*