ftfont.c 73 KB
Newer Older
Kenichi Handa's avatar
Kenichi Handa committed
1
/* ftfont.c -- FreeType 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

#include <config.h>
#include <stdio.h>
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>

27 28
#include <c-strcase.h>

Kenichi Handa's avatar
Kenichi Handa committed
29 30 31 32
#include "lisp.h"
#include "dispextern.h"
#include "character.h"
#include "charset.h"
33
#include "category.h"
Kenichi Handa's avatar
Kenichi Handa committed
34
#include "composite.h"
Kenichi Handa's avatar
Kenichi Handa committed
35
#include "font.h"
36
#include "ftfont.h"
Kenichi Handa's avatar
Kenichi Handa committed
37

38 39
static struct font_driver const ftfont_driver;

Juanma Barranquero's avatar
Juanma Barranquero committed
40
/* Flag to tell if FcInit is already called or not.  */
41
static bool fc_initialized;
42 43

/* Handle to a FreeType library instance.  */
Kenichi Handa's avatar
Kenichi Handa committed
44 45
static FT_Library ft_library;

46
/* Cache for FreeType fonts.  */
Kenichi Handa's avatar
Kenichi Handa committed
47 48
static Lisp_Object freetype_font_cache;

49
/* Cache for FT_Face and FcCharSet. */
Kenichi Handa's avatar
Kenichi Handa committed
50
static Lisp_Object ft_face_cache;
Kenichi Handa's avatar
Kenichi Handa committed
51

Paul Eggert's avatar
Paul Eggert committed
52
/* The actual structure for FreeType font that can be cast to struct
Kenichi Handa's avatar
Kenichi Handa committed
53 54 55 56 57
   font.  */

struct ftfont_info
{
  struct font font;
58
#ifdef HAVE_LIBOTF
59 60 61
  /* The following members up to and including 'matrix' must be here in
     this order to be compatible with struct xftfont_info (in
     xftfont.c).  */
62
  bool maybe_otf;	/* Flag to tell if this may be OTF or not.  */
63 64
  OTF *otf;
#endif	/* HAVE_LIBOTF */
65 66
  FT_Size ft_size;
  int index;
67
  FT_Matrix matrix;
Kenichi Handa's avatar
Kenichi Handa committed
68 69
};

Jan D's avatar
Jan D committed
70 71
size_t ftfont_info_size = sizeof (struct ftfont_info);

72 73 74 75 76 77 78
enum ftfont_cache_for
  {
    FTFONT_CACHE_FOR_FACE,
    FTFONT_CACHE_FOR_CHARSET,
    FTFONT_CACHE_FOR_ENTITY
  };

79 80
static Lisp_Object ftfont_lookup_cache (Lisp_Object,
                                        enum ftfont_cache_for);
81

82 83
#define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))

