(font_find_for_lface): If registry is NULL, try iso8859-1 and ascii-0.
[bpt/emacs.git] / src / w32font.c
index 5418171..dc0612f 100644 (file)
@@ -1,12 +1,12 @@
 /* Font backend for the Microsoft W32 API.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008 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 2, 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,12 +14,12 @@ 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/>.  */
 
 #include <config.h>
 #include <windows.h>
+#include <math.h>
+#include <ctype.h>
 
 #include "lisp.h"
 #include "w32term.h"
@@ -29,6 +29,7 @@ Boston, MA 02110-1301, USA.  */
 #include "charset.h"
 #include "fontset.h"
 #include "font.h"
+#include "w32font.h"
 
 /* Cleartype available on Windows XP, cleartype_natural from XP SP1.
    The latter does not try to fit cleartype smoothed fonts into the
@@ -41,25 +42,23 @@ Boston, MA 02110-1301, USA.  */
 #define CLEARTYPE_NATURAL_QUALITY 6
 #endif
 
-/* The actual structure for a w32 font, that can be cast to struct font.  */
-struct w32font_info
-{
-  struct font font;
-  TEXTMETRIC metrics;
-};
-
 extern struct font_driver w32font_driver;
 
 Lisp_Object Qgdi;
-extern Lisp_Object QCfamily; /* reuse from xfaces.c  */
-static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
-static Lisp_Object Qscript, Qdecorative, Qraster, Qoutline, Qunknown;
+Lisp_Object Quniscribe;
+static Lisp_Object QCformat;
+static Lisp_Object Qmonospace, Qsansserif, Qmono, Qsans, Qsans_serif;
+static Lisp_Object Qserif, Qscript, Qdecorative;
+static Lisp_Object Qraster, Qoutline, Qunknown;
 
 /* antialiasing  */
-extern Lisp_Object QCantialias; /* defined in font.c  */
+extern Lisp_Object QCantialias, QCotf, QClang; /* defined in font.c  */
 extern Lisp_Object Qnone; /* reuse from w32fns.c  */
 static Lisp_Object Qstandard, Qsubpixel, Qnatural;
 
+/* languages */
+static Lisp_Object Qja, Qko, Qzh;
+
 /* scripts */
 static Lisp_Object Qlatin, Qgreek, Qcoptic, Qcyrillic, Qarmenian, Qhebrew;
 static Lisp_Object Qarabic, Qsyriac, Qnko, Qthaana, Qdevanagari, Qbengali;
@@ -71,22 +70,30 @@ static Lisp_Object Qkhmer, Qmongolian, Qsymbol, Qbraille, Qhan;
 static Lisp_Object Qideographic_description, Qcjk_misc, Qkana, Qbopomofo;
 static Lisp_Object Qkanbun, Qyi, Qbyzantine_musical_symbol;
 static Lisp_Object Qmusical_symbol, Qmathematical;
+/* Not defined in characters.el, but referenced in fontset.el.  */
+static Lisp_Object Qbalinese, Qbuginese, Qbuhid, Qcuneiform, Qcypriot;
+static Lisp_Object Qdeseret, Qglagolitic, Qgothic, Qhanunoo, Qkharoshthi;
+static Lisp_Object Qlimbu, Qlinear_b, Qold_italic, Qold_persian, Qosmanya;
+static Lisp_Object Qphags_pa, Qphoenician, Qshavian, Qsyloti_nagri;
+static Lisp_Object Qtagalog, Qtagbanwa, Qtai_le, Qtifinagh, Qugaritic;
+/* Only defined here, but useful for distinguishing IPA capable fonts.  */
+static Lisp_Object Qphonetic;
 
 /* Font spacing symbols - defined in font.c.  */
 extern Lisp_Object Qc, Qp, Qm;
 
-static void fill_in_logfont P_ ((FRAME_PTR f, LOGFONT *logfont,
-                                 Lisp_Object font_spec));
+static void fill_in_logfont P_ ((FRAME_PTR, LOGFONT *, Lisp_Object));
 
-static BYTE w32_antialias_type P_ ((Lisp_Object type));
-static Lisp_Object lispy_antialias_type P_ ((BYTE type));
+static BYTE w32_antialias_type P_ ((Lisp_Object));
+static Lisp_Object lispy_antialias_type P_ ((BYTE));
 
-static Lisp_Object font_supported_scripts P_ ((FONTSIGNATURE * sig));
+static Lisp_Object font_supported_scripts P_ ((FONTSIGNATURE *));
+static int w32font_full_name P_ ((LOGFONT *, Lisp_Object, int, char *, int));
+static void compute_metrics P_ ((HDC, struct w32font_info *, unsigned int,
+                                struct w32_metric_cache *));
+static void clear_cached_metrics P_ ((struct w32font_info *));
 
-/* From old font code in w32fns.c */
-char * w32_to_x_charset P_ ((int charset, char * matching));
-
-static Lisp_Object w32_registry P_ ((LONG w32_charset));
+static Lisp_Object w32_registry P_ ((LONG, DWORD));
 
 /* EnumFontFamiliesEx callbacks.  */
 static int CALLBACK add_font_entity_to_list P_ ((ENUMLOGFONTEX *,
@@ -113,16 +120,17 @@ struct font_callback_data
   Lisp_Object frame;
   /* The list to add matches to.  */
   Lisp_Object list;
+  /* Whether to match only opentype fonts.  */
+  int opentype_only;
 };
 
 /* Handles the problem that EnumFontFamiliesEx will not return all
    style variations if the font name is not specified.  */
-static void list_all_matching_fonts P_ ((struct font_callback_data *match_data));
+static void list_all_matching_fonts P_ ((struct font_callback_data *));
 
+/* From old font code in w32fns.c */
+char * w32_to_x_charset P_ ((int, char *));
 
-/* MingW headers only define this when _WIN32_WINNT >= 0x0500, but we
-   target older versions.  */
-#define GGI_MARK_NONEXISTING_GLYPHS 1
 
 static int
 memq_no_quit (elt, list)
@@ -136,11 +144,11 @@ memq_no_quit (elt, list)
 /* w32 implementation of get_cache for font backend.
    Return a cache of font-entities on FRAME.  The cache must be a
    cons whose cdr part is the actual cache area.  */
-static Lisp_Object
-w32font_get_cache (frame)
-     Lisp_Object frame;
+Lisp_Object
+w32font_get_cache (f)
+     FRAME_PTR f;
 {
-  struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (frame));
+  struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
   return (dpyinfo->name_list_element);
 }
@@ -153,33 +161,7 @@ static Lisp_Object
 w32font_list (frame, font_spec)
      Lisp_Object frame, font_spec;
 {
-  struct font_callback_data match_data;
-  HDC dc;
-  FRAME_PTR f = XFRAME (frame);
-
-  match_data.orig_font_spec = font_spec;
-  match_data.list = Qnil;
-  match_data.frame = frame;
-  bzero (&match_data.pattern, sizeof (LOGFONT));
-  fill_in_logfont (f, &match_data.pattern, font_spec);
-
-  if (match_data.pattern.lfFaceName[0] == '\0')
-    {
-      /* EnumFontFamiliesEx does not take other fields into account if
-         font name is blank, so need to use two passes.  */
-      list_all_matching_fonts (&match_data);
-    }
-  else
-    {
-      dc = get_frame_dc (f);
-
-      EnumFontFamiliesEx (dc, &match_data.pattern,
-                          (FONTENUMPROC) add_font_entity_to_list,
-                          (LPARAM) &match_data, 0);
-      release_frame_dc (f, dc);
-    }
-
-  return NILP (match_data.list) ? null_vector : Fvconcat (1, &match_data.list);
+  return w32font_list_internal (frame, font_spec, 0);
 }
 
 /* w32 implementation of match for font backend.
@@ -190,27 +172,9 @@ static Lisp_Object
 w32font_match (frame, font_spec)
      Lisp_Object frame, font_spec;
 {
-  struct font_callback_data match_data;
-  HDC dc;
-  FRAME_PTR f = XFRAME (frame);
-
-  match_data.orig_font_spec = font_spec;
-  match_data.frame = frame;
-  match_data.list = Qnil;
-  bzero (&match_data.pattern, sizeof (LOGFONT));
-  fill_in_logfont (f, &match_data.pattern, font_spec);
-
-  dc = get_frame_dc (f);
-
-  EnumFontFamiliesEx (dc, &match_data.pattern,
-                      (FONTENUMPROC) add_one_font_entity_to_list,
-                      (LPARAM) &match_data, 0);
-  release_frame_dc (f, dc);
-
-  return NILP (match_data.list) ? Qnil : XCAR (match_data.list);
+  return w32font_match_internal (frame, font_spec, 0);
 }
 
-
 /* w32 implementation of list_family for font backend.
    List available families.  The value is a list of family names
    (symbols).  */
@@ -224,6 +188,7 @@ w32font_list_family (frame)
   FRAME_PTR f = XFRAME (frame);
 
   bzero (&font_match_pattern, sizeof (font_match_pattern));
+  font_match_pattern.lfCharSet = DEFAULT_CHARSET;
 
   dc = get_frame_dc (f);
 
@@ -238,112 +203,40 @@ w32font_list_family (frame)
 /* w32 implementation of open for font backend.
    Open a font specified by FONT_ENTITY on frame F.
    If the font is scalable, open it with PIXEL_SIZE.  */
