root/src/xftfont.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xftfont_get_colors
  2. xftfont_list
  3. xftfont_match
  4. xftfont_open
  5. xftfont_close
  6. xftfont_prepare_face
  7. xftfont_done_face
  8. xftfont_has_char
  9. xftfont_encode_char
  10. xftfont_text_extents
  11. xftfont_get_xft_draw
  12. xftfont_draw
  13. xftfont_shape
  14. xftfont_end_for_frame
  15. xftfont_drop_xrender_surfaces
  16. xftfont_cached_font_ok
  17. xfthbfont_list
  18. xfthbfont_match
  19. xfthbfont_begin_hb_font
  20. xfthbfont_end_hb_font
  21. syms_of_xftfont
  22. syms_of_xftfont_for_pdumper

     1 /* xftfont.c -- XFT font driver.
     2    Copyright (C) 2006-2023 Free Software Foundation, Inc.
     3    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
     4      National Institute of Advanced Industrial Science and Technology (AIST)
     5      Registration Number H13PRO009
     6 
     7 This file is part of GNU Emacs.
     8 
     9 GNU Emacs is free software: you can redistribute it and/or modify
    10 it under the terms of the GNU General Public License as published by
    11 the Free Software Foundation, either version 3 of the License, or (at
    12 your option) any later version.
    13 
    14 GNU Emacs is distributed in the hope that it will be useful,
    15 but WITHOUT ANY WARRANTY; without even the implied warranty of
    16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17 GNU General Public License for more details.
    18 
    19 You should have received a copy of the GNU General Public License
    20 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    21 
    22 #include <config.h>
    23 #include <X11/Xlib.h>
    24 #include <X11/Xft/Xft.h>
    25 
    26 #include "lisp.h"
    27 #include "xterm.h"
    28 #include "frame.h"
    29 #include "blockinput.h"
    30 #include "charset.h"
    31 #include "composite.h"
    32 #include "font.h"
    33 #include "ftfont.h"
    34 #include "pdumper.h"
    35 
    36 #ifdef HAVE_XRENDER
    37 #include <X11/extensions/Xrender.h>
    38 #endif
    39 
    40 #ifndef FC_LCD_FILTER
    41 /* Older fontconfig versions don't have FC_LCD_FILTER.  */
    42 # define FC_LCD_FILTER "lcdfilter"
    43 #endif
    44 
    45 
    46 /* Xft font driver.  */
    47 
    48 /* Structure pointed by (struct face *)->extra  */
    49 
    50 struct xftface_info
    51 {
    52   bool bg_allocated_p;
    53   bool fg_allocated_p;
    54   XftColor xft_fg;              /* color for face->foreground */
    55   XftColor xft_bg;              /* color for face->background */
    56 };
    57 
    58 /* Setup foreground and background colors of GC into FG and BG.  If
    59    XFTFACE_INFO is not NULL, reuse the colors in it if possible.  BG
    60    may be NULL.  Return whether or not colors were allocated in
    61    BG_ALLOCATED_P and FG_ALLOCATED_P.  */
    62 
    63 static void
    64 xftfont_get_colors (struct frame *f, struct face *face, GC gc,
    65                     struct xftface_info *xftface_info,
    66                     XftColor *fg, XftColor *bg,
    67                     bool *bg_allocated_p, bool *fg_allocated_p)
    68 {
    69   *bg_allocated_p = false;
    70   *fg_allocated_p = false;
    71 
    72   if (xftface_info && face->gc == gc)
    73     {
    74       *fg = xftface_info->xft_fg;
    75       if (bg)
    76         *bg = xftface_info->xft_bg;
    77     }
    78   else
    79     {
    80       XGCValues xgcv;
    81       bool fg_done = false, bg_done = false;
    82 
    83       block_input ();
    84       XGetGCValues (FRAME_X_DISPLAY (f), gc,
    85                     GCForeground | GCBackground, &xgcv);
    86       if (xftface_info)
    87         {
    88           if (xgcv.foreground == face->foreground)
    89             *fg = xftface_info->xft_fg, fg_done = true;
    90           else if (xgcv.foreground == face->background)
    91             *fg = xftface_info->xft_bg, fg_done = true;
    92           if (! bg)
    93             bg_done = true;
    94           else if (xgcv.background == face->background)
    95             *bg = xftface_info->xft_bg, bg_done = true;
    96           else if (xgcv.background == face->foreground)
    97             *bg = xftface_info->xft_fg, bg_done = true;
    98         }
    99 
   100       if (! (fg_done & bg_done))
   101         {
   102           XColor colors[2];
   103 
   104           colors[0].pixel = xgcv.foreground;
   105           if (bg)
   106             colors[1].pixel = xgcv.background;
   107           x_query_colors (f, colors, bg ? 2 : 1);
   108           fg->color.alpha = 0xFFFF;
   109           fg->color.red = colors[0].red;
   110           fg->color.green = colors[0].green;
   111           fg->color.blue = colors[0].blue;
   112 
   113           if (!XftColorAllocValue (FRAME_X_DISPLAY (f),
   114                                    FRAME_X_VISUAL (f),
   115                                    FRAME_X_COLORMAP (f),
   116                                    &fg->color, fg))
   117             /* This color should've been allocated when creating the
   118                GC.  */
   119             emacs_abort ();
   120           else
   121             *fg_allocated_p = true;
   122 
   123           if (bg)
   124             {
   125               bg->color.alpha = 0xFFFF;
   126               bg->color.red = colors[1].red;
   127               bg->color.green = colors[1].green;
   128               bg->color.blue = colors[1].blue;
   129 
   130               if (!XftColorAllocValue (FRAME_X_DISPLAY (f),
   131                                        FRAME_X_VISUAL (f),
   132                                        FRAME_X_COLORMAP (f),
   133                                        &bg->color, bg))
   134                 emacs_abort ();
   135               else
   136                 *bg_allocated_p = true;
   137             }
   138         }
   139       unblock_input ();
   140     }
   141 }
   142 
   143 static Lisp_Object
   144 xftfont_list (struct frame *f, Lisp_Object spec)
   145 {
   146   return ftfont_list2 (f, spec, Qxft);
   147 }
   148 
   149 static Lisp_Object
   150 xftfont_match (struct frame *f, Lisp_Object spec)
   151 {
   152   return ftfont_match2 (f, spec, Qxft);
   153 }
   154 
   155 static FcChar8 ascii_printable[95];
   156 
   157 static Lisp_Object
   158 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
   159 {
   160   FcResult result;
   161   Display *display = FRAME_X_DISPLAY (f);
   162   Lisp_Object val, filename, font_object;
   163   FcPattern *pat = NULL, *match;
   164   struct font_info *xftfont_info = NULL;
   165   struct font *font;
   166   double size = 0;
   167   XftFont *xftfont = NULL;
   168   int spacing;
   169   XGlyphInfo extents;
   170   FT_Face ft_face;
   171   FcMatrix *matrix;
   172 
   173   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
   174   if (! CONSP (val))
   175     return Qnil;
   176   val = XCDR (val);
   177   filename = XCAR (val);
   178   size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
   179   if (size == 0)
   180     size = pixel_size;
   181 
   182   block_input ();
   183 
   184   pat = ftfont_entity_pattern (entity, pixel_size);
   185   /* Substitute in values from X resources and XftDefaultSet.  */
   186   XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
   187   match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
   188   ftfont_fix_match (pat, match);
   189 
   190   FcPatternDestroy (pat);
   191   xftfont = XftFontOpenPattern (display, match);
   192   if (!xftfont)
   193     {
   194       unblock_input ();
   195       XftPatternDestroy (match);
   196       return Qnil;
   197     }
   198   ft_face = XftLockFace (xftfont);
   199   unblock_input ();
   200 
   201   /* We should not destroy PAT here because it is kept in XFTFONT and
   202      destroyed automatically when XFTFONT is closed.  */
   203   font_object = font_build_object (VECSIZE (struct font_info),
   204                                    AREF (entity, FONT_TYPE_INDEX),
   205                                    entity, size);
   206   ASET (font_object, FONT_FILE_INDEX, filename);
   207   font = XFONT_OBJECT (font_object);
   208   font->pixel_size = size;
   209 #ifdef HAVE_HARFBUZZ
   210   if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qxfthb))
   211     font->driver = &xfthbfont_driver;
   212   else
   213 #endif  /* HAVE_HARFBUZZ */
   214   font->driver = &xftfont_driver;
   215   font->encoding_charset = font->repertory_charset = -1;
   216 
   217   xftfont_info = (struct font_info *) font;
   218   xftfont_info->display = display;
   219   xftfont_info->xftfont = xftfont;
   220   xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
   221   /* This means that there's no need of transformation.  */
   222   xftfont_info->matrix.xx = 0;
   223   if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
   224       == FcResultMatch)
   225     {
   226       xftfont_info->matrix.xx = 0x10000L * matrix->xx;
   227       xftfont_info->matrix.yy = 0x10000L * matrix->yy;
   228       xftfont_info->matrix.xy = 0x10000L * matrix->xy;
   229       xftfont_info->matrix.yx = 0x10000L * matrix->yx;
   230     }
   231   if (FIXNUMP (AREF (entity, FONT_SPACING_INDEX)))
   232     spacing = XFIXNUM (AREF (entity, FONT_SPACING_INDEX));
   233   else
   234     spacing = FC_PROPORTIONAL;
   235   if (! ascii_printable[0])
   236     {
   237       int ch;
   238       for (ch = 0; ch < 95; ch++)
   239         ascii_printable[ch] = ' ' + ch;
   240     }
   241   block_input ();
   242 
   243   /* Unfortunately Xft doesn't provide a way to get minimum char
   244      width.  So, we set min_width to space_width.  */
   245 
   246   if (spacing != FC_PROPORTIONAL
   247 #ifdef FC_DUAL
   248       && spacing != FC_DUAL
   249 #endif  /* FC_DUAL */
   250 #ifdef FC_CHARCELL
   251       && spacing != FC_CHARCELL
   252 #endif  /* FC_CHARCELL */
   253       )
   254     {
   255       font->min_width = font->max_width = font->average_width
   256         = font->space_width = xftfont->max_advance_width;
   257       XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
   258     }
   259   else
   260     {
   261       XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
   262       font->min_width = font->max_width = font->space_width
   263         = extents.xOff;
   264       if (font->space_width <= 0)
   265         /* dirty workaround */
   266         font->space_width = pixel_size;
   267       XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
   268       font->average_width = (font->space_width + extents.xOff) / 95;
   269     }
   270   unblock_input ();
   271 
   272   font->ascent = xftfont->ascent;
   273   font->descent = xftfont->descent;
   274   /* The following workaround is unnecessary on most systems, and
   275      causes annoying differences in glyph height between regular and
   276      bold fonts (see bug#22383).  However, with some fonts, such as
   277      monaco, removing the workaround results in overlapping vertical
   278      space of a line, see bug#23360.  As long as the way to reconcile
   279      these opposites is not known, we provide a user option to work
   280      around the problem.  */
   281   if (pixel_size >= 5
   282       && xft_font_ascent_descent_override)
   283     {
   284       /* The above condition is a dirty workaround because
   285          XftTextExtents8 behaves strangely for some fonts
   286          (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
   287       if (font->ascent < extents.y)
   288         font->ascent = extents.y;
   289       if (font->descent < extents.height - extents.y)
   290         font->descent = extents.height - extents.y;
   291     }
   292   font->height = font->ascent + font->descent;
   293 
   294   if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) == 0)
   295     {
   296       int upEM = ft_face->units_per_EM;
   297 
   298       font->underline_position = -ft_face->underline_position * size / upEM;
   299       font->underline_thickness = ft_face->underline_thickness * size / upEM;
   300       if (font->underline_thickness > 2)
   301         font->underline_position -= font->underline_thickness / 2;
   302     }
   303   else
   304     {
   305       font->underline_position = -1;
   306       font->underline_thickness = 0;
   307     }
   308 #ifdef HAVE_LIBOTF
   309   xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
   310   xftfont_info->otf = NULL;
   311 #endif  /* HAVE_LIBOTF */
   312 #ifdef HAVE_HARFBUZZ
   313   xftfont_info->hb_font = NULL;
   314 #endif  /* HAVE_HARFBUZZ */
   315   xftfont_info->ft_size = ft_face->size;
   316 
   317   font->baseline_offset = 0;
   318   font->relative_compose = 0;
   319   font->default_ascent = 0;
   320   font->vertical_centering = false;
   321 #ifdef FT_BDF_H
   322   if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
   323     {
   324       BDF_PropertyRec rec;
   325 
   326       if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
   327           && rec.type == BDF_PROPERTY_TYPE_INTEGER)
   328         font->baseline_offset = rec.u.integer;
   329       if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
   330           && rec.type == BDF_PROPERTY_TYPE_INTEGER)
   331         font->relative_compose = rec.u.integer;
   332       if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
   333           && rec.type == BDF_PROPERTY_TYPE_INTEGER)
   334         font->default_ascent = rec.u.integer;
   335     }
   336 #endif
   337 
   338   return font_object;
   339 }
   340 
   341 static void
   342 xftfont_close (struct font *font)
   343 {
   344   struct x_display_info *xdi;
   345   struct font_info *xftfont_info = (struct font_info *) font;
   346 
   347 #ifdef HAVE_LIBOTF
   348   if (xftfont_info->otf)
   349     {
   350       OTF_close (xftfont_info->otf);
   351       xftfont_info->otf = NULL;
   352     }
   353 #endif
   354 #ifdef HAVE_HARFBUZZ
   355   if (xftfont_info->hb_font)
   356     {
   357       hb_font_destroy (xftfont_info->hb_font);
   358       xftfont_info->hb_font = NULL;
   359     }
   360 #endif
   361 
   362   /* See comment in xfont_close.  */
   363   if (xftfont_info->xftfont
   364       && ((xdi = x_display_info_for_display (xftfont_info->display))
   365           && xftfont_info->x_display_id == xdi->x_id))
   366     {
   367       block_input ();
   368       XftUnlockFace (xftfont_info->xftfont);
   369       XftFontClose (xftfont_info->display, xftfont_info->xftfont);
   370       unblock_input ();
   371       xftfont_info->xftfont = NULL;
   372     }
   373 }
   374 
   375 static void
   376 xftfont_prepare_face (struct frame *f, struct face *face)
   377 {
   378   struct xftface_info *xftface_info;
   379 
   380 #if false
   381   /* This doesn't work if face->ascii_face doesn't use an Xft font. */
   382   if (face != face->ascii_face)
   383     {
   384       face->extra = face->ascii_face->extra;
   385       return;
   386     }
   387 #endif
   388 
   389   xftface_info = xzalloc (sizeof *xftface_info);
   390   xftfont_get_colors (f, face, face->gc, NULL,
   391                       &xftface_info->xft_fg,
   392                       &xftface_info->xft_bg,
   393                       &xftface_info->bg_allocated_p,
   394                       &xftface_info->fg_allocated_p);
   395   face->extra = xftface_info;
   396 }
   397 
   398 static void
   399 xftfont_done_face (struct frame *f, struct face *face)
   400 {
   401   struct xftface_info *xftface_info;
   402 
   403 #if false
   404   /* This doesn't work if face->ascii_face doesn't use an Xft font. */
   405   if (face != face->ascii_face
   406       || ! face->extra)
   407     return;
   408 #endif
   409 
   410   xftface_info = (struct xftface_info *) face->extra;
   411   if (xftface_info)
   412     {
   413       if (xftface_info->fg_allocated_p)
   414         XftColorFree (FRAME_X_DISPLAY (f),
   415                       FRAME_X_VISUAL (f),
   416                       FRAME_X_COLORMAP (f),
   417                       &xftface_info->xft_fg);
   418 
   419       if (xftface_info->bg_allocated_p)
   420         XftColorFree (FRAME_X_DISPLAY (f),
   421                       FRAME_X_VISUAL (f),
   422                       FRAME_X_COLORMAP (f),
   423                       &xftface_info->xft_bg);
   424 
   425       xfree (xftface_info);
   426       face->extra = NULL;
   427     }
   428 }
   429 
   430 static int
   431 xftfont_has_char (Lisp_Object font, int c)
   432 {
   433   struct font_info *xftfont_info;
   434   struct charset *cs = NULL;
   435 
   436   if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
   437       && charset_jisx0208 >= 0)
   438     cs = CHARSET_FROM_ID (charset_jisx0208);
   439   else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
   440       && charset_ksc5601 >= 0)
   441     cs = CHARSET_FROM_ID (charset_ksc5601);
   442   if (cs)
   443     return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
   444 
   445   if (FONT_ENTITY_P (font))
   446     return ftfont_has_char (font, c);
   447   xftfont_info = (struct font_info *) XFONT_OBJECT (font);
   448   return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
   449                          (FcChar32) c) == FcTrue);
   450 }
   451 
   452 static unsigned
   453 xftfont_encode_char (struct font *font, int c)
   454 {
   455   struct font_info *xftfont_info = (struct font_info *) font;
   456   unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
   457                                 (FcChar32) c);
   458 
   459   return (code ? code : FONT_INVALID_CODE);
   460 }
   461 
   462 static void
   463 xftfont_text_extents (struct font *font, const unsigned int *code,
   464                       int nglyphs, struct font_metrics *metrics)
   465 {
   466   struct font_info *xftfont_info = (struct font_info *) font;
   467   XGlyphInfo extents;
   468 
   469   block_input ();
   470   XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
   471                    &extents);
   472   unblock_input ();
   473 
   474   metrics->lbearing = - extents.x;
   475   metrics->rbearing = - extents.x + extents.width;
   476   metrics->width = extents.xOff;
   477   metrics->ascent = extents.y;
   478   metrics->descent = extents.height - extents.y;
   479 }
   480 
   481 static XftDraw *
   482 xftfont_get_xft_draw (struct frame *f)
   483 {
   484   XftDraw *xft_draw = font_get_frame_data (f, Qxft);
   485 
   486   if (! xft_draw)
   487     {
   488       block_input ();
   489       xft_draw = XftDrawCreate (FRAME_X_DISPLAY (f),
   490                                 FRAME_X_DRAWABLE (f),
   491                                 FRAME_X_VISUAL (f),
   492                                 FRAME_X_COLORMAP (f));
   493       unblock_input ();
   494       eassert (xft_draw != NULL);
   495       font_put_frame_data (f, Qxft, xft_draw);
   496     }
   497   return xft_draw;
   498 }
   499 
   500 static int
   501 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
   502               bool with_background)
   503 {
   504   block_input ();
   505 
   506   struct frame *f = s->f;
   507   struct face *face = s->face;
   508   struct font_info *xftfont_info = (struct font_info *) s->font;
   509   struct xftface_info *xftface_info = NULL;
   510   XftDraw *xft_draw = xftfont_get_xft_draw (f);
   511   FT_UInt *code;
   512   XftColor fg, bg;
   513   bool bg_allocated_p, fg_allocated_p;
   514   int len = to - from;
   515   int i;
   516 
   517   if (s->font == face->font)
   518     xftface_info = (struct xftface_info *) face->extra;
   519   xftfont_get_colors (f, face, s->gc, xftface_info,
   520                       &fg, with_background ? &bg : NULL,
   521                       &bg_allocated_p, &fg_allocated_p);
   522 
   523   if (s->num_clips > 0)
   524     XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
   525   else
   526     XftDrawSetClip (xft_draw, NULL);
   527 
   528   if (with_background)
   529     {
   530       int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
   531 
   532       /* Font's global height and ascent values might be
   533          preposterously large for some fonts.  We fix here the case
   534          when those fonts are used for display of glyphless
   535          characters, because drawing background with font dimensions
   536          in those cases makes the display illegible.  There's only one
   537          more call to the draw method with with_background set to
   538          true, and that's in x_draw_glyph_string_foreground, when
   539          drawing the cursor, where we have no such heuristics
   540          available.  FIXME.  */
   541       if (s->first_glyph->type == GLYPHLESS_GLYPH
   542           && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
   543               || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
   544         height = ascent =
   545           s->first_glyph->slice.glyphless.lower_yoff
   546           - s->first_glyph->slice.glyphless.upper_yoff;
   547 
   548 #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
   549       if (with_background
   550           && FRAME_DISPLAY_INFO (s->f)->alpha_bits
   551           && FRAME_CHECK_XR_VERSION (s->f, 0, 2))
   552         {
   553           x_xr_ensure_picture (s->f);
   554 
   555           if (FRAME_X_PICTURE (s->f) != None)
   556             {
   557               XRenderColor xc;
   558               int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
   559 
   560               if (s->num_clips > 0)
   561                 XRenderSetPictureClipRectangles (FRAME_X_DISPLAY (s->f),
   562                                                  FRAME_X_PICTURE (s->f),
   563                                                  0, 0, s->clip, s->num_clips);
   564               else
   565                 x_xr_reset_ext_clip (f);
   566               x_xrender_color_from_gc_background (s->f, s->gc, &xc, s->hl != DRAW_CURSOR);
   567               XRenderFillRectangle (FRAME_X_DISPLAY (s->f),
   568                                     PictOpSrc, FRAME_X_PICTURE (s->f),
   569                                     &xc, x, y - ascent, s->width, height);
   570               x_xr_reset_ext_clip (f);
   571               x_mark_frame_dirty (s->f);
   572 
   573               with_background = false;
   574             }
   575           else
   576             XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
   577         }
   578       else
   579 #endif
   580         XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
   581     }
   582   code = alloca (sizeof (FT_UInt) * len);
   583   for (i = 0; i < len; i++)
   584     code[i] = s->char2b[from + i];
   585 
   586   if (s->padding_p)
   587     for (i = 0; i < len; i++)
   588       XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
   589                      x + i, y, code + i, 1);
   590   else
   591     XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
   592                    x, y, code, len);
   593   /* Need to explicitly mark the frame dirty because we didn't call
   594      FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
   595      XftDraw structure.  */
   596   x_mark_frame_dirty (f);
   597 
   598   if (bg_allocated_p)
   599     XftColorFree (FRAME_X_DISPLAY (f),
   600                   FRAME_X_VISUAL (f),
   601                   FRAME_X_COLORMAP (f),
   602                   &bg);
   603 
   604   if (fg_allocated_p)
   605     XftColorFree (FRAME_X_DISPLAY (f),
   606                   FRAME_X_VISUAL (f),
   607                   FRAME_X_COLORMAP (f),
   608                   &fg);
   609 
   610   unblock_input ();
   611   return len;
   612 }
   613 
   614 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
   615 static Lisp_Object
   616 xftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
   617 {
   618   struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
   619   struct font_info *xftfont_info = (struct font_info *) font;
   620   FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
   621   xftfont_info->ft_size = ft_face->size;
   622   Lisp_Object val = ftfont_shape (lgstring, direction);
   623   XftUnlockFace (xftfont_info->xftfont);
   624   return val;
   625 }
   626 #endif
   627 
   628 static int
   629 xftfont_end_for_frame (struct frame *f)
   630 {
   631   /* XftDrawDestroy tries to access dpyinfo->display, which could've
   632      been destroyed by now, causing Emacs to crash.  The alternative
   633      is to leak the XftDraw, but that's better than a crash.  */
   634   if (!FRAME_X_DISPLAY (f))
   635     return 0;
   636 
   637   block_input ();
   638   XftDraw *xft_draw;
   639 
   640   xft_draw = font_get_frame_data (f, Qxft);
   641   if (xft_draw)
   642     {
   643       block_input ();
   644       XftDrawDestroy (xft_draw);
   645       unblock_input ();
   646       font_put_frame_data (f, Qxft, NULL);
   647     }
   648   unblock_input ();
   649   return 0;
   650 }
   651 
   652 /* When using X double buffering, the XRender surfaces we create seem
   653    to become useless once the window acting as the front buffer is
   654    resized for an unknown reason (X server bug?), so recreate it on
   655    ConfigureNotify and in some other cases.  */
   656 
   657 #ifdef HAVE_XDBE
   658 static void
   659 xftfont_drop_xrender_surfaces (struct frame *f)
   660 {
   661   if (FRAME_X_DOUBLE_BUFFERED_P (f))
   662     {
   663       block_input ();
   664       xftfont_end_for_frame (f);
   665       unblock_input ();
   666     }
   667 }
   668 #endif
   669 
   670 static bool
   671 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
   672                         Lisp_Object entity)
   673 {
   674   struct font_info *info = (struct font_info *) XFONT_OBJECT (font_object);
   675   FcPattern *oldpat = info->xftfont->pattern;
   676   Display *display = FRAME_X_DISPLAY (f);
   677   FcPattern *pat = FcPatternCreate ();
   678   FcBool b1, b2;
   679   bool ok = false;
   680   int i1, i2, r1, r2;
   681 
   682   ftfont_add_rendering_parameters (pat, entity);
   683   XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
   684 
   685   r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
   686   r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
   687   if (r1 != r2 || b1 != b2) goto out;
   688   r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
   689   r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
   690   if (r1 != r2 || b1 != b2) goto out;
   691   r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
   692   r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
   693   if (r1 != r2 || b1 != b2) goto out;
   694 #ifdef FC_EMBOLDEN
   695   r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
   696   r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
   697   if (r1 != r2 || b1 != b2) goto out;
   698 #endif
   699   r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
   700   r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
   701   if (r1 != r2 || i1 != i2) goto out;
   702   r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
   703   r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
   704   if (r1 != r2 || i1 != i2) goto out;
   705   r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
   706   r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
   707   if (r1 != r2 || i1 != i2) goto out;
   708 
   709   ok = true;
   710  out:
   711   FcPatternDestroy (pat);
   712   return ok;
   713 }
   714 
   715 #ifdef HAVE_HARFBUZZ
   716 
   717 static Lisp_Object
   718 xfthbfont_list (struct frame *f, Lisp_Object spec)
   719 {
   720   return ftfont_list2 (f, spec, Qxfthb);
   721 }
   722 
   723 static Lisp_Object
   724 xfthbfont_match (struct frame *f, Lisp_Object spec)
   725 {
   726   return ftfont_match2 (f, spec, Qxfthb);
   727 }
   728 
   729 static hb_font_t *
   730 xfthbfont_begin_hb_font (struct font *font, double *position_unit)
   731 {
   732   struct font_info *xftfont_info = (struct font_info *) font;
   733   FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
   734 
   735   xftfont_info->ft_size = ft_face->size;
   736 
   737   return fthbfont_begin_hb_font (font, position_unit);
   738 }
   739 
   740 static void
   741 xfthbfont_end_hb_font (struct font *font, hb_font_t *hb_font)
   742 {
   743   struct font_info *xftfont_info = (struct font_info *) font;
   744 
   745   XftUnlockFace (xftfont_info->xftfont);
   746 }
   747 
   748 #endif  /* HAVE_HARFBUZZ */
   749 
   750 static void syms_of_xftfont_for_pdumper (void);
   751 
   752 struct font_driver const xftfont_driver =
   753   {
   754     /* We can't draw a text without device dependent functions.  */
   755     .type = LISPSYM_INITIALLY (Qxft),
   756     .get_cache = xfont_get_cache,
   757     .list = xftfont_list,
   758     .match = xftfont_match,
   759     .list_family = ftfont_list_family,
   760     .open_font = xftfont_open,
   761     .close_font = xftfont_close,
   762     .prepare_face = xftfont_prepare_face,
   763     .done_face = xftfont_done_face,
   764     .has_char = xftfont_has_char,
   765     .encode_char = xftfont_encode_char,
   766     .text_extents = xftfont_text_extents,
   767     .draw = xftfont_draw,
   768     .get_bitmap = ftfont_get_bitmap,
   769     .anchor_point = ftfont_anchor_point,
   770 #ifdef HAVE_LIBOTF
   771     .otf_capability = ftfont_otf_capability,
   772 #endif
   773     .end_for_frame = xftfont_end_for_frame,
   774 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
   775     .shape = xftfont_shape,
   776 #endif
   777 #if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
   778     .get_variation_glyphs = ftfont_variation_glyphs,
   779 #endif
   780     .filter_properties = ftfont_filter_properties,
   781     .cached_font_ok = xftfont_cached_font_ok,
   782     .combining_capability = ftfont_combining_capability,
   783 #ifdef HAVE_XDBE
   784     .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
   785 #endif
   786   };
   787 #ifdef HAVE_HARFBUZZ
   788 struct font_driver xfthbfont_driver;
   789 #endif  /* HAVE_HARFBUZZ */
   790 
   791 void
   792 syms_of_xftfont (void)
   793 {
   794   DEFSYM (Qxft, "xft");
   795 #ifdef HAVE_HARFBUZZ
   796   DEFSYM (Qxfthb, "xfthb");
   797   Fput (Qxft, Qfont_driver_superseded_by, Qxfthb);
   798 #endif  /* HAVE_HARFBUZZ */
   799 
   800   DEFVAR_BOOL ("xft-font-ascent-descent-override",
   801                xft_font_ascent_descent_override,
   802                doc:  /* Non-nil means override the ascent and descent values for Xft font driver.
   803 This is needed with some fonts to correct vertical overlap of glyphs.  */);
   804   xft_font_ascent_descent_override = 0;
   805 
   806   DEFVAR_LISP ("xft-color-font-whitelist", Vxft_color_font_whitelist,
   807     doc: /* List of "color" font families that don't actually have color glyphs.
   808 Some fonts (such as Source Code Pro) are reported as color fonts, but
   809 do not actually have glyphs with colors that can cause Xft crashes.
   810 
   811 The font families in this list will not be ignored when
   812 `xft-ignore-color-fonts' is non-nil.  */);
   813   Vxft_color_font_whitelist = list1 (build_pure_c_string ("Source Code Pro"));
   814 
   815   pdumper_do_now_and_after_load (syms_of_xftfont_for_pdumper);
   816 }
   817 
   818 static void
   819 syms_of_xftfont_for_pdumper (void)
   820 {
   821   register_font_driver (&xftfont_driver, NULL);
   822 #ifdef HAVE_HARFBUZZ
   823   xfthbfont_driver = xftfont_driver;
   824   xfthbfont_driver.type = Qxfthb;
   825   xfthbfont_driver.list = xfthbfont_list;
   826   xfthbfont_driver.match = xfthbfont_match;
   827   xfthbfont_driver.otf_capability = hbfont_otf_capability;
   828   xfthbfont_driver.shape = hbfont_shape;
   829   xfthbfont_driver.combining_capability = hbfont_combining_capability;
   830   xfthbfont_driver.begin_hb_font = xfthbfont_begin_hb_font;
   831   xfthbfont_driver.end_hb_font = xfthbfont_end_hb_font;
   832   register_font_driver (&xfthbfont_driver, NULL);
   833 #endif  /* HAVE_HARFBUZZ */
   834 }

/* [<][>][^][v][top][bottom][index][help] */