Kenichi Handa's avatar
Kenichi Handa committed
84
static struct
Kenichi Handa's avatar
Kenichi Handa committed
85
{
86
  /* registry name */
87
  const char *name;
Kenichi Handa's avatar
Kenichi Handa committed
88 89
  /* characters to distinguish the charset from the others */
  int uniquifier[6];
90
  /* additional constraint by language */
91
  const char *lang;
Kenichi Handa's avatar
Kenichi Handa committed
92 93 94
  /* set on demand */
  FcCharSet *fc_charset;
} fc_charset_table[] =
95
  { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
    { "iso8859-2", { 0x00A0, 0x010E }},
    { "iso8859-3", { 0x00A0, 0x0108 }},
    { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
    { "iso8859-5", { 0x00A0, 0x0401 }},
    { "iso8859-6", { 0x00A0, 0x060C }},
    { "iso8859-7", { 0x00A0, 0x0384 }},
    { "iso8859-8", { 0x00A0, 0x05D0 }},
    { "iso8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
    { "iso8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
    { "iso8859-11", { 0x00A0, 0x0E01 }},
    { "iso8859-13", { 0x00A0, 0x201C }},
    { "iso8859-14", { 0x00A0, 0x0174 }},
    { "iso8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
    { "iso8859-16", { 0x00A0, 0x0218}},
    { "gb2312.1980-0", { 0x4E13 }, "zh-cn"},
    { "big5-0", { 0xF6B1 }, "zh-tw" },
    { "jisx0208.1983-0", { 0x4E55 }, "ja"},
    { "ksc5601.1985-0", { 0xAC00 }, "ko"},
    { "cns11643.1992-1", { 0xFE32 }, "zh-tw"},
    { "cns11643.1992-2", { 0x4E33, 0x7934 }},
    { "cns11643.1992-3", { 0x201A9 }},
    { "cns11643.1992-4", { 0x20057 }},
    { "cns11643.1992-5", { 0x20000 }},
    { "cns11643.1992-6", { 0x20003 }},
    { "cns11643.1992-7", { 0x20055 }},
    { "gbk-0", { 0x4E06 }, "zh-cn"},
    { "jisx0212.1990-0", { 0x4E44 }},
    { "jisx0213.2000-1", { 0xFA10 }, "ja"},
    { "jisx0213.2000-2", { 0xFA49 }},
    { "jisx0213.2004-1", { 0x20B9F }},
    { "viscii1.1-1", { 0x1EA0, 0x1EAE, 0x1ED2 }, "vi"},
    { "tis620.2529-1", { 0x0E01 }, "th"},
128 129
    { "windows-1251", { 0x0401, 0x0490 }, "ru"},
    { "koi8-r", { 0x0401, 0x2219 }, "ru"},
130
    { "mulelao-1", { 0x0E81 }, "lo"},
131
    { "unicode-sip", { 0x20000 }},
Kenichi Handa's avatar
Kenichi Handa committed
132 133
    { NULL }
  };
Kenichi Handa's avatar
Kenichi Handa committed
134

135 136 137 138 139 140
static bool
matching_prefix (char const *str, ptrdiff_t len, char const *pat)
{
  return len == strlen (pat) && c_strncasecmp (str, pat, len) == 0;
}

Kenichi Handa's avatar
Kenichi Handa committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
/* Dirty hack for handing ADSTYLE property.

   Fontconfig (actually the underlying FreeType) gives such ADSTYLE
   font property of PCF/BDF fonts in FC_STYLE.  And, "Bold",
   "Oblique", "Italic", or any non-normal SWIDTH property names
   (e.g. SemiCondensed) are appended.  In addition, if there's no
   ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties,
   "Regular" is used for FC_STYLE (see the function
   pcf_interpret_style in src/pcf/pcfread.c of FreeType).

   Unfortunately this behavior is not documented, so the following
   code may fail if FreeType changes the behavior in the future.  */

static Lisp_Object
get_adstyle_property (FcPattern *p)
{
157 158
  FcChar8 *fcstr;
  char *str, *end;
Kenichi Handa's avatar
Kenichi Handa committed
159 160
  Lisp_Object adstyle;

161 162
#ifdef FC_FONTFORMAT
  if ((FcPatternGetString (p, FC_FONTFORMAT, 0, &fcstr) == FcResultMatch)
163 164
      && xstrcasecmp ((char *) fcstr, "bdf") != 0
      && xstrcasecmp ((char *) fcstr, "pcf") != 0)
165 166 167
    /* Not a BDF nor PCF font.  */
    return Qnil;
#endif
168
  if (FcPatternGetString (p, FC_STYLE, 0, &fcstr) != FcResultMatch)
Kenichi Handa's avatar
Kenichi Handa committed
169
    return Qnil;
170
  str = (char *) fcstr;
Kenichi Handa's avatar
Kenichi Handa committed
171
  for (end = str; *end && *end != ' '; end++);
172 173 174 175
  if (matching_prefix (str, end - str, "Regular")
      || matching_prefix (str, end - str, "Bold")
      || matching_prefix (str, end - str, "Oblique")
      || matching_prefix (str, end - str, "Italic"))
Kenichi Handa's avatar
Kenichi Handa committed
176
    return Qnil;
177
  adstyle = font_intern_prop (str, end - str, 1);
Kenichi Handa's avatar
Kenichi Handa committed
178 179 180 181 182
  if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
    return Qnil;
  return adstyle;
}

183
static Lisp_Object
184
ftfont_pattern_entity (FcPattern *p, Lisp_Object extra)
185
{
186
  Lisp_Object key, cache, entity;
187 188
  FcChar8 *str;
  char *file;
189
  int idx;
190 191
  int numeric;
  double dbl;
192
  FcBool b;
193

194
  if (FcPatternGetString (p, FC_FILE, 0, &str) != FcResultMatch)
195
    return Qnil;
196
  if (FcPatternGetInteger (p, FC_INDEX, 0, &idx) != FcResultMatch)
197
    return Qnil;
198

199
  file = (char *) str;
200
  key = Fcons (build_unibyte_string (file), make_number (idx));
201 202 203
  cache = ftfont_lookup_cache (key, FTFONT_CACHE_FOR_ENTITY);
  entity = XCAR (cache);
  if (! NILP (entity))
204 205 206 207 208 209
    {
      Lisp_Object val = font_make_entity ();
      int i;

      for (i = 0; i < FONT_OBJLIST_INDEX; i++)
	ASET (val, i, AREF (entity, i));
210 211 212 213

      ASET (val, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
      font_put_extra (val, QCfont_entity, key);

214 215
      return val;
    }
216
  entity = font_make_entity ();
217
  XSETCAR (cache, entity);
218 219

  ASET (entity, FONT_TYPE_INDEX, Qfreetype);
220
  ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
221

222 223 224 225 226 227 228 229 230 231
  if (FcPatternGetString (p, FC_FOUNDRY, 0, &str) == FcResultMatch)
    {
      char *s = (char *) str;
      ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (s, strlen (s), 1));
    }
  if (FcPatternGetString (p, FC_FAMILY, 0, &str) == FcResultMatch)
    {
      char *s = (char *) str;
      ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (s, strlen (s), 1));
    }
232
  if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
233
    {
234 235 236
      if (numeric >= FC_WEIGHT_REGULAR && numeric < FC_WEIGHT_MEDIUM)
	numeric = FC_WEIGHT_MEDIUM;
      FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, make_number (numeric));
237
    }
238
  if (FcPatternGetInteger (p, FC_SLANT, 0, &numeric) == FcResultMatch)
239 240 241 242
    {
      numeric += 100;
      FONT_SET_STYLE (entity, FONT_SLANT_INDEX, make_number (numeric));
    }
243
  if (FcPatternGetInteger (p, FC_WIDTH, 0, &numeric) == FcResultMatch)
244 245 246
    {
      FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric));
    }
247
  if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
Kenichi Handa's avatar
Kenichi Handa committed
248 249 250
    {
      ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
    }
251 252
  else
    ASET (entity, FONT_SIZE_INDEX, make_number (0));
253 254 255 256 257 258 259 260 261
  if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch)
    ASET (entity, FONT_SPACING_INDEX, make_number (numeric));
  if (FcPatternGetDouble (p, FC_DPI, 0, &dbl) == FcResultMatch)
    {
      int dpi = dbl;
      ASET (entity, FONT_DPI_INDEX, make_number (dpi));
    }
  if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
      && b == FcTrue)
