Remove __P and P_ from .c and .m files and definition of P_
[bpt/emacs.git] / src / xftfont.c
index 8eadd06..8aeb639 100644 (file)
@@ -1,6 +1,6 @@
 /* xftfont.c -- XFT font driver.
 /* xftfont.c -- XFT font driver.
-   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
-   Copyright (C) 2006, 2007, 2008
+   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
 
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
 
@@ -21,6 +21,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
 
 #include <config.h>
 #include <stdio.h>
+#include <setjmp.h>
 #include <X11/Xlib.h>
 #include <X11/Xft/Xft.h>
 
 #include <X11/Xlib.h>
 #include <X11/Xft/Xft.h>
 
@@ -38,7 +39,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Xft font driver.  */
 
 static Lisp_Object Qxft;
 /* Xft font driver.  */
 
 static Lisp_Object Qxft;
-static Lisp_Object QChinting , QCautohint, QChintstyle, QCrgba, QCembolden;
+static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
+  QClcdfilter;
 
 /* The actual structure for Xft font that can be casted to struct
    font.  */
 
 /* The actual structure for Xft font that can be casted to struct
    font.  */
@@ -46,13 +48,15 @@ static Lisp_Object QChinting , QCautohint, QChintstyle, QCrgba, QCembolden;
 struct xftfont_info
 {
   struct font font;
 struct xftfont_info
 {
   struct font font;
-  /* The following three members must be here in this order to be
+  /* The following five members must be here in this order to be
      compatible with struct ftfont_info (in ftfont.c).  */
 #ifdef HAVE_LIBOTF
   int maybe_otf;         /* Flag to tell if this may be OTF or not.  */
   OTF *otf;
 #endif /* HAVE_LIBOTF */
   FT_Size ft_size;
      compatible with struct ftfont_info (in ftfont.c).  */
 #ifdef HAVE_LIBOTF
   int maybe_otf;         /* Flag to tell if this may be OTF or not.  */
   OTF *otf;
 #endif /* HAVE_LIBOTF */
   FT_Size ft_size;
+  int index;
+  FT_Matrix matrix;
   Display *display;
   int screen;
   XftFont *xftfont;
   Display *display;
   int screen;
   XftFont *xftfont;
@@ -66,9 +70,9 @@ struct xftface_info
   XftColor xft_bg;             /* color for face->background */
 };
 
   XftColor xft_bg;             /* color for face->background */
 };
 
