Merge from emacs-23; up to 2010-06-02T00:10:42Z!yamaoka@jpl.org.
[bpt/emacs.git] / src / font.c
index 33c3cbd..35821ae 100644 (file)
@@ -1,8 +1,9 @@
 /* font.c -- "Font" primitives.
-   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
-   Copyright (C) 2006, 2007, 2008, 2009, 2010
-     National Institute of Advanced Industrial Science and Technology (AIST)
-     Registration Number H13PRO009
+
+Copyright (C) 2006-2011  Free Software Foundation, Inc.
+Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
+  National Institute of Advanced Industrial Science and Technology (AIST)
+  Registration Number H13PRO009
 
 This file is part of GNU Emacs.
 
@@ -61,8 +62,6 @@ static Lisp_Object QCf;
    font_driver *)->list when a specified font is not found. */
 static Lisp_Object null_vector;
 
-static Lisp_Object Vfont_weight_table, Vfont_slant_table, Vfont_width_table;
-
 /* Vector of Vfont_weight_table, Vfont_slant_table, and Vfont_width_table. */
 static Lisp_Object font_style_table;
 
@@ -122,7 +121,8 @@ static const struct table_entry width_table[] =
   { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
 };
 
-Lisp_Object QCfoundry, QCadstyle, QCregistry;
+Lisp_Object QCfoundry;
+static Lisp_Object QCadstyle, QCregistry;
 /* Symbols representing keys of font extra info.  */
 Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
 Lisp_Object QCantialias, QCfont_entity, QCfc_unknown_spec;
@@ -134,8 +134,6 @@ Lisp_Object Qja, Qko;
 
 Lisp_Object QCuser_spec;
 
-Lisp_Object Vfont_encoding_alist;
-
 /* Alist of font registry symbol and the corresponding charsets
    information.  The information is retrieved from
    Vfont_encoding_alist on demand.
@@ -163,7 +161,7 @@ static struct font_driver_list *font_driver_list;
 
 /* Creaters of font-related Lisp object.  */
 
-Lisp_Object
+static Lisp_Object
 font_make_spec (void)
 {
   Lisp_Object font_spec;
@@ -219,6 +217,7 @@ static int font_pixel_size (FRAME_PTR f, Lisp_Object);
 static Lisp_Object font_open_entity (FRAME_PTR, Lisp_Object, int);
 static Lisp_Object font_matching_entity (FRAME_PTR, Lisp_Object *,
                                          Lisp_Object);
+static unsigned font_encode_char (Lisp_Object, int);
 
 /* Number of registered font drivers.  */
 static int num_font_drivers;
@@ -316,7 +315,7 @@ font_style_to_value (enum font_property_index prop, Lisp_Object val, int noerror
 
   if (SYMBOLP (val))
     {
-      unsigned char *s;
+      char *s;
       Lisp_Object args[2], elt;
 
       /* At first try exact match.  */
@@ -326,12 +325,12 @@ font_style_to_value (enum font_property_index prop, Lisp_Object val, int noerror
            return ((XINT (AREF (AREF (table, i), 0)) << 8)
                    | (i << 4) | (j - 1));
       /* Try also with case-folding match.  */
-      s = SDATA (SYMBOL_NAME (val));
+      s = SSDATA (SYMBOL_NAME (val));
       for (i = 0; i < len; i++)
        for (j = 1; j < ASIZE (AREF (table, i)); j++)
          {
            elt = AREF (AREF (table, i), j);
-           if (xstrcasecmp (s, SDATA (SYMBOL_NAME (elt))) == 0)
+           if (xstrcasecmp (s, SSDATA (SYMBOL_NAME (elt))) == 0)
              return ((XINT (AREF (AREF (table, i), 0)) << 8)
                      | (i << 4) | (j - 1));
          }
@@ -1190,7 +1189,7 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
          if (SYMBOLP (val))
            val = SYMBOL_NAME (val);
          if (j == XLFD_REGISTRY_INDEX
-             && ! strchr ((char *) SDATA (val), '-'))
+             && ! strchr (SSDATA (val), '-'))
            {
              /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*".  */
              if (SDATA (val)[SBYTES (val) - 1] == '*')
@@ -1207,7 +1206,7 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
                }
            }
          else
-           f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
+           f[j] = SSDATA (val), len += SBYTES (val) + 1;
        }
     }
 