262 263 264 265 266 267
    {
      ASET (entity, FONT_SIZE_INDEX, make_number (0));
      ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
    }
  else
    {
Paul Eggert's avatar
Paul Eggert committed
268
      /* As this font is not scalable, perhaps this is a BDF or PCF
269
	 font. */
270 271 272 273
      FT_Face ft_face;

      ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
      if ((ft_library || FT_Init_FreeType (&ft_library) == 0)
274
	  && FT_New_Face (ft_library, file, idx, &ft_face) == 0)
275 276 277 278 279 280 281 282 283
	{
	  BDF_PropertyRec rec;

	  if (FT_Get_BDF_Property (ft_face, "AVERAGE_WIDTH", &rec) == 0
	      && rec.type == BDF_PROPERTY_TYPE_INTEGER)
	    ASET (entity, FONT_AVGWIDTH_INDEX, make_number (rec.u.integer));
	  FT_Done_Face (ft_face);
	}
    }
284

285
  ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
286
  font_put_extra (entity, QCfont_entity, key);
287 288 289
  return entity;
}

290

291 292 293
static Lisp_Object ftfont_generic_family_list;

static Lisp_Object
294
ftfont_resolve_generic_family (Lisp_Object family, FcPattern *pattern)
295
{
296
  Lisp_Object slot;
297
  FcPattern *match;
298
  FcResult result;
Kenichi Handa's avatar
Kenichi Handa committed
299
  FcLangSet *langset;
300

301
  family = Fintern (Fdowncase (SYMBOL_NAME (family)), Qnil);
302 303 304 305 306 307
  if (EQ (family, Qmono))
    family = Qmonospace;
  else if (EQ (family, Qsans) || EQ (family, Qsans__serif))
    family = Qsans_serif;
  slot = assq_no_quit (family, ftfont_generic_family_list);
  if (! CONSP (slot))
308
    return Qnil;
309 310
  if (! EQ (XCDR (slot), Qt))
    return XCDR (slot);
311
  pattern = FcPatternDuplicate (pattern);
312 313
  if (! pattern)
    goto err;
314
  FcPatternDel (pattern, FC_FOUNDRY);
315 316
  FcPatternDel (pattern, FC_FAMILY);
  FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (family));
Kenichi Handa's avatar
Kenichi Handa committed
317 318 319
  if (FcPatternGetLangSet (pattern, FC_LANG, 0, &langset) != FcResultMatch)
    {
      /* This is to avoid the effect of locale.  */
320
      static const FcChar8 lang[] = "en";
Kenichi Handa's avatar
Kenichi Handa committed
321
      langset = FcLangSetCreate ();
322
      FcLangSetAdd (langset, lang);
Kenichi Handa's avatar
Kenichi Handa committed
323 324 325
      FcPatternAddLangSet (pattern, FC_LANG, langset);
      FcLangSetDestroy (langset);
    }
