xftfont.c 24.1 KB
Newer Older
Kenichi Handa's avatar
Kenichi Handa committed
1
/* xftfont.c -- XFT font driver.
Paul Eggert's avatar
Paul Eggert committed
2
   Copyright (C) 2006-2019 Free Software Foundation, Inc.
3
   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
Kenichi Handa's avatar
Kenichi Handa committed
4 5 6 7 8
     National Institute of Advanced Industrial Science and Technology (AIST)
     Registration Number H13PRO009

This file is part of GNU Emacs.

9
GNU Emacs is free software: you can redistribute it and/or modify
Kenichi Handa's avatar
Kenichi Handa committed
10
it under the terms of the GNU General Public License as published by
11 12
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
Kenichi Handa's avatar
Kenichi Handa committed
13 14 15 16 17 18 19

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

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/>.  */
Kenichi Handa's avatar
Kenichi Handa committed
21 22 23 24 25 26 27 28 29 30 31

#include <config.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>

#include "lisp.h"
#include "xterm.h"
#include "frame.h"
#include "blockinput.h"
#include "charset.h"
32
#include "composite.h"
Kenichi Handa's avatar
Kenichi Handa committed
33
#include "font.h"
Kenichi Handa's avatar
Kenichi Handa committed
34
#include "ftfont.h"
Kenichi Handa's avatar
Kenichi Handa committed
35 36 37 38

/* Xft font driver.  */


Paul Eggert's avatar
Paul Eggert committed
39
/* The actual structure for Xft font that can be cast to struct
Kenichi Handa's avatar
Kenichi Handa committed
40 41 42 43 44
   font.  */

struct xftfont_info
{
  struct font font;
45 46 47
  /* The following members up to and including 'matrix' must be here
     in this order to be compatible with struct ftfont_info (in
     ftfont.c).  */
Kenichi Handa's avatar
Kenichi Handa committed
48
#ifdef HAVE_LIBOTF
49
  bool maybe_otf;	  /* Flag to tell if this may be OTF or not.  */
Kenichi Handa's avatar
Kenichi Handa committed
50
  OTF *otf;
Kenichi Handa's avatar
Kenichi Handa committed
51
#endif	/* HAVE_LIBOTF */
52
  FT_Size ft_size;
53
  int index;
54
  FT_Matrix matrix;
55

56 57
  Display *display;
  XftFont *xftfont;
58
  unsigned x_display_id;
Kenichi Handa's avatar
Kenichi Handa committed
59 60 61
};

/* Structure pointed by (struct face *)->extra  */
Kenichi Handa's avatar
Kenichi Handa committed
62

Kenichi Handa's avatar
Kenichi Handa committed
63 64
struct xftface_info
{
Kenichi Handa's avatar
Kenichi Handa committed
65 66
  XftColor xft_fg;		/* color for face->foreground */
  XftColor xft_bg;		/* color for face->background */
Kenichi Handa's avatar
Kenichi Handa committed
67 68
};

Kenichi Handa's avatar
Kenichi Handa committed
69 70 71 72
/* Setup foreground and background colors of GC into FG and BG.  If
   XFTFACE_INFO is not NULL, reuse the colors in it if possible.  BG
   may be NULL.  */

Kenichi Handa's avatar
Kenichi Handa committed
73
static void
Dmitry Antipov's avatar
Dmitry Antipov committed
74 75 76
xftfont_get_colors (struct frame *f, struct face *face, GC gc,
		    struct xftface_info *xftface_info,
		    XftColor *fg, XftColor *bg)