@@ -1220,7 +1219,7 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
       else
        {
          val = SYMBOL_NAME (val);
-         f[j] = (char *) SDATA (val), len += SBYTES (val) + 1;
+         f[j] = SSDATA (val), len += SBYTES (val) + 1;
        }
     }
 
@@ -1304,7 +1303,7 @@ font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
 
    This function tries to guess which format it is.  */
 
-int
+static int
 font_parse_fcname (char *name, Lisp_Object font)
 {
   char *p, *q;
@@ -1381,25 +1380,26 @@ font_parse_fcname (char *name, Lisp_Object font)
                  word_len = q - p;
                  val = font_intern_prop (p, q - p, 1);
 
-#define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
+#define PROP_MATCH(STR) (word_len == strlen (STR)              \
+                        && memcmp (p, STR, strlen (STR)) == 0)
 
-                 if (PROP_MATCH ("light", 5)
-                     || PROP_MATCH ("medium", 6)
-                     || PROP_MATCH ("demibold", 8)
-                     || PROP_MATCH ("bold", 4)
-                     || PROP_MATCH ("black", 5))
+                 if (PROP_MATCH ("light")
+                     || PROP_MATCH ("medium")
+                     || PROP_MATCH ("demibold")
+                     || PROP_MATCH ("bold")
+                     || PROP_MATCH ("black"))
                    FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val);
-                 else if (PROP_MATCH ("roman", 5)
-                          || PROP_MATCH ("italic", 6)
-                          || PROP_MATCH ("oblique", 7))
+                 else if (PROP_MATCH ("roman")
+                          || PROP_MATCH ("italic")
+                          || PROP_MATCH ("oblique"))
                    FONT_SET_STYLE (font, FONT_SLANT_INDEX, val);
-                 else if (PROP_MATCH ("charcell", 8))
+                 else if (PROP_MATCH ("charcell"))
                    ASET (font, FONT_SPACING_INDEX,
                          make_number (FONT_SPACING_CHARCELL));
-                 else if (PROP_MATCH ("mono", 4))
+                 else if (PROP_MATCH ("mono"))
                    ASET (font, FONT_SPACING_INDEX,
                          make_number (FONT_SPACING_MONO));
-                 else if (PROP_MATCH ("proportional", 12))
+                 else if (PROP_MATCH ("proportional"))
                    ASET (font, FONT_SPACING_INDEX,
                          make_number (FONT_SPACING_PROPORTIONAL));
 #undef PROP_MATCH
@@ -1449,109 +1449,85 @@ font_parse_fcname (char *name, Lisp_Object font)
       /* Either a fontconfig-style name with no size and property
         data, or a GTK-style name.  */
       Lisp_Object prop;
-      int word_len, prop_found = 0;
+      Lisp_Object weight = Qnil, slant = Qnil;
+      Lisp_Object width  = Qnil, size  = Qnil;
+      char *word_start;
+      int word_len;
+      int size_found = 0;
+
+      /* Scan backwards from the end, looking for a size.  */
+      for (p = name + len - 1; p >= name; p--)
+       if (!isdigit (*p))
+         break;
 