-static struct font *
+static Lisp_Object
 w32font_open (f, font_entity, pixel_size)
      FRAME_PTR f;
      Lisp_Object font_entity;
      int pixel_size;
 {
-  int len, size;
-  LOGFONT logfont;
-  HDC dc;
-  HFONT hfont, old_font;
-  Lisp_Object val, extra;
-  /* For backwards compatibility.  */
-  W32FontStruct *compat_w32_font;
-
-  struct w32font_info *w32_font = xmalloc (sizeof (struct w32font_info));
+  Lisp_Object font_object;
 
-  struct font * font = (struct font *) w32_font;
-  if (!font)
-    return NULL;
+  font_object = font_make_object (VECSIZE (struct w32font_info));
 
-  bzero (&logfont, sizeof (logfont));
-  fill_in_logfont (f, &logfont, font_entity);
-
-  size = XINT (AREF (font_entity, FONT_SIZE_INDEX));
-  if (!size)
-    size = pixel_size;
-
-  logfont.lfHeight = -size;
-  hfont = CreateFontIndirect (&logfont);
-
-  if (hfont == NULL)
+  if (!w32font_open_internal (f, font_entity, pixel_size, font_object))
     {
-      xfree (w32_font);
-      return NULL;
+      return Qnil;
     }
 
-  /* Get the metrics for this font.  */
-  dc = get_frame_dc (f);
-  old_font = SelectObject (dc, hfont);
-
-  GetTextMetrics (dc, &w32_font->metrics);
-
-  SelectObject (dc, old_font);
-  release_frame_dc (f, dc);
-  /* W32FontStruct - we should get rid of this, and use the w32font_info
-     struct for any W32 specific fields. font->font.font can then be hfont.  */
-  font->font.font = xmalloc (sizeof (W32FontStruct));
-  compat_w32_font = (W32FontStruct *) font->font.font;
-  bzero (compat_w32_font, sizeof (W32FontStruct));
-  compat_w32_font->font_type = UNICODE_FONT;
-  /* Duplicate the text metrics.  */
-  bcopy (&w32_font->metrics,  &compat_w32_font->tm, sizeof (TEXTMETRIC));
-  compat_w32_font->hfont = hfont;
-
-  len = strlen (logfont.lfFaceName);
-  font->font.name = (char *) xmalloc (len + 1);
-  bcopy (logfont.lfFaceName, font->font.name, len);
-  font->font.name[len] = '\0';
-  font->font.full_name = font->font.name;
-  font->font.charset = 0;
-  font->font.codepage = 0;
-  font->font.size = w32_font->metrics.tmMaxCharWidth;
-  font->font.height = w32_font->metrics.tmHeight
-    + w32_font->metrics.tmExternalLeading;
-  font->font.space_width = font->font.average_width
-    = w32_font->metrics.tmAveCharWidth;
-
-  font->font.vertical_centering = 0;
-  font->font.encoding_type = 0;
-  font->font.baseline_offset = 0;
-  font->font.relative_compose = 0;
-  font->font.default_ascent = w32_font->metrics.tmAscent;
-  font->font.font_encoder = NULL;
-  font->entity = font_entity;
-  font->pixel_size = size;
-  font->driver = &w32font_driver;
-  font->format = Qgdi;
-  font->file_name = NULL;
-  font->encoding_charset = -1;
-  font->repertory_charset = -1;
-  font->min_width = 0;
-  font->ascent = w32_font->metrics.tmAscent;
-  font->descent = w32_font->metrics.tmDescent;
-  font->scalable = w32_font->metrics.tmPitchAndFamily & TMPF_VECTOR;
-
-  return font;
+  return font_object;
 }
 
 /* w32 implementation of close for font_backend.
    Close FONT on frame F.  */
-static void
+void
 w32font_close (f, font)
      FRAME_PTR f;
      struct font *font;
 {
-  if (font->font.font)
+  struct w32font_info *w32_font = (struct w32font_info *) font;
+
+  if (w32_font->compat_w32_font)
     {
-      W32FontStruct *old_w32_font = (W32FontStruct *)font->font.font;
+      W32FontStruct *old_w32_font = w32_font->compat_w32_font;
       DeleteObject (old_w32_font->hfont);
       xfree (old_w32_font);
-      font->font.font = 0;
+      w32_font->compat_w32_font = 0;
     }
-
-  if (font->font.name)
-    xfree (font->font.name);
-  xfree (font);
 }
 
 /* w32 implementation of has_char for font backend.
@@ -351,7 +244,7 @@ w32font_close (f, font)
    If FONT_ENTITY has a glyph for character C (Unicode code point),
    return 1.  If not, return 0.  If a font must be opened to check
    it, return -1.  */
-static int
+int
 w32font_has_char (entity, c)
      Lisp_Object entity;
      int c;
@@ -371,7 +264,7 @@ w32font_has_char (entity, c)
 
   script = CHAR_TABLE_REF (Vchar_script_table, c);
 
-  return (memq_no_quit (script, supported_scripts)) ? 1 : 0;
+  return (memq_no_quit (script, supported_scripts)) ? -1 : 0;
 }
 
 /* w32 implementation of encode_char for font backend.
@@ -382,9 +275,71 @@ w32font_encode_char (font, c)
      struct font *font;
      int c;
 {
-  /* Avoid unneccesary conversion - all the Win32 APIs will take a unicode
-     character.  */
-  return c;
+  struct frame *f;
+  HDC dc;
+  HFONT old_font;
+  DWORD retval;
+  GCP_RESULTSW result;
+  wchar_t in[2];
+  wchar_t out[2];
+  int len;
+  struct w32font_info *w32_font = (struct w32font_info *) font;
+
+  /* If glyph indexing is not working for this font, just return the
+     unicode code-point.  */
+  if (!w32_font->glyph_idx)
+    return c;
+
+  if (c > 0xFFFF)
+    {
+      /* TODO: Encode as surrogate pair and lookup the glyph.  */
+      return FONT_INVALID_CODE;
+    }
+  else
+    {
+      in[0] = (wchar_t) c;
+      len = 1;
+    }
+
+  bzero (&result, sizeof (result));
+  result.lStructSize = sizeof (result);
+  result.lpGlyphs = out;
+  result.nGlyphs = 2;
+
+  f = XFRAME (selected_frame);
+
+  dc = get_frame_dc (f);
+  old_font = SelectObject (dc, w32_font->compat_w32_font->hfont);
+
+  /* GetCharacterPlacement is used here rather than GetGlyphIndices because
+     it is supported on Windows NT 4 and 9x/ME.  But it cannot reliably report
+     missing glyphs, see below for workaround.  */
+  retval = GetCharacterPlacementW (dc, in, len, 0, &result, 0);
+
+  SelectObject (dc, old_font);
+  release_frame_dc (f, dc);
+
+  if (retval)
+    {
+      if (result.nGlyphs != 1 || !result.lpGlyphs[0]
+          /* GetCharacterPlacementW seems to return 3, which seems to be
+             the space glyph in most/all truetype fonts, instead of 0
+             for unsupported glyphs.  */
+          || (result.lpGlyphs[0] == 3 && !iswspace (in[0])))
+        return FONT_INVALID_CODE;
+      return result.lpGlyphs[0];
+    }
+  else
+    {
+      int i;
+      /* Mark this font as not supporting glyph indices. This can happen
+         on Windows9x, and maybe with non-Truetype fonts on NT etc.  */
+      w32_font->glyph_idx = 0;
+      /* Clear metrics cache.  */
+      clear_cached_metrics (w32_font);
+
+      return c;
+    }
 }
 
 /* w32 implementation of text_extents for font backend.
@@ -392,7 +347,7 @@ w32font_encode_char (font, c)
    of METRICS.  The glyphs are specified by their glyph codes in
    CODE (length NGLYPHS).  Apparently metrics can be NULL, in this
    case just return the overall width.  */
-static int
+int
 w32font_text_extents (font, code, nglyphs, metrics)
      struct font *font;
      unsigned *code;