Kenichi Handa's avatar
Kenichi Handa committed
77 78 79 80 81 82 83 84 85 86
{
  if (xftface_info && face->gc == gc)
    {
      *fg = xftface_info->xft_fg;
      if (bg)
	*bg = xftface_info->xft_bg;
    }
  else
    {
      XGCValues xgcv;
87
      bool fg_done = false, bg_done = false;
Kenichi Handa's avatar
Kenichi Handa committed
88

89
      block_input ();
Kenichi Handa's avatar
Kenichi Handa committed
90 91 92 93 94
      XGetGCValues (FRAME_X_DISPLAY (f), gc,
		    GCForeground | GCBackground, &xgcv);
      if (xftface_info)
	{
	  if (xgcv.foreground == face->foreground)
95
	    *fg = xftface_info->xft_fg, fg_done = true;
Kenichi Handa's avatar
Kenichi Handa committed
96
	  else if (xgcv.foreground == face->background)
97
	    *fg = xftface_info->xft_bg, fg_done = true;
Kenichi Handa's avatar
Kenichi Handa committed
98
	  if (! bg)
99
	    bg_done = true;
Kenichi Handa's avatar
Kenichi Handa committed
100
	  else if (xgcv.background == face->background)
101
	    *bg = xftface_info->xft_bg, bg_done = true;
Kenichi Handa's avatar
Kenichi Handa committed
102
	  else if (xgcv.background == face->foreground)
103
	    *bg = xftface_info->xft_fg, bg_done = true;
Kenichi Handa's avatar
Kenichi Handa committed
104 105
	}

106
      if (! (fg_done & bg_done))
Kenichi Handa's avatar
Kenichi Handa committed
107 108 109 110 111 112
	{
	  XColor colors[2];

	  colors[0].pixel = fg->pixel = xgcv.foreground;
	  if (bg)
	    colors[1].pixel = bg->pixel = xgcv.background;
113
	  x_query_colors (f, colors, bg ? 2 : 1);
Kenichi Handa's avatar
Kenichi Handa committed
114 115 116 117 118 119 120 121 122 123 124 125
	  fg->color.alpha = 0xFFFF;
	  fg->color.red = colors[0].red;
	  fg->color.green = colors[0].green;
	  fg->color.blue = colors[0].blue;
	  if (bg)
	    {
	      bg->color.alpha = 0xFFFF;
	      bg->color.red = colors[1].red;
	      bg->color.green = colors[1].green;
	      bg->color.blue = colors[1].blue;
	    }
	}
126
      unblock_input ();
Kenichi Handa's avatar
Kenichi Handa committed
127 128 129 130
    }
}

static Lisp_Object
131
xftfont_list (struct frame *f, Lisp_Object spec)
Kenichi Handa's avatar
Kenichi Handa committed
132
{
133
  Lisp_Object list = ftfont_list (f, spec);
134

135
  for (Lisp_Object tail = list; CONSP (tail); tail = XCDR (tail))
136 137
    ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
  return list;
Kenichi Handa's avatar
Kenichi Handa committed
138 139
}

Kenichi Handa's avatar
Kenichi Handa committed
140
static Lisp_Object
141
xftfont_match (struct frame *f, Lisp_Object spec)
Kenichi Handa's avatar
Kenichi Handa committed
142
{
143
  Lisp_Object entity = ftfont_match (f, spec);
Kenichi Handa's avatar
Kenichi Handa committed
144

145
  if (! NILP (entity))
Kenichi Handa's avatar
Kenichi Handa committed
146 147 148 149
    ASET (entity, FONT_TYPE_INDEX, Qxft);
  return entity;
}

Kenichi Handa's avatar
Kenichi Handa committed
150 151
static FcChar8 ascii_printable[95];

152
static void
153
xftfont_fix_match (FcPattern *pat, FcPattern *match)
154 155 156 157 158 159 160 161 162 163 164
{
  /*  These values are not used for matching (except antialias), but for
      rendering, so make sure they are carried over to the match.
      We also put antialias here because most fonts are antialiased, so
      the match will have antialias true.  */

  FcBool b = FcTrue;
  int i;
  double dpi;

  FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
165
  if (! b)
166 167 168 169 170
    {
      FcPatternDel (match, FC_ANTIALIAS);
      FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
    }
  FcPatternGetBool (pat, FC_HINTING, 0, &b);
171
  if (! b)
172 173 174 175
    {
      FcPatternDel (match, FC_HINTING);
      FcPatternAddBool (match, FC_HINTING, FcFalse);
    }
176 177 178
#ifndef FC_HINT_STYLE
# define FC_HINT_STYLE "hintstyle"
#endif
179 180 181 182 183
  if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
    {
      FcPatternDel (match, FC_HINT_STYLE);
      FcPatternAddInteger (match, FC_HINT_STYLE, i);
    }
184
#ifndef FC_LCD_FILTER
Jan Djärv's avatar
Jan Djärv committed
185
  /* Older fontconfig versions don't have FC_LCD_FILTER. */
186 187
#define FC_LCD_FILTER "lcdfilter"
#endif
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
  if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
    {
      FcPatternDel (match, FC_LCD_FILTER);
      FcPatternAddInteger (match, FC_LCD_FILTER, i);
    }
  if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
    {
      FcPatternDel (match, FC_RGBA);
      FcPatternAddInteger (match, FC_RGBA, i);
    }
  if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
    {
      FcPatternDel (match, FC_DPI);
      FcPatternAddDouble (match, FC_DPI, dpi);
    }
}