-      for (p = name; *p; p = *q ? q + 1 : q)
+      if ((p < name + len - 1) && ((p + 1 == name) || *p == ' '))
+       /* Found a font size.  */
+       size = make_float (strtod (p + 1, NULL));
+      else
+       p = name + len;
+
+      /* Now P points to the termination of the string, sans size.
+        Scan backwards, looking for font properties.  */
+      for (; p > name; p = q)
        {
-         if (isdigit (*p))
+         for (q = p - 1; q >= name; q--)
            {
-             int size_found = 1;
-
-             for (q = p + 1; *q && *q != ' '; q++)
-               if (! isdigit (*q) && *q != '.')
-                 {
-                   size_found = 0;
-                   break;
-                 }
-             if (size_found)
-               {
-                 double point_size = strtod (p, &q);
-                 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
-                 continue;
-               }
+             if (q > name && *(q-1) == '\\')
+               --q;   /* Skip quoting backslashes.  */
+             else if (*q == ' ')
+               break;
            }
 
-         for (q = p + 1; *q && *q != ' '; q++)
-           if (*q == '\\' && q[1])
-             q++;
-         word_len = q - p;
-
-#define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
-
-         if (PROP_MATCH ("Ultra-Light", 11))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("ultra-light", 11, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
-         else if (PROP_MATCH ("Light", 5))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("light", 5, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
-         else if (PROP_MATCH ("Book", 4))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("book", 4, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
-         else if (PROP_MATCH ("Medium", 6))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("medium", 6, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
-         else if (PROP_MATCH ("Semi-Bold", 9))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("semi-bold", 9, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
-         else if (PROP_MATCH ("Bold", 4))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("bold", 4, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
-         else if (PROP_MATCH ("Italic", 6))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("italic", 4, 1);
-             FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
-           }
-         else if (PROP_MATCH ("Oblique", 7))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("oblique", 7, 1);
-             FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
-           }
-         else if (PROP_MATCH ("Semi-Condensed", 14))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("semi-condensed", 14, 1);
-             FONT_SET_STYLE (font, FONT_WIDTH_INDEX, prop);
-           }
-         else if (PROP_MATCH ("Condensed", 9))
+         word_start = q + 1;
+         word_len = p - word_start;
+
+#define PROP_MATCH(STR)                                                \
+         (word_len == strlen (STR)                             \
+          && memcmp (word_start, STR, strlen (STR)) == 0)
+#define PROP_SAVE(VAR, STR)                                    \
+         (VAR = NILP (VAR) ? font_intern_prop (STR, strlen (STR), 1) : VAR)
+
+         if (PROP_MATCH ("Ultra-Light"))
+           PROP_SAVE (weight, "ultra-light");
+         else if (PROP_MATCH ("Light"))
+           PROP_SAVE (weight, "light");
+         else if (PROP_MATCH ("Book"))
+           PROP_SAVE (weight, "book");
+         else if (PROP_MATCH ("Medium"))
+           PROP_SAVE (weight, "medium");
+         else if (PROP_MATCH ("Semi-Bold"))
+           PROP_SAVE (weight, "semi-bold");
+         else if (PROP_MATCH ("Bold"))
+           PROP_SAVE (weight, "bold");
+         else if (PROP_MATCH ("Italic"))
+           PROP_SAVE (slant, "italic");
+         else if (PROP_MATCH ("Oblique"))
+           PROP_SAVE (slant, "oblique");
+         else if (PROP_MATCH ("Semi-Condensed"))
+           PROP_SAVE (width, "semi-condensed");
+         else if (PROP_MATCH ("Condensed"))
+           PROP_SAVE (width, "condensed");
+         /* An unknown word must be part of the font name.  */
+         else
            {
-             prop_found = 1;
-             prop = font_intern_prop ("condensed", 9, 1);
-             FONT_SET_STYLE (font, FONT_WIDTH_INDEX, prop);
+             family_end = p;
+             break;
            }
-         else {
-           if (prop_found)
-             return -1; /* Unknown property in GTK-style font name.  */
-           family_end = q;
-         }
        }
 #undef PROP_MATCH
+#undef PROP_SAVE
 
       if (family_end)
-       {
-         Lisp_Object family;
-         family = font_intern_prop (name, family_end - name, 1);
-         ASET (font, FONT_FAMILY_INDEX, family);
-       }
+       ASET (font, FONT_FAMILY_INDEX,
+             font_intern_prop (name, family_end - name, 1));
+      if (!NILP (size))
+       ASET (font, FONT_SIZE_INDEX, size);
+      if (!NILP (weight))
+       FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, weight);
+      if (!NILP (slant))
+       FONT_SET_STYLE (font, FONT_SLANT_INDEX, slant);
+      if (!NILP (width))
+       FONT_SET_STYLE (font, FONT_WIDTH_INDEX, width);
     }
 
   return 0;
@@ -1675,90 +1651,6 @@ font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes)
   return (p - name);
 }
 
