This source file includes following definitions.
- xftfont_get_colors
- xftfont_list
- xftfont_match
- xftfont_open
- xftfont_close
- xftfont_prepare_face
- xftfont_done_face
- xftfont_has_char
- xftfont_encode_char
- xftfont_text_extents
- xftfont_get_xft_draw
- xftfont_draw
- xftfont_shape
- xftfont_end_for_frame
- xftfont_drop_xrender_surfaces
- xftfont_cached_font_ok
- xfthbfont_list
- xfthbfont_match
- xfthbfont_begin_hb_font
- xfthbfont_end_hb_font
- syms_of_xftfont
- syms_of_xftfont_for_pdumper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
42 # define FC_LCD_FILTER "lcdfilter"
43 #endif
44
45
46
47
48
49
50 struct xftface_info
51 {
52 bool bg_allocated_p;
53 bool fg_allocated_p;
54 XftColor xft_fg;
55 XftColor xft_bg;
56 };
57
58
59
60
61
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
118
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
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
202
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
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
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
244
245
246 if (spacing != FC_PROPORTIONAL
247 #ifdef FC_DUAL
248 && spacing != FC_DUAL
249 #endif
250 #ifdef FC_CHARCELL
251 && spacing != FC_CHARCELL
252 #endif
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
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
275
276
277
278
279
280
281 if (pixel_size >= 5
282 && xft_font_ascent_descent_override)
283 {
284
285
286
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
312 #ifdef HAVE_HARFBUZZ
313 xftfont_info->hb_font = NULL;
314 #endif
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
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
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
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
533
534
535
536
537
538
539
540
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
594
595
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
632
633
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
653
654
655
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
749
750 static void syms_of_xftfont_for_pdumper (void);
751
752 struct font_driver const xftfont_driver =
753 {
754
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
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
799
800 DEFVAR_BOOL ("xft-font-ascent-descent-override",
801 xft_font_ascent_descent_override,
802 doc:
803 );
804 xft_font_ascent_descent_override = 0;
805
806 DEFVAR_LISP ("xft-color-font-whitelist", Vxft_color_font_whitelist,
807 doc:
808
809
810
811
812 );
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
834 }