@@ -400,71 +355,123 @@ w32font_text_extents (font, code, nglyphs, metrics)
      struct font_metrics *metrics;
 {
   int i;
-  HFONT old_font;
-  /* FIXME: Be nice if we had a frame here, rather than getting the desktop's
-     device context to measure against... */
-  HDC dc = GetDC (NULL);
+  HFONT old_font = NULL;
+  HDC dc = NULL;
+  struct frame * f;
   int total_width = 0;
-  WORD *wcode = alloca(nglyphs * sizeof (WORD));
+  WORD *wcode = NULL;
   SIZE size;
 
-  old_font = SelectObject (dc, ((W32FontStruct *)(font->font.font))->hfont);
-
   if (metrics)
     {
-      GLYPHMETRICS gm;
-      MAT2 transform;
+      struct w32font_info *w32_font = (struct w32font_info *) font;
 
-      /* Set transform to the identity matrix.  */
-      bzero (&transform, sizeof (transform));
-      transform.eM11.value = 1;
-      transform.eM22.value = 1;
-      metrics->width = 0;
-      metrics->ascent = 0;
-      metrics->descent = 0;
+      bzero (metrics, sizeof (struct font_metrics));
+      metrics->ascent = font->ascent;
+      metrics->descent = font->descent;
 
       for (i = 0; i < nglyphs; i++)
         {
-          if (GetGlyphOutlineW (dc, *(code + i), GGO_METRICS, &gm, 0,
-                                NULL, &transform) != GDI_ERROR)
-            {
-              int new_val = metrics->width + gm.gmBlackBoxX
-                + gm.gmptGlyphOrigin.x;
-
-              metrics->rbearing = max (metrics->rbearing, new_val);
-              metrics->width += gm.gmCellIncX;
-              new_val = -gm.gmptGlyphOrigin.y;
-              metrics->ascent = max (metrics->ascent, new_val);
-              new_val = gm.gmBlackBoxY + gm.gmptGlyphOrigin.y;
-              metrics->descent = max (metrics->descent, new_val);
-            }
-          else
-            {
-              /* Rely on an estimate based on the overall font metrics.  */
-              break;
-            }
-        }
-
+         struct w32_metric_cache *char_metric;
+         int block = *(code + i) / CACHE_BLOCKSIZE;
+         int pos_in_block = *(code + i) % CACHE_BLOCKSIZE;
+
+         if (block >= w32_font->n_cache_blocks)
+           {
+             if (!w32_font->cached_metrics)
+               w32_font->cached_metrics
+                 = xmalloc ((block + 1)
+                            * sizeof (struct w32_cached_metric *));
+             else
+               w32_font->cached_metrics
+                 = xrealloc (w32_font->cached_metrics,
+                             (block + 1)
+                             * sizeof (struct w32_cached_metric *));
+             bzero (w32_font->cached_metrics + w32_font->n_cache_blocks,
+                    ((block + 1 - w32_font->n_cache_blocks)
+                     * sizeof (struct w32_cached_metric *)));
+             w32_font->n_cache_blocks = block + 1;
+           }
+
+         if (!w32_font->cached_metrics[block])
+           {
+             w32_font->cached_metrics[block]
+               = xmalloc (CACHE_BLOCKSIZE * sizeof (struct font_metrics));
+             bzero (w32_font->cached_metrics[block],
+                    CACHE_BLOCKSIZE * sizeof (struct font_metrics));
+           }
+
+         char_metric = w32_font->cached_metrics[block] + pos_in_block;
+
+         if (char_metric->status == W32METRIC_NO_ATTEMPT)
+           {
+             if (dc == NULL)
+               {
+                 /* TODO: Frames can come and go, and their fonts
+                    outlive them. So we can't cache the frame in the
+                    font structure.  Use selected_frame until the API
+                    is updated to pass in a frame.  */
+                 f = XFRAME (selected_frame);
+
+                  dc = get_frame_dc (f);
+                  old_font = SelectObject (dc, FONT_COMPAT (font)->hfont);
+               }
+             compute_metrics (dc, w32_font, *(code + i), char_metric);
+           }
+
+         if (char_metric->status == W32METRIC_SUCCESS)
+           {
+             metrics->lbearing = min (metrics->lbearing,
+                                      metrics->width + char_metric->lbearing);
+             metrics->rbearing = max (metrics->rbearing,
+                                      metrics->width + char_metric->rbearing);
+             metrics->width += char_metric->width;
+           }
+         else
+           /* If we couldn't get metrics for a char,
+              use alternative method.  */
+           break;
+       }
       /* If we got through everything, return.  */
       if (i == nglyphs)
         {
-          /* Restore state and release DC.  */
-          SelectObject (dc, old_font);
-          ReleaseDC (NULL, dc);
+          if (dc != NULL)
+            {
+              /* Restore state and release DC.  */
+              SelectObject (dc, old_font);
+              release_frame_dc (f, dc);
+            }
 
           return metrics->width;
         }
     }
 
-  for (i = 0; i < nglyphs; i++)
+  /* 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;
+         }
+      }
+  }
+  if (dc == NULL)
     {
-      if (code[i] < 0x10000)
-        wcode[i] = code[i];
-      else
-        {
-          /* TODO: Convert to surrogate, reallocating array if needed */
-          wcode[i] = 0xffff;
-        }
+      /* TODO: Frames can come and go, and their fonts outlive
+        them. So we can't cache the frame in the font structure.  Use
+        selected_frame until the API is updated to pass in a
+        frame.  */
+      f = XFRAME (selected_frame);
+
+      dc = get_frame_dc (f);
+      old_font = SelectObject (dc, FONT_COMPAT (font)->hfont);
     }
 
   if (GetTextExtentPoint32W (dc, wcode, nglyphs, &size))
@@ -472,20 +479,21 @@ w32font_text_extents (font, code, nglyphs, metrics)
       total_width = size.cx;
     }
 
+  /* On 95/98/ME, only some unicode functions are available, so fallback
+     on doing a dummy draw to find the total width.  */
   if (!total_width)
     {
       RECT rect;
-      rect.top = 0; rect.bottom = font->font.height; rect.left = 0; rect.right = 1;
+      rect.top = 0; rect.bottom = font->height; rect.left = 0; rect.right = 1;
       DrawTextW (dc, wcode, nglyphs, &rect,
                  DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE);
       total_width = rect.right;
     }
 
+  /* Give our best estimate of the metrics, based on what we know.  */
   if (metrics)
     {
       metrics->width = total_width;
-      metrics->ascent = font->ascent;
-      metrics->descent = font->descent;
       metrics->lbearing = 0;
       metrics->rbearing = total_width
         + ((struct w32font_info *) font)->metrics.tmOverhang;
@@ -493,7 +501,7 @@ w32font_text_extents (font, code, nglyphs, metrics)
 
   /* Restore state and release DC.  */
   SelectObject (dc, old_font);
-  ReleaseDC (NULL, dc);
+  release_frame_dc (f, dc);
 
   return total_width;
 }
@@ -503,14 +511,24 @@ w32font_text_extents (font, code, nglyphs, metrics)
    Draw glyphs between FROM and TO of S->char2b at (X Y) pixel
    position of frame F with S->FACE and S->GC.  If WITH_BACKGROUND
    is nonzero, fill the background in advance.  It is assured that
