]> code.delx.au - gnu-emacs/blobdiff - src/w32uniscribe.c
Reformat copyright line.
[gnu-emacs] / src / w32uniscribe.c
index dbf26011ff1dfed2bfe662e9dfd9fbedaa1353ab..f2bd0f44b50fcff4b42d5541c244a1cf43db8560 100644 (file)
@@ -1,12 +1,12 @@
 /* Font backend for the Microsoft W32 Uniscribe API.
-   Copyright (C) 2008 Free Software Foundation, Inc.
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,22 +14,20 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#ifdef USE_FONT_BACKEND
 
 #include <config.h>
 /* Override API version - Uniscribe is only available as standard since
    Windows 2000, though most users of older systems will have it
    since it installs with Internet Explorer 5.0 and other software.
    We only enable the feature if it is available, so there is no chance
-   of calling non-existant functions.  */
+   of calling non-existent functions.  */
 #undef _WIN32_WINNT
 #define _WIN32_WINNT 0x500
 #include <windows.h>
 #include <usp10.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "w32term.h"
@@ -37,6 +35,7 @@ Boston, MA 02110-1301, USA.  */
 #include "dispextern.h"
 #include "character.h"
 #include "charset.h"
+#include "composite.h"
 #include "fontset.h"
 #include "font.h"
 #include "w32font.h"
@@ -79,14 +78,18 @@ static Lisp_Object
 uniscribe_list (frame, font_spec)
      Lisp_Object frame, font_spec;
 {
-  return w32font_list_internal (frame, font_spec, 1);
+  Lisp_Object fonts = w32font_list_internal (frame, font_spec, 1);
+  FONT_ADD_LOG ("uniscribe-list", font_spec, fonts);
+  return fonts;
 }
 
 static Lisp_Object
 uniscribe_match (frame, font_spec)
      Lisp_Object frame, font_spec;
 {
-  return w32font_match_internal (frame, font_spec, 1);
+  Lisp_Object entity = w32font_match_internal (frame, font_spec, 1);
+  FONT_ADD_LOG ("uniscribe-match", font_spec, entity);
+  return entity;
 }
 
 static Lisp_Object
@@ -112,32 +115,36 @@ uniscribe_list_family (frame)
   return list;
 }
 
-static struct font *
+static Lisp_Object
 uniscribe_open (f, font_entity, pixel_size)
      FRAME_PTR f;
      Lisp_Object font_entity;
      int pixel_size;
 {
+  Lisp_Object font_object
+    = font_make_object (VECSIZE (struct uniscribe_font_info),
+                       font_entity, pixel_size);
   struct uniscribe_font_info *uniscribe_font
-    = xmalloc (sizeof (struct uniscribe_font_info));
+    = (struct uniscribe_font_info *) XFONT_OBJECT (font_object);
 
-  if (uniscribe_font == NULL)
-    return NULL;
+  ASET (font_object, FONT_TYPE_INDEX, Quniscribe);
 
-  if (!w32font_open_internal (f, font_entity, pixel_size,
-                              (struct w32font_info *) uniscribe_font))
+  if (!w32font_open_internal (f, font_entity, pixel_size, font_object))
     {
-      xfree (uniscribe_font);
-      return NULL;
+      return Qnil;
     }
 
   /* Initialize the cache for this font.  */
   uniscribe_font->cache = NULL;
+
+  /* Uniscribe backend uses glyph indices.  */
+  uniscribe_font->w32_font.glyph_idx = ETO_GLYPH_INDEX;
+
   /* Mark the format as opentype  */
-  uniscribe_font->w32_font.font.format = Qopentype;
+  uniscribe_font->w32_font.font.props[FONT_FORMAT_INDEX] = Qopentype;
   uniscribe_font->w32_font.font.driver = &uniscribe_font_driver;
 
-  return (struct font *) uniscribe_font;
+  return font_object;
 }
 
 static void
@@ -149,7 +156,7 @@ uniscribe_close (f, font)
     = (struct uniscribe_font_info *) font;
 
   if (uniscribe_font->cache)
-    ScriptFreeCache (&uniscribe_font->cache);
+    ScriptFreeCache (&(uniscribe_font->cache));
 
   w32font_close (f, font);
 }
@@ -168,8 +175,7 @@ uniscribe_otf_capability (font)
 
   f = XFRAME (selected_frame);
   context = get_frame_dc (f);
-  old_font = SelectObject (context,
-                          ((W32FontStruct *) (font->font.font))->hfont);
+  old_font = SelectObject (context, FONT_HANDLE(font));
 
   features = otf_features (context, "GSUB");
   XSETCAR (capability, features);