-/* Store GTK-style font name of FONT (font-spec or font-entity) in
-   NAME (NBYTES length), and return the name length.  F is the frame
-   on which the font is displayed; it is used to calculate the point
-   size.  */
-
-int
-font_unparse_gtkname (Lisp_Object font, struct frame *f, char *name, int nbytes)
-{
-  char *p;
-  int len = 1;
-  Lisp_Object family, weight, slant, size;
-  int point_size = -1;
-
-  family = AREF (font, FONT_FAMILY_INDEX);
-  if (! NILP (family))
-    {
-      if (! SYMBOLP (family))
-       return -1;
-      family = SYMBOL_NAME (family);
-      len += SBYTES (family);
-    }
-
-  weight = font_style_symbolic (font, FONT_WEIGHT_INDEX, 0);
-  if (EQ (weight, Qnormal))
-    weight = Qnil;
-  else if (! NILP (weight))
-    {
-      weight = SYMBOL_NAME (weight);
-      len += SBYTES (weight);
-    }
-
-  slant = font_style_symbolic (font, FONT_SLANT_INDEX, 0);
-  if (EQ (slant, Qnormal))
-    slant = Qnil;
-  else if (! NILP (slant))
-    {
-      slant = SYMBOL_NAME (slant);
-      len += SBYTES (slant);
-    }
-
-  size = AREF (font, FONT_SIZE_INDEX);
-  /* Convert pixel size to point size.  */
-  if (INTEGERP (size))
-    {
-      Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
-      int dpi = 75;
-      if (INTEGERP (font_dpi))
-       dpi = XINT (font_dpi);
-      else if (f)
-       dpi = f->resy;
-      point_size = PIXEL_TO_POINT (XINT (size), dpi);
-      len += 11;
-    }
-  else if (FLOATP (size))
-    {
-      point_size = (int) XFLOAT_DATA (size);
-      len += 11;
-    }
-
-  if (len > nbytes)
-    return -1;
-
-  p = name + sprintf (name, "%s", SDATA (family));
-
-  if (! NILP (weight))
-    {
-      char *q = p;
-      p += sprintf (p, " %s", SDATA (weight));
-      q[1] = toupper (q[1]);
-    }
-
-  if (! NILP (slant))
-    {
-      char *q = p;
-      p += sprintf (p, " %s", SDATA (slant));
-      q[1] = toupper (q[1]);
-    }
-
-  if (point_size > 0)
-    p += sprintf (p, " %d", point_size);
-
-  return (p - name);
-}
-
 /* Parse NAME (null terminated) and store information in FONT
    (font-spec or font-entity).  If NAME is successfully parsed, return
    0.  Otherwise return -1.  */