-   WITH_BACKGROUND is zero when (FROM > 0 || TO < S->nchars).  */
-static int
+   WITH_BACKGROUND is zero when (FROM > 0 || TO < S->nchars).
+
+   TODO: Currently this assumes that the colors and fonts are already
+   set in the DC. This seems to be true now, but maybe only due to
+   the old font code setting it up. It may be safer to resolve faces
+   and fonts in here and set them explicitly
+*/
+
+int
 w32font_draw (s, from, to, x, y, with_background)
      struct glyph_string *s;
      int from, to, x, y, with_background;
 {
-  UINT options = 0;
+  UINT options;
   HRGN orig_clip;
+  struct w32font_info *w32font = (struct w32font_info *) s->font;
+
+  options = w32font->glyph_idx;
 
   /* Save clip region for later restoration.  */
   GetClipRgn(s->hdc, orig_clip);
@@ -538,7 +556,7 @@ w32font_draw (s, from, to, x, y, with_background)
     {
       HBRUSH brush;
       RECT rect;
-      struct font *font = (struct font *) s->face->font_info;
+      struct font *font = s->font;
 
       brush = CreateSolidBrush (s->gc->background);
       rect.left = x;
@@ -549,7 +567,16 @@ w32font_draw (s, from, to, x, y, with_background)
       DeleteObject (brush);
     }
 
-  ExtTextOutW (s->hdc, x, y, options, NULL, s->char2b + from, to - from, NULL);
+  if (s->padding_p)
+    {
+      int len = to - from, i;
+
+      for (i = 0; i < len; i++)
+       ExtTextOutW (s->hdc, x + i, y, options, NULL,
+                    s->char2b + from + i, 1, NULL);
+    }
+  else
+    ExtTextOutW (s->hdc, x, y, options, NULL, s->char2b + from, to - from, NULL);
 
   /* Restore clip region.  */
   if (s->num_clips > 0)
@@ -646,6 +673,254 @@ w32font_otf_drive (struct font *font, Lisp_Object features,
                    int alternate_subst);
   */
 
+/* Internal implementation of w32font_list.
+   Additional parameter opentype_only restricts the returned fonts to
+   opentype fonts, which can be used with the Uniscribe backend.  */
+Lisp_Object
+w32font_list_internal (frame, font_spec, opentype_only)
+     Lisp_Object frame, font_spec;
+     int opentype_only;
+{
+  struct font_callback_data match_data;
+  HDC dc;
+  FRAME_PTR f = XFRAME (frame);
+
+  match_data.orig_font_spec = font_spec;
+  match_data.list = Qnil;
+  match_data.frame = frame;
+
+  bzero (&match_data.pattern, sizeof (LOGFONT));
+  fill_in_logfont (f, &match_data.pattern, font_spec);
+
+  match_data.opentype_only = opentype_only;
+  if (opentype_only)
+    match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
+
+  if (match_data.pattern.lfFaceName[0] == '\0')
+    {
+      /* EnumFontFamiliesEx does not take other fields into account if
+         font name is blank, so need to use two passes.  */
+      list_all_matching_fonts (&match_data);
+    }
+  else
+    {
+      dc = get_frame_dc (f);
+
+      EnumFontFamiliesEx (dc, &match_data.pattern,
+                          (FONTENUMPROC) add_font_entity_to_list,
+                          (LPARAM) &match_data, 0);
+      release_frame_dc (f, dc);
+    }
+
+  return NILP (match_data.list) ? Qnil : match_data.list;
+}
+
+/* Internal implementation of w32font_match.
+   Additional parameter opentype_only restricts the returned fonts to
+   opentype fonts, which can be used with the Uniscribe backend.  */
+Lisp_Object
+w32font_match_internal (frame, font_spec, opentype_only)
+     Lisp_Object frame, font_spec;
+     int opentype_only;
+{
+  struct font_callback_data match_data;
+  HDC dc;
+  FRAME_PTR f = XFRAME (frame);
+
+  match_data.orig_font_spec = font_spec;
+  match_data.frame = frame;
+  match_data.list = Qnil;
+
+  bzero (&match_data.pattern, sizeof (LOGFONT));
+  fill_in_logfont (f, &match_data.pattern, font_spec);
+
+  match_data.opentype_only = opentype_only;
+  if (opentype_only)
+    match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
+
+  dc = get_frame_dc (f);
+
+  EnumFontFamiliesEx (dc, &match_data.pattern,
+                      (FONTENUMPROC) add_one_font_entity_to_list,
+                      (LPARAM) &match_data, 0);
+  release_frame_dc (f, dc);
+
+  return NILP (match_data.list) ? Qnil : XCAR (match_data.list);
+}
+
+int
+w32font_open_internal (f, font_entity, pixel_size, font_object)
+     FRAME_PTR f;
+     Lisp_Object font_entity;
+     int pixel_size;
+     Lisp_Object font_object;
+{
+  int len, size, i;
+  LOGFONT logfont;
+  HDC dc;
+  HFONT hfont, old_font;
+  Lisp_Object val, extra;
+  /* For backwards compatibility.  */
+  W32FontStruct *compat_w32_font;
+  struct w32font_info *w32_font;
+  struct font * font;
+  OUTLINETEXTMETRIC* metrics = NULL;
+
+  w32_font = (struct w32font_info *) XFONT_OBJECT (font_object);
+  font = (struct font *) w32_font;
+
+  if (!font)
+    return 0;
+
+  /* Copy from font entity.  */
+  for (i = 0; i < FONT_ENTITY_MAX; i++)
+    ASET (font_object, i, AREF (font_entity, i));
+  ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size));
+
+  bzero (&logfont, sizeof (logfont));
+  fill_in_logfont (f, &logfont, font_entity);
+
+  /* Prefer truetype fonts, to avoid known problems with type1 fonts, and
+     limitations in bitmap fonts.  */
+  val = AREF (font_entity, FONT_FOUNDRY_INDEX);
+  if (!EQ (val, Qraster))
+    logfont.lfOutPrecision = OUT_TT_PRECIS;
+
+  size = XINT (AREF (font_entity, FONT_SIZE_INDEX));
+  if (!size)
+    size = pixel_size;
+
+  logfont.lfHeight = -size;
+  hfont = CreateFontIndirect (&logfont);
+
+  if (hfont == NULL)
+    return 0;
+
+  /* Get the metrics for this font.  */
+  dc = get_frame_dc (f);
+  old_font = SelectObject (dc, hfont);
+
+  /* Try getting the outline metrics (only works for truetype fonts).  */
+  len = GetOutlineTextMetrics (dc, 0, NULL);
+  if (len)
+    {
+      metrics = (OUTLINETEXTMETRIC *) alloca (len);
+      if (GetOutlineTextMetrics (dc, len, metrics))
+        bcopy (&metrics->otmTextMetrics, &w32_font->metrics,
+               sizeof (TEXTMETRIC));
+      else
+        metrics = NULL;
+
+      /* If it supports outline metrics, it should support Glyph Indices.  */
+      w32_font->glyph_idx = ETO_GLYPH_INDEX;
+    }
+
+  if (!metrics)
+    {
+      GetTextMetrics (dc, &w32_font->metrics);
+      w32_font->glyph_idx = 0;
+    }
+
+  w32_font->cached_metrics = NULL;
+  w32_font->n_cache_blocks = 0;
+
+  SelectObject (dc, old_font);
+  release_frame_dc (f, dc);
+
+  /* W32FontStruct - we should get rid of this, and use the w32font_info
+     struct for any W32 specific fields. font->font.font can then be hfont.  */
+  w32_font->compat_w32_font = xmalloc (sizeof (W32FontStruct));
+  compat_w32_font = w32_font->compat_w32_font;
+  bzero (compat_w32_font, sizeof (W32FontStruct));
+  compat_w32_font->font_type = UNICODE_FONT;
+  /* Duplicate the text metrics.  */
+  bcopy (&w32_font->metrics,  &compat_w32_font->tm, sizeof (TEXTMETRIC));
+  compat_w32_font->hfont = hfont;
+
+  {
+    char *name;
+
+    /* We don't know how much space we need for the full name, so start with
+       96 bytes and go up in steps of 32.  */
+    len = 96;
+    name = xmalloc (len);
+    while (name && w32font_full_name (&logfont, font_entity, pixel_size,
+                                      name, len) < 0)
+      {
+        char *new = xrealloc (name, len += 32);
+
+        if (! new)
+          xfree (name);
+        name = new;
+      }
+    if (name)
+      font->props[FONT_FULLNAME_INDEX]
+        = make_unibyte_string (name, strlen (name));
+    else
+      font->props[FONT_FULLNAME_INDEX] =
+        make_unibyte_string (logfont.lfFaceName, len);
+  }
+
+  font->max_width = w32_font->metrics.tmMaxCharWidth;
+  font->height = w32_font->metrics.tmHeight
+    + w32_font->metrics.tmExternalLeading;
+  font->space_width = font->average_width = w32_font->metrics.tmAveCharWidth;
+
+  font->vertical_centering = 0;
+  font->encoding_type = 0;
+  font->baseline_offset = 0;
+  font->relative_compose = 0;
+  font->default_ascent = w32_font->metrics.tmAscent;
+  font->font_encoder = NULL;
+  font->pixel_size = size;
+  font->driver = &w32font_driver;
+  /* Use format cached during list, as the information we have access to
+     here is incomplete.  */
+  extra = AREF (font_entity, FONT_EXTRA_INDEX);
+  if (CONSP (extra))
+    {
+      val = assq_no_quit (QCformat, extra);
+      if (CONSP (val))
+        font->props[FONT_FORMAT_INDEX] = XCDR (val);
+      else
+        font->props[FONT_FORMAT_INDEX] = Qunknown;
+    }
+  else
+    font->props[FONT_FORMAT_INDEX] = Qunknown;
+
+  font->props[FONT_FILE_INDEX] = Qnil;
+  font->encoding_charset = -1;
+  font->repertory_charset = -1;
+  /* TODO: do we really want the minimum width here, which could be negative? */
+  font->min_width = font->space_width;
+  font->ascent = w32_font->metrics.tmAscent;
+  font->descent = w32_font->metrics.tmDescent;
+
+  if (metrics)
+    {
+      font->underline_thickness = metrics->otmsUnderscoreSize;
+      font->underline_position = -metrics->otmsUnderscorePosition;
+    }
+  else
+    {
+      font->underline_thickness = 0;
+      font->underline_position = -1;
+    }
+
+  /* max_descent is used for underlining in w32term.c.  Hopefully this
+     is temporary, as we'll want to get rid of the old compatibility
+     stuff later.  */
+  compat_w32_font->max_bounds.descent = font->descent;
+
+  /* For temporary compatibility with legacy code that expects the
+     name to be usable in x-list-fonts. Eventually we expect to change
+     x-list-fonts and other places that use fonts so that this can be
+     an fcname or similar.  */
+  font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
+
+  return 1;
+}
+
 /* Callback function for EnumFontFamiliesEx.
  * Adds the name of a font to a Lisp list (passed in as the lParam arg).  */
 static int CALLBACK
@@ -662,38 +937,42 @@ add_font_name_to_list (logical_font, physical_font, font_type, list_object)
   if (logical_font->elfLogFont.lfFaceName[0] == '@')
     return 1;
 
-  family = intern_downcase (logical_font->elfLogFont.lfFaceName,
-                            strlen (logical_font->elfLogFont.lfFaceName));
+  family = font_intern_prop (logical_font->elfLogFont.lfFaceName,
+                            strlen (logical_font->elfLogFont.lfFaceName), 1);
   if (! memq_no_quit (family, *list))
     *list = Fcons (family, *list);
 
   return 1;
 }
 
+static int w32_decode_weight P_ ((int));
+static int w32_encode_weight P_ ((int));
+
 /* Convert an enumerated Windows font to an Emacs font entity.  */
 static Lisp_Object
 w32_enumfont_pattern_entity (frame, logical_font, physical_font,
-                             font_type, requested_font)
+                             font_type, requested_font, backend)
      Lisp_Object frame;
      ENUMLOGFONTEX *logical_font;
      NEWTEXTMETRICEX *physical_font;
      DWORD font_type;
      LOGFONT *requested_font;