-static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
-                                   struct xftface_info *,
-                                   XftColor *fg, XftColor *bg));
+static void xftfont_get_colors (FRAME_PTR, struct face *, GC gc,
+                                struct xftface_info *,
+                                XftColor *fg, XftColor *bg);
 
 
 /* Setup foreground and background colors of GC into FG and BG.  If
 
 
 /* Setup foreground and background colors of GC into FG and BG.  If
@@ -137,17 +141,18 @@ xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
 }
 
 
 }
 
 
-static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
-static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
-static Lisp_Object xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
-static void xftfont_close P_ ((FRAME_PTR, struct font *));
-static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
-static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
-static unsigned xftfont_encode_char P_ ((struct font *, int));
-static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
-                                    struct font_metrics *));
-static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
-static int xftfont_end_for_frame P_ ((FRAME_PTR f));
+static Lisp_Object xftfont_list (Lisp_Object, Lisp_Object);
+static Lisp_Object xftfont_match (Lisp_Object, Lisp_Object);
+static Lisp_Object xftfont_open (FRAME_PTR, Lisp_Object, int);
+static void xftfont_close (FRAME_PTR, struct font *);
+static int xftfont_prepare_face (FRAME_PTR, struct face *);
+static void xftfont_done_face (FRAME_PTR, struct face *);
+static int xftfont_has_char (Lisp_Object, int);
+static unsigned xftfont_encode_char (struct font *, int);
+static int xftfont_text_extents (struct font *, unsigned *, int,
+                                 struct font_metrics *);
+static int xftfont_draw (struct glyph_string *, int, int, int, int, int);
+static int xftfont_end_for_frame (FRAME_PTR f);
 
 struct font_driver xftfont_driver;
 
 
 struct font_driver xftfont_driver;
 
@@ -157,7 +162,7 @@ xftfont_list (frame, spec)
      Lisp_Object spec;
 {
   Lisp_Object list = ftfont_driver.list (frame, spec), tail;
      Lisp_Object spec;
 {
   Lisp_Object list = ftfont_driver.list (frame, spec), tail;
-  
+
   for (tail = list; CONSP (tail); tail = XCDR (tail))
     ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
   return list;
   for (tail = list; CONSP (tail); tail = XCDR (tail))
     ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
   return list;
@@ -175,12 +180,113 @@ xftfont_match (frame, spec)
   return entity;
 }
 
   return entity;
 }
 
-extern Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
-extern FcCharSet *ftfont_get_fc_charset P_ ((Lisp_Object));
+extern Lisp_Object ftfont_font_format (FcPattern *, Lisp_Object);
+extern FcCharSet *ftfont_get_fc_charset (Lisp_Object);
 extern Lisp_Object QCantialias;
 
 static FcChar8 ascii_printable[95];
 
 extern Lisp_Object QCantialias;
 
 static FcChar8 ascii_printable[95];
 
+static void
+xftfont_fix_match (pat, match)
+     FcPattern *pat, *match;
+{
+  /*  These values are not used for matching (except antialias), but for
+      rendering, so make sure they are carried over to the match.
+      We also put antialias here because most fonts are antialiased, so
+      the match will have antialias true.  */
+
+  FcBool b = FcTrue;
+  int i;
+  double dpi;
+
+  FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
+  if (! b) 
+    {
+      FcPatternDel (match, FC_ANTIALIAS);
+      FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
+    }
+  FcPatternGetBool (pat, FC_HINTING, 0, &b);
+  if (! b) 
+    {
+      FcPatternDel (match, FC_HINTING);
+      FcPatternAddBool (match, FC_HINTING, FcFalse);
+    }
+  if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
+    {
+      FcPatternDel (match, FC_HINT_STYLE);
+      FcPatternAddInteger (match, FC_HINT_STYLE, i);
+    }
+#ifndef FC_LCD_FILTER
+  /* Older fontconfig versions don't have FC_LCD_FILTER. */
+#define FC_LCD_FILTER "lcdfilter"
+#endif
+  if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
+    {
+      FcPatternDel (match, FC_LCD_FILTER);
+      FcPatternAddInteger (match, FC_LCD_FILTER, i);
+    }
+  if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
+    {
+      FcPatternDel (match, FC_RGBA);
+      FcPatternAddInteger (match, FC_RGBA, i);
+    }
+  if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
+    {
+      FcPatternDel (match, FC_DPI);
+      FcPatternAddDouble (match, FC_DPI, dpi);
+    }
+}
+
+static void
+xftfont_add_rendering_parameters (pat, entity)
+     FcPattern *pat;
+     Lisp_Object entity;
+{
+  Lisp_Object tail;
+  int ival;
+
+  for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
+    {
+      Lisp_Object key = XCAR (XCAR (tail));
+      Lisp_Object val = XCDR (XCAR (tail));
+
+      if (EQ (key, QCantialias))
+          FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
+      else if (EQ (key, QChinting))
+       FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
+      else if (EQ (key, QCautohint))
+       FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
+      else if (EQ (key, QChintstyle))
+       {
+         if (INTEGERP (val))
+           FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
+          else if (SYMBOLP (val)
+                   && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
+           FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
+       }
+      else if (EQ (key, QCrgba))
+       {
+         if (INTEGERP (val))
+           FcPatternAddInteger (pat, FC_RGBA, XINT (val));
+          else if (SYMBOLP (val)
+                   && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
+           FcPatternAddInteger (pat, FC_RGBA, ival);
+       }
+      else if (EQ (key, QClcdfilter))
+       {
+         if (INTEGERP (val))
+           FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
+          else if (SYMBOLP (val)
+                   && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
+           FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
+       }
+#ifdef FC_EMBOLDEN
+      else if (EQ (key, QCembolden))
+       FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
+#endif
+    }
+}
+
 static Lisp_Object
 xftfont_open (f, entity, pixel_size)
      FRAME_PTR f;
 static Lisp_Object
 xftfont_open (f, entity, pixel_size)
      FRAME_PTR f;
@@ -189,7 +295,7 @@ xftfont_open (f, entity, pixel_size)
 {
   FcResult result;
   Display *display = FRAME_X_DISPLAY (f);
 {
   FcResult result;
   Display *display = FRAME_X_DISPLAY (f);
-  Lisp_Object val, filename, index, tail, font_object;
+  Lisp_Object val, filename, index, font_object;
   FcPattern *pat = NULL, *match;
   struct xftfont_info *xftfont_info = NULL;
   struct font *font;
   FcPattern *pat = NULL, *match;
   struct xftfont_info *xftfont_info = NULL;
   struct font *font;
@@ -200,6 +306,7 @@ xftfont_open (f, entity, pixel_size)
   int len, i;
   XGlyphInfo extents;
   FT_Face ft_face;
   int len, i;
   XGlyphInfo extents;
   FT_Face ft_face;
+  FcMatrix *matrix;
 
   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
   if (! CONSP (val))
 
   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
   if (! CONSP (val))
@@ -240,56 +347,50 @@ xftfont_open (f, entity, pixel_size)
      over 10x20-ISO8859-1.pcf.gz).  */
   FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
 
      over 10x20-ISO8859-1.pcf.gz).  */
   FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
 
-  for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
-    {
-      Lisp_Object key, val;
-
-      key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail));
-      if (EQ (key, QCantialias))
-       FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
-      else if (EQ (key, QChinting))
-       FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
-      else if (EQ (key, QCautohint))
-       FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
-      else if (EQ (key, QChintstyle))
-       {
-         if (INTEGERP (val))
-           FcPatternAddInteger (pat, FC_RGBA, XINT (val));
-       }
-      else if (EQ (key, QCrgba))
-       {
-         if (INTEGERP (val))
-           FcPatternAddInteger (pat, FC_RGBA, XINT (val));
-       }
-#ifdef FC_EMBOLDEN
-      else if (EQ (key, QCembolden))
-       FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
-#endif
-    }
+  xftfont_add_rendering_parameters (pat, entity);
 
   FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
   FcPatternAddInteger (pat, FC_INDEX, XINT (index));
 
   FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
   FcPatternAddInteger (pat, FC_INDEX, XINT (index));
-                      
+
 
   BLOCK_INPUT;
 
   BLOCK_INPUT;
+  /* Make sure that the Xrender extension is added before the Xft one.
+     Otherwise, the close-display hook set by Xft is called after the
+     one for Xrender, and the former tries to re-add the latter.  This
+     results in inconsistency of internal states and leads to X
+     protocol error when one reconnects to the same X server.
+     (Bug#1696)  */
+  {
+    int event_base, error_base;
+    XRenderQueryExtension (display, &event_base, &error_base);
+  }
+
+  /* Substitute in values from X resources and XftDefaultSet.  */
+  XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
   match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
   match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
+  xftfont_fix_match (pat, match);
+
   FcPatternDestroy (pat);
   xftfont = XftFontOpenPattern (display, match);
   FcPatternDestroy (pat);
   xftfont = XftFontOpenPattern (display, match);
+  if (!xftfont)
+    {
+      UNBLOCK_INPUT;
+      XftPatternDestroy (match);
+      return Qnil;
+    }
   ft_face = XftLockFace (xftfont);
   UNBLOCK_INPUT;
 
   ft_face = XftLockFace (xftfont);
   UNBLOCK_INPUT;
 
-  if (! xftfont)
-    return Qnil;
   /* We should not destroy PAT here because it is kept in XFTFONT and
      destroyed automatically when XFTFONT is closed.  */
   font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
   ASET (font_object, FONT_TYPE_INDEX, Qxft);
   len = font_unparse_xlfd (entity, size, name, 256);
   if (len > 0)
   /* We should not destroy PAT here because it is kept in XFTFONT and
      destroyed automatically when XFTFONT is closed.  */
   font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
   ASET (font_object, FONT_TYPE_INDEX, Qxft);
   len = font_unparse_xlfd (entity, size, name, 256);
   if (len > 0)
-    ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
+    ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
   len = font_unparse_fcname (entity, size, name, 256);
   if (len > 0)
   len = font_unparse_fcname (entity, size, name, 256);
   if (len > 0)
-    ASET (font_object, FONT_FULLNAME_INDEX, make_unibyte_string (name, len));
+    ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
   else
     ASET (font_object, FONT_FULLNAME_INDEX,
          AREF (font_object, FONT_NAME_INDEX));
   else
     ASET (font_object, FONT_FULLNAME_INDEX,
          AREF (font_object, FONT_NAME_INDEX));
@@ -305,6 +406,16 @@ xftfont_open (f, entity, pixel_size)
   xftfont_info->display = display;
   xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
   xftfont_info->xftfont = xftfont;
   xftfont_info->display = display;
   xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
   xftfont_info->xftfont = xftfont;
+  /* This means that there's no need of transformation.  */
+  xftfont_info->matrix.xx = 0;
+  if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
+      == FcResultMatch)
+    {
+      xftfont_info->matrix.xx = 0x10000L * matrix->xx;
+      xftfont_info->matrix.yy = 0x10000L * matrix->yy;
+      xftfont_info->matrix.xy = 0x10000L * matrix->xy;
+      xftfont_info->matrix.yx = 0x10000L * matrix->yx;
+    }
   font->pixel_size = size;
   font->driver = &xftfont_driver;
   if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
   font->pixel_size = size;
   font->driver = &xftfont_driver;
   if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
