emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/src/w32uniscribe.c,v


From: Jason Rumney
Subject: [Emacs-diffs] Changes to emacs/src/w32uniscribe.c,v
Date: Tue, 29 Jul 2008 16:24:25 +0000

CVSROOT:        /sources/emacs
Module name:    emacs
Changes by:     Jason Rumney <jasonr>   08/07/29 16:24:24

Index: w32uniscribe.c
===================================================================
RCS file: /sources/emacs/emacs/src/w32uniscribe.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- w32uniscribe.c      25 Jul 2008 21:53:21 -0000      1.20
+++ w32uniscribe.c      29 Jul 2008 16:24:24 -0000      1.21
@@ -211,10 +211,10 @@
   int *advances;
   GOFFSET *offsets;
   ABC overall_metrics;
-  HDC context;
-  HFONT old_font;
   HRESULT result;
-  struct frame * f;
+  struct frame * f = NULL;
+  HDC context = NULL;
+  HFONT old_font = NULL;
 
   CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
   uniscribe_font = (struct uniscribe_font_info *) font;
@@ -248,7 +248,7 @@
                                        sizeof (SCRIPT_ITEM) * max_items + 1);
     }
 
-  if (!SUCCEEDED (result))
+  if (FAILED (result))
     {
       xfree (items);
       return Qnil;
@@ -257,10 +257,6 @@
   /* TODO: When we get BIDI support, we need to call ScriptLayout here.
      Requires that we know the surrounding context.  */
 
-  f = XFRAME (selected_frame);
-  context = get_frame_dc (f);
-  old_font = SelectObject (context, FONT_HANDLE(font));
-
   glyphs = alloca (max_glyphs * sizeof (WORD));
   clusters = alloca (nchars * sizeof (WORD));
   attributes = alloca (max_glyphs * sizeof (SCRIPT_VISATTR));
@@ -272,17 +268,35 @@
       int nglyphs, nchars_in_run, rtl = items[i].a.fRTL ? -1 : 1;
       nchars_in_run = items[i+1].iCharPos - items[i].iCharPos;
 
+      /* Context may be NULL here, in which case the cache should be
+         used without needing to select the font.  */
       result = ScriptShape (context, &(uniscribe_font->cache),
                            chars + items[i].iCharPos, nchars_in_run,
                            max_glyphs - done_glyphs, &(items[i].a),
                            glyphs, clusters, attributes, &nglyphs);
+
+      if (result == E_PENDING && !context)
+       {
+         /* This assumes the selected frame is on the same display as the
+            one we are drawing.  It would be better for the frame to be
+            passed in.  */
+         f = XFRAME (selected_frame);
+         context = get_frame_dc (f);
+         old_font = SelectObject (context, FONT_HANDLE(font));
+
+         result = ScriptShape (context, &(uniscribe_font->cache),
+                               chars + items[i].iCharPos, nchars_in_run,
+                               max_glyphs - done_glyphs, &(items[i].a),
+                               glyphs, clusters, attributes, &nglyphs);
+       }
+
       if (result == E_OUTOFMEMORY)
        {
          /* Need a bigger lgstring.  */
          lgstring = Qnil;
          break;
        }
-      else if (result) /* Failure.  */
+      else if (FAILED (result))
        {
          /* Can't shape this run - return results so far if any.  */
          break;
@@ -298,6 +312,17 @@
          result = ScriptPlace (context, &(uniscribe_font->cache),
                                glyphs, nglyphs, attributes, &(items[i].a),
                                advances, offsets, &overall_metrics);
+         if (result == E_PENDING && !context)
+           {
+             /* Cache not complete...  */
+             f = XFRAME (selected_frame);
+             context = get_frame_dc (f);
+             old_font = SelectObject (context, FONT_HANDLE(font));
+
+             result = ScriptPlace (context, &(uniscribe_font->cache),
+                                   glyphs, nglyphs, attributes, &(items[i].a),
+                                   advances, offsets, &overall_metrics);
+           }
          if (SUCCEEDED (result))
            {
              int j, nclusters, from, to;
@@ -357,6 +382,16 @@
                  result = ScriptGetGlyphABCWidth (context,
                                                   &(uniscribe_font->cache),
                                                   glyphs[j], &char_metric);
+                 if (result == E_PENDING && !context)
+                   {
+                     /* Cache incomplete... */
+                     f = XFRAME (selected_frame);
+                     context = get_frame_dc (f);
+                     old_font = SelectObject (context, FONT_HANDLE(font));
+                     result = ScriptGetGlyphABCWidth (context,
+                                                      &(uniscribe_font->cache),
+                                                      glyphs[j], &char_metric);
+                   }
 
                  if (SUCCEEDED (result))
                    {
@@ -382,14 +417,19 @@
                    }
                  else
                    LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
-               }           }
+               }
+           }
        }
       done_glyphs += nglyphs;
     }
 
   xfree (items);
