changeset 97004:1b8d15c8653f

* w32font.c (w32font_encode_char): Encode characters outside BMP as surrogates before looking up glyph index. (w32font_text_extents): Encode as surrogates if falling back to functions that need UTF-16 wide chars. * w32uniscribe.c (uniscribe_encode_char): Encode characters outside BMP as surrogates before looking up glyph index.
author Jason Rumney <jasonr@gnu.org>
date Fri, 25 Jul 2008 11:25:43 +0000
parents 1c0b739f899d
children 8e17e43e57e9
files src/ChangeLog src/w32font.c src/w32uniscribe.c
diffstat 3 files changed, 55 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Jul 25 05:51:24 2008 +0000
+++ b/src/ChangeLog	Fri Jul 25 11:25:43 2008 +0000
@@ -1,3 +1,13 @@
+2008-07-25  Jason Rumney  <jasonr@gnu.org>
+
+        * w32font.c (w32font_encode_char): Encode characters outside BMP as
+        surrogates before looking up glyph index.
+        (w32font_text_extents): Encode as surrogates if falling back to
+        functions that need UTF-16 wide chars.
+
+        * w32uniscribe.c (uniscribe_encode_char): Encode characters outside
+        BMP as surrogates before looking up glyph index.
+
 2008-07-25  Chong Yidong  <cyd@stupidchicken.com>
 
 	* image.c (svg_load_image): Check for failure in return value of
--- a/src/w32font.c	Fri Jul 25 05:51:24 2008 +0000
+++ b/src/w32font.c	Fri Jul 25 11:25:43 2008 +0000
@@ -327,8 +327,13 @@
 
   if (c > 0xFFFF)
     {
-      /* TODO: Encode as surrogate pair and lookup the glyph.  */
-      return FONT_INVALID_CODE;
+      DWORD surrogate = c - 0x10000;
+
+      /* High surrogate: U+D800 - U+DBFF.  */
+      in[0] = 0xD800 + ((surrogate >> 10) & 0x03FF);
+      /* Low surrogate: U+DC00 - U+DFFF.  */
+      in[1] = 0xDC00 + (surrogate & 0x03FF);
+      len = 2;
     }
   else
     {
@@ -394,7 +399,7 @@
   HDC dc = NULL;
   struct frame * f;
   int total_width = 0;
-  WORD *wcode = NULL;
+  WORD *wcode;
   SIZE size;
 
   struct w32font_info *w32_font = (struct w32font_info *) font;
@@ -484,19 +489,27 @@
   /* For non-truetype fonts, GetGlyphOutlineW is not supported, so
      fallback on other methods that will at least give some of the metric
      information.  */
-  if (!wcode) {
-    wcode = alloca (nglyphs * sizeof (WORD));
-    for (i = 0; i < nglyphs; i++)
-      {
-	if (code[i] < 0x10000)
-	  wcode[i] = code[i];
-	else
-	  {
-	    /* TODO: Convert to surrogate, reallocating array if needed */
-	    wcode[i] = 0xffff;
-	  }
-      }
-  }
+  
+  /* Make array big enough to hold surrogates.  */
+  wcode = alloca (nglyphs * sizeof (WORD) * 2);
+  for (i = 0; i < nglyphs; i++)
+    {
+      if (code[i] < 0x10000)
+        wcode[i] = code[i];
+      else
+        {
+          DWORD surrogate = code[i] - 0x10000;
+
+          /* High surrogate: U+D800 - U+DBFF.  */
+          wcode[i++] = 0xD800 + ((surrogate >> 10) & 0x03FF);
+          /* Low surrogate: U+DC00 - U+DFFF.  */
+          wcode[i] = 0xDC00 + (surrogate & 0x03FF);
+          /* An extra glyph. wcode is already double the size of code to
+             cope with this.  */
+          nglyphs++;
+        }
+    }
+
   if (dc == NULL)
     {
       /* TODO: Frames can come and go, and their fonts outlive
--- a/src/w32uniscribe.c	Fri Jul 25 05:51:24 2008 +0000
+++ b/src/w32uniscribe.c	Fri Jul 25 11:25:43 2008 +0000
@@ -411,25 +411,36 @@
      struct font *font;
      int c;
 {
-  wchar_t chars[1];
+  wchar_t chars[2];
+  int len;
   WORD indices[1];
   HDC context;
   struct frame *f;
   HFONT old_font;
   DWORD retval;
 
-  /* TODO: surrogates.  */
   if (c > 0xFFFF)
-    return FONT_INVALID_CODE;
+    {
+      DWORD surrogate = c - 0x10000;
 
-  chars[0] = (wchar_t) c;
+      /* 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;
+    }
 
   /* 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, 1, indices,
+  retval = GetGlyphIndicesW (context, chars, len, indices,
 			     GGI_MARK_NONEXISTING_GLYPHS);
 
   SelectObject (context, old_font);