326
  FcConfigSubstitute (NULL, pattern, FcMatchPattern);
327 328 329
  FcDefaultSubstitute (pattern);
  match = FcFontMatch (NULL, pattern, &result);
  if (match)
330
    {
331 332 333 334
      FcChar8 *fam;

      if (FcPatternGetString (match, FC_FAMILY, 0, &fam) == FcResultMatch)
	family = intern ((char *) fam);
335
    }
336 337 338 339
  else
    family = Qnil;
  XSETCDR (slot, family);
  if (match) FcPatternDestroy (match);
340
 err:
341
  if (pattern) FcPatternDestroy (pattern);
342
  return family;
343 344
}

345 346 347 348 349 350 351
struct ftfont_cache_data
{
  FT_Face ft_face;
  FcCharSet *fc_charset;
};

static Lisp_Object
352
ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for)
Kenichi Handa's avatar
Kenichi Handa committed
353
{
Kenichi Handa's avatar
Kenichi Handa committed
354
  Lisp_Object cache, val, entity;
355
  struct ftfont_cache_data *cache_data;
Kenichi Handa's avatar
Kenichi Handa committed
356

Kenichi Handa's avatar
Kenichi Handa committed
357 358 359 360
  if (FONT_ENTITY_P (key))
    {
      entity = key;
      val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
361
      eassert (CONSP (val));
Kenichi Handa's avatar
Kenichi Handa committed
362 363 364 365 366
      key = XCDR (val);
    }
  else
    entity = Qnil;

367 368 369 370
  if (NILP (ft_face_cache))
    cache = Qnil;
  else
    cache = Fgethash (key, ft_face_cache, Qnil);
Kenichi Handa's avatar
Kenichi Handa committed
371 372
  if (NILP (cache))
    {
373
      if (NILP (ft_face_cache))
374
	ft_face_cache = CALLN (Fmake_hash_table, QCtest, Qequal);
375
      cache_data = xmalloc (sizeof *cache_data);
376 377
      cache_data->ft_face = NULL;
      cache_data->fc_charset = NULL;
378
      val = make_save_ptr_int (cache_data, 0);
379 380
      cache = Fcons (Qnil, val);
      Fputhash (key, cache, ft_face_cache);
Kenichi Handa's avatar
Kenichi Handa committed
381 382 383
    }
  else
    {
384
      val = XCDR (cache);
385
      cache_data = XSAVE_POINTER (val, 0);
386
    }
387 388 389 390 391 392

  if (cache_for == FTFONT_CACHE_FOR_ENTITY)
    return cache;

  if (cache_for == FTFONT_CACHE_FOR_FACE
      ? ! cache_data->ft_face : ! cache_data->fc_charset)
393
    {
394
      char *filename = SSDATA (XCAR (key));
395
      int idx = XINT (XCDR (key));
Kenichi Handa's avatar
Kenichi Handa committed
396

397
      if (cache_for == FTFONT_CACHE_FOR_FACE)
398 399 400 401
	{
	  if (! ft_library
	      && FT_Init_FreeType (&ft_library) != 0)
	    return Qnil;
402
	  if (FT_New_Face (ft_library, filename, idx, &cache_data->ft_face)
403 404 405 406 407
	      != 0)
	    return Qnil;
	}
      else
	{
Kenichi Handa's avatar
Kenichi Handa committed
408 409 410 411
	  FcPattern *pat = NULL;
	  FcFontSet *fontset = NULL;
	  FcObjectSet *objset = NULL;
	  FcCharSet *charset = NULL;
412 413

	  pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename,
414
				FC_INDEX, FcTypeInteger, idx, NULL);
Kenichi Handa's avatar
Kenichi Handa committed
415 416 417 418 419
	  if (! pat)
	    goto finish;
	  objset = FcObjectSetBuild (FC_CHARSET, FC_STYLE, NULL);
	  if (! objset)
	    goto finish;
420
	  fontset = FcFontList (NULL, pat, objset);
Kenichi Handa's avatar
Kenichi Handa committed
421 422
	  if (! fontset)
	    goto finish;
423 424
	  if (fontset && fontset->nfont > 0
	      && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
425
				       &charset)
426 427
		  == FcResultMatch))
	    cache_data->fc_charset = FcCharSetCopy (charset);
428 429
	  else
	    cache_data->fc_charset = FcCharSetCreate ();
Kenichi Handa's avatar
Kenichi Handa committed
430 431 432 433 434 435 436 437

	finish:
	  if (fontset)
	    FcFontSetDestroy (fontset);
	  if (objset)
	    FcObjectSetDestroy (objset);
	  if (pat)
	    FcPatternDestroy (pat);