@@ -1787,7 +1679,7 @@ font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Objec
     {
       CHECK_STRING (family);
       len = SBYTES (family);
-      p0 = (char *) SDATA (family);
+      p0 = SSDATA (family);
       p1 = strchr (p0, '-');
       if (p1)
        {
@@ -1806,7 +1698,7 @@ font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Objec
       /* Convert "XXX" and "XXX*" to "XXX*-*".  */
       CHECK_STRING (registry);
       len = SBYTES (registry);
-      p0 = (char *) SDATA (registry);
+      p0 = SSDATA (registry);
       p1 = strchr (p0, '-');
       if (! p1)
        {
@@ -1939,7 +1831,7 @@ otf_open (file)
     otf = XSAVE_VALUE (XCDR (val))->pointer;
   else
     {
-      otf = STRINGP (file) ? OTF_open ((char *) SDATA (file)) : NULL;
+      otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL;
       val = make_save_value (otf, 0);
       otf_list = Fcons (Fcons (file, val), otf_list);
     }
@@ -2914,7 +2806,7 @@ font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
   Lisp_Object objlist, size, val, font_object;
   struct font *font;
   int min_width, height;
-  int scaled_pixel_size;
+  int scaled_pixel_size = pixel_size;
 
   font_assert (FONT_ENTITY_P (entity));
   size = AREF (entity, FONT_SIZE_INDEX);
@@ -3038,7 +2930,7 @@ font_has_char (FRAME_PTR f, Lisp_Object font, int c)
 
 /* Return the glyph ID of FONT_OBJECT for character C.  */
 
-unsigned
+static unsigned
 font_encode_char (Lisp_Object font_object, int c)
 {
   struct font *font;
@@ -3084,7 +2976,7 @@ font_spec_from_name (Lisp_Object font_name)
   Lisp_Object spec = Ffont_spec (0, NULL);
 
   CHECK_STRING (font_name);
-  if (font_parse_name ((char *) SDATA (font_name), spec) == -1)
+  if (font_parse_name (SSDATA (font_name), spec) == -1)
     return Qnil;
   font_put_extra (spec, QCname, font_name);
   font_put_extra (spec, QCuser_spec, font_name);
@@ -3143,50 +3035,6 @@ font_clear_prop (Lisp_Object *attrs, enum font_property_index prop)
   attrs[LFACE_FONT_INDEX] = font;
 }
 
-void
-font_update_lface (FRAME_PTR f, Lisp_Object *attrs)
-{
-  Lisp_Object spec;
-
-  spec = attrs[LFACE_FONT_INDEX];
-  if (! FONT_SPEC_P (spec))
-    return;
-
-  if (! NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
-    attrs[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX));
-  if (! NILP (AREF (spec, FONT_FAMILY_INDEX)))
-    attrs[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FAMILY_INDEX));
-  if (! NILP (AREF (spec, FONT_WEIGHT_INDEX)))
-    attrs[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (spec);
-  if (! NILP (AREF (spec, FONT_SLANT_INDEX)))
-    attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);
-  if (! NILP (AREF (spec, FONT_WIDTH_INDEX)))
-    attrs[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (spec);
-  if (! NILP (AREF (spec, FONT_SIZE_INDEX)))
-    {
-      int point;
-
-      if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
-       {
-         Lisp_Object val;
-         int dpi = f->resy;
-
-         val = Ffont_get (spec, QCdpi);
-         if (! NILP (val))
-           dpi = XINT (val);
-         point = PIXEL_TO_POINT (XINT (AREF (spec, FONT_SIZE_INDEX)) * 10,
-                                 dpi);
-         attrs[LFACE_HEIGHT_INDEX] = make_number (point);
-       }
-      else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
-       {
-         point = XFLOAT_DATA (AREF (spec, FONT_SIZE_INDEX)) * 10;
-         attrs[LFACE_HEIGHT_INDEX] = make_number (point);
-       }
-    }
-}
-
-
 /* Selecte a font from ENTITIES (list of font-entity vectors) that
    supports C and matches best with ATTRS and PIXEL_SIZE.  */
 
@@ -3273,7 +3121,7 @@ font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
   XSETFRAME (frame, f);
   size = AREF (spec, FONT_SIZE_INDEX);
   pixel_size = font_pixel_size (f, spec);
-  if (pixel_size == 0)
+  if (pixel_size == 0 && INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
     {
       double pt = XINT (attrs[LFACE_HEIGHT_INDEX]);
 
@@ -3286,7 +3134,7 @@ font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
   else if (STRINGP (attrs[LFACE_FOUNDRY_INDEX]))
     {
       val = attrs[LFACE_FOUNDRY_INDEX];
-      foundry[0] = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
+      foundry[0] = font_intern_prop (SSDATA (val), SBYTES (val), 1);
       foundry[1] = Qnil;
       foundry[2] = null_vector;
     }
@@ -3317,7 +3165,7 @@ font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
   if (NILP (val) && STRINGP (attrs[LFACE_FAMILY_INDEX]))
     {
       val = attrs[LFACE_FAMILY_INDEX];
-      val = font_intern_prop ((char *) SDATA (val), SBYTES (val), 1);
+      val = font_intern_prop (SSDATA (val), SBYTES (val), 1);
     }
   if (NILP (val))
     {
@@ -3443,7 +3291,7 @@ font_load_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
       if (NILP (entity))
        return Qnil;
     }
-  /* Don't loose the original name that was put in initially.  We need
+  /* Don't lose the original name that was put in initially.  We need
      it to re-apply the font when font parameters (like hinting or dpi) have
      changed.  */
   entity = font_open_for_lface (f, entity, attrs, spec);
@@ -3514,7 +3362,7 @@ font_open_by_name (FRAME_PTR f, const char *name)
   args[1] = make_unibyte_string (name, strlen (name));
   spec = Ffont_spec (2, args);
   ret = font_open_by_spec (f, spec);
-  /* Do not loose name originally put in.  */
+  /* Do not lose name originally put in.  */
   if (!NILP (ret))
     font_put_extra (ret, QCuser_spec, args[1]);
 
@@ -3723,20 +3571,73 @@ font_get_frame_data (FRAME_PTR f, struct font_driver *driver)
 }
 
 
+/* Sets attributes on a font.  Any properties that appear in ALIST and
+   BOOLEAN_PROPERTIES or NON_BOOLEAN_PROPERTIES are set on the font.
+   BOOLEAN_PROPERTIES and NON_BOOLEAN_PROPERTIES are NULL-terminated
+   arrays of strings.  This function is intended for use by the font
+   drivers to implement their specific font_filter_properties.  */
+void
+font_filter_properties (Lisp_Object font,
+                       Lisp_Object alist,
+                       const char *const boolean_properties[],
+                       const char *const non_boolean_properties[])
+{
+  Lisp_Object it;
+  int i;
+
+  /* Set boolean values to Qt or Qnil */
+  for (i = 0; boolean_properties[i] != NULL; ++i)
+    for (it = alist; ! NILP (it); it = XCDR (it))
+      {
+        Lisp_Object key = XCAR (XCAR (it));
+        Lisp_Object val = XCDR (XCAR (it));
+        char *keystr = SSDATA (SYMBOL_NAME (key));
+
+        if (strcmp (boolean_properties[i], keystr) == 0)
+          {
+            const char *str = INTEGERP (val) ? (XINT (val) ? "true" : "false")
+             : SYMBOLP (val) ? SSDATA (SYMBOL_NAME (val))
+             : "true";
+
+            if (strcmp ("false", str) == 0 || strcmp ("False", str) == 0
+                || strcmp ("FALSE", str) == 0 || strcmp ("FcFalse", str) == 0
+                || strcmp ("off", str) == 0 || strcmp ("OFF", str) == 0
+                || strcmp ("Off", str) == 0)
+              val = Qnil;
+           else
+              val = Qt;
+
+            Ffont_put (font, key, val);
+          }
+      }
+
+  for (i = 0; non_boolean_properties[i] != NULL; ++i)
+    for (it = alist; ! NILP (it); it = XCDR (it))
+      {
+        Lisp_Object key = XCAR (XCAR (it));
+        Lisp_Object val = XCDR (XCAR (it));
+        char *keystr = SSDATA (SYMBOL_NAME (key));
+        if (strcmp (non_boolean_properties[i], keystr) == 0)
+          Ffont_put (font, key, val);
+      }
+}
+
+
 /* Return the font used to draw character C by FACE at buffer position
    POS in window W.  If STRING is non-nil, it is a string containing C
    at index POS.  If C is negative, get C from the current buffer or
    STRING.  */
 
-Lisp_Object
-font_at (int c, EMACS_INT pos, struct face *face, struct window *w, Lisp_Object string)
+static Lisp_Object
+font_at (int c, EMACS_INT pos, struct face *face, struct window *w,
+        Lisp_Object string)
 {
   FRAME_PTR f;
   int multibyte;
   Lisp_Object font_object;
 
   multibyte = (NILP (string)
-              ? ! NILP (current_buffer->enable_multibyte_characters)
+              ? ! NILP (BVAR (current_buffer, enable_multibyte_characters))
               : STRING_MULTIBYTE (string));
   if (c < 0)
     {
@@ -3965,7 +3866,7 @@ usage: (font-spec ARGS...)  */)
       if (EQ (key, QCname))
        {
          CHECK_STRING (val);
-         font_parse_name ((char *) SDATA (val), spec);
+         font_parse_name (SSDATA (val), spec);
          font_put_extra (spec, key, val);
        }
       else
@@ -4081,7 +3982,6 @@ Layout tags.  */)
        val = fontp->driver->otf_capability (fontp);
       else
        val = Fcons (Qnil, Qnil);
-      font_put_extra (font, QCotf, val);
     }
   else
     val = Fcdr (val);
@@ -4325,7 +4225,7 @@ the consecutive wildcards are folded to one.  */)
        {
          if (NILP (fold_wildcards))
            return font_name;
-         strcpy (name, (char *) SDATA (font_name));
+         strcpy (name, SSDATA (font_name));
          goto done;
        }
       pixel_size = XFONT_OBJECT (font)->pixel_size;
@@ -4486,7 +4386,7 @@ DEFUN ("font-variation-glyphs", Ffont_variation_glyphs, Sfont_variation_glyphs,
        doc: /* Return a list of variation glyphs for CHAR in FONT-OBJECT.
 Each element of the value is a cons (VARIATION-SELECTOR . GLYPH-ID),
 where
-  VARIATION-SELECTOR is a chracter code of variation selection
+  VARIATION-SELECTOR is a character code of variation selection
     (#xFE00..#xFE0F or #xE0100..#xE01EF)
   GLYPH-ID is a glyph code of the corresponding variation glyph.  */)
   (Lisp_Object font_object, Lisp_Object character)
@@ -4988,7 +4888,7 @@ If the named font is not yet loaded, return nil.  */)
 
       if (fontset >= 0)
        name = fontset_ascii (fontset);
-      font_object = font_open_by_name (f, (char *) SDATA (name));
+      font_object = font_open_by_name (f, SSDATA (name));
     }
   else if (FONT_OBJECT_P (name))
     font_object = name;