205
static void
206
xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
{
  Lisp_Object tail;
  int ival;

  for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
    {
      Lisp_Object key = XCAR (XCAR (tail));
      Lisp_Object val = XCDR (XCAR (tail));

      if (EQ (key, QCantialias))
          FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
      else if (EQ (key, QChinting))
	FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
      else if (EQ (key, QCautohint))
	FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
      else if (EQ (key, QChintstyle))
	{
	  if (INTEGERP (val))
	    FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val));
          else if (SYMBOLP (val)
                   && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
	    FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
	}
      else if (EQ (key, QCrgba))
	{
	  if (INTEGERP (val))
	    FcPatternAddInteger (pat, FC_RGBA, XINT (val));
          else if (SYMBOLP (val)
                   && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
	    FcPatternAddInteger (pat, FC_RGBA, ival);
	}
      else if (EQ (key, QClcdfilter))
	{
	  if (INTEGERP (val))
	    FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val));
          else if (SYMBOLP (val)
                   && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
	    FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
	}
#ifdef FC_EMBOLDEN
      else if (EQ (key, QCembolden))
	FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
#endif
    }
}

253
static Lisp_Object
Dmitry Antipov's avatar
Dmitry Antipov committed
254
xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
Kenichi Handa's avatar
Kenichi Handa committed
255
{
256
  FcResult result;
Kenichi Handa's avatar
Kenichi Handa committed
257
  Display *display = FRAME_X_DISPLAY (f);
258
  Lisp_Object val, filename, idx, font_object;
259
  FcPattern *pat = NULL, *match;
260
  struct xftfont_info *xftfont_info = NULL;
Kenichi Handa's avatar
Kenichi Handa committed
261 262
  struct font *font;
  double size = 0;
263
  XftFont *xftfont = NULL;
Kenichi Handa's avatar
Kenichi Handa committed
264
  int spacing;
265
  int i;
266
  XGlyphInfo extents;
267
  FT_Face ft_face;
268
  FcMatrix *matrix;
Kenichi Handa's avatar
Kenichi Handa committed
269

270
  val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
271
  if (! CONSP (val))
272
    return Qnil;
273 274
  val = XCDR (val);
  filename = XCAR (val);
275
  idx = XCDR (val);
Kenichi Handa's avatar
Kenichi Handa committed
276 277 278 279
  size = XINT (AREF (entity, FONT_SIZE_INDEX));
  if (size == 0)
    size = pixel_size;
  pat = FcPatternCreate ();
280 281 282 283 284
  FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
  i = FONT_SLANT_NUMERIC (entity) - 100;
  if (i < 0) i = 0;
  FcPatternAddInteger (pat, FC_SLANT, i);
  FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
Kenichi Handa's avatar
Kenichi Handa committed
285
  FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
286 287 288
  val = AREF (entity, FONT_FAMILY_INDEX);
  if (! NILP (val))
    FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
  val = AREF (entity, FONT_FOUNDRY_INDEX);
  if (! NILP (val))
    FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
  val = AREF (entity, FONT_SPACING_INDEX);
  if (! NILP (val))
    FcPatternAddInteger (pat, FC_SPACING, XINT (val));
  val = AREF (entity, FONT_DPI_INDEX);
  if (! NILP (val))
    {
      double dbl = XINT (val);

      FcPatternAddDouble (pat, FC_DPI, dbl);
    }
  val = AREF (entity, FONT_AVGWIDTH_INDEX);
  if (INTEGERP (val) && XINT (val) == 0)
    FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
305 306 307
  /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
     over 10x20-ISO8859-1.pcf.gz).  */
  FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