+     Lisp_Object backend;
 {
   Lisp_Object entity, tem;
   LOGFONT *lf = (LOGFONT*) logical_font;
   BYTE generic_type;
+  DWORD full_type = physical_font->ntmTm.ntmFlags;
 
-  entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
+  entity = font_make_entity ();
 
-  ASET (entity, FONT_TYPE_INDEX, Qgdi);
-  ASET (entity, FONT_FRAME_INDEX, frame);
-  ASET (entity, FONT_REGISTRY_INDEX, w32_registry (lf->lfCharSet));
+  ASET (entity, FONT_TYPE_INDEX, backend);
+  ASET (entity, FONT_REGISTRY_INDEX, w32_registry (lf->lfCharSet, font_type));
   ASET (entity, FONT_OBJLIST_INDEX, Qnil);
 
   /* Foundry is difficult to get in readable form on Windows.
      But Emacs crashes if it is not set, so set it to something more
-     generic.  Thes values make xflds compatible with Emacs 22. */
+     generic.  These values make xlfds compatible with Emacs 22. */
   if (lf->lfOutPrecision == OUT_STRING_PRECIS)
     tem = Qraster;
   else if (lf->lfOutPrecision == OUT_STROKE_PRECIS)
@@ -709,23 +988,22 @@ w32_enumfont_pattern_entity (frame, logical_font, physical_font,
   if (generic_type == FF_DECORATIVE)
     tem = Qdecorative;
   else if (generic_type == FF_MODERN)
-    tem = Qmonospace;
+    tem = Qmono;
   else if (generic_type == FF_ROMAN)
     tem = Qserif;
   else if (generic_type == FF_SCRIPT)
     tem = Qscript;
   else if (generic_type == FF_SWISS)
-    tem = Qsans_serif;
+    tem = Qsans;
   else
     tem = Qnil;
-    
-  if (! NILP (tem))
-    font_put_extra (entity, QCfamily, tem);
+
+  ASET (entity, FONT_ADSTYLE_INDEX, tem);
 
   if (physical_font->ntmTm.tmPitchAndFamily & 0x01)
-    font_put_extra (entity, QCspacing, make_number (FONT_SPACING_PROPORTIONAL));
+    ASET (entity, FONT_SPACING_INDEX, make_number (FONT_SPACING_PROPORTIONAL));
   else
-    font_put_extra (entity, QCspacing, make_number (FONT_SPACING_MONO));
+    ASET (entity, FONT_SPACING_INDEX, make_number (FONT_SPACING_CHARCELL));
 
   if (requested_font->lfQuality != DEFAULT_QUALITY)
     {
@@ -733,13 +1011,15 @@ w32_enumfont_pattern_entity (frame, logical_font, physical_font,
                       lispy_antialias_type (requested_font->lfQuality));
     }
   ASET (entity, FONT_FAMILY_INDEX,
-        intern_downcase (lf->lfFaceName, strlen (lf->lfFaceName)));
+        font_intern_prop (lf->lfFaceName, strlen (lf->lfFaceName), 1));
 
-  ASET (entity, FONT_WEIGHT_INDEX, make_number (lf->lfWeight));
-  ASET (entity, FONT_SLANT_INDEX, make_number (lf->lfItalic ? 200 : 100));
+  FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
+                 make_number (w32_decode_weight (lf->lfWeight)));
+  FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
+                 make_number (lf->lfItalic ? 200 : 100));
   /* TODO: PANOSE struct has this info, but need to call GetOutlineTextMetrics
      to get it.  */
-  ASET (entity, FONT_WIDTH_INDEX, make_number (100));
+  FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (100));
 
   if (font_type & RASTER_FONTTYPE)
     ASET (entity, FONT_SIZE_INDEX, make_number (physical_font->ntmTm.tmHeight));
@@ -750,10 +1030,31 @@ w32_enumfont_pattern_entity (frame, logical_font, physical_font,
      of getting this information easily.  */
   if (font_type & TRUETYPE_FONTTYPE)
     {
-      font_put_extra (entity, QCscript,
-                      font_supported_scripts (&physical_font->ntmFontSig));
+      tem = font_supported_scripts (&physical_font->ntmFontSig);
+      if (!NILP (tem))
+        font_put_extra (entity, QCscript, tem);
     }
 
+  /* This information is not fully available when opening fonts, so
+     save it here.  Only Windows 2000 and later return information
+     about opentype and type1 fonts, so need a fallback for detecting
+     truetype so that this information is not any worse than we could
+     have obtained later.  */
+  if (EQ (backend, Quniscribe) && (full_type & NTMFLAGS_OPENTYPE))
+    tem = intern ("opentype");
+  else if (font_type & TRUETYPE_FONTTYPE)
+    tem = intern ("truetype");
+  else if (full_type & NTM_PS_OPENTYPE)
+    tem = intern ("postscript");
+  else if (full_type & NTM_TYPE1)
+    tem = intern ("type1");
+  else if (font_type & RASTER_FONTTYPE)
+    tem = intern ("w32bitmap");
+  else
+    tem = intern ("w32vector");
+
+  font_put_extra (entity, QCformat, tem);
+
   return entity;
 }
 
@@ -765,8 +1066,7 @@ w32_generic_family (Lisp_Object name)
   /* Generic families.  */
   if (EQ (name, Qmonospace) || EQ (name, Qmono))
     return FF_MODERN;
-  else if (EQ (name, Qsans_serif) || EQ (name, Qsans__serif)
-           || EQ (name, Qsans))
+  else if (EQ (name, Qsans) || EQ (name, Qsans_serif) || EQ (name, Qsansserif))
     return FF_SWISS;
   else if (EQ (name, Qserif))
     return FF_ROMAN;
@@ -799,24 +1099,48 @@ logfonts_match (font, pattern)
 }
 
 static int
-font_matches_spec (type, font, spec)
+font_matches_spec (type, font, spec, backend, logfont)
      DWORD type;
      NEWTEXTMETRICEX *font;
      Lisp_Object spec;
+     Lisp_Object backend;
+     LOGFONT *logfont;
 {
   Lisp_Object extra, val;
 
   /* Check italic. Can't check logfonts, since it is a boolean field,
      so there is no difference between "non-italic" and "don't care".  */
-  val = AREF (spec, FONT_SLANT_INDEX);
-  if (INTEGERP (val))
+  {
+    int slant = FONT_SLANT_NUMERIC (spec);
+
+    if (slant >= 0
+       && ((slant > 150 && !font->ntmTm.tmItalic)
+           || (slant <= 150 && font->ntmTm.tmItalic)))
+         return 0;
+  }
+
+  /* Check adstyle against generic family.  */
+  val = AREF (spec, FONT_ADSTYLE_INDEX);
+  if (!NILP (val))
     {
-      int slant = XINT (val);
-      if ((slant > 150 && !font->ntmTm.tmItalic)
-          || (slant <= 150 && font->ntmTm.tmItalic))
+      BYTE family = w32_generic_family (val);
+      if (family != FF_DONTCARE
+          && family != (font->ntmTm.tmPitchAndFamily & 0xF0))
         return 0;
     }
 
+  /* Check spacing */
+  val = AREF (spec, FONT_SPACING_INDEX);
+  if (INTEGERP (val))
+    {
+      int spacing = XINT (val);
+      int proportional = (spacing < FONT_SPACING_MONO);
+
+      if ((proportional && !(font->ntmTm.tmPitchAndFamily & 0x01))
+         || (!proportional && (font->ntmTm.tmPitchAndFamily & 0x01)))
+       return 0;
+    }
+
   /* Check extra parameters.  */
   for (extra = AREF (spec, FONT_EXTRA_INDEX);
        CONSP (extra); extra = XCDR (extra))
@@ -826,42 +1150,9 @@ font_matches_spec (type, font, spec)
       if (CONSP (extra_entry))
         {
           Lisp_Object key = XCAR (extra_entry);
-          val = XCDR (extra_entry);
-          if (EQ (key, QCfamily))
-            {
-              /* Generic family. Most useful when there is no font name
-                 specified. eg, if a script does not exist in the default
-                 font, we could look for a font with the same generic family
-                 that does support the script. Full PANOSE support would
-                 be better, but we need to open the font to get that.  */
-              BYTE w32_family = w32_generic_family (val);
-
-              /* Reject if FF_DONTCARE is returned, as it means the
-                 font spec is bad.  */
-              if (w32_family == FF_DONTCARE
-                  || w32_family != (font->ntmTm.tmPitchAndFamily & 0xF0))
-                return 0;
-            }
-          else if (EQ (key, QCspacing))
-            {
-              int proportional;
-              if (INTEGERP (val))
-                {
-                  int spacing = XINT (val);
-                  proportional = (spacing < FONT_SPACING_MONO);
-                }
-              else if (EQ (val, Qp))
-                proportional = 1;
-              else if (EQ (val, Qc) || EQ (val, Qm))
-                proportional = 0;
-              else
-                return 0; /* Bad font spec.  */
 
-              if ((proportional && !(font->ntmTm.tmPitchAndFamily & 0x01))
-                  || (!proportional && (font->ntmTm.tmPitchAndFamily & 0x01)))
-                return 0;
-            }
-          else if (EQ (key, QCscript) && SYMBOLP (val))
+          val = XCDR (extra_entry);
+          if (EQ (key, QCscript) && SYMBOLP (val))
             {
               /* Only truetype fonts will have information about what
                  scripts they support.  This probably means the user
@@ -944,15 +1235,84 @@ font_matches_spec (type, font, spec)
                         return 0;
                     }
                   else
-                    /* Other scripts unlikely to be handled.  */
+                    /* Other scripts unlikely to be handled by non-truetype
+                      fonts.  */
                     return 0;
                 }
             }
+         else if (EQ (key, QClang) && SYMBOLP (val))
+           {
+             /* Just handle the CJK languages here, as the language
+                parameter is used to select a font with appropriate
+                glyphs in the cjk unified ideographs block. Other fonts
+                support for a language can be solely determined by
+                its character coverage.  */
+             if (EQ (val, Qja))
+               {
+                 if (font->ntmTm.tmCharSet != SHIFTJIS_CHARSET)
+                   return 0;
+               }
+             else if (EQ (val, Qko))
+               {
+                 if (font->ntmTm.tmCharSet != HANGUL_CHARSET
+                     && font->ntmTm.tmCharSet != JOHAB_CHARSET)
+                   return 0;
+               }
+             else if (EQ (val, Qzh))
+               {
+                 if (font->ntmTm.tmCharSet != GB2312_CHARSET
+                     && font->ntmTm.tmCharSet != CHINESEBIG5_CHARSET)
+               return 0;
+               }
+             else
+               /* Any other language, we don't recognize it. Fontset
+                  spec should have a fallback, as some backends do
+                  not recognize language at all.  */
+               return 0;
+           }
+          else if (EQ (key, QCotf) && CONSP (val))
+           {
+             /* OTF features only supported by the uniscribe backend.  */
+             if (EQ (backend, Quniscribe))
+               {
+                 if (!uniscribe_check_otf (logfont, val))
+                   return 0;
+               }
+             else
+               return 0;
+           }
         }
     }
   return 1;
 }
 
