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 <stdio.h>
24 #include <setjmp.h>
25 #include <X11/Xlib.h>
26 #include <X11/Xft/Xft.h>
27
28 #include "lisp.h"
29 #include "dispextern.h"
30 #include "xterm.h"
31 #include "frame.h"
32 #include "blockinput.h"
33 #include "character.h"
34 #include "charset.h"
35 #include "fontset.h"
36 #include "font.h"
37 #include "ftfont.h"
38
39
40
41 static Lisp_Object Qxft;
42 static Lisp_Object QChinting, QCautohint, QChintstyle, QCrgba, QCembolden,
43 QClcdfilter;
44
45 46
47
48 struct xftfont_info
49 {
50 struct font font;
51 52
53 #ifdef HAVE_LIBOTF
54 int maybe_otf;
55 OTF *otf;
56 #endif
57 FT_Size ft_size;
58 int index;
59 FT_Matrix matrix;
60 Display *display;
61 int screen;
62 XftFont *xftfont;
63 };
64
65
66
67 struct xftface_info
68 {
69 XftColor xft_fg;
70 XftColor xft_bg;
71 };
72
73 static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc,
74 struct xftface_info *,
75 XftColor *fg, XftColor *bg));
76
77
78 79 80
81
82 static void
83 xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
84 FRAME_PTR f;
85 struct face *face;
86 GC gc;
87 struct xftface_info *xftface_info;
88 XftColor *fg, *bg;
89 {
90 if (xftface_info && face->gc == gc)
91 {
92 *fg = xftface_info->xft_fg;
93 if (bg)
94 *bg = xftface_info->xft_bg;
95 }
96 else
97 {
98 XGCValues xgcv;
99 int fg_done = 0, bg_done = 0;
100
101 BLOCK_INPUT;
102 XGetGCValues (FRAME_X_DISPLAY (f), gc,
103 GCForeground | GCBackground, &xgcv);
104 if (xftface_info)
105 {
106 if (xgcv.foreground == face->foreground)
107 *fg = xftface_info->xft_fg, fg_done = 1;
108 else if (xgcv.foreground == face->background)
109 *fg = xftface_info->xft_bg, fg_done = 1;
110 if (! bg)
111 bg_done = 1;
112 else if (xgcv.background == face->background)
113 *bg = xftface_info->xft_bg, bg_done = 1;
114 else if (xgcv.background == face->foreground)
115 *bg = xftface_info->xft_fg, bg_done = 1;
116 }
117
118 if (fg_done + bg_done < 2)
119 {
120 XColor colors[2];
121
122 colors[0].pixel = fg->pixel = xgcv.foreground;
123 if (bg)
124 colors[1].pixel = bg->pixel = xgcv.background;
125 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
126 bg ? 2 : 1);
127 fg->color.alpha = 0xFFFF;
128 fg->color.red = colors[0].red;
129 fg->color.green = colors[0].green;
130 fg->color.blue = colors[0].blue;
131 if (bg)
132 {
133 bg->color.alpha = 0xFFFF;
134 bg->color.red = colors[1].red;
135 bg->color.green = colors[1].green;
136 bg->color.blue = colors[1].blue;
137 }
138 }
139 UNBLOCK_INPUT;
140 }
141 }
142
143
144 static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
145 static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
146 static Lisp_Object xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
147 static void xftfont_close P_ ((FRAME_PTR, struct font *));
148 static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
149 static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
150 static int xftfont_has_char P_ ((Lisp_Object, int));
151 static unsigned xftfont_encode_char P_ ((struct font *, int));
152 static int xftfont_text_extents P_ ((struct font *, unsigned *, int,
153 struct font_metrics *));
154 static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
155 static int xftfont_end_for_frame P_ ((FRAME_PTR f));
156
157 struct font_driver xftfont_driver;
158
159 static Lisp_Object
160 xftfont_list (frame, spec)
161 Lisp_Object frame;
162 Lisp_Object spec;
163 {
164 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
165
166 for (tail = list; CONSP (tail); tail = XCDR (tail))
167 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
168 return list;
169 }
170
171 static Lisp_Object
172 xftfont_match (frame, spec)
173 Lisp_Object frame;
174 Lisp_Object spec;
175 {
176 Lisp_Object entity = ftfont_driver.match (frame, spec);
177
178 if (! NILP (entity))
179 ASET (entity, FONT_TYPE_INDEX, Qxft);
180 return entity;
181 }
182
183 extern Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
184 extern FcCharSet *ftfont_get_fc_charset P_ ((Lisp_Object));
185 extern Lisp_Object QCantialias;
186
187 static FcChar8 ascii_printable[95];
188
189 static void
190 xftfont_fix_match (pat, match)
191 FcPattern *pat, *match;
192 {
193 194 195 196
197
198 FcBool b = FcTrue;
199 int i;
200 double dpi;
201
202 FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
203 if (! b)
204 {
205 FcPatternDel (match, FC_ANTIALIAS);
206 FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
207 }
208 FcPatternGetBool (pat, FC_HINTING, 0, &b);
209 if (! b)
210 {
211 FcPatternDel (match, FC_HINTING);
212 FcPatternAddBool (match, FC_HINTING, FcFalse);
213 }
214 if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
215 {
216 FcPatternDel (match, FC_HINT_STYLE);
217 FcPatternAddInteger (match, FC_HINT_STYLE, i);
218 }
219 #ifndef FC_LCD_FILTER
220
221 #define FC_LCD_FILTER "lcdfilter"
222 #endif
223 if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
224 {
225 FcPatternDel (match, FC_LCD_FILTER);
226 FcPatternAddInteger (match, FC_LCD_FILTER, i);
227 }
228 if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
229 {
230 FcPatternDel (match, FC_RGBA);
231 FcPatternAddInteger (match, FC_RGBA, i);
232 }
233 if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
234 {
235 FcPatternDel (match, FC_DPI);
236 FcPatternAddDouble (match, FC_DPI, dpi);
237 }
238 }
239
240 static void
241 xftfont_add_rendering_parameters (pat, entity)
242 FcPattern *pat;
243 Lisp_Object entity;
244 {
245 Lisp_Object tail;
246 int ival;
247
248 for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
249 {
250 Lisp_Object key = XCAR (XCAR (tail));
251 Lisp_Object val = XCDR (XCAR (tail));
252
253 if (EQ (key, QCantialias))
254 FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
255 else if (EQ (key, QChinting))
256 FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
257 else if (EQ (key, QCautohint))
258 FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
259 else if (EQ (key, QChintstyle))
260 {
261 if (INTEGERP (val))
262 FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
263 else if (SYMBOLP (val)
264 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
265 FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
266 }
267 else if (EQ (key, QCrgba))
268 {
269 if (INTEGERP (val))
270 FcPatternAddInteger (pat, FC_RGBA, XINT (val));
271 else if (SYMBOLP (val)
272 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
273 FcPatternAddInteger (pat, FC_RGBA, ival);
274 }
275 else if (EQ (key, QClcdfilter))
276 {
277 if (INTEGERP (val))
278 FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
279 else if (SYMBOLP (val)
280 && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
281 FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
282 }
283 #ifdef FC_EMBOLDEN
284 else if (EQ (key, QCembolden))
285 FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
286 #endif
287 }
288 }
289
290 static Lisp_Object
291 xftfont_open (f, entity, pixel_size)
292 FRAME_PTR f;
293 Lisp_Object entity;
294 int pixel_size;
295 {
296 FcResult result;
297 Display *display = FRAME_X_DISPLAY (f);
298 Lisp_Object val, filename, index, font_object;
299 FcPattern *pat = NULL, *match;
300 struct xftfont_info *xftfont_info = NULL;
301 struct font *font;
302 double size = 0;
303 XftFont *xftfont = NULL;
304 int spacing;
305 char name[256];
306 int len, i;
307 XGlyphInfo extents;
308 FT_Face ft_face;
309 FcMatrix *matrix;
310
311 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
312 if (! CONSP (val))
313 return Qnil;
314 val = XCDR (val);
315 filename = XCAR (val);
316 index = XCDR (val);
317 size = XINT (AREF (entity, FONT_SIZE_INDEX));
318 if (size == 0)
319 size = pixel_size;
320 pat = FcPatternCreate ();
321 FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
322 i = FONT_SLANT_NUMERIC (entity) - 100;
323 if (i < 0) i = 0;
324 FcPatternAddInteger (pat, FC_SLANT, i);
325 FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
326 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
327 val = AREF (entity, FONT_FAMILY_INDEX);
328 if (! NILP (val))
329 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
330 val = AREF (entity, FONT_FOUNDRY_INDEX);
331 if (! NILP (val))
332 FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
333 val = AREF (entity, FONT_SPACING_INDEX);
334 if (! NILP (val))
335 FcPatternAddInteger (pat, FC_SPACING, XINT (val));
336 val = AREF (entity, FONT_DPI_INDEX);
337 if (! NILP (val))
338 {
339 double dbl = XINT (val);
340
341 FcPatternAddDouble (pat, FC_DPI, dbl);
342 }
343 val = AREF (entity, FONT_AVGWIDTH_INDEX);
344 if (INTEGERP (val) && XINT (val) == 0)
345 FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
346 347
348 FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
349
350 xftfont_add_rendering_parameters (pat, entity);
351
352 FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
353 FcPatternAddInteger (pat, FC_INDEX, XINT (index));
354
355
356 BLOCK_INPUT;
357 358 359 360 361 362
363 {
364 int event_base, error_base;
365 XRenderQueryExtension (display, &event_base, &error_base);
366 }
367
368
369 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
370 match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
371 xftfont_fix_match (pat, match);
372
373 FcPatternDestroy (pat);
374 xftfont = XftFontOpenPattern (display, match);
375 if (!xftfont)
376 {
377 UNBLOCK_INPUT;
378 XftPatternDestroy (match);
379 return Qnil;
380 }
381 ft_face = XftLockFace (xftfont);
382 UNBLOCK_INPUT;
383
384 385
386 font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size);
387 ASET (font_object, FONT_TYPE_INDEX, Qxft);
388 len = font_unparse_xlfd (entity, size, name, 256);
389 if (len > 0)
390 ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
391 len = font_unparse_fcname (entity, size, name, 256);
392 if (len > 0)
393 ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
394 else
395 ASET (font_object, FONT_FULLNAME_INDEX,
396 AREF (font_object, FONT_NAME_INDEX));
397 ASET (font_object, FONT_FILE_INDEX, filename);
398 ASET (font_object, FONT_FORMAT_INDEX,
399 ftfont_font_format (xftfont->pattern, filename));
400 font = XFONT_OBJECT (font_object);
401 font->pixel_size = pixel_size;
402 font->driver = &xftfont_driver;
403 font->encoding_charset = font->repertory_charset = -1;
404
405 xftfont_info = (struct xftfont_info *) font;
406 xftfont_info->display = display;
407 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
408 xftfont_info->xftfont = xftfont;
409
410 xftfont_info->matrix.xx = 0;
411 if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
412 == FcResultMatch)
413 {
414 xftfont_info->matrix.xx = 0x10000L * matrix->xx;
415 xftfont_info->matrix.yy = 0x10000L * matrix->yy;
416 xftfont_info->matrix.xy = 0x10000L * matrix->xy;
417 xftfont_info->matrix.yx = 0x10000L * matrix->yx;
418 }
419 font->pixel_size = size;
420 font->driver = &xftfont_driver;
421 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
422 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
423 else
424 spacing = FC_PROPORTIONAL;
425 if (! ascii_printable[0])
426 {
427 int i;
428 for (i = 0; i < 95; i++)
429 ascii_printable[i] = ' ' + i;
430 }
431 BLOCK_INPUT;
432 if (spacing != FC_PROPORTIONAL)
433 {
434 font->min_width = font->average_width = font->space_width
435 = xftfont->max_advance_width;
436 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
437 }
438 else
439 {
440 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
441 font->space_width = extents.xOff;
442 if (font->space_width <= 0)
443
444 font->space_width = pixel_size;
445 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
446 font->average_width = (font->space_width + extents.xOff) / 95;
447 }
448 UNBLOCK_INPUT;
449
450 font->ascent = xftfont->ascent;
451 font->descent = xftfont->descent;
452 if (pixel_size >= 5)
453 {
454 455 456
457 if (font->ascent < extents.y)
458 font->ascent = extents.y;
459 if (font->descent < extents.height - extents.y)
460 font->descent = extents.height - extents.y;
461 }
462 font->height = font->ascent + font->descent;
463
464 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
465 {
466 int upEM = ft_face->units_per_EM;
467
468 font->underline_position = -ft_face->underline_position * size / upEM;
469 font->underline_thickness = ft_face->underline_thickness * size / upEM;
470 if (font->underline_thickness > 2)
471 font->underline_position -= font->underline_thickness / 2;
472 }
473 else
474 {
475 font->underline_position = -1;
476 font->underline_thickness = 0;
477 }
478 #ifdef HAVE_LIBOTF
479 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
480 xftfont_info->otf = NULL;
481 #endif
482 xftfont_info->ft_size = ft_face->size;
483
484 485
486 font->min_width = font->space_width;
487
488 font->baseline_offset = 0;
489 font->relative_compose = 0;
490 font->default_ascent = 0;
491 font->vertical_centering = 0;
492 #ifdef FT_BDF_H
493 if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
494 {
495 BDF_PropertyRec rec;
496
497 if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
498 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
499 font->baseline_offset = rec.u.integer;
500 if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
501 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
502 font->relative_compose = rec.u.integer;
503 if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
504 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
505 font->default_ascent = rec.u.integer;
506 }
507 #endif
508
509 return font_object;
510 }
511
512 static void
513 xftfont_close (f, font)
514 FRAME_PTR f;
515 struct font *font;
516 {
517 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
518
519 #ifdef HAVE_LIBOTF
520 if (xftfont_info->otf)
521 OTF_close (xftfont_info->otf);
522 #endif
523 BLOCK_INPUT;
524 XftUnlockFace (xftfont_info->xftfont);
525 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
526 UNBLOCK_INPUT;
527 }
528
529 static int
530 xftfont_prepare_face (f, face)
531 FRAME_PTR f;
532 struct face *face;
533 {
534 struct xftface_info *xftface_info;
535
536 #if 0
537
538 if (face != face->ascii_face)
539 {
540 face->extra = face->ascii_face->extra;
541 return 0;
542 }
543 #endif
544
545 xftface_info = malloc (sizeof (struct xftface_info));
546 if (! xftface_info)
547 return -1;
548 xftfont_get_colors (f, face, face->gc, NULL,
549 &xftface_info->xft_fg, &xftface_info->xft_bg);
550 face->extra = xftface_info;
551 return 0;
552 }
553
554 static void
555 xftfont_done_face (f, face)
556 FRAME_PTR f;
557 struct face *face;
558 {
559 struct xftface_info *xftface_info;
560
561 #if 0
562
563 if (face != face->ascii_face
564 || ! face->extra)
565 return;
566 #endif
567
568 xftface_info = (struct xftface_info *) face->extra;
569 if (xftface_info)
570 {
571 free (xftface_info);
572 face->extra = NULL;
573 }
574 }
575
576 extern Lisp_Object Qja, Qko;
577
578 static int
579 xftfont_has_char (font, c)
580 Lisp_Object font;
581 int c;
582 {
583 struct xftfont_info *xftfont_info;
584 struct charset *cs = NULL;
585
586 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
587 && charset_jisx0208 >= 0)
588 cs = CHARSET_FROM_ID (charset_jisx0208);
589 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
590 && charset_ksc5601 >= 0)
591 cs = CHARSET_FROM_ID (charset_ksc5601);
592 if (cs)
593 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
594
595 if (FONT_ENTITY_P (font))
596 return ftfont_driver.has_char (font, c);
597 xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
598 return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
599 (FcChar32) c) == FcTrue);
600 }
601
602 static unsigned
603 xftfont_encode_char (font, c)
604 struct font *font;
605 int c;
606 {
607 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
608 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
609 (FcChar32) c);
610
611 return (code ? code : FONT_INVALID_CODE);
612 }
613
614 static int
615 xftfont_text_extents (font, code, nglyphs, metrics)
616 struct font *font;
617 unsigned *code;
618 int nglyphs;
619 struct font_metrics *metrics;
620 {
621 struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
622 XGlyphInfo extents;
623
624 BLOCK_INPUT;
625 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
626 &extents);
627 UNBLOCK_INPUT;
628 if (metrics)
629 {
630 metrics->lbearing = - extents.x;
631 metrics->rbearing = - extents.x + extents.width;
632 metrics->width = extents.xOff;
633 metrics->ascent = extents.y;
634 metrics->descent = extents.height - extents.y;
635 }
636 return extents.xOff;
637 }
638
639 static XftDraw *
640 xftfont_get_xft_draw (f)
641 FRAME_PTR f;
642 {
643 XftDraw *xft_draw = font_get_frame_data (f, &xftfont_driver);
644
645 if (! xft_draw)
646 {
647 BLOCK_INPUT;
648 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
649 FRAME_X_WINDOW (f),
650 FRAME_X_VISUAL (f),
651 FRAME_X_COLORMAP (f));
652 UNBLOCK_INPUT;
653 if (! xft_draw)
654 abort ();
655 font_put_frame_data (f, &xftfont_driver, xft_draw);
656 }
657 return xft_draw;
658 }
659
660 static int
661 xftfont_draw (s, from, to, x, y, with_background)
662 struct glyph_string *s;
663 int from, to, x, y, with_background;
664 {
665 FRAME_PTR f = s->f;
666 struct face *face = s->face;
667 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
668 struct xftface_info *xftface_info = NULL;
669 XftDraw *xft_draw = xftfont_get_xft_draw (f);
670 FT_UInt *code;
671 XftColor fg, bg;
672 int len = to - from;
673 int i;
674
675 if (s->font == face->font)
676 xftface_info = (struct xftface_info *) face->extra;
677 xftfont_get_colors (f, face, s->gc, xftface_info,
678 &fg, with_background ? &bg : NULL);
679 BLOCK_INPUT;
680 if (s->num_clips > 0)
681 XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
682 else
683 XftDrawSetClip (xft_draw, NULL);
684
685 if (with_background)
686 XftDrawRect (xft_draw, &bg,
687 x, y - face->font->ascent, s->width, face->font->height);
688 code = alloca (sizeof (FT_UInt) * len);
689 for (i = 0; i < len; i++)
690 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
691 | XCHAR2B_BYTE2 (s->char2b + from + i));
692
693 if (s->padding_p)
694 for (i = 0; i < len; i++)
695 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
696 x + i, y, code + i, 1);
697 else
698 XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
699 x, y, code, len);
700 UNBLOCK_INPUT;
701
702 return len;
703 }
704
705 static int
706 xftfont_end_for_frame (f)
707 FRAME_PTR f;
708 {
709 XftDraw *xft_draw;
710
711
712 if (FRAME_X_DISPLAY (f) == NULL) return 0;
713
714 xft_draw = font_get_frame_data (f, &xftfont_driver);
715
716 if (xft_draw)
717 {
718 BLOCK_INPUT;
719 XftDrawDestroy (xft_draw);
720 UNBLOCK_INPUT;
721 font_put_frame_data (f, &xftfont_driver, NULL);
722 }
723 return 0;
724 }
725
726 static int
727 xftfont_cached_font_ok (f, font_object, entity)
728 struct frame *f;
729 Lisp_Object font_object;
730 Lisp_Object entity;
731
732 {
733 struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
734 FcPattern *oldpat = info->xftfont->pattern;
735 Display *display = FRAME_X_DISPLAY (f);
736 FcPattern *pat = FcPatternCreate ();
737 FcBool b1, b2;
738 int ok = 0, i1, i2, r1, r2;
739
740 xftfont_add_rendering_parameters (pat, entity);
741 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
742
743 r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
744 r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
745 if (r1 != r2 || b1 != b2) goto out;
746 r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
747 r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
748 if (r1 != r2 || b1 != b2) goto out;
749 r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
750 r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
751 if (r1 != r2 || b1 != b2) goto out;
752 #ifdef FC_EMBOLDEN
753 r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
754 r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
755 if (r1 != r2 || b1 != b2) goto out;
756 #endif
757 r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
758 r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
759 if (r1 != r2 || i1 != i2) goto out;
760 r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
761 r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
762 if (r1 != r2 || i1 != i2) goto out;
763 r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
764 r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
765 if (r1 != r2 || i1 != i2) goto out;
766
767 ok = 1;
768 out:
769 FcPatternDestroy (pat);
770 return ok;
771 }
772
773 void
774 syms_of_xftfont ()
775 {
776 DEFSYM (Qxft, "xft");
777 DEFSYM (QChinting, ":hinting");
778 DEFSYM (QCautohint, ":autohint");
779 DEFSYM (QChintstyle, ":hintstyle");
780 DEFSYM (QCrgba, ":rgba");
781 DEFSYM (QCembolden, ":embolden");
782 DEFSYM (QClcdfilter, ":lcdfilter");
783
784 xftfont_driver = ftfont_driver;
785 xftfont_driver.type = Qxft;
786 xftfont_driver.get_cache = xfont_driver.get_cache;
787 xftfont_driver.list = xftfont_list;
788 xftfont_driver.match = xftfont_match;
789 xftfont_driver.open = xftfont_open;
790 xftfont_driver.close = xftfont_close;
791 xftfont_driver.prepare_face = xftfont_prepare_face;
792 xftfont_driver.done_face = xftfont_done_face;
793 xftfont_driver.has_char = xftfont_has_char;
794 xftfont_driver.encode_char = xftfont_encode_char;
795 xftfont_driver.text_extents = xftfont_text_extents;
796 xftfont_driver.draw = xftfont_draw;
797 xftfont_driver.end_for_frame = xftfont_end_for_frame;
798 xftfont_driver.cached_font_ok = xftfont_cached_font_ok;
799
800 register_font_driver (&xftfont_driver, NULL);
801 }
802
803 804