308

309
  xftfont_add_rendering_parameters (pat, entity);
310

311
  FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
312
  FcPatternAddInteger (pat, FC_INDEX, XINT (idx));
313

314

315
  block_input ();
316 317 318

  /* Substitute in values from X resources and XftDefaultSet.  */
  XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
319
  match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
320
  xftfont_fix_match (pat, match);
321

322 323
  FcPatternDestroy (pat);
  xftfont = XftFontOpenPattern (display, match);
324
  if (!xftfont)
325
    {
326
      unblock_input ();
327 328 329
      XftPatternDestroy (match);
      return Qnil;
    }
330
  ft_face = XftLockFace (xftfont);
331
  unblock_input ();
332

Kenichi Handa's avatar
Kenichi Handa committed
333 334
  /* We should not destroy PAT here because it is kept in XFTFONT and
     destroyed automatically when XFTFONT is closed.  */
335 336
  font_object = font_build_object (VECSIZE (struct xftfont_info),
				   Qxft, entity, size);
337
  ASET (font_object, FONT_FILE_INDEX, filename);
338
  font = XFONT_OBJECT (font_object);
339
  font->pixel_size = size;
340 341 342 343
  font->driver = &xftfont_driver;
  font->encoding_charset = font->repertory_charset = -1;

  xftfont_info = (struct xftfont_info *) font;
Kenichi Handa's avatar
Kenichi Handa committed
344 345
  xftfont_info->display = display;
  xftfont_info->xftfont = xftfont;
346
  xftfont_info->x_display_id = FRAME_DISPLAY_INFO (f)->x_id;
347 348 349 350 351 352 353 354 355 356
  /* This means that there's no need of transformation.  */
  xftfont_info->matrix.xx = 0;
  if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix)
      == FcResultMatch)
    {
      xftfont_info->matrix.xx = 0x10000L * matrix->xx;
      xftfont_info->matrix.yy = 0x10000L * matrix->yy;
      xftfont_info->matrix.xy = 0x10000L * matrix->xy;
      xftfont_info->matrix.yx = 0x10000L * matrix->yx;
    }
357 358 359
  if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
    spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
  else
Kenichi Handa's avatar
Kenichi Handa committed
360
    spacing = FC_PROPORTIONAL;
361 362
  if (! ascii_printable[0])
    {
363 364 365
      int ch;
      for (ch = 0; ch < 95; ch++)
	ascii_printable[ch] = ' ' + ch;
366
    }
367
  block_input ();
368 369 370 371

  /* Unfortunately Xft doesn't provide a way to get minimum char
     width.  So, we set min_width to space_width.  */

372 373 374 375 376
  if (spacing != FC_PROPORTIONAL
#ifdef FC_DUAL
      && spacing != FC_DUAL
#endif	/* FC_DUAL */
      )
377
    {
378 379
      font->min_width = font->max_width = font->average_width
	= font->space_width = xftfont->max_advance_width;
380 381
      XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
    }
Kenichi Handa's avatar
Kenichi Handa committed
382 383 384
  else
    {
      XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
385 386
      font->min_width = font->max_width = font->space_width
	= extents.xOff;
387
      if (font->space_width <= 0)
Kenichi Handa's avatar
Kenichi Handa committed
388
	/* dirty workaround */
389
	font->space_width = pixel_size;
Kenichi Handa's avatar
Kenichi Handa committed
390
      XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
391
      font->average_width = (font->space_width + extents.xOff) / 95;
Kenichi Handa's avatar
Kenichi Handa committed
392
    }
393
  unblock_input ();
Kenichi Handa's avatar
Kenichi Handa committed
394