+static int
+w32font_coverage_ok (coverage, charset)
+     FONTSIGNATURE * coverage;
+     BYTE charset;
+{
+  DWORD subrange1 = coverage->fsUsb[1];
+
+#define SUBRANGE1_HAN_MASK 0x08000000
+#define SUBRANGE1_HANGEUL_MASK 0x01000000
+#define SUBRANGE1_JAPANESE_MASK (0x00060000 | SUBRANGE1_HAN_MASK)
+
+  if (charset == GB2312_CHARSET || charset == CHINESEBIG5_CHARSET)
+    {
+      return (subrange1 & SUBRANGE1_HAN_MASK) == SUBRANGE1_HAN_MASK;
+    }
+  else if (charset == SHIFTJIS_CHARSET)
+    {
+      return (subrange1 & SUBRANGE1_JAPANESE_MASK) == SUBRANGE1_JAPANESE_MASK;
+    }
+  else if (charset == HANGEUL_CHARSET)
+    {
+      return (subrange1 & SUBRANGE1_HANGEUL_MASK) == SUBRANGE1_HANGEUL_MASK;
+    }
+
+  return 1;
+}
+
 /* Callback function for EnumFontFamiliesEx.
  * Checks if a font matches everything we are trying to check agaist,
  * and if so, adds it to a list. Both the data we are checking against
@@ -967,21 +1327,82 @@ add_font_entity_to_list (logical_font, physical_font, font_type, lParam)
 {
   struct font_callback_data *match_data
     = (struct font_callback_data *) lParam;
-
-  if (logfonts_match (&logical_font->elfLogFont, &match_data->pattern)
+  Lisp_Object backend = match_data->opentype_only ? Quniscribe : Qgdi;
+
+  if ((!match_data->opentype_only
+       || (((physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE)
+            || (font_type & TRUETYPE_FONTTYPE))
+           /* For the uniscribe backend, only consider fonts that claim
+              to cover at least some part of Unicode.  */
+           && (physical_font->ntmFontSig.fsUsb[3]
+               || physical_font->ntmFontSig.fsUsb[2]
+               || physical_font->ntmFontSig.fsUsb[1]
+               || (physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff))))
+      && logfonts_match (&logical_font->elfLogFont, &match_data->pattern)
       && font_matches_spec (font_type, physical_font,
-                            match_data->orig_font_spec)
-      /* Avoid Windows substitution so we can control substitution with
-         alternate-fontname-alist.  */
-      && !strnicmp (&logical_font->elfFullName,
-                    &match_data->pattern.lfFaceName, LF_FACESIZE))
+                            match_data->orig_font_spec, backend,
+                           &logical_font->elfLogFont)
+      && w32font_coverage_ok (&physical_font->ntmFontSig,
+                              match_data->pattern.lfCharSet)
+      /* Avoid substitutions involving raster fonts (eg Helv -> MS Sans Serif)
+         We limit this to raster fonts, because the test can catch some
+         genuine fonts (eg the full name of DejaVu Sans Mono Light is actually
+         DejaVu Sans Mono ExtraLight). Helvetica -> Arial substitution will
+         therefore get through this test.  Since full names can be prefixed
+         by a foundry, we accept raster fonts if the font name is found
+         anywhere within the full name.  */
+      && (logical_font->elfLogFont.lfOutPrecision != OUT_STRING_PRECIS
+          || strstr (logical_font->elfFullName,
+                     logical_font->elfLogFont.lfFaceName)))
     {
       Lisp_Object entity
         = w32_enumfont_pattern_entity (match_data->frame, logical_font,
                                        physical_font, font_type,
-                                       &match_data->pattern);
+                                       &match_data->pattern,
+                                       backend);
       if (!NILP (entity))
-        match_data->list = Fcons (entity, match_data->list);
+        {
+          Lisp_Object spec_charset = AREF (match_data->orig_font_spec,
+                                           FONT_REGISTRY_INDEX);
+
+          /* If registry was specified as iso10646-1, only report
+             ANSI and DEFAULT charsets, as most unicode fonts will
+             contain one of those plus others.  */
+          if ((EQ (spec_charset, Qiso10646_1)
+               || EQ (spec_charset, Qunicode_bmp)
+               || EQ (spec_charset, Qunicode_sip))
+              && logical_font->elfLogFont.lfCharSet != DEFAULT_CHARSET
+              && logical_font->elfLogFont.lfCharSet != ANSI_CHARSET)
+            return 1;
+          /* If registry was specified, but did not map to a windows
+             charset, only report fonts that have unknown charsets.
+             This will still report fonts that don't match, but at
+             least it eliminates known definite mismatches.  */
+          else if (!NILP (spec_charset)
+                   && !EQ (spec_charset, Qiso10646_1)
+                   && !EQ (spec_charset, Qunicode_bmp)
+                   && !EQ (spec_charset, Qunicode_sip)
+                   && match_data->pattern.lfCharSet == DEFAULT_CHARSET
+                   && logical_font->elfLogFont.lfCharSet != DEFAULT_CHARSET)
+            return 1;
+
+          /* If registry was specified, ensure it is reported as the same.  */
+          if (!NILP (spec_charset))
+            ASET (entity, FONT_REGISTRY_INDEX, spec_charset);
+
+          match_data->list = Fcons (entity, match_data->list);
+
+          /* If no registry specified, duplicate iso8859-1 truetype fonts
+             as iso10646-1.  */
+          if (NILP (spec_charset)
+              && font_type == TRUETYPE_FONTTYPE
+              && logical_font->elfLogFont.lfCharSet == ANSI_CHARSET)
+            {
+              Lisp_Object tem = Fcopy_font_spec (entity);
+              ASET (tem, FONT_REGISTRY_INDEX, Qiso10646_1);
+              match_data->list = Fcons (tem, match_data->list);
+            }
+        }
     }
   return 1;
 }
@@ -1015,23 +1436,54 @@ registry_to_w32_charset (charset)
     return ANSI_CHARSET;
   else if (SYMBOLP (charset))
     return x_to_w32_charset (SDATA (SYMBOL_NAME (charset)));
-  else if (STRINGP (charset))
-    return x_to_w32_charset (SDATA (charset));
   else
     return DEFAULT_CHARSET;
 }
 
 static Lisp_Object
-w32_registry (w32_charset)
+w32_registry (w32_charset, font_type)
      LONG w32_charset;
+     DWORD font_type;
 {
-  if (w32_charset == ANSI_CHARSET)
-    return Qiso10646_1;
-  else
-    {
-      char * charset = w32_to_x_charset (w32_charset, NULL);
-      return intern_downcase (charset, strlen(charset));
-    }
+  char *charset;
+
+  /* If charset is defaulted, charset is unicode or unknown, depending on
+     font type.  */
+  if (w32_charset == DEFAULT_CHARSET)
+    return font_type == TRUETYPE_FONTTYPE ? Qiso10646_1 : Qunknown;
+
+  charset = w32_to_x_charset (w32_charset, NULL);
+  return font_intern_prop (charset, strlen(charset), 1);
+}
+
+static int
+w32_decode_weight (fnweight)
+     int fnweight;
+{
+  if (fnweight >= FW_HEAVY)      return 210;
+  if (fnweight >= FW_EXTRABOLD)  return 205;
+  if (fnweight >= FW_BOLD)       return 200;
+  if (fnweight >= FW_SEMIBOLD)   return 180;
+  if (fnweight >= FW_NORMAL)     return 100;
+  if (fnweight >= FW_LIGHT)      return 50;
+  if (fnweight >= FW_EXTRALIGHT) return 40;
+  if (fnweight > FW_THIN)        return 20;
+  return 0;
+}
+
+static int
+w32_encode_weight (n)
+     int n;
+{
+  if (n >= 210) return FW_HEAVY;
+  if (n >= 205) return FW_EXTRABOLD;
+  if (n >= 200) return FW_BOLD;
+  if (n >= 180) return FW_SEMIBOLD;
+  if (n >= 100) return FW_NORMAL;
+  if (n >= 50)  return FW_LIGHT;
+  if (n >= 40)  return FW_EXTRALIGHT;
+  if (n >= 20)  return  FW_THIN;
+  return 0;
 }
 
 /* Fill in all the available details of LOGFONT from FONT_SPEC.  */
@@ -1044,19 +1496,14 @@ fill_in_logfont (f, logfont, font_spec)
   Lisp_Object tmp, extra;
   int dpi = FRAME_W32_DISPLAY_INFO (f)->resy;
 
