]> code.delx.au - gnu-emacs/blobdiff - src/xftfont.c
Merge from Gnus git master
[gnu-emacs] / src / xftfont.c
index 5e60ab0c4d30bd2cfd2cfe1db2d68336ce962473..18c180f906a0a46fb376c3b37cff67d13713b60b 100644 (file)
@@ -1,5 +1,5 @@
 /* xftfont.c -- XFT font driver.
-   Copyright (C) 2006-2012 Free Software Foundation, Inc.
+   Copyright (C) 2006-2014 Free Software Foundation, Inc.
    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
@@ -21,7 +21,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
-#include <setjmp.h>
 #include <X11/Xlib.h>
 #include <X11/Xft/Xft.h>
 
@@ -43,7 +42,7 @@ Lisp_Object Qxft;
 static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
   QClcdfilter;
 
-/* The actual structure for Xft font that can be casted to struct
+/* The actual structure for Xft font that can be cast to struct
    font.  */
 
 struct xftfont_info
@@ -52,15 +51,15 @@ struct xftfont_info
   /* 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.  */
+  bool 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;
+  unsigned x_display_id;
 };
 
 /* Structure pointed by (struct face *)->extra  */
@@ -71,17 +70,14 @@ struct xftface_info
   XftColor xft_bg;             /* color for face->background */
 };
 
-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
    XFTFACE_INFO is not NULL, reuse the colors in it if possible.  BG
    may be NULL.  */
 
 static void
-xftfont_get_colors (FRAME_PTR f, struct face *face, GC gc, struct xftface_info *xftface_info, XftColor *fg, XftColor *bg)
+xftfont_get_colors (struct frame *f, struct face *face, GC gc,
+                   struct xftface_info *xftface_info,
+                   XftColor *fg, XftColor *bg)
 {
   if (xftface_info && face->gc == gc)
     {
@@ -92,9 +88,9 @@ xftfont_get_colors (FRAME_PTR f, struct face *face, GC gc, struct xftface_info *
   else
     {
       XGCValues xgcv;
-      int fg_done = 0, bg_done = 0;
+      bool fg_done = 0, bg_done = 0;
 
-      BLOCK_INPUT;
+      block_input ();
       XGetGCValues (FRAME_X_DISPLAY (f), gc,
                    GCForeground | GCBackground, &xgcv);
       if (xftface_info)
@@ -111,7 +107,7 @@ xftfont_get_colors (FRAME_PTR f, struct face *face, GC gc, struct xftface_info *
            *bg = xftface_info->xft_fg, bg_done = 1;
        }
 
-      if (fg_done + bg_done < 2)
+      if (! (fg_done & bg_done))
        {
          XColor colors[2];
 
@@ -132,30 +128,17 @@ xftfont_get_colors (FRAME_PTR f, struct face *face, GC gc, struct xftface_info *
              bg->color.blue = colors[1].blue;
            }
        }
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
 
-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;
 
 static Lisp_Object
-xftfont_list (Lisp_Object frame, Lisp_Object spec)
+xftfont_list (struct frame *f, Lisp_Object spec)
 {
-  Lisp_Object list = ftfont_driver.list (frame, spec), tail;
+  Lisp_Object list = ftfont_driver.list (f, spec), tail;
 
   for (tail = list; CONSP (tail); tail = XCDR (tail))
     ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
@@ -163,9 +146,9 @@ xftfont_list (Lisp_Object frame, Lisp_Object spec)
 }
 
 static Lisp_Object
-xftfont_match (Lisp_Object frame, Lisp_Object spec)
+xftfont_match (struct frame *f, Lisp_Object spec)
 {
-  Lisp_Object entity = ftfont_driver.match (frame, spec);
+  Lisp_Object entity = ftfont_driver.match (f, spec);
 
   if (! NILP (entity))
     ASET (entity, FONT_TYPE_INDEX, Qxft);
@@ -276,7 +259,7 @@ xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
 }
 
 static Lisp_Object
-xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
+xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
 {
   FcResult result;
   Display *display = FRAME_X_DISPLAY (f);
@@ -338,7 +321,7 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
   FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
 
 
-  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
@@ -359,12 +342,12 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
   xftfont = XftFontOpenPattern (display, match);
   if (!xftfont)
     {
-      UNBLOCK_INPUT;
+      unblock_input ();
       XftPatternDestroy (match);
       return Qnil;
     }
   ft_face = XftLockFace (xftfont);
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   /* We should not destroy PAT here because it is kept in XFTFONT and
      destroyed automatically when XFTFONT is closed.  */
@@ -383,14 +366,14 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
   ASET (font_object, FONT_FORMAT_INDEX,
        ftfont_font_format (xftfont->pattern, filename));
   font = XFONT_OBJECT (font_object);
-  font->pixel_size = pixel_size;
+  font->pixel_size = size;
   font->driver = &xftfont_driver;
   font->encoding_charset = font->repertory_charset = -1;
 
   xftfont_info = (struct xftfont_info *) font;
   xftfont_info->display = display;
-  xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
   xftfont_info->xftfont = xftfont;
+  xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
   /* This means that there's no need of transformation.  */
   xftfont_info->matrix.xx = 0;
   if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
@@ -401,8 +384,6 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
       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)))
     spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
   else
@@ -413,7 +394,7 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
       for (ch = 0; ch < 95; ch++)
        ascii_printable[ch] = ' ' + ch;
     }
-  BLOCK_INPUT;
+  block_input ();
 
   /* Unfortunately Xft doesn't provide a way to get minimum char
      width.  So, we set min_width to space_width.  */
@@ -439,7 +420,7 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
       XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
       font->average_width = (font->space_width + extents.xOff) / 95;
     }
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   font->ascent = xftfont->ascent;
   font->descent = xftfont->descent;