395 396
  font->ascent = xftfont->ascent;
  font->descent = xftfont->descent;
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
  /* The following workaround is unnecessary on most systems, and
     causes annoying differences in glyph height between regular and
     bold fonts (see bug#22383).  However, with some fonts, such as
     monaco, removing the workaround results in overlapping vertical
     space of a line, see bug#23360.  As long as the way to reconcile
     these opposites is not known, we provide a user option to work
     around the problem.  */
  if (pixel_size >= 5
      && xft_font_ascent_descent_override)
    {
      /* The above condition is a dirty workaround because
	 XftTextExtents8 behaves strangely for some fonts
	 (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */
      if (font->ascent < extents.y)
	font->ascent = extents.y;
      if (font->descent < extents.height - extents.y)
	font->descent = extents.height - extents.y;
    }
415
  font->height = font->ascent + font->descent;
416

417
  if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
Kenichi Handa's avatar
Kenichi Handa committed
418
    {
419 420 421
      int upEM = ft_face->units_per_EM;

      font->underline_position = -ft_face->underline_position * size / upEM;
422
      font->underline_thickness = ft_face->underline_thickness * size / upEM;
423 424
      if (font->underline_thickness > 2)
	font->underline_position -= font->underline_thickness / 2;
Kenichi Handa's avatar
Kenichi Handa committed
425 426 427
    }
  else
    {
428 429
      font->underline_position = -1;
      font->underline_thickness = 0;
Kenichi Handa's avatar
Kenichi Handa committed
430
    }
431
#ifdef HAVE_LIBOTF
432
  xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
433 434
  xftfont_info->otf = NULL;
#endif	/* HAVE_LIBOTF */
435
  xftfont_info->ft_size = ft_face->size;
Kenichi Handa's avatar
Kenichi Handa committed
436

437 438 439
  font->baseline_offset = 0;
  font->relative_compose = 0;
  font->default_ascent = 0;
440
  font->vertical_centering = false;
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
#ifdef FT_BDF_H
  if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT))
    {
      BDF_PropertyRec rec;

      if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0
	  && rec.type == BDF_PROPERTY_TYPE_INTEGER)
	font->baseline_offset = rec.u.integer;
      if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0
	  && rec.type == BDF_PROPERTY_TYPE_INTEGER)
	font->relative_compose = rec.u.integer;
      if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0
	  && rec.type == BDF_PROPERTY_TYPE_INTEGER)
	font->default_ascent = rec.u.integer;
    }
#endif
457 458

  return font_object;
Kenichi Handa's avatar
Kenichi Handa committed
459 460 461
}

static void
462
xftfont_close (struct font *font)
Kenichi Handa's avatar
Kenichi Handa committed
463
{
464
  struct x_display_info *xdi;
Kenichi Handa's avatar
Kenichi Handa committed
465 466
  struct xftfont_info *xftfont_info = (struct xftfont_info *) font;

Kenichi Handa's avatar
Kenichi Handa committed
467 468
#ifdef HAVE_LIBOTF
  if (xftfont_info->otf)
469 470 471 472
    {
      OTF_close (xftfont_info->otf);
      xftfont_info->otf = NULL;
    }
Kenichi Handa's avatar
Kenichi Handa committed
473
#endif
474

475 476
  /* See comment in xfont_close.  */
  if (xftfont_info->xftfont
477 478
      && ((xdi = x_display_info_for_display (xftfont_info->display))
	  && xftfont_info->x_display_id == xdi->x_id))
479 480 481 482 483 484 485
    {
      block_input ();
      XftUnlockFace (xftfont_info->xftfont);
      XftFontClose (xftfont_info->display, xftfont_info->xftfont);
      unblock_input ();
      xftfont_info->xftfont = NULL;
    }
Kenichi Handa's avatar
Kenichi Handa committed
486 487
}

488
static void
Dmitry Antipov's avatar
Dmitry Antipov committed
489
xftfont_prepare_face (struct frame *f, struct face *face)
Kenichi Handa's avatar
Kenichi Handa committed
490
{
491
  struct xftface_info *xftface_info;
Kenichi Handa's avatar
Kenichi Handa committed
492

493
#if false
494
  /* This doesn't work if face->ascii_face doesn't use an Xft font. */
495 496 497
  if (face != face->ascii_face)
    {
      face->extra = face->ascii_face->extra;
498
      return;
499
    }
500
#endif
501

502
  xftface_info = xmalloc (sizeof *xftface_info);
Kenichi Handa's avatar
Kenichi Handa committed
503 504 505 506 507 508
  xftfont_get_colors (f, face, face->gc, NULL,
		      &xftface_info->xft_fg, &xftface_info->xft_bg);
  face->extra = xftface_info;
}