@@ -318,7 +429,7 @@ xftfont_open (f, entity, pixel_size)
        ascii_printable[i] = ' ' + i;
     }
   BLOCK_INPUT;
        ascii_printable[i] = ' ' + i;
     }
   BLOCK_INPUT;
-  if (spacing != FC_PROPORTIONAL)
+  if (spacing != FC_PROPORTIONAL && spacing != FC_DUAL)
     {
       font->min_width = font->average_width = font->space_width
        = xftfont->max_advance_width;
     {
       font->min_width = font->average_width = font->space_width
        = xftfont->max_advance_width;
@@ -330,7 +441,7 @@ xftfont_open (f, entity, pixel_size)
       font->space_width = extents.xOff;
       if (font->space_width <= 0)
        /* dirty workaround */
       font->space_width = extents.xOff;
       if (font->space_width <= 0)
        /* dirty workaround */
-       font->space_width = pixel_size; 
+       font->space_width = pixel_size;
       XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
       font->average_width = (font->space_width + extents.xOff) / 95;
     }
       XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
       font->average_width = (font->space_width + extents.xOff) / 95;
     }
@@ -355,7 +466,7 @@ xftfont_open (f, entity, pixel_size)
       int upEM = ft_face->units_per_EM;
 
       font->underline_position = -ft_face->underline_position * size / upEM;
       int upEM = ft_face->units_per_EM;
 
       font->underline_position = -ft_face->underline_position * size / upEM;
