1 /* xftfont.c -- XFT font driver.
2    Copyright (C) 2006-2021 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 #ifndef FC_LCD_FILTER
37 /* Older fontconfig versions don't have FC_LCD_FILTER.  */
38 # define FC_LCD_FILTER "lcdfilter"
39 #endif
40 
41 
42 /* Xft font driver.  */
43 
44 /* Structure pointed by (struct face *)->extra  */
45 
46 struct xftface_info
47 {
48   XftColor xft_fg;		/* color for face->foreground */
49   XftColor xft_bg;		/* color for face->background */
50 };
51 
52 /* Setup foreground and background colors of GC into FG and BG.  If
53    XFTFACE_INFO is not NULL, reuse the colors in it if possible.  BG
54    may be NULL.  */
55 
56 static void
xftfont_get_colors(struct frame * f,struct face * face,GC gc,struct xftface_info * xftface_info,XftColor * fg,XftColor * bg)57 xftfont_get_colors (struct frame *f, struct face *face, GC gc,
58 		    struct xftface_info *xftface_info,
59 		    XftColor *fg, XftColor *bg)
60 {
61   if (xftface_info && face->gc == gc)
62     {
63       *fg = xftface_info->xft_fg;
64       if (bg)
65 	*bg = xftface_info->xft_bg;
66     }
67   else
68     {
69       XGCValues xgcv;
70       bool fg_done = false, bg_done = false;
71 
72       block_input ();
73       XGetGCValues (FRAME_X_DISPLAY (f), gc,
74 		    GCForeground | GCBackground, &xgcv);
75       if (xftface_info)
76 	{
77 	  if (xgcv.foreground == face->foreground)
78 	    *fg = xftface_info->xft_fg, fg_done = true;
79 	  else if (xgcv.foreground == face->background)
80 	    *fg = xftface_info->xft_bg, fg_done = true;
81 	  if (! bg)
82 	    bg_done = true;
83 	  else if (xgcv.background == face->background)
84 	    *bg = xftface_info->xft_bg, bg_done = true;
85 	  else if (xgcv.background == face->foreground)
86 	    *bg = xftface_info->xft_fg, bg_done = true;
87 	}
88 
89       if (! (fg_done & bg_done))
90 	{
91 	  XColor colors[2];
92 
93 	  colors[0].pixel = fg->pixel = xgcv.foreground;
94 	  if (bg)
95 	    colors[1].pixel = bg->pixel = xgcv.background;
96 	  x_query_colors (f, colors, bg ? 2 : 1);
97 	  fg->color.alpha = 0xFFFF;
98 	  fg->color.red = colors[0].red;
99 	  fg->color.green = colors[0].green;
100 	  fg->color.blue = colors[0].blue;
101 	  if (bg)
102 	    {
103 	      bg->color.alpha = 0xFFFF;
104 	      bg->color.red = colors[1].red;
105 	      bg->color.green = colors[1].green;
106 	      bg->color.blue = colors[1].blue;
107 	    }
108 	}
109       unblock_input ();
110     }
111 }
112 
113 static Lisp_Object
xftfont_list(struct frame * f,Lisp_Object spec)114 xftfont_list (struct frame *f, Lisp_Object spec)
115 {
116   return ftfont_list2 (f, spec, Qxft);
117 }
118 
119 static Lisp_Object
xftfont_match(struct frame * f,Lisp_Object spec)120 xftfont_match (struct frame *f, Lisp_Object spec)
121 {
122   return ftfont_match2 (f, spec, Qxft);
123 }
124 
125 static FcChar8 ascii_printable[95];
126 
127 static Lisp_Object
xftfont_open(struct frame * f,Lisp_Object entity,int pixel_size)128 xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
129 {
130   FcResult result;
131   Display *display = FRAME_X_DISPLAY (f);
132   Lisp_Object val, filename, font_object;
133   FcPattern *pat = NULL, *match;
134   struct font_info *xftfont_info = NULL;
135   struct font *font;
136   double size = 0;
137   XftFont *xftfont = NULL;
138   int spacing;
139   XGlyphInfo extents;
140   FT_Face ft_face;
141   FcMatrix *matrix;
142 
143   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
144   if (! CONSP (val))
145     return Qnil;
146   val = XCDR (val);
147   filename = XCAR (val);
148   size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
149   if (size == 0)
150     size = pixel_size;
151 
152   block_input ();
153 
154   pat = ftfont_entity_pattern (entity, pixel_size);
155   /* Substitute in values from X resources and XftDefaultSet.  */
156   XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
157   match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
158   ftfont_fix_match (pat, match);
159 
160   FcPatternDestroy (pat);
161   xftfont = XftFontOpenPattern (display, match);
162   if (!xftfont)
163     {
164       unblock_input ();
165       XftPatternDestroy (match);
166       return Qnil;
167     }
168   ft_face = XftLockFace (xftfont);
169   unblock_input ();
170 
171   /* We should not destroy PAT here because it is kept in XFTFONT and
172      destroyed automatically when XFTFONT is closed.  */
173   font_object = font_build_object (VECSIZE (struct font_info),
174 				   AREF (entity, FONT_TYPE_INDEX),
175 				   entity, size);
176   ASET (font_object, FONT_FILE_INDEX, filename);
177   font = XFONT_OBJECT (font_object);
178   font->pixel_size = size;
179 #ifdef HAVE_HARFBUZZ
180   if (EQ (AREF (font_object, FONT_TYPE_INDEX), Qxfthb))
181     font->driver = &xfthbfont_driver;
182   else
183 #endif	/* HAVE_HARFBUZZ */
184   font->driver = &xftfont_driver;
185   font->encoding_charset = font->repertory_charset = -1;
186 
187   xftfont_info = (struct font_info *) font;
188   xftfont_info->display = display;
189   xftfont_info->xftfont = xftfont;
190   xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
191   /* This means that there's no need of transformation.  */
192   xftfont_info->matrix.xx = 0;
193   if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
194       == FcResultMatch)
195     {
196       xftfont_info->matrix.xx = 0x10000L * matrix->xx;
197       xftfont_info->matrix.yy = 0x10000L * matrix->yy;
198       xftfont_info->matrix.xy = 0x10000L * matrix->xy;
199       xftfont_info->matrix.yx = 0x10000L * matrix->yx;
200     }
201   if (FIXNUMP (AREF (entity, FONT_SPACING_INDEX)))
202     spacing = XFIXNUM (AREF (entity, FONT_SPACING_INDEX));
203   else
204     spacing = FC_PROPORTIONAL;
205   if (! ascii_printable[0])
206     {
207       int ch;
208       for (ch = 0; ch < 95; ch++)
209 	ascii_printable[ch] = ' ' + ch;
210     }
211   block_input ();
212 
213   /* Unfortunately Xft doesn't provide a way to get minimum char
214      width.  So, we set min_width to space_width.  */
215 
216   if (spacing != FC_PROPORTIONAL
217 #ifdef FC_DUAL
218       && spacing != FC_DUAL
219 #endif	/* FC_DUAL */
220 #ifdef FC_CHARCELL
221       && spacing != FC_CHARCELL
222 #endif	/* FC_CHARCELL */
223       )
224     {
225       font->min_width = font->max_width = font->average_width
226 	= font->space_width = xftfont->max_advance_width;
227       XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
228     }
229   else
230     {
231       XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
232       font->min_width = font->max_width = font->space_width
233 	= extents.xOff;
234       if (font->space_width <= 0)
235 	/* dirty workaround */
236 	font->space_width = pixel_size;
237       XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
238       font->average_width = (font->space_width + extents.xOff) / 95;
239     }
240   unblock_input ();
241 
242   font->ascent = xftfont->ascent;
243   font->descent = xftfont->descent;
244   /* The following workaround is unnecessary on most systems, and
245      causes annoying differences in glyph height between regular and
246      bold fonts (see bug#22383).  However, with some fonts, such as
247      monaco, removing the workaround results in overlapping vertical
248      space of a line, see bug#23360.  As long as the way to reconcile
249      these opposites is not known, we provide a user option to work
250      around the problem.  */
251   if (pixel_size >= 5
252       && xft_font_ascent_descent_override)
253     {
254       /* The above condition is a dirty workaround because
255 	 XftTextExtents8 behaves strangely for some fonts
256 	 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
257       if (font->ascent < extents.y)
258 	font->ascent = extents.y;
259       if (font->descent < extents.height - extents.y)
260 	font->descent = extents.height - extents.y;
261     }
262   font->height = font->ascent + font->descent;
263 
264   if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) == 0)
265     {
266       int upEM = ft_face->units_per_EM;
267 
268       font->underline_position = -ft_face->underline_position * size / upEM;
269       font->underline_thickness = ft_face->underline_thickness * size / upEM;
270       if (font->underline_thickness > 2)
271 	font->underline_position -= font->underline_thickness / 2;
272     }
273   else
274     {
275       font->underline_position = -1;
276       font->underline_thickness = 0;
277     }
278 #ifdef HAVE_LIBOTF
279   xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
280   xftfont_info->otf = NULL;
281 #endif	/* HAVE_LIBOTF */
282 #ifdef HAVE_HARFBUZZ
283   xftfont_info->hb_font = NULL;
284 #endif	/* HAVE_HARFBUZZ */
285   xftfont_info->ft_size = ft_face->size;
286 
287   font->baseline_offset = 0;
288   font->relative_compose = 0;
289   font->default_ascent = 0;
290   font->vertical_centering = false;
291 #ifdef FT_BDF_H
292   if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
293     {
294       BDF_PropertyRec rec;
295 
296       if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
297 	  && rec.type == BDF_PROPERTY_TYPE_INTEGER)
298 	font->baseline_offset = rec.u.integer;
299       if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
300 	  && rec.type == BDF_PROPERTY_TYPE_INTEGER)
301 	font->relative_compose = rec.u.integer;
302       if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
303 	  && rec.type == BDF_PROPERTY_TYPE_INTEGER)
304 	font->default_ascent = rec.u.integer;
305     }
306 #endif
307 
308   return font_object;
309 }
310 
311 static void
xftfont_close(struct font * font)312 xftfont_close (struct font *font)
313 {
314   struct x_display_info *xdi;
315   struct font_info *xftfont_info = (struct font_info *) font;
316 
317 #ifdef HAVE_LIBOTF
318   if (xftfont_info->otf)
319     {
320       OTF_close (xftfont_info->otf);
321       xftfont_info->otf = NULL;
322     }
323 #endif
324 #ifdef HAVE_HARFBUZZ
325   if (xftfont_info->hb_font)
326     {
327       hb_font_destroy (xftfont_info->hb_font);
328       xftfont_info->hb_font = NULL;
329     }
330 #endif
331 
332   /* See comment in xfont_close.  */
333   if (xftfont_info->xftfont
334       && ((xdi = x_display_info_for_display (xftfont_info->display))
335 	  && xftfont_info->x_display_id == xdi->x_id))
336     {
337       block_input ();
338       XftUnlockFace (xftfont_info->xftfont);
339       XftFontClose (xftfont_info->display, xftfont_info->xftfont);
340       unblock_input ();
341       xftfont_info->xftfont = NULL;
342     }
343 }
344 
345 static void
xftfont_prepare_face(struct frame * f,struct face * face)346 xftfont_prepare_face (struct frame *f, struct face *face)
347 {
348   struct xftface_info *xftface_info;
349 
350 #if false
351   /* This doesn't work if face->ascii_face doesn't use an Xft font. */
352   if (face != face->ascii_face)
353     {
354       face->extra = face->ascii_face->extra;
355       return;
356     }
357 #endif
358 
359   xftface_info = xmalloc (sizeof *xftface_info);
360   xftfont_get_colors (f, face, face->gc, NULL,
361 		      &xftface_info->xft_fg, &xftface_info->xft_bg);
362   face->extra = xftface_info;
363 }
364 
365 static void
xftfont_done_face(struct frame * f,struct face * face)366 xftfont_done_face (struct frame *f, struct face *face)
367 {
368   struct xftface_info *xftface_info;
369 
370 #if false
371   /* This doesn't work if face->ascii_face doesn't use an Xft font. */
372   if (face != face->ascii_face
373       || ! face->extra)
374     return;
375 #endif
376 
377   xftface_info = (struct xftface_info *) face->extra;
378   if (xftface_info)
379     {
380       xfree (xftface_info);
381       face->extra = NULL;
382     }
383 }
384 
385 static int
xftfont_has_char(Lisp_Object font,int c)386 xftfont_has_char (Lisp_Object font, int c)
387 {
388   struct font_info *xftfont_info;
389   struct charset *cs = NULL;
390 
391   if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
392       && charset_jisx0208 >= 0)
393     cs = CHARSET_FROM_ID (charset_jisx0208);
394   else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
395       && charset_ksc5601 >= 0)
396     cs = CHARSET_FROM_ID (charset_ksc5601);
397   if (cs)
398     return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
399 
400   if (FONT_ENTITY_P (font))
401     return ftfont_has_char (font, c);
402   xftfont_info = (struct font_info *) XFONT_OBJECT (font);
403   return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
404 			 (FcChar32) c) == FcTrue);
405 }
406 
407 static unsigned
xftfont_encode_char(struct font * font,int c)408 xftfont_encode_char (struct font *font, int c)
409 {
410   struct font_info *xftfont_info = (struct font_info *) font;
411   unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
412 				(FcChar32) c);
413 
414   return (code ? code : FONT_INVALID_CODE);
415 }
416 
417 static void
xftfont_text_extents(struct font * font,const unsigned int * code,int nglyphs,struct font_metrics * metrics)418 xftfont_text_extents (struct font *font, const unsigned int *code,
419 		      int nglyphs, struct font_metrics *metrics)
420 {
421   struct font_info *xftfont_info = (struct font_info *) font;
422   XGlyphInfo extents;
423 
424   block_input ();
425   XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
426 		   &extents);
427   unblock_input ();
428 
429   metrics->lbearing = - extents.x;
430   metrics->rbearing = - extents.x + extents.width;
431   metrics->width = extents.xOff;
432   metrics->ascent = extents.y;
433   metrics->descent = extents.height - extents.y;
434 }
435 
436 static XftDraw *
xftfont_get_xft_draw(struct frame * f)437 xftfont_get_xft_draw (struct frame *f)
438 {
439   XftDraw *xft_draw = font_get_frame_data (f, Qxft);
440 
441   if (! xft_draw)
442     {
443       block_input ();
444       xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
445                                FRAME_X_DRAWABLE (f),
446 			       FRAME_X_VISUAL (f),
447 			       FRAME_X_COLORMAP (f));
448       unblock_input ();
449       eassert (xft_draw != NULL);
450       font_put_frame_data (f, Qxft, xft_draw);
451     }
452   return xft_draw;
453 }
454 
455 static int
xftfont_draw(struct glyph_string * s,int from,int to,int x,int y,bool with_background)456 xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
457               bool with_background)
458 {
459   block_input ();
460 
461   struct frame *f = s->f;
462   struct face *face = s->face;
463   struct font_info *xftfont_info = (struct font_info *) s->font;
464   struct xftface_info *xftface_info = NULL;
465   XftDraw *xft_draw = xftfont_get_xft_draw (f);
466   FT_UInt *code;
467   XftColor fg, bg;
468   int len = to - from;
469   int i;
470 
471   if (s->font == face->font)
472     xftface_info = (struct xftface_info *) face->extra;
473   xftfont_get_colors (f, face, s->gc, xftface_info,
474 		      &fg, with_background ? &bg : NULL);
475   if (s->num_clips > 0)
476     XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
477   else
478     XftDrawSetClip (xft_draw, NULL);
479 
480   if (with_background)
481     {
482       int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
483 
484       /* Font's global height and ascent values might be
485 	 preposterously large for some fonts.  We fix here the case
486 	 when those fonts are used for display of glyphless
487 	 characters, because drawing background with font dimensions
488 	 in those cases makes the display illegible.  There's only one
489 	 more call to the draw method with with_background set to
490 	 true, and that's in x_draw_glyph_string_foreground, when
491 	 drawing the cursor, where we have no such heuristics
492 	 available.  FIXME.  */
493       if (s->first_glyph->type == GLYPHLESS_GLYPH
494 	  && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
495 	      || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
496 	height = ascent =
497 	  s->first_glyph->slice.glyphless.lower_yoff
498 	  - s->first_glyph->slice.glyphless.upper_yoff;
499       XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
500     }
501   code = alloca (sizeof (FT_UInt) * len);
502   for (i = 0; i < len; i++)
503     code[i] = s->char2b[from + i];
504 
505   if (s->padding_p)
506     for (i = 0; i < len; i++)
507       XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
508 		     x + i, y, code + i, 1);
509   else
510     XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
511                    x, y, code, len);
512   /* Need to explicitly mark the frame dirty because we didn't call
513      FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
514      XftDraw structure.  */
515   x_mark_frame_dirty (f);
516   unblock_input ();
517   return len;
518 }
519 
520 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
521 static Lisp_Object
xftfont_shape(Lisp_Object lgstring,Lisp_Object direction)522 xftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
523 {
524   struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
525   struct font_info *xftfont_info = (struct font_info *) font;
526   FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
527   xftfont_info->ft_size = ft_face->size;
528   Lisp_Object val = ftfont_shape (lgstring, direction);
529   XftUnlockFace (xftfont_info->xftfont);
530   return val;
531 }
532 #endif
533 
534 static int
xftfont_end_for_frame(struct frame * f)535 xftfont_end_for_frame (struct frame *f)
536 {
537   block_input ();
538   XftDraw *xft_draw;
539 
540   xft_draw = font_get_frame_data (f, Qxft);
541   if (xft_draw)
542     {
543       block_input ();
544       XftDrawDestroy (xft_draw);
545       unblock_input ();
546       font_put_frame_data (f, Qxft, NULL);
547     }
548   unblock_input ();
549   return 0;
550 }
551 
552 /* When using X double buffering, the XftDraw structure we build
553    seems to be useless once a frame is resized, so recreate it on
554    ConfigureNotify and in some other cases.  */
555 
556 static void
xftfont_drop_xrender_surfaces(struct frame * f)557 xftfont_drop_xrender_surfaces (struct frame *f)
558 {
559   block_input ();
560   if (FRAME_X_DOUBLE_BUFFERED_P (f))
561     xftfont_end_for_frame (f);
562   unblock_input ();
563 }
564 
565 static bool
xftfont_cached_font_ok(struct frame * f,Lisp_Object font_object,Lisp_Object entity)566 xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
567                         Lisp_Object entity)
568 {
569   struct font_info *info = (struct font_info *) XFONT_OBJECT (font_object);
570   FcPattern *oldpat = info->xftfont->pattern;
571   Display *display = FRAME_X_DISPLAY (f);
572   FcPattern *pat = FcPatternCreate ();
573   FcBool b1, b2;
574   bool ok = false;
575   int i1, i2, r1, r2;
576 
577   ftfont_add_rendering_parameters (pat, entity);
578   XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
579 
580   r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
581   r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
582   if (r1 != r2 || b1 != b2) goto out;
583   r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
584   r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
585   if (r1 != r2 || b1 != b2) goto out;
586   r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
587   r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
588   if (r1 != r2 || b1 != b2) goto out;
589 #ifdef FC_EMBOLDEN
590   r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
591   r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
592   if (r1 != r2 || b1 != b2) goto out;
593 #endif
594   r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
595   r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
596   if (r1 != r2 || i1 != i2) goto out;
597   r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
598   r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
599   if (r1 != r2 || i1 != i2) goto out;
600   r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
601   r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
602   if (r1 != r2 || i1 != i2) goto out;
603 
604   ok = true;
605  out:
606   FcPatternDestroy (pat);
607   return ok;
608 }
609 
610 #ifdef HAVE_HARFBUZZ
611 
612 static Lisp_Object
xfthbfont_list(struct frame * f,Lisp_Object spec)613 xfthbfont_list (struct frame *f, Lisp_Object spec)
614 {
615   return ftfont_list2 (f, spec, Qxfthb);
616 }
617 
618 static Lisp_Object
xfthbfont_match(struct frame * f,Lisp_Object spec)619 xfthbfont_match (struct frame *f, Lisp_Object spec)
620 {
621   return ftfont_match2 (f, spec, Qxfthb);
622 }
623 
624 static hb_font_t *
xfthbfont_begin_hb_font(struct font * font,double * position_unit)625 xfthbfont_begin_hb_font (struct font *font, double *position_unit)
626 {
627   struct font_info *xftfont_info = (struct font_info *) font;
628   FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
629 
630   xftfont_info->ft_size = ft_face->size;
631 
632   return fthbfont_begin_hb_font (font, position_unit);
633 }
634 
635 static void
xfthbfont_end_hb_font(struct font * font,hb_font_t * hb_font)636 xfthbfont_end_hb_font (struct font *font, hb_font_t *hb_font)
637 {
638   struct font_info *xftfont_info = (struct font_info *) font;
639 
640   XftUnlockFace (xftfont_info->xftfont);
641 }
642 
643 #endif	/* HAVE_HARFBUZZ */
644 
645 static void syms_of_xftfont_for_pdumper (void);
646 
647 struct font_driver const xftfont_driver =
648   {
649     /* We can't draw a text without device dependent functions.  */
650   .type = LISPSYM_INITIALLY (Qxft),
651   .get_cache = xfont_get_cache,
652   .list = xftfont_list,
653   .match = xftfont_match,
654   .list_family = ftfont_list_family,
655   .open_font = xftfont_open,
656   .close_font = xftfont_close,
657   .prepare_face = xftfont_prepare_face,
658   .done_face = xftfont_done_face,
659   .has_char = xftfont_has_char,
660   .encode_char = xftfont_encode_char,
661   .text_extents = xftfont_text_extents,
662   .draw = xftfont_draw,
663   .get_bitmap = ftfont_get_bitmap,
664   .anchor_point = ftfont_anchor_point,
665 #ifdef HAVE_LIBOTF
666   .otf_capability = ftfont_otf_capability,
667 #endif
668   .end_for_frame = xftfont_end_for_frame,
669 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
670   .shape = xftfont_shape,
671 #endif
672 #if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined HAVE_FT_FACE_GETCHARVARIANTINDEX
673   .get_variation_glyphs = ftfont_variation_glyphs,
674 #endif
675   .filter_properties = ftfont_filter_properties,
676   .cached_font_ok = xftfont_cached_font_ok,
677   .combining_capability = ftfont_combining_capability,
678   .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
679   };
680 #ifdef HAVE_HARFBUZZ
681 struct font_driver xfthbfont_driver;
682 #endif	/* HAVE_HARFBUZZ */
683 
684 void
syms_of_xftfont(void)685 syms_of_xftfont (void)
686 {
687   DEFSYM (Qxft, "xft");
688 #ifdef HAVE_HARFBUZZ
689   DEFSYM (Qxfthb, "xfthb");
690   Fput (Qxft, Qfont_driver_superseded_by, Qxfthb);
691 #endif	/* HAVE_HARFBUZZ */
692 
693   DEFVAR_BOOL ("xft-font-ascent-descent-override",
694 	       xft_font_ascent_descent_override,
695 	       doc:  /* Non-nil means override the ascent and descent values for Xft font driver.
696 This is needed with some fonts to correct vertical overlap of glyphs.  */);
697   xft_font_ascent_descent_override = 0;
698 
699   pdumper_do_now_and_after_load (syms_of_xftfont_for_pdumper);
700 }
701 
702 static void
syms_of_xftfont_for_pdumper(void)703 syms_of_xftfont_for_pdumper (void)
704 {
705   register_font_driver (&xftfont_driver, NULL);
706 #ifdef HAVE_HARFBUZZ
707   xfthbfont_driver = xftfont_driver;
708   xfthbfont_driver.type = Qxfthb;
709   xfthbfont_driver.list = xfthbfont_list;
710   xfthbfont_driver.match = xfthbfont_match;
711   xfthbfont_driver.otf_capability = hbfont_otf_capability;
712   xfthbfont_driver.shape = hbfont_shape;
713   xfthbfont_driver.combining_capability = hbfont_combining_capability;
714   xfthbfont_driver.begin_hb_font = xfthbfont_begin_hb_font;
715   xfthbfont_driver.end_hb_font = xfthbfont_end_hb_font;
716   register_font_driver (&xfthbfont_driver, NULL);
717 #endif	/* HAVE_HARFBUZZ */
718 }
719