static void
Dmitry Antipov's avatar
Dmitry Antipov committed
509
xftfont_done_face (struct frame *f, struct face *face)
Kenichi Handa's avatar
Kenichi Handa committed
510
{
511
  struct xftface_info *xftface_info;
512

513
#if false
514
  /* This doesn't work if face->ascii_face doesn't use an Xft font. */
515 516 517
  if (face != face->ascii_face
      || ! face->extra)
    return;
518
#endif
Kenichi Handa's avatar
Kenichi Handa committed
519

520
  xftface_info = (struct xftface_info *) face->extra;
521 522
  if (xftface_info)
    {
523
      xfree (xftface_info);
524
      face->extra = NULL;
525
    }
Kenichi Handa's avatar
Kenichi Handa committed
526 527
}

528
static int
529
xftfont_has_char (Lisp_Object font, int c)
530 531
{
  struct xftfont_info *xftfont_info;
532
  struct charset *cs = NULL;
533

534 535 536 537 538 539 540 541 542
  if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
      && charset_jisx0208 >= 0)
    cs = CHARSET_FROM_ID (charset_jisx0208);
  else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
      && charset_ksc5601 >= 0)
    cs = CHARSET_FROM_ID (charset_ksc5601);
  if (cs)
    return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));

543
  if (FONT_ENTITY_P (font))
544
    return ftfont_has_char (font, c);
545 546 547 548 549
  xftfont_info = (struct xftfont_info *) XFONT_OBJECT (font);
  return (XftCharExists (xftfont_info->display, xftfont_info->xftfont,
			 (FcChar32) c) == FcTrue);
}

Kenichi Handa's avatar
Kenichi Handa committed
550
static unsigned
551
xftfont_encode_char (struct font *font, int c)
Kenichi Handa's avatar
Kenichi Handa committed
552 553 554 555
{
  struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
  unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont,
				(FcChar32) c);
556

557
  return (code ? code : FONT_INVALID_CODE);
Kenichi Handa's avatar
Kenichi Handa committed
558 559
}

560 561 562
static void
xftfont_text_extents (struct font *font, unsigned int *code,
		      int nglyphs, struct font_metrics *metrics)
Kenichi Handa's avatar
Kenichi Handa committed
563 564 565 566
{
  struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
  XGlyphInfo extents;

567
  block_input ();
Kenichi Handa's avatar
Kenichi Handa committed
568 569
  XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs,
		   &extents);
570
  unblock_input ();
571 572 573 574 575 576

  metrics->lbearing = - extents.x;
  metrics->rbearing = - extents.x + extents.width;
  metrics->width = extents.xOff;
  metrics->ascent = extents.y;
  metrics->descent = extents.height - extents.y;
Kenichi Handa's avatar
Kenichi Handa committed
577 578
}

579
static XftDraw *
Dmitry Antipov's avatar
Dmitry Antipov committed
580
xftfont_get_xft_draw (struct frame *f)
581
{
582
  XftDraw *xft_draw = font_get_frame_data (f, Qxft);
583 584 585

  if (! xft_draw)
    {
586
      block_input ();
587
      xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f),
588
                               FRAME_X_DRAWABLE (f),
589 590
			       FRAME_X_VISUAL (f),
			       FRAME_X_COLORMAP (f));
591
      unblock_input ();
592
      eassert (xft_draw != NULL);
593
      font_put_frame_data (f, Qxft, xft_draw);
594 595 596 597
    }
  return xft_draw;
}

Kenichi Handa's avatar
Kenichi Handa committed
598
static int
599 600
xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
              bool with_background)