438
	}
Kenichi Handa's avatar
Kenichi Handa committed
439 440 441 442
    }
  return cache;
}

443
FcCharSet *
444
ftfont_get_fc_charset (Lisp_Object entity)
445 446 447 448
{
  Lisp_Object val, cache;
  struct ftfont_cache_data *cache_data;

449
  cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
450
  val = XCDR (cache);
451
  cache_data = XSAVE_POINTER (val, 0);
452 453 454 455 456
  return cache_data->fc_charset;
}

#ifdef HAVE_LIBOTF
static OTF *
Andreas Schwab's avatar
Andreas Schwab committed
457
ftfont_get_otf (struct ftfont_info *ftfont_info)
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
{
  OTF *otf;

  if (ftfont_info->otf)
    return ftfont_info->otf;
  if (! ftfont_info->maybe_otf)
    return NULL;
  otf = OTF_open_ft_face (ftfont_info->ft_size->face);
  if (! otf || OTF_get_table (otf, "head") < 0)
    {
      if (otf)
	OTF_close (otf);
      ftfont_info->maybe_otf = 0;
      return NULL;
    }
  ftfont_info->otf = otf;
  return otf;
}
#endif	/* HAVE_LIBOTF */

478
Lisp_Object
Dmitry Antipov's avatar
Dmitry Antipov committed
479
ftfont_get_cache (struct frame *f)
Kenichi Handa's avatar
Kenichi Handa committed
480 481 482 483
{
  return freetype_font_cache;
}

Kenichi Handa's avatar
Kenichi Handa committed
484
static int
485
ftfont_get_charset (Lisp_Object registry)
Kenichi Handa's avatar
Kenichi Handa committed
486
{
487
  char *str = SSDATA (SYMBOL_NAME (registry));
488 489
  USE_SAFE_ALLOCA;
  char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
Kenichi Handa's avatar
Kenichi Handa committed
490 491
  int i, j;

492 493 494 495 496 497 498 499 500 501 502
  for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
    {
      if (str[i] == '.')
	re[j++] = '\\';
      else if (str[i] == '*')
	re[j++] = '.';
      re[j] = str[i];
      if (re[j] == '?')
	re[j] = '.';
    }
  re[j] = '\0';
Paul Eggert's avatar
Paul Eggert committed
503
  AUTO_STRING_WITH_LEN (regexp, re, j);
Kenichi Handa's avatar
Kenichi Handa committed
504
  for (i = 0; fc_charset_table[i].name; i++)
505 506 507
    if (fast_c_string_match_ignore_case
	(regexp, fc_charset_table[i].name,
	 strlen (fc_charset_table[i].name)) >= 0)
Kenichi Handa's avatar
Kenichi Handa committed
508
      break;
Paul Eggert's avatar
Paul Eggert committed
509
  SAFE_FREE ();
Kenichi Handa's avatar
Kenichi Handa committed
510 511 512 513
  if (! fc_charset_table[i].name)
    return -1;
  if (! fc_charset_table[i].fc_charset)
    {
514 515
      FcCharSet *charset = FcCharSetCreate ();
      int *uniquifier = fc_charset_table[i].uniquifier;
Kenichi Handa's avatar
Kenichi Handa committed
516

517 518 519 520 521 522
      if (! charset)
	return -1;
      for (j = 0; uniquifier[j]; j++)
	if (! FcCharSetAddChar (charset, uniquifier[j]))
	  {
	    FcCharSetDestroy (charset);
Kenichi Handa's avatar
Kenichi Handa committed
523
	    return -1;
524 525
	  }
      fc_charset_table[i].fc_charset = charset;
Kenichi Handa's avatar
Kenichi Handa committed
526 527 528 529
    }
  return i;
}

530 531
struct OpenTypeSpec
{
532 533
  Lisp_Object script;
  unsigned int script_tag, langsys_tag;
534 535 536 537
  int nfeatures[2];
  unsigned int *features[2];
};

538
#define OTF_SYM_TAG(SYM, TAG)					\
539
  do {								\
540 541
    unsigned char *p = SDATA (SYMBOL_NAME (SYM));		\
    TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];	\
542 543
  } while (0)

544
#define OTF_TAG_STR(TAG, P)			\
545
  do {						\
546 547 548 549
    (P)[0] = (char) (TAG >> 24);		\
    (P)[1] = (char) ((TAG >> 16) & 0xFF);	\
    (P)[2] = (char) ((TAG >> 8) & 0xFF);	\
    (P)[3] = (char) (TAG & 0xFF);		\
550
    (P)[4] = '\0';				\
551 552
  } while (0)