@@ -202,27 +208,25 @@ uniscribe_shape (lgstring)
   struct font * font;
   struct uniscribe_font_info * uniscribe_font;
   EMACS_UINT nchars;
-  int nitems, max_items, i, max_glyphs, done_glyphs, done_chars;
+  int nitems, max_items, i, max_glyphs, done_glyphs;
   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;
-  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;
 
   /* Get the chars from lgstring in a form we can use with uniscribe.  */
-  max_glyphs = nchars = LGSTRING_LENGTH (lgstring);
-  done_glyphs = done_chars = 0;
+  max_glyphs = nchars = LGSTRING_GLYPH_LEN (lgstring);
+  done_glyphs = 0;
   chars = (wchar_t *) alloca (nchars * sizeof (wchar_t));
   for (i = 0; i < nchars; i++)
     {
@@ -238,177 +242,209 @@ uniscribe_shape (lgstring)
   /* First we need to break up the glyph string into runs of glyphs that
      can be treated together.  First try a single run.  */
   max_items = 2;
-  items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items);
-  bzero (&control, sizeof (control));
+  items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1);
 
-  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.  */
       max_items++;
       items = (SCRIPT_ITEM *) xrealloc (items,
-                                       sizeof (SCRIPT_ITEM) * max_items);
+                                       sizeof (SCRIPT_ITEM) * max_items + 1);
     }
 
-  /* 0 = success in Microsoft's backwards world.  */
-  if (result)
+  if (FAILED (result))
     {
       xfree (items);
       return Qnil;
     }
 
-  f = XFRAME (selected_frame);
-  context = get_frame_dc (f);
-  old_font = SelectObject (context,
-                          ((W32FontStruct *) (font->font.font))->hfont);
+  /* TODO: When we get BIDI support, we need to call ScriptLayout here.
+     Requires that we know the surrounding context.  */
 
   glyphs = alloca (max_glyphs * sizeof (WORD));
   clusters = alloca (nchars * sizeof (WORD));
   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++)
     {
-      int nglyphs, nchars_in_run;
+      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)
+      else if (FAILED (result))
        {
          /* Can't shape this run - return results so far if any.  */
          break;
        }
+      else if (items[i].a.fNoGlyphIndex)
+       {
+         /* Glyph indices not supported by this font (or OS), means we
+            can't really do any meaningful shaping.  */
+         break;
+       }
       else
        {
          result = ScriptPlace (context, &(uniscribe_font->cache),
                                glyphs, nglyphs, attributes, &(items[i].a),
                                advances, offsets, &overall_metrics);
-         if (!result)
+         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;
+             int j, nclusters, from, to;
+
+             from = rtl > 0 ? 0 : nchars_in_run - 1;
+             to = from;
 
              for (j = 0; j < nglyphs; j++)
                {
                  int lglyph_index = j + done_glyphs;
                  Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, lglyph_index);
-                 GLYPHMETRICS metrics;
+                 ABC char_metric;
+                 unsigned gl;
 
                  if (NILP (lglyph))
                    {
                      lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
                      LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph);
                    }
-                 LGLYPH_SET_CODE (lglyph, glyphs[j]);
+                 /* Copy to a 32-bit data type to shut up the
+                    compiler warning in LGLYPH_SET_CODE about
+                    comparison being always false.  */
+                 gl = glyphs[j];
+                 LGLYPH_SET_CODE (lglyph, gl);
+
+                 /* Detect clusters, for linking codes back to characters.  */
+                 if (attributes[j].fClusterStart)
+                   {
+                     while (from >= 0 && from < nchars_in_run
+                            && clusters[from] < j)
+                       from += rtl;
+                     if (from < 0)
+                       from = to = 0;
+                     else if (from >= nchars_in_run)
+                       from = to = nchars_in_run - 1;
+                     else
+                       {
+                         int k;
+                         to = rtl > 0 ? nchars_in_run - 1 : 0;
+                         for (k = from + rtl; k >= 0 && k < nchars_in_run;
+                              k += rtl)
+                           {
+                             if (clusters[k] > j)
+                               {
+                                 to = k - 1;
+                                 break;
+                               }
+                           }
+                       }
+                   }
+
+                 LGLYPH_SET_CHAR (lglyph, chars[items[i].iCharPos
+                                                + from]);
+                 LGLYPH_SET_FROM (lglyph, items[i].iCharPos + from);
+                 LGLYPH_SET_TO (lglyph, items[i].iCharPos + to);
+
+                 /* Metrics.  */
                  LGLYPH_SET_WIDTH (lglyph, advances[j]);