-  extra = AREF (font_spec, FONT_EXTRA_INDEX);
-  /* Allow user to override dpi settings.  */
-  if (CONSP (extra))
+  tmp = AREF (font_spec, FONT_DPI_INDEX);
+  if (INTEGERP (tmp))
     {
-      tmp = assq_no_quit (QCdpi, extra);
-      if (CONSP (tmp) && INTEGERP (XCDR (tmp)))
-        {
-          dpi = XINT (XCDR (tmp));
-        }
-      else if (CONSP (tmp) && FLOATP (XCDR (tmp)))
-        {
-          dpi = (int) (XFLOAT_DATA (XCDR (tmp)) + 0.5);
-        }
+      dpi = XINT (tmp);
+    }
+  else if (FLOATP (tmp))
+    {
+      dpi = (int) (XFLOAT_DATA (tmp) + 0.5);
     }
 
   /* Height  */
@@ -1073,13 +1520,13 @@ fill_in_logfont (f, logfont, font_spec)
   /* Weight  */
   tmp = AREF (font_spec, FONT_WEIGHT_INDEX);
   if (INTEGERP (tmp))
-    logfont->lfWeight = XINT (tmp);
+    logfont->lfWeight = w32_encode_weight (FONT_WEIGHT_NUMERIC (font_spec));
 
   /* Italic  */
   tmp = AREF (font_spec, FONT_SLANT_INDEX);
   if (INTEGERP (tmp))
     {
-      int slant = XINT (tmp);
+      int slant = FONT_SLANT_NUMERIC (font_spec);
       logfont->lfItalic = slant > 150 ? 1 : 0;
     }
 
@@ -1091,6 +1538,8 @@ fill_in_logfont (f, logfont, font_spec)
   tmp = AREF (font_spec, FONT_REGISTRY_INDEX);
   if (! NILP (tmp))
     logfont->lfCharSet = registry_to_w32_charset (tmp);
+  else
+    logfont->lfCharSet = DEFAULT_CHARSET;
 
   /* Out Precision  */
 
@@ -1112,53 +1561,47 @@ fill_in_logfont (f, logfont, font_spec)
            user input.  */
       else if (SYMBOLP (tmp))
         strncpy (logfont->lfFaceName, SDATA (SYMBOL_NAME (tmp)), LF_FACESIZE);
-      else if (STRINGP (tmp))
-        strncpy (logfont->lfFaceName, SDATA (tmp), LF_FACESIZE);
+    }
+
+  tmp = AREF (font_spec, FONT_ADSTYLE_INDEX);
+  if (!NILP (tmp))
+    {
+      /* Override generic family.  */
+      BYTE family = w32_generic_family (tmp);
+      if (family != FF_DONTCARE)
+        logfont->lfPitchAndFamily = family | DEFAULT_PITCH;
+    }
+
+
+  /* Set pitch based on the spacing property.  */
+  tmp = AREF (font_spec, FONT_SPACING_INDEX);
+  if (INTEGERP (tmp))
+    {
+      int spacing = XINT (tmp);
+      if (spacing < FONT_SPACING_MONO)
+       logfont->lfPitchAndFamily
+         = logfont->lfPitchAndFamily & 0xF0 | VARIABLE_PITCH;
+      else
+       logfont->lfPitchAndFamily
+         = logfont->lfPitchAndFamily & 0xF0 | FIXED_PITCH;
     }
 
   /* Process EXTRA info.  */
