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