@@ -470,7 +451,7 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
       font->underline_thickness = 0;
     }
 #ifdef HAVE_LIBOTF
-  xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
+  xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
   xftfont_info->otf = NULL;
 #endif /* HAVE_LIBOTF */
   xftfont_info->ft_size = ft_face->size;
@@ -500,22 +481,34 @@ xftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
 }
 
 static void
-xftfont_close (FRAME_PTR f, struct font *font)
+xftfont_close (struct font *font)
 {
+  struct x_display_info *xdi;
   struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
 
 #ifdef HAVE_LIBOTF
   if (xftfont_info->otf)
-    OTF_close (xftfont_info->otf);
+    {
+      OTF_close (xftfont_info->otf);
+      xftfont_info->otf = NULL;
+    }
 #endif
-  BLOCK_INPUT;
-  XftUnlockFace (xftfont_info->xftfont);
-  XftFontClose (xftfont_info->display, xftfont_info->xftfont);
-  UNBLOCK_INPUT;
+
+  /* See comment in xfont_close.  */
+  if (xftfont_info->xftfont
+      && ((xdi = x_display_info_for_display (xftfont_info->display))
+         && xftfont_info->x_display_id == xdi->x_id))
+    {
+      block_input ();
+      XftUnlockFace (xftfont_info->xftfont);
+      XftFontClose (xftfont_info->display, xftfont_info->xftfont);
+      unblock_input ();
+      xftfont_info->xftfont = NULL;
+    }
 }
 
 static int
-xftfont_prepare_face (FRAME_PTR f, struct face *face)
+xftfont_prepare_face (struct frame *f, struct face *face)
 {
   struct xftface_info *xftface_info;
 
@@ -538,7 +531,7 @@ xftfont_prepare_face (FRAME_PTR f, struct face *face)
 }
 
 static void
-xftfont_done_face (FRAME_PTR f, struct face *face)
+xftfont_done_face (struct frame *f, struct face *face)
 {
   struct xftface_info *xftface_info;
 
@@ -595,10 +588,10 @@ xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct
   struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
   XGlyphInfo extents;
 
-  BLOCK_INPUT;
+  block_input ();
   XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
                   &extents);
-  UNBLOCK_INPUT;
+  unblock_input ();
   if (metrics)
     {
       metrics->lbearing = - extents.x;
@@ -611,18 +604,18 @@ xftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct
 }
 
 static XftDraw *
-xftfont_get_xft_draw (FRAME_PTR f)
+xftfont_get_xft_draw (struct frame *f)
 {
   XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
 
   if (! xft_draw)
     {
-      BLOCK_INPUT;
+      block_input ();
       xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
                               FRAME_X_WINDOW (f),
                               FRAME_X_VISUAL (f),
                               FRAME_X_COLORMAP (f));
-      UNBLOCK_INPUT;
+      unblock_input ();
       eassert (xft_draw != NULL);
       font_put_frame_data (f, &xftfont_driver, xft_draw);
     }
@@ -630,9 +623,10 @@ xftfont_get_xft_draw (FRAME_PTR f)
 }
 
 static int
-xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_background)
+xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
+              bool with_background)
 {
-  FRAME_PTR f = s->f;
+  struct frame *f = s->f;
   struct face *face = s->face;
   struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
   struct xftface_info *xftface_info = NULL;
@@ -646,7 +640,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_b
     xftface_info = (struct xftface_info *) face->extra;
   xftfont_get_colors (f, face, s->gc, xftface_info,
                      &fg, with_background ? &bg : NULL);
-  BLOCK_INPUT;
+  block_input ();
   if (s->num_clips > 0)
     XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
   else
@@ -667,7 +661,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, int with_b
   else
     XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
                   x, y, code, len);
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   return len;
 }
@@ -692,7 +686,7 @@ xftfont_shape (Lisp_Object lgstring)
 #endif
 
 static int
-xftfont_end_for_frame (FRAME_PTR f)
+xftfont_end_for_frame (struct frame *f)
 {
   XftDraw *xft_draw;
 
@@ -703,23 +697,25 @@ xftfont_end_for_frame (FRAME_PTR f)
 
   if (xft_draw)
     {
-      BLOCK_INPUT;
+      block_input ();
       XftDrawDestroy (xft_draw);
-      UNBLOCK_INPUT;
+      unblock_input ();
       font_put_frame_data (f, &xftfont_driver, NULL);
     }
   return 0;
 }
 
-static int
-xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object, Lisp_Object entity)
+static bool
+xftfont_cached_font_ok (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;
+  bool ok = 0;
+  int i1, i2, r1, r2;
 
   xftfont_add_rendering_parameters (pat, entity);
   XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);