-                 if (offsets[j].du || offsets[j].dv)
+                 LGLYPH_SET_ASCENT (lglyph, font->ascent);
+                 LGLYPH_SET_DESCENT (lglyph, font->descent);
+
+                 result = ScriptGetGlyphABCWidth (context,
+                                                  &(uniscribe_font->cache),
+                                                  glyphs[j], &char_metric);
+                 if (result == E_PENDING && !context)
                    {
-                     Lisp_Object vec;
-                     /* Convert from logical inches.  */
-                     int dpi = FRAME_W32_DISPLAY_INFO (f)->resy;
-                     int dx = (int)(offsets[j].du * dpi / 72.27 + 0.5);
-                     int dy = (int)(offsets[j].dv * dpi / 72.27 + 0.5);
-                     vec = Fmake_vector (make_number (3), Qnil);
-                     ASET (vec, 0, make_number (dx));
-                     ASET (vec, 1, make_number (dy));
-                     /* Based on what ftfont.c does... */
-                     ASET (vec, 2, make_number (advances[j]));
-                     LGLYPH_SET_ADJUSTMENT (lglyph, vec);
+                     /* 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);
                    }
-                 else
-                   LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
 
-                 if (GetGlyphOutlineW (context, glyphs[j],
-                                       GGO_METRICS | GGO_GLYPH_INDEX,
-                                       &metrics, 0, NULL, &transform)
-                     != GDI_ERROR)
+                 if (SUCCEEDED (result))
                    {
-                     LGLYPH_SET_LBEARING (lglyph, metrics.gmptGlyphOrigin.x);
-                     LGLYPH_SET_RBEARING (lglyph,
-                                          metrics.gmBlackBoxX
-                                          + metrics.gmptGlyphOrigin.x);
-                     LGLYPH_SET_ASCENT (lglyph, metrics.gmBlackBoxY);
-                     LGLYPH_SET_DESCENT (lglyph,
-                                         (metrics.gmCellIncY
-                                          - metrics.gmptGlyphOrigin.y
-                                          - metrics.gmBlackBoxY));
+                     LGLYPH_SET_LBEARING (lglyph, char_metric.abcA);
+                     LGLYPH_SET_RBEARING (lglyph, (char_metric.abcA
+                                                   + char_metric.abcB));
                    }
                  else
                    {
-                     /* Defaults based on what we know from elsewhere.  */
                      LGLYPH_SET_LBEARING (lglyph, 0);
                      LGLYPH_SET_RBEARING (lglyph, advances[j]);
-                     LGLYPH_SET_ASCENT (lglyph, font->ascent);
-                     LGLYPH_SET_DESCENT (lglyph, font->descent);
                    }
-               }
-
-             /* Set character codes as indicated in clusters.  */
-             for (j = 0; j < nchars_in_run - 1; j++)
-               {
-                 int k, start, end;
-                 wchar_t this_char = *(chars + items[i].iCharPos + j);
 
-                 start = clusters[i];
-                 end = clusters[i+1];
-                 if (start > end)
-                   {
-                     int temp = start;
-                     start = end;
-                     end = temp;
-                   }
-                 for (k = start; k < end; k++)
+                 if (offsets[j].du || offsets[j].dv)
                    {
-                     Lisp_Object lglyph = LGSTRING_GLYPH (lgstring,
-                                                          done_glyphs + k);
-                     LGLYPH_SET_CHAR (lglyph, this_char);
+                     Lisp_Object vec;
+                     vec = Fmake_vector (make_number (3), Qnil);
+                     ASET (vec, 0, make_number (offsets[j].du));
+                     ASET (vec, 1, make_number (offsets[j].dv));
+                     /* Based on what ftfont.c does... */
+                     ASET (vec, 2, make_number (advances[j]));
+                     LGLYPH_SET_ADJUSTMENT (lglyph, vec);
                    }
+                 else
+                   LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
                }
-             /* Last one until end (or beginning) of string.  */
-             {
-               int k, start, end;
-               wchar_t last_char = *(chars + items[i].iCharPos
-                                     + nchars_in_run - 1);
-               start = clusters[nchars_in_run - 1];
-               end = nglyphs;
-               if (start < clusters[nchars_in_run - 2])
-                 {
-                   end = start + 1;
-                   start = 0;
-                 }
-               for (k = start; k < end; k++)
-                 {
-                   Lisp_Object lglyph = LGSTRING_GLYPH (lgstring,
-                                                        done_glyphs + k);
-                   LGLYPH_SET_CHAR (lglyph, last_char);
-                 }
-             }
            }
        }
       done_glyphs += nglyphs;
-      done_chars += nchars_in_run;
     }
 
   xfree (items);