+
+  if (context)
+    {
   SelectObject (context, old_font);
   release_frame_dc (f, context);
+    }
 
   if (NILP (lgstring))
     return Qnil;
@@ -405,66 +445,88 @@
      struct font *font;
      int c;
 {
-  HDC context;
-  struct frame *f;
-  HFONT old_font;
+  HDC context = NULL;
+  struct frame *f = NULL;
+  HFONT old_font = NULL;
   unsigned code = FONT_INVALID_CODE;
+  wchar_t ch[2];
+  int len;
+  SCRIPT_ITEM* items;
+  int nitems;
+  struct uniscribe_font_info *uniscribe_font
+    = (struct uniscribe_font_info *)font;
 
-  /* 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));
-
-  /* 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;
+      ch[0] = (wchar_t) c;
+      len = 1;
     }
-
-  /* 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);
+      len = 2;
+    }
 
+  /* 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.  */
+    {
       items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1);
-      if (SUCCEEDED (ScriptItemize (ch, 2, 2, NULL, NULL, items, &nitems)))
+      if (SUCCEEDED (ScriptItemize (ch, len, 2, NULL, NULL, items, &nitems)))
         {
-          WORD glyphs[2], clusters[2];
-          SCRIPT_VISATTR attrs[2];
+         HRESULT result;
+          /* Some Indic characters result in more than 1 glyph.  */
+          WORD glyphs[1], clusters[1];
+          SCRIPT_VISATTR attrs[1];
           int nglyphs;
 
-          if (SUCCEEDED (ScriptShape (context, &(uniscribe_font->cache),
-                                      ch, 2, 2, &(items[0].a),
-                                      glyphs, clusters, attrs, &nglyphs))
-              && nglyphs == 1)
+          result = ScriptShape (context, &(uniscribe_font->cache),
+                                ch, len, 20, &(items[0].a),
+                                glyphs, clusters, attrs, &nglyphs);
+
+          if (result == E_PENDING)
+            {
+              /* 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));
+              result = ScriptShape (context, &(uniscribe_font->cache),
+                                    ch, len, 2, &(items[0].a),
+                                    glyphs, clusters, attrs, &nglyphs);
+            }
+
+          if (SUCCEEDED (result) && nglyphs == 1)
             {
               code = glyphs[0];
             }
+          else if (SUCCEEDED (result) || result == E_OUTOFMEMORY)
+            {
+              /* This character produces zero or more than one glyph
+                 when shaped. But we still need the return from here
+                 to be valid for the shaping engine to be invoked
+                 later.  */
+              result = ScriptGetCMap (context, &(uniscribe_font->cache),
+                                      ch, len, 0, glyphs);
+              if (SUCCEEDED (result))
+                return glyphs[0];
+              else
+                return 0; /* notdef - enough in some cases to get the script
+                             engine working, but not others... */
+            }
         }
     }
-
+    if (context)
+      {
   SelectObject (context, old_font);
   release_frame_dc (f, context);
+      }
 
   return code;
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]