@@ -5047,8 +4947,6 @@ build_style_table (const struct table_entry *entry, int nelement)
   return table;
 }
 
-Lisp_Object Vfont_log;
-
 /* The deferred font-log data of the form [ACTION ARG RESULT].
    If ACTION is not nil, that is added to the log when font_add_log is
    called next time.  At that time, ACTION is set back to nil.  */
@@ -5068,7 +4966,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
     return;
   if (STRINGP (AREF (Vfont_log_deferred, 0)))
     {
-      char *str = (char *) SDATA (AREF (Vfont_log_deferred, 0));
+      char *str = SSDATA (AREF (Vfont_log_deferred, 0));
 
       ASET (Vfont_log_deferred, 0, Qnil);
       font_add_log (str, AREF (Vfont_log_deferred, 1),
@@ -5254,7 +5152,7 @@ syms_of_font (void)
   defsubr (&Sfont_info);
 #endif
 
-  DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
+  DEFVAR_LISP ("font-encoding-alist", Vfont_encoding_alist,
               doc: /*
 Alist of fontname patterns vs the corresponding encoding and repertory info.
 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
@@ -5281,7 +5179,7 @@ gets the repertory information by an opened font and ENCODING.  */);
      table used by the font display code.  So we make them read-only,
      to avoid this confusing situation.  */
 
-  DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table,
+  DEFVAR_LISP_NOPRO ("font-weight-table", Vfont_weight_table,
               doc: /*  Vector of valid font weight values.
 Each element has the form:
     [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
@@ -5289,13 +5187,13 @@ NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
   Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
   XSYMBOL (intern_c_string ("font-weight-table"))->constant = 1;
 
-  DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table,
+  DEFVAR_LISP_NOPRO ("font-slant-table", Vfont_slant_table,
               doc: /*  Vector of font slant symbols vs the corresponding numeric values.
 See `font-weight-table' for the format of the vector. */);
   Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
   XSYMBOL (intern_c_string ("font-slant-table"))->constant = 1;
 
-  DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table,
+  DEFVAR_LISP_NOPRO ("font-width-table", Vfont_width_table,
               doc: /*  Alist of font width symbols vs the corresponding numeric values.
 See `font-weight-table' for the format of the vector. */);
   Vfont_width_table = BUILD_STYLE_TABLE (width_table);
@@ -5307,7 +5205,7 @@ See `font-weight-table' for the format of the vector. */);
   ASET (font_style_table, 1, Vfont_slant_table);
   ASET (font_style_table, 2, Vfont_width_table);
 
-  DEFVAR_LISP ("font-log", &Vfont_log, doc: /*
+  DEFVAR_LISP ("font-log", Vfont_log, doc: /*
 *Logging list of font related actions and results.
 The value t means to suppress the logging.
 The initial value is set to nil if the environment variable
@@ -5346,6 +5244,3 @@ init_font (void)
 {
   Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;
 }
-
-/* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
-   (do not change this comment) */