Kenichi Handa's avatar
Kenichi Handa committed
601
{
602 603
  block_input ();

Dmitry Antipov's avatar
Dmitry Antipov committed
604
  struct frame *f = s->f;
Kenichi Handa's avatar
Kenichi Handa committed
605
  struct face *face = s->face;
606
  struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
607
  struct xftface_info *xftface_info = NULL;
608
  XftDraw *xft_draw = xftfont_get_xft_draw (f);
Kenichi Handa's avatar
Kenichi Handa committed
609 610 611 612 613
  FT_UInt *code;
  XftColor fg, bg;
  int len = to - from;
  int i;

614
  if (s->font == face->font)
615
    xftface_info = (struct xftface_info *) face->extra;
Kenichi Handa's avatar
Kenichi Handa committed
616
  xftfont_get_colors (f, face, s->gc, xftface_info,
617
		      &fg, with_background ? &bg : NULL);
618 619 620 621 622
  if (s->num_clips > 0)
    XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips);
  else
    XftDrawSetClip (xft_draw, NULL);

Kenichi Handa's avatar
Kenichi Handa committed
623
  if (with_background)
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
    {
      int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);

      /* Font's global height and ascent values might be
	 preposterously large for some fonts.  We fix here the case
	 when those fonts are used for display of glyphless
	 characters, because drawing background with font dimensions
	 in those cases makes the display illegible.  There's only one
	 more call to the draw method with with_background set to
	 true, and that's in x_draw_glyph_string_foreground, when
	 drawing the cursor, where we have no such heuristics
	 available.  FIXME.  */
      if (s->first_glyph->type == GLYPHLESS_GLYPH
	  && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
	      || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
	height = ascent =
	  s->first_glyph->slice.glyphless.lower_yoff
	  - s->first_glyph->slice.glyphless.upper_yoff;
      XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
    }
Kenichi Handa's avatar
Kenichi Handa committed
644 645 646 647 648
  code = alloca (sizeof (FT_UInt) * len);
  for (i = 0; i < len; i++)
    code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
	       | XCHAR2B_BYTE2 (s->char2b + from + i));

649 650 651 652 653 654
  if (s->padding_p)
    for (i = 0; i < len; i++)
      XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
		     x + i, y, code + i, 1);
  else
    XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont,
655 656 657 658 659
                   x, y, code, len);
  /* Need to explicitly mark the frame dirty because we didn't call
     FRAME_X_DRAWABLE in order to draw: we cached the drawable in the
     XftDraw structure.  */
  x_mark_frame_dirty (f);
660
  unblock_input ();
Kenichi Handa's avatar
Kenichi Handa committed
661 662 663
  return len;
}

664 665
#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
static Lisp_Object
666 667
xftfont_shape (Lisp_Object lgstring)
{
668 669
  struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
  struct xftfont_info *xftfont_info = (struct xftfont_info *) font;
670
  FT_Face ft_face = XftLockFace (xftfont_info->xftfont);
671
  xftfont_info->ft_size = ft_face->size;
672
  Lisp_Object val = ftfont_shape (lgstring);
673 674 675
  XftUnlockFace (xftfont_info->xftfont);
  return val;
}
676
#endif
677

678
static int
Dmitry Antipov's avatar
Dmitry Antipov committed
679
xftfont_end_for_frame (struct frame *f)
680
{
681
  block_input ();
682 683
  XftDraw *xft_draw;

684
  xft_draw = font_get_frame_data (f, Qxft);
685 686
  if (xft_draw)
    {
687
      block_input ();
688
      XftDrawDestroy (xft_draw);
689
      unblock_input ();
690
      font_put_frame_data (f, Qxft, NULL);
691
    }
692
  unblock_input ();
693 694
  return 0;
}
Kenichi Handa's avatar
Kenichi Handa committed
695

696 697 698 699
/* When using X double buffering, the XftDraw structure we build
   seems to be useless once a frame is resized, so recreate it on
   ConfigureNotify and in some other cases.  */

700 701 702 703 704 705 706 707 708
static void
xftfont_drop_xrender_surfaces (struct frame *f)
{
  block_input ();
  if (FRAME_X_DOUBLE_BUFFERED_P (f))
    xftfont_end_for_frame (f);
  unblock_input ();
}

709 710 711
static bool
xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
                        Lisp_Object entity)