-      font->underline_thickness = -ft_face->underline_thickness * size / upEM;
+      font->underline_thickness = ft_face->underline_thickness * size / upEM;
       if (font->underline_thickness > 2)
        font->underline_position -= font->underline_thickness / 2;
     }
       if (font->underline_thickness > 2)
        font->underline_position -= font->underline_thickness / 2;
     }
@@ -446,7 +557,7 @@ xftfont_done_face (f, face)
      struct face *face;
 {
   struct xftface_info *xftface_info;
      struct face *face;
 {
   struct xftface_info *xftface_info;
-  
+
 #if 0
   /* This doesn't work if face->ascii_face doesn't use an Xft font. */
   if (face != face->ascii_face
 #if 0
   /* This doesn't work if face->ascii_face doesn't use an Xft font. */
   if (face != face->ascii_face
@@ -462,6 +573,32 @@ xftfont_done_face (f, face)
     }
 }
 
     }
 }
 
+extern Lisp_Object Qja, Qko;
+
+static int
+xftfont_has_char (font, c)
+     Lisp_Object font;
+     int c;
+{
+  struct xftfont_info *xftfont_info;
+  struct charset *cs = NULL;
+
+  if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
+      && charset_jisx0208 >= 0)
+    cs = CHARSET_FROM_ID (charset_jisx0208);
+  else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
+      && charset_ksc5601 >= 0)
+    cs = CHARSET_FROM_ID (charset_ksc5601);
+  if (cs)
+    return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
+
+  if (FONT_ENTITY_P (font))
+    return ftfont_driver.has_char (font, c);
+  xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
+  return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
+                        (FcChar32) c) == FcTrue);
+}
+
 static unsigned
 xftfont_encode_char (font, c)
      struct font *font;
 static unsigned
 xftfont_encode_char (font, c)
      struct font *font;
@@ -470,7 +607,7 @@ xftfont_encode_char (font, c)
   struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
   unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
                                (FcChar32) c);
   struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
   unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
                                (FcChar32) c);