-  SelectObject (context, old_font);
-  release_frame_dc (f, context);
+
+  if (context)
+    {
+      SelectObject (context, old_font);
+      release_frame_dc (f, context);
+    }
 
   if (NILP (lgstring))
     return Qnil;
   else
-    return make_number (done_chars);
+    return make_number (done_glyphs);
 }
 
 /* Uniscribe implementation of encode_char for font backend.
@@ -419,35 +455,93 @@ uniscribe_encode_char (font, c)
      struct font *font;
      int c;
 {
-  wchar_t chars[1];
-  WORD indices[1];
-  HDC context;
-  struct frame *f;
-  HFONT old_font;
-  DWORD retval;
-
-  /* TODO: surrogates.  */
-  if (c > 0xFFFF)
-    return FONT_INVALID_CODE;
-
-  chars[0] = (wchar_t) c;
+  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,
-                           ((W32FontStruct *)(font->font.font))->hfont);
+  if (c < 0x10000)
+    {
+      ch[0] = (wchar_t) c;
+      len = 1;
+    }
+  else
+    {
+      DWORD surrogate = c - 0x10000;
 
-  retval = GetGlyphIndicesW (context, chars, 1, indices,
-                            GGI_MARK_NONEXISTING_GLYPHS);
+      /* 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;
+    }
 
-  SelectObject (context, old_font);
-  release_frame_dc (f, context);
+  /* 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, len, 2, NULL, NULL, items, &nitems)))
+       {
+         HRESULT result;
+          /* Surrogates seem to need 2 here, even though only one glyph is
+            returned.  Indic characters can also produce 2 or more glyphs for
+            a single code point, but they need to use uniscribe_shape
+            above for correct display.  */
+          WORD glyphs[2], clusters[2];
+          SCRIPT_VISATTR attrs[2];
+          int nglyphs;
+
+          result = ScriptShape (context, &(uniscribe_font->cache),
+                                ch, len, 2, &(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)
+            {
+             /* Some fonts return .notdef glyphs instead of failing.
+                (Truetype spec reserves glyph code 0 for .notdef)  */
+             if (glyphs[0])
+               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) && glyphs[0])
+                code = glyphs[0];
+            }
+       }
+    }
+    if (context)
+      {
+       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;
 }
 
 /*
@@ -501,8 +595,14 @@ add_opentype_font_name_to_list (logical_font, physical_font, font_type,
       && font_type != TRUETYPE_FONTTYPE)
     return 1;
 
-  family = intern_downcase (logical_font->elfLogFont.lfFaceName,
-                            strlen (logical_font->elfLogFont.lfFaceName));
+  /* Skip fonts that have no unicode coverage.  */
+  if (!physical_font->ntmFontSig.fsUsb[3]
+      && !physical_font->ntmFontSig.fsUsb[2]
+      && !physical_font->ntmFontSig.fsUsb[1]
+      && !(physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff))
+    return 1;
+
+  family = intern_font_name (logical_font->elfLogFont.lfFaceName);
   if (! memq_no_quit (family, *list))
     *list = Fcons (family, *list);
 
@@ -545,7 +645,7 @@ add_opentype_font_name_to_list (logical_font, physical_font, font_type,
 
 static char* NOTHING = "    ";
 
-#define SNAME(VAL) SDATA (STRINGP (VAL) ? VAL : SYMBOL_NAME (VAL))
+#define SNAME(VAL) SDATA (SYMBOL_NAME (VAL))
 
 /* Check if font supports the otf script/language/features specified.
    OTF_SPEC is in the format
@@ -637,10 +737,12 @@ int uniscribe_check_otf (font, otf_spec)
              OTF_INT16_VAL (tbl, scriptlist_table + 6 + j * 6, &script_table);
              break;
            }
+#if 0    /* Causes false positives.  */
          /* If there is a DFLT script defined in the font, use it
             if the specified script is not found.  */
          else if (script_id == default_script)
            OTF_INT16_VAL (tbl, scriptlist_table + 6 + j * 6, &script_table);
+#endif
        }
       /* If no specific or default script table was found, then this font
         does not support the script.  */
@@ -826,6 +928,7 @@ font_table_error:
 struct font_driver uniscribe_font_driver =
   {
     0, /* Quniscribe */
+    0, /* case insensitive */
     w32font_get_cache,
     uniscribe_list,
     uniscribe_match,
@@ -873,4 +976,5 @@ syms_of_w32uniscribe ()
   register_font_driver (&uniscribe_font_driver, NULL);
 }
 
-#endif /* USE_FONT_BACKEND  */
+/* arch-tag: 9530f0e1-7471-47dd-a780-94330af87ea0
+   (do not change this comment) */