712 713 714 715 716 717
{
  struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object);
  FcPattern *oldpat = info->xftfont->pattern;
  Display *display = FRAME_X_DISPLAY (f);
  FcPattern *pat = FcPatternCreate ();
  FcBool b1, b2;
718
  bool ok = false;
719
  int i1, i2, r1, r2;
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747

  xftfont_add_rendering_parameters (pat, entity);
  XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);

  r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1);
  r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2);
  if (r1 != r2 || b1 != b2) goto out;
  r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1);
  r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2);
  if (r1 != r2 || b1 != b2) goto out;
  r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1);
  r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2);
  if (r1 != r2 || b1 != b2) goto out;
#ifdef FC_EMBOLDEN
  r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1);
  r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2);
  if (r1 != r2 || b1 != b2) goto out;
#endif
  r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1);
  r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2);
  if (r1 != r2 || i1 != i2) goto out;
  r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1);
  r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2);
  if (r1 != r2 || i1 != i2) goto out;
  r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1);
  r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2);
  if (r1 != r2 || i1 != i2) goto out;

748
  ok = true;
749 750 751 752 753
 out:
  FcPatternDestroy (pat);
  return ok;
}

754 755 756
struct font_driver const xftfont_driver =
  {
    /* We can't draw a text without device dependent functions.  */
Paul Eggert's avatar
Paul Eggert committed
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
  .type = LISPSYM_INITIALLY (Qxft),
  .get_cache = xfont_get_cache,
  .list = xftfont_list,
  .match = xftfont_match,
  .list_family = ftfont_list_family,
  .open = xftfont_open,
  .close = xftfont_close,
  .prepare_face = xftfont_prepare_face,
  .done_face = xftfont_done_face,
  .has_char = xftfont_has_char,
  .encode_char = xftfont_encode_char,
  .text_extents = xftfont_text_extents,
  .draw = xftfont_draw,
  .get_bitmap = ftfont_get_bitmap,
  .anchor_point = ftfont_anchor_point,
772
#ifdef HAVE_LIBOTF
Paul Eggert's avatar
Paul Eggert committed
773
  .otf_capability = ftfont_otf_capability,
774
#endif
Paul Eggert's avatar
Paul Eggert committed
775
  .end_for_frame = xftfont_end_for_frame,
776
#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
Paul Eggert's avatar
Paul Eggert committed
777
  .shape = xftfont_shape,
778 779
#endif
#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
Paul Eggert's avatar
Paul Eggert committed
780
  .get_variation_glyphs = ftfont_variation_glyphs,
781
#endif
Paul Eggert's avatar
Paul Eggert committed
782 783 784 785
  .filter_properties = ftfont_filter_properties,
  .cached_font_ok = xftfont_cached_font_ok,
  .combining_capability = ftfont_combining_capability,
  .drop_xrender_surfaces = xftfont_drop_xrender_surfaces,
786 787
  };

Kenichi Handa's avatar
Kenichi Handa committed
788
void
789
syms_of_xftfont (void)
Kenichi Handa's avatar
Kenichi Handa committed
790 791
{
  DEFSYM (Qxft, "xft");
792
  DEFSYM (QChinting, ":hinting");
Chong Yidong's avatar
Chong Yidong committed
793
  DEFSYM (QCautohint, ":autohint");
794 795 796
  DEFSYM (QChintstyle, ":hintstyle");
  DEFSYM (QCrgba, ":rgba");
  DEFSYM (QCembolden, ":embolden");
797
  DEFSYM (QClcdfilter, ":lcdfilter");
Kenichi Handa's avatar
Kenichi Handa committed
798

799 800 801 802 803 804
  DEFVAR_BOOL ("xft-font-ascent-descent-override",
	       xft_font_ascent_descent_override,
	       doc:  /* Non-nil means override the ascent and descent values for Xft font driver.
This is needed with some fonts to correct vertical overlap of glyphs.  */);
  xft_font_ascent_descent_override = 0;

805 806
  ascii_printable[0] = 0;

Kenichi Handa's avatar
Kenichi Handa committed
807 808
  register_font_driver (&xftfont_driver, NULL);
}