553
#ifdef HAVE_LIBOTF
554 555 556 557 558 559 560
#define OTF_TAG_SYM(SYM, TAG)			\
  do {						\
    char str[5];				\
    						\
    OTF_TAG_STR (TAG, str);			\
    (SYM) = font_intern_prop (str, 4, 1);	\
  } while (0)
561
#endif
562 563


564 565 566
static struct OpenTypeSpec *
ftfont_get_open_type_spec (Lisp_Object otf_spec)
{
567
  struct OpenTypeSpec *spec = malloc (sizeof *spec);
568
  Lisp_Object val;
569 570
  int i, j;
  bool negative;
571 572 573

  if (! spec)
    return NULL;
574
  spec->script = XCAR (otf_spec);
575
  if (! NILP (spec->script))
576 577 578 579 580 581 582 583
    {
      OTF_SYM_TAG (spec->script, spec->script_tag);
      val = assq_no_quit (spec->script, Votf_script_alist);
      if (CONSP (val) && SYMBOLP (XCDR (val)))
	spec->script = XCDR (val);
      else
	spec->script = Qnil;
    }
584
  else
585
    spec->script_tag = 0x44464C54; 	/* "DFLT" */
586
  otf_spec = XCDR (otf_spec);
Kenichi Handa's avatar
Kenichi Handa committed
587 588 589 590 591 592 593 594
  spec->langsys_tag = 0;
  if (! NILP (otf_spec))
    {
      val = XCAR (otf_spec);
      if (! NILP (val))
	OTF_SYM_TAG (val, spec->langsys_tag);
      otf_spec = XCDR (otf_spec);
    }
595
  spec->nfeatures[0] = spec->nfeatures[1] = 0;
Kenichi Handa's avatar
Kenichi Handa committed
596
  for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
597 598 599 600 601 602 603
    {
      Lisp_Object len;

      val = XCAR (otf_spec);
      if (NILP (val))
	continue;
      len = Flength (val);
604 605 606
      spec->features[i] =
	(min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
	 ? 0
607
	 : malloc (XINT (len) * sizeof *spec->features[i]));
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
      if (! spec->features[i])
	{
	  if (i > 0 && spec->features[0])
	    free (spec->features[0]);
	  free (spec);
	  return NULL;
	}
      for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
	{
	  if (NILP (XCAR (val)))
	    negative = 1;
	  else
	    {
	      unsigned int tag;

	      OTF_SYM_TAG (XCAR (val), tag);
	      spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
	    }
	}
      spec->nfeatures[i] = j;
    }
  return spec;
}

632
static FcPattern *
633
ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **otspec, const char **langname)
Kenichi Handa's avatar
Kenichi Handa committed
634
{
Kenichi Handa's avatar
Kenichi Handa committed
635
  Lisp_Object tmp, extra;
Kenichi Handa's avatar
Kenichi Handa committed
636 637 638
  FcPattern *pattern = NULL;
  FcCharSet *charset = NULL;
  FcLangSet *langset = NULL;
639 640
  int n;
  int dpi = -1;
641
  int scalable = -1;
642
  Lisp_Object script = Qnil;
Kenichi Handa's avatar
Kenichi Handa committed
643
  Lisp_Object registry;
644
  int fc_charset_idx;
Kenichi Handa's avatar
Kenichi Handa committed
645

646 647
  if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
      && n < 100)
Paul Eggert's avatar
Paul Eggert committed
648
    /* Fontconfig doesn't support reverse-italic/oblique.  */
649 650 651 652 653 654 655
    return NULL;

  if (INTEGERP (AREF (spec, FONT_DPI_INDEX)))
    dpi = XINT (AREF (spec, FONT_DPI_INDEX));
  if (INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
      && XINT (AREF (spec, FONT_AVGWIDTH_INDEX)) == 0)
    scalable = 1;
656

Kenichi Handa's avatar
Kenichi Handa committed
657 658
  registry = AREF (spec, FONT_REGISTRY_INDEX);
  if (NILP (registry)
659
      || EQ (registry, Qascii_0)
Kenichi Handa's avatar
Kenichi Handa committed
660
      || EQ (registry, Qiso10646_1)
661
      || EQ (registry, Qunicode_bmp))
662
    fc_charset_idx = -1;
Kenichi Handa's avatar
Kenichi Handa committed
663
  else
Kenichi Handa's avatar
Kenichi Handa committed
664
    {
665 666
      FcChar8 *lang;

667 668
      fc_charset_idx = ftfont_get_charset (registry);
      if (fc_charset_idx < 0)
669
	return NULL;
670
      charset = fc_charset_table[fc_charset_idx].fc_charset;
671 672
      *langname = fc_charset_table[fc_charset_idx].lang;
      lang = (FcChar8 *) *langname;
673 674 675 676 677 678 679
      if (lang)
	{
	  langset = FcLangSetCreate ();
	  if (! langset)
	    goto err;
	  FcLangSetAdd (langset, lang);
	}
Kenichi Handa's avatar
Kenichi Handa committed
680 681
    }