-  for ( ; CONSP (extra); extra = XCDR (extra))
+  for (extra = AREF (font_spec, FONT_EXTRA_INDEX);
+       CONSP (extra); extra = XCDR (extra))
     {
       tmp = XCAR (extra);
       if (CONSP (tmp))
         {
           Lisp_Object key, val;
           key = XCAR (tmp), val = XCDR (tmp);
-          if (EQ (key, QCfamily))
-            {
-              /* Override generic family.  */
-              BYTE family = w32_generic_family (val);
-              if (family != FF_DONTCARE)
-                logfont->lfPitchAndFamily
-                  = logfont->lfPitchAndFamily & 0x0F | family;
-            }
-          else if (EQ (key, QCspacing))
-            {
-              /* Set pitch based on the spacing property.  */
-              if (INTEGERP (val))
-                {
-                  int spacing = XINT (val);
-                  if (spacing < FONT_SPACING_MONO)
-                    logfont->lfPitchAndFamily
-                      = logfont->lfPitchAndFamily & 0xF0 | VARIABLE_PITCH;
-                  else
-                    logfont->lfPitchAndFamily
-                      = logfont->lfPitchAndFamily & 0xF0 | FIXED_PITCH;
-                }
-              else if (EQ (val, Qp))
-                logfont->lfPitchAndFamily
-                  = logfont->lfPitchAndFamily & 0xF0 | VARIABLE_PITCH;
-              else if (EQ (val, Qc) || EQ (val, Qm))
-                logfont->lfPitchAndFamily
-                  = logfont->lfPitchAndFamily & 0xF0 | FIXED_PITCH;
-            }
           /* Only use QCscript if charset is not provided, or is unicode
              and a single script is specified.  This is rather crude,
              and is only used to narrow down the fonts returned where
              there is a definite match.  Some scripts, such as latin, han,
              cjk-misc match multiple lfCharSet values, so we can't pre-filter
              them.  */
-          else if (EQ (key, QCscript)
+         if (EQ (key, QCscript)
                    && logfont->lfCharSet == DEFAULT_CHARSET
                    && SYMBOLP (val))
             {
@@ -1212,10 +1655,10 @@ list_all_matching_fonts (match_data)
       families = CDR (families);
       if (NILP (family))
         continue;
-      else if (STRINGP (family))
-        name = SDATA (family);
+      else if (SYMBOLP (family))
+        name = SDATA (SYMBOL_NAME (family));
       else
-        name = SDATA (SYMBOL_NAME (family)); 
+       continue;
 
       strncpy (match_data->pattern.lfFaceName, name, LF_FACESIZE);
       match_data->pattern.lfFaceName[LF_FACESIZE - 1] = '\0';
@@ -1291,8 +1734,12 @@ font_supported_scripts (FONTSIGNATURE * sig)
       || (subranges[2] & (mask2)) || (subranges[3] & (mask3))) \
     supported = Fcons ((sym), supported)
 
-  SUBRANGE (0, Qlatin); /* There are many others... */
-
+  SUBRANGE (0, Qlatin);
+  /* The following count as latin too, ASCII should be present in these fonts,
+     so don't need to mark them separately.  */
+  /* 1: Latin-1 supplement, 2: Latin Extended A, 3: Latin Extended B.  */
+  SUBRANGE (4, Qphonetic);
+  /* 5: Spacing and tone modifiers, 6: Combining Diacriticals.  */
   SUBRANGE (7, Qgreek);
   SUBRANGE (8, Qcoptic);
   SUBRANGE (9, Qcyrillic);
@@ -1312,15 +1759,28 @@ font_supported_scripts (FONTSIGNATURE * sig)
   SUBRANGE (24, Qthai);
   SUBRANGE (25, Qlao);
   SUBRANGE (26, Qgeorgian);
-
+  SUBRANGE (27, Qbalinese);
+  /* 28: Hangul Jamo.  */
+  /* 29: Latin Extended, 30: Greek Extended, 31: Punctuation.  */
+  /* 32-47: Symbols (defined below).  */
   SUBRANGE (48, Qcjk_misc);
+  /* Match either 49: katakana or 50: hiragana for kana.  */
+  MASK_ANY (0, 0x00060000, 0, 0, Qkana);
   SUBRANGE (51, Qbopomofo);
-  SUBRANGE (54, Qkanbun); /* Is this right?  */
+  /* 52: Compatibility Jamo */
+  SUBRANGE (53, Qphags_pa);
+  /* 54: Enclosed CJK letters and months, 55: CJK Compatibility.  */
   SUBRANGE (56, Qhangul);
-
+  /* 57: Surrogates.  */
+  SUBRANGE (58, Qphoenician);
   SUBRANGE (59, Qhan); /* There are others, but this is the main one.  */
-  SUBRANGE (59, Qideographic_description); /* Windows lumps this in  */
-
+  SUBRANGE (59, Qideographic_description); /* Windows lumps this in.  */
+  SUBRANGE (59, Qkanbun); /* And this.  */
+  /* 60: Private use, 61: CJK strokes and compatibility.  */
+  /* 62: Alphabetic Presentation, 63: Arabic Presentation A.  */
+  /* 64: Combining half marks, 65: Vertical and CJK compatibility.  */
+  /* 66: Small forms, 67: Arabic Presentation B, 68: Half and Full width.  */
+  /* 69: Specials.  */
   SUBRANGE (70, Qtibetan);
   SUBRANGE (71, Qsyriac);
   SUBRANGE (72, Qthaana);
@@ -1335,29 +1795,178 @@ font_supported_scripts (FONTSIGNATURE * sig)
   SUBRANGE (81, Qmongolian);
   SUBRANGE (82, Qbraille);
   SUBRANGE (83, Qyi);
-
+  SUBRANGE (84, Qbuhid);
+  SUBRANGE (84, Qhanunoo);
+  SUBRANGE (84, Qtagalog);
+  SUBRANGE (84, Qtagbanwa);
+  SUBRANGE (85, Qold_italic);
+  SUBRANGE (86, Qgothic);
+  SUBRANGE (87, Qdeseret);
   SUBRANGE (88, Qbyzantine_musical_symbol);
   SUBRANGE (88, Qmusical_symbol); /* Windows doesn't distinguish these.  */
-
   SUBRANGE (89, Qmathematical);
-
-  /* Match either katakana or hiragana for kana.  */
-  MASK_ANY (0, 0x00060000, 0, 0, Qkana);
+  /* 90: Private use, 91: Variation selectors, 92: Tags.  */
+  SUBRANGE (93, Qlimbu);
+  SUBRANGE (94, Qtai_le);
+  /* 95: New Tai Le */
+  SUBRANGE (90, Qbuginese);
+  SUBRANGE (97, Qglagolitic);
+  SUBRANGE (98, Qtifinagh);
+  /* 99: Yijing Hexagrams.  */
+  SUBRANGE (100, Qsyloti_nagri);
+  SUBRANGE (101, Qlinear_b);
+  /* 102: Ancient Greek Numbers.  */
+  SUBRANGE (103, Qugaritic);
+  SUBRANGE (104, Qold_persian);
+  SUBRANGE (105, Qshavian);
+  SUBRANGE (106, Qosmanya);
+  SUBRANGE (107, Qcypriot);
+  SUBRANGE (108, Qkharoshthi);
+  /* 109: Tai Xuan Jing.  */
+  SUBRANGE (110, Qcuneiform);
+  /* 111: Counting Rods.  */
 
   /* There isn't really a main symbol range, so include symbol if any
      relevant range is set.  */
   MASK_ANY (0x8000000, 0x0000FFFF, 0, 0, Qsymbol);
 
+  /* Missing: Tai Viet (U+AA80) and Cham (U+AA00) .  */
 #undef SUBRANGE
 #undef MASK_ANY
 
   return supported;
 }
 
+/* Generate a full name for a Windows font.
+   The full name is in fcname format, with weight, slant and antialiasing
+   specified if they are not "normal".  */
+static int
+w32font_full_name (font, font_obj, pixel_size, name, nbytes)
+  LOGFONT * font;
+  Lisp_Object font_obj;
+  int pixel_size;
+  char *name;
+  int nbytes;
+{
+  int len, height, outline;
+  char *p;
+  Lisp_Object antialiasing, weight = Qnil;
+
+  len = strlen (font->lfFaceName);
+
+  outline = EQ (AREF (font_obj, FONT_FOUNDRY_INDEX), Qoutline);
+
+  /* Represent size of scalable fonts by point size. But use pixelsize for
+     raster fonts to indicate that they are exactly that size.  */
+  if (outline)
+    len += 11; /* -SIZE */
+  else
+    len = strlen (font->lfFaceName) + 21;
+
+  if (font->lfItalic)
+    len += 7; /* :italic */
+
+  if (font->lfWeight && font->lfWeight != FW_NORMAL)
+    {
+      weight = FONT_WEIGHT_SYMBOLIC (font_obj);
+      len += 8 + SBYTES (SYMBOL_NAME (weight)); /* :weight=NAME */
+    }
+
+  antialiasing = lispy_antialias_type (font->lfQuality);
+  if (! NILP (antialiasing))
+    len += 11 + SBYTES (SYMBOL_NAME (antialiasing)); /* :antialias=NAME */
+
+  /* Check that the buffer is big enough  */
+  if (len > nbytes)
+    return -1;
+
+  p = name;
+  p += sprintf (p, "%s", font->lfFaceName);
+
+  height = font->lfHeight ? eabs (font->lfHeight) : pixel_size;
+
+  if (height > 0)
+    {
+      if (outline)
+        {
+          float pointsize = height * 72.0 / one_w32_display_info.resy;
+          /* Round to nearest half point.  floor is used, since round is not
+            supported in MS library.  */
+          pointsize = floor (pointsize * 2 + 0.5) / 2;
+          p += sprintf (p, "-%1.1f", pointsize);
+        }
+      else
+        p += sprintf (p, ":pixelsize=%d", height);
+    }
+
+  if (font->lfItalic)
+    p += sprintf (p, ":italic");
+
+  if (SYMBOLP (weight) && ! NILP (weight))
+    p += sprintf (p, ":weight=%s", SDATA (SYMBOL_NAME (weight)));
+
+  if (SYMBOLP (antialiasing) && ! NILP (antialiasing))
+    p += sprintf (p, ":antialias=%s", SDATA (SYMBOL_NAME (antialiasing)));
+
+  return (p - name);
+}
+
+
+static void
+compute_metrics (dc, w32_font, code, metrics)
+     HDC dc;
+     struct w32font_info *w32_font;
+     unsigned int code;
+     struct w32_metric_cache *metrics;
+{
+  GLYPHMETRICS gm;
+  MAT2 transform;
+  unsigned int options = GGO_METRICS;
+
+  if (w32_font->glyph_idx)
+    options |= GGO_GLYPH_INDEX;
+
+  bzero (&transform, sizeof (transform));
+  transform.eM11.value = 1;
+  transform.eM22.value = 1;
+
+  if (GetGlyphOutlineW (dc, code, options, &gm, 0, NULL, &transform)
+      != GDI_ERROR)
+    {
+      metrics->lbearing = gm.gmptGlyphOrigin.x;
+      metrics->rbearing = gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
+      metrics->width = gm.gmCellIncX;
+      metrics->status = W32METRIC_SUCCESS;
+    }
+  else if (w32_font->glyph_idx)
+    {
+      /* Can't use glyph indexes after all.
+        Avoid it in future, and clear any metrics that were based on
+        glyph indexes.  */
+      w32_font->glyph_idx = 0;
+      clear_cached_metrics (w32_font);
+    }
+  else
+    metrics->status = W32METRIC_FAIL;
+}
+
+static void
+clear_cached_metrics (w32_font)
+     struct w32font_info *w32_font;
+{
+  int i;
+  for (i = 0; i < w32_font->n_cache_blocks; i++)
+    {
+      if (w32_font->cached_metrics[i])
+        bzero (w32_font->cached_metrics[i],
+               CACHE_BLOCKSIZE * sizeof (struct font_metrics));
+    }
+}
 
 struct font_driver w32font_driver =
   {
     0, /* Qgdi */
+    0, /* case insensitive */
     w32font_get_cache,
     w32font_list,
     w32font_match,
@@ -1390,15 +1999,17 @@ void
 syms_of_w32font ()
 {
   DEFSYM (Qgdi, "gdi");
+  DEFSYM (Quniscribe, "uniscribe");
+  DEFSYM (QCformat, ":format");
 
   /* Generic font families.  */
   DEFSYM (Qmonospace, "monospace");
   DEFSYM (Qserif, "serif");
-  DEFSYM (Qsans_serif, "sans-serif");
+  DEFSYM (Qsansserif, "sansserif");
   DEFSYM (Qscript, "script");
   DEFSYM (Qdecorative, "decorative");
   /* Aliases.  */
-  DEFSYM (Qsans__serif, "sans_serif");
+  DEFSYM (Qsans_serif, "sans_serif");
   DEFSYM (Qsans, "sans");
   DEFSYM (Qmono, "mono");
 
@@ -1412,6 +2023,11 @@ syms_of_w32font ()
   DEFSYM (Qsubpixel, "subpixel");
   DEFSYM (Qnatural, "natural");
 
+  /* Languages  */
+  DEFSYM (Qja, "ja");
+  DEFSYM (Qko, "ko");
+  DEFSYM (Qzh, "zh");
+
   /* Scripts  */
   DEFSYM (Qlatin, "latin");
   DEFSYM (Qgreek, "greek");
@@ -1458,6 +2074,31 @@ syms_of_w32font ()
   DEFSYM (Qbyzantine_musical_symbol, "byzantine-musical-symbol");
   DEFSYM (Qmusical_symbol, "musical-symbol");
   DEFSYM (Qmathematical, "mathematical");
+  DEFSYM (Qphonetic, "phonetic");
+  DEFSYM (Qbalinese, "balinese");
+  DEFSYM (Qbuginese, "buginese");
+  DEFSYM (Qbuhid, "buhid");
+  DEFSYM (Qcuneiform, "cuneiform");
+  DEFSYM (Qcypriot, "cypriot");
+  DEFSYM (Qdeseret, "deseret");
+  DEFSYM (Qglagolitic, "glagolitic");
+  DEFSYM (Qgothic, "gothic");
+  DEFSYM (Qhanunoo, "hanunoo");
+  DEFSYM (Qkharoshthi, "kharoshthi");
+  DEFSYM (Qlimbu, "limbu");
+  DEFSYM (Qlinear_b, "linear_b");
+  DEFSYM (Qold_italic, "old_italic");
+  DEFSYM (Qold_persian, "old_persian");
+  DEFSYM (Qosmanya, "osmanya");
+  DEFSYM (Qphags_pa, "phags-pa");
+  DEFSYM (Qphoenician, "phoenician");
+  DEFSYM (Qshavian, "shavian");
+  DEFSYM (Qsyloti_nagri, "syloti_nagri");
+  DEFSYM (Qtagalog, "tagalog");
+  DEFSYM (Qtagbanwa, "tagbanwa");
+  DEFSYM (Qtai_le, "tai_le");
+  DEFSYM (Qtifinagh, "tifinagh");
+  DEFSYM (Qugaritic, "ugaritic");
 
   w32font_driver.type = Qgdi;
   register_font_driver (&w32font_driver, NULL);