-  
+
   return (code ? code : FONT_INVALID_CODE);
 }
 
   return (code ? code : FONT_INVALID_CODE);
 }
 
@@ -503,7 +640,7 @@ static XftDraw *
 xftfont_get_xft_draw (f)
      FRAME_PTR f;
 {
 xftfont_get_xft_draw (f)
      FRAME_PTR f;
 {
-  XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);;
+  XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
 
   if (! xft_draw)
     {
 
   if (! xft_draw)
     {
@@ -569,7 +706,12 @@ static int
 xftfont_end_for_frame (f)
      FRAME_PTR f;
 {
 xftfont_end_for_frame (f)
      FRAME_PTR f;
 {
-  XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
+  XftDraw *xft_draw;
+
+  /* Don't do anything if display is dead */
+  if (FRAME_X_DISPLAY (f) == NULL) return 0;
+
+  xft_draw = font_get_frame_data (f, &xftfont_driver);
 
   if (xft_draw)
     {
 
   if (xft_draw)
     {
@@ -581,6 +723,53 @@ xftfont_end_for_frame (f)
   return 0;
 }
 
   return 0;
 }
 
+static int
+xftfont_cached_font_ok (f, font_object, entity)
+     struct frame *f;
+     Lisp_Object font_object;
+     Lisp_Object entity;
+
+{
+  struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
+  FcPattern *oldpat = info->xftfont->pattern;
+  Display *display = FRAME_X_DISPLAY (f);
+  FcPattern *pat = FcPatternCreate ();
+  FcBool b1, b2;
+  int ok = 0, i1, i2, r1, r2;
+
+  xftfont_add_rendering_parameters (pat, entity);
+  XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
+
+  r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
+  r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
+  if (r1 != r2 || b1 != b2) goto out;
+  r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
+  r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
+  if (r1 != r2 || b1 != b2) goto out;
+  r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
+  r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
+  if (r1 != r2 || b1 != b2) goto out;
+#ifdef FC_EMBOLDEN
+  r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
+  r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
+  if (r1 != r2 || b1 != b2) goto out;
+#endif
+  r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
+  r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
+  if (r1 != r2 || i1 != i2) goto out;
+  r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
+  r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
+  if (r1 != r2 || i1 != i2) goto out;
+  r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
+  r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
+  if (r1 != r2 || i1 != i2) goto out;
+
+  ok = 1;
+ out:
+  FcPatternDestroy (pat);
+  return ok;
+}
+
 void
 syms_of_xftfont ()
 {
 void
 syms_of_xftfont ()
 {
@@ -590,6 +779,7 @@ syms_of_xftfont ()
   DEFSYM (QChintstyle, ":hintstyle");
   DEFSYM (QCrgba, ":rgba");
   DEFSYM (QCembolden, ":embolden");
   DEFSYM (QChintstyle, ":hintstyle");
   DEFSYM (QCrgba, ":rgba");
   DEFSYM (QCembolden, ":embolden");
+  DEFSYM (QClcdfilter, ":lcdfilter");
 
   xftfont_driver = ftfont_driver;
   xftfont_driver.type = Qxft;
 
   xftfont_driver = ftfont_driver;
   xftfont_driver.type = Qxft;
@@ -600,10 +790,12 @@ syms_of_xftfont ()
   xftfont_driver.close = xftfont_close;
   xftfont_driver.prepare_face = xftfont_prepare_face;
   xftfont_driver.done_face = xftfont_done_face;
   xftfont_driver.close = xftfont_close;
   xftfont_driver.prepare_face = xftfont_prepare_face;
   xftfont_driver.done_face = xftfont_done_face;
+  xftfont_driver.has_char = xftfont_has_char;
   xftfont_driver.encode_char = xftfont_encode_char;
   xftfont_driver.text_extents = xftfont_text_extents;
   xftfont_driver.draw = xftfont_draw;
   xftfont_driver.end_for_frame = xftfont_end_for_frame;
   xftfont_driver.encode_char = xftfont_encode_char;
   xftfont_driver.text_extents = xftfont_text_extents;
   xftfont_driver.draw = xftfont_draw;
   xftfont_driver.end_for_frame = xftfont_end_for_frame;
+  xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
 
   register_font_driver (&xftfont_driver, NULL);
 }
 
   register_font_driver (&xftfont_driver, NULL);
 }