682
  otlayout[0] = '\0';
683 684
  for (extra = AREF (spec, FONT_EXTRA_INDEX);
       CONSP (extra); extra = XCDR (extra))
Kenichi Handa's avatar
Kenichi Handa committed
685
    {
686 687
      Lisp_Object key, val;

688 689
      key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
      if (EQ (key, QCdpi))
690 691 692 693
	{
	  if (INTEGERP (val))
	    dpi = XINT (val);
	}
694
      else if (EQ (key, QClang))
Kenichi Handa's avatar
Kenichi Handa committed
695
	{
696 697
	  if (! langset)
	    langset = FcLangSetCreate ();
Kenichi Handa's avatar
Kenichi Handa committed
698 699
	  if (! langset)
	    goto err;
700
	  if (SYMBOLP (val))
Kenichi Handa's avatar
Kenichi Handa committed
701
	    {
702
	      if (! FcLangSetAdd (langset, SYMBOL_FcChar8 (val)))
Kenichi Handa's avatar
Kenichi Handa committed
703 704 705
		goto err;
	    }
	  else
706 707 708 709
	    for (; CONSP (val); val = XCDR (val))
	      if (SYMBOLP (XCAR (val))
		  && ! FcLangSetAdd (langset, SYMBOL_FcChar8 (XCAR (val))))
		goto err;
Kenichi Handa's avatar
Kenichi Handa committed
710
	}
711 712
      else if (EQ (key, QCotf))
	{
713 714 715 716 717
	  if (CONSP (val))
	    {
	      *otspec = ftfont_get_open_type_spec (val);
	      if (! *otspec)
		return NULL;
718
	      strcpy (otlayout, "otlayout:");
719 720 721
	      OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
	      script = (*otspec)->script;
	    }
722
	}
723 724 725 726 727
      else if (EQ (key, QCscript))
	script = val;
      else if (EQ (key, QCscalable))
	scalable = ! NILP (val);
    }
Kenichi Handa's avatar
Kenichi Handa committed
728

729 730 731 732
  if (! NILP (script) && ! charset)
    {
      Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);

733
      if (CONSP (chars) && CONSP (CDR (chars)))
734 735 736 737 738 739
	{
	  charset = FcCharSetCreate ();
	  if (! charset)
	    goto err;
	  for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
	    if (CHARACTERP (XCAR (chars))
740
		&& ! FcCharSetAddChar (charset, XFASTINT (XCAR (chars))))
741
	      goto err;
Kenichi Handa's avatar
Kenichi Handa committed
742 743 744
	}
    }

745
  pattern = FcPatternCreate ();
746 747 748
  if (! pattern)
    goto err;
  tmp = AREF (spec, FONT_FOUNDRY_INDEX);
749
  if (! NILP (tmp)
750 751
      && ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
    goto err;
752 753 754 755
  tmp = AREF (spec, FONT_FAMILY_INDEX);
  if (! NILP (tmp)
      && ! FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (tmp)))
    goto err;
Kenichi Handa's avatar
Kenichi Handa committed
756 757 758 759 760 761
  if (charset
      && ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
    goto err;
  if (langset
      && ! FcPatternAddLangSet (pattern, FC_LANG, langset))
    goto err;
762 763 764 765
  if (dpi >= 0
      && ! FcPatternAddDouble (pattern, FC_DPI, dpi))
    goto err;
  if (scalable >= 0
Kenichi Handa's avatar
Kenichi Handa committed
766
      && ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
767
    goto err;
768
#if defined HAVE_XFT && defined FC_COLOR
769 770 771
  /* We really don't like color fonts, they cause Xft crashes.  See
     Bug#30874.  */
  if (Vxft_ignore_color_fonts
772
      && ! FcPatternAddBool (pattern, FC_COLOR, FcFalse))
773 774
    goto err;
#endif
775

776
  goto finish;
Kenichi Handa's avatar
Kenichi Handa committed
777

778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
 err:
  /* We come here because of unexpected error in fontconfig API call
     (usually insufficient memory).  */
  if (pattern)
    {
      FcPatternDestroy (pattern);
      pattern = NULL;
    }
  if (*otspec)
    {
      if ((*otspec)->nfeatures[0] > 0)
	free ((*otspec)->features[0]);
      if ((*otspec)->nfeatures[1] > 0)
	free ((*otspec)->features[1]);
      free (*otspec);
      *otspec = NULL;
    }

 finish:
  if (langset) FcLangSetDestroy (langset);
798
  if (charset && fc_charset_idx < 0) FcCharSetDestroy (charset);
799 800 801
  return pattern;
}

802
Lisp_Object
803
ftfont_list (struct frame *f, Lisp_Object spec)
804
{
Kenichi Handa's avatar
Kenichi Handa committed
805
  Lisp_Object val = Qnil, family, adstyle;
806 807 808 809
  int i;
  FcPattern *pattern;
  FcFontSet *fontset = NULL;
  FcObjectSet *objset = NULL;
810 811
  FcCharSet *charset;
  Lisp_Object chars = Qnil;
812 813
  char otlayout[15];		/* For "otlayout:XXXX" */
  struct OpenTypeSpec *otspec = NULL;
814
  int spacing = -1;
815
  const char *langname = NULL;
Juanma Barranquero's avatar
Juanma Barranquero committed
816

817 818 819 820 821 822
  if (! fc_initialized)
    {
      FcInit ();
      fc_initialized = 1;
    }

823
  pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
824 825
  if (! pattern)
    return Qnil;
826 827 828 829 830 831 832 833 834 835 836
  if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
    {
      val = assq_no_quit (QCscript, AREF (spec, FONT_EXTRA_INDEX));
      if (! NILP (val))
	{
	  val = assq_no_quit (XCDR (val), Vscript_representative_chars);
	  if (CONSP (val) && VECTORP (XCDR (val)))
	    chars = XCDR (val);
	}
      val = Qnil;
    }
837 838
  if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
    spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
839 840 841 842 843
  family = AREF (spec, FONT_FAMILY_INDEX);
  if (! NILP (family))
    {
      Lisp_Object resolved;

844
      resolved = ftfont_resolve_generic_family (family, pattern);
845 846 847 848 849 850 851 852
      if (! NILP (resolved))
	{
	  FcPatternDel (pattern, FC_FAMILY);
	  if (! FcPatternAddString (pattern, FC_FAMILY,
				    SYMBOL_FcChar8 (resolved)))
	    goto err;
	}
    }
Kenichi Handa's avatar
Kenichi Handa committed
853 854 855
  adstyle = AREF (spec, FONT_ADSTYLE_INDEX);
  if (! NILP (adstyle) && SBYTES (SYMBOL_NAME (adstyle)) == 0)
    adstyle = Qnil;
856
  objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
857
			     FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
Kenichi Handa's avatar
Kenichi Handa committed
858
			     FC_STYLE, FC_FILE, FC_INDEX,
859 860 861
#ifdef FC_CAPABILITY
			     FC_CAPABILITY,
#endif	/* FC_CAPABILITY */
862 863 864
#ifdef FC_FONTFORMAT
			     FC_FONTFORMAT,
#endif
865
			     NULL);
866 867
  if (! objset)
    goto err;
868 869
  if (! NILP (chars))
    FcObjectSetAdd (objset, FC_CHARSET);
870

871
  fontset = FcFontList (NULL, pattern, objset);
872 873
  if (! fontset || fontset->nfont == 0)
    goto finish;
874 875 876 877
#if 0
  /* Need fix because this finds any fonts.  */
  if (fontset->nfont == 0 && ! NILP (family))
    {
Paul Eggert's avatar
Paul Eggert committed
878
      /* Try matching with configuration.  For instance, the
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
	 configuration may specify "Nimbus Mono L" as an alias of
	 "Courier".  */
      FcPattern *pat = FcPatternBuild (0, FC_FAMILY, FcTypeString,
				       SYMBOL_FcChar8 (family), NULL);
      FcChar8 *fam;

      if (FcConfigSubstitute (NULL, pat, FcMatchPattern) == FcTrue)
	{
	  for (i = 0;
	       FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
	       i++)
	    {
	      FcPatternDel (pattern, FC_FAMILY);
	      FcPatternAddString (pattern, FC_FAMILY, fam);
	      FcFontSetDestroy (fontset);
	      fontset = FcFontList (NULL, pattern, objset);
895
	      if (fontset && fontset->nfont > 0)
896 897 898 899 900
		break;
	    }
	}
    }
#endif
901
  for (i = 0; i < fontset->nfont; i++)
902
    {
903
      Lisp_Object entity;
904

905 906 907 908 909 910 911 912 913 914
      if (spacing >= 0)
	{
	  int this;

	  if ((FcPatternGetInteger (fontset->fonts[i], FC_SPACING, 0, &this)
	       == FcResultMatch)
	      && spacing != this)
	    continue;
	}

915
#ifdef FC_CAPABILITY
916 917 918
      if (otlayout[0])
	{
	  FcChar8 *this;