ftfont.c 71 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-2015 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 <http://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 33 34 35
#include "lisp.h"
#include "dispextern.h"
#include "frame.h"
#include "blockinput.h"
#include "character.h"
#include "charset.h"
#include "coding.h"
Kenichi Handa's avatar
Kenichi Handa committed
36
#include "composite.h"
Kenichi Handa's avatar
Kenichi Handa committed
37 38
#include "fontset.h"
#include "font.h"
39
#include "ftfont.h"
Kenichi Handa's avatar
Kenichi Handa committed
40

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

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

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

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

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

struct ftfont_info
{
  struct font font;
59
#ifdef HAVE_LIBOTF
60
  /* The following four members must be here in this order to be
61
     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
};

70 71 72 73 74 75 76
enum ftfont_cache_for
  {
    FTFONT_CACHE_FOR_FACE,
    FTFONT_CACHE_FOR_CHARSET,
    FTFONT_CACHE_FOR_ENTITY
  };

77
static Lisp_Object ftfont_pattern_entity (FcPattern *, Lisp_Object);
Kenichi Handa's avatar
Kenichi Handa committed
78

79 80 81 82
static Lisp_Object ftfont_resolve_generic_family (Lisp_Object,
                                                  FcPattern *);
static Lisp_Object ftfont_lookup_cache (Lisp_Object,
                                        enum ftfont_cache_for);
83

84
static void ftfont_filter_properties (Lisp_Object font, Lisp_Object alist);
85

86 87
#define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))

Kenichi Handa's avatar
Kenichi Handa committed
88
static struct
Kenichi Handa's avatar
Kenichi Handa committed
89
{
90
  /* registry name */
91
  const char *name;
Kenichi Handa's avatar
Kenichi Handa committed
92 93
  /* characters to distinguish the charset from the others */
  int uniquifier[6];
94
  /* additional constraint by language */
95
  const char *lang;
Kenichi Handa's avatar
Kenichi Handa committed
96 97 98
  /* set on demand */
  FcCharSet *fc_charset;
} fc_charset_table[] =
99
  { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
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 128 129 130 131
    { "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"},
132 133
    { "windows-1251", { 0x0401, 0x0490 }, "ru"},
    { "koi8-r", { 0x0401, 0x2219 }, "ru"},
134
    { "mulelao-1", { 0x0E81 }, "lo"},
135
    { "unicode-sip", { 0x20000 }},
Kenichi Handa's avatar
Kenichi Handa committed
136 137
    { NULL }
  };
Kenichi Handa's avatar
Kenichi Handa committed
138

139 140 141 142 143 144
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
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
/* 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)
{
161 162
  FcChar8 *fcstr;
  char *str, *end;
Kenichi Handa's avatar
Kenichi Handa committed
163 164
  Lisp_Object adstyle;

165 166
#ifdef FC_FONTFORMAT
  if ((FcPatternGetString (p, FC_FONTFORMAT, 0, &fcstr) == FcResultMatch)
167 168
      && xstrcasecmp ((char *) fcstr, "bdf") != 0
      && xstrcasecmp ((char *) fcstr, "pcf") != 0)
169 170 171
    /* Not a BDF nor PCF font.  */
    return Qnil;
#endif
172
  if (FcPatternGetString (p, FC_STYLE, 0, &fcstr) != FcResultMatch)
Kenichi Handa's avatar
Kenichi Handa committed
173
    return Qnil;
174
  str = (char *) fcstr;
Kenichi Handa's avatar
Kenichi Handa committed
175
  for (end = str; *end && *end != ' '; end++);
176 177 178 179
  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
180
    return Qnil;
181
  adstyle = font_intern_prop (str, end - str, 1);
Kenichi Handa's avatar
Kenichi Handa committed
182 183 184 185 186
  if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
    return Qnil;
  return adstyle;
}

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

198
  if (FcPatternGetString (p, FC_FILE, 0, &str) != FcResultMatch)
199
    return Qnil;
200
  if (FcPatternGetInteger (p, FC_INDEX, 0, &idx) != FcResultMatch)
201
    return Qnil;
202

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

      for (i = 0; i < FONT_OBJLIST_INDEX; i++)
	ASET (val, i, AREF (entity, i));
214 215 216 217

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

218 219
      return val;
    }
220
  entity = font_make_entity ();
221
  XSETCAR (cache, entity);
222 223

  ASET (entity, FONT_TYPE_INDEX, Qfreetype);
224
  ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
225

226 227 228 229 230 231 232 233 234 235
  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));
    }
236
  if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
237
    {
238 239 240
      if (numeric >= FC_WEIGHT_REGULAR && numeric < FC_WEIGHT_MEDIUM)
	numeric = FC_WEIGHT_MEDIUM;
      FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, make_number (numeric));
241
    }
242
  if (FcPatternGetInteger (p, FC_SLANT, 0, &numeric) == FcResultMatch)
243 244 245 246
    {
      numeric += 100;
      FONT_SET_STYLE (entity, FONT_SLANT_INDEX, make_number (numeric));
    }
247
  if (FcPatternGetInteger (p, FC_WIDTH, 0, &numeric) == FcResultMatch)
248 249 250
    {
      FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric));
    }
251
  if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
Kenichi Handa's avatar
Kenichi Handa committed
252 253 254
    {
      ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
    }
255 256
  else
    ASET (entity, FONT_SIZE_INDEX, make_number (0));
257 258 259 260 261 262 263 264 265
  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)
266 267 268 269 270 271
    {
      ASET (entity, FONT_SIZE_INDEX, make_number (0));
      ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
    }
  else
    {
Paul Eggert's avatar
Paul Eggert committed
272
      /* As this font is not scalable, perhaps this is a BDF or PCF
273
	 font. */
274 275 276 277
      FT_Face ft_face;

      ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
      if ((ft_library || FT_Init_FreeType (&ft_library) == 0)
278
	  && FT_New_Face (ft_library, file, idx, &ft_face) == 0)
279 280 281 282 283 284 285 286 287
	{
	  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);
	}
    }
288

289
  ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
290
  font_put_extra (entity, QCfont_entity, key);
291 292 293
  return entity;
}

294

295 296 297
static Lisp_Object ftfont_generic_family_list;

static Lisp_Object
298
ftfont_resolve_generic_family (Lisp_Object family, FcPattern *pattern)
299
{
300
  Lisp_Object slot;
301
  FcPattern *match;
302
  FcResult result;
Kenichi Handa's avatar
Kenichi Handa committed
303
  FcLangSet *langset;
304

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

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

349 350 351 352 353 354 355
struct ftfont_cache_data
{
  FT_Face ft_face;
  FcCharSet *fc_charset;
};

static Lisp_Object
356
ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for)
Kenichi Handa's avatar
Kenichi Handa committed
357
{
Kenichi Handa's avatar
Kenichi Handa committed
358
  Lisp_Object cache, val, entity;
359
  struct ftfont_cache_data *cache_data;
Kenichi Handa's avatar
Kenichi Handa committed
360

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

371 372 373 374
  if (NILP (ft_face_cache))
    cache = Qnil;
  else
    cache = Fgethash (key, ft_face_cache, Qnil);
Kenichi Handa's avatar
Kenichi Handa committed
375 376
  if (NILP (cache))
    {
377 378 379 380 381 382 383 384
      if (NILP (ft_face_cache))
	{
	  Lisp_Object args[2];

	  args[0] = QCtest;
	  args[1] = Qequal;
	  ft_face_cache = Fmake_hash_table (2, args);
	}
385
      cache_data = xmalloc (sizeof *cache_data);
386 387
      cache_data->ft_face = NULL;
      cache_data->fc_charset = NULL;
388
      val = make_save_ptr_int (cache_data, 0);
389 390
      cache = Fcons (Qnil, val);
      Fputhash (key, cache, ft_face_cache);
Kenichi Handa's avatar
Kenichi Handa committed
391 392 393
    }
  else
    {
394
      val = XCDR (cache);
395
      cache_data = XSAVE_POINTER (val, 0);
396
    }
397 398 399 400 401 402

  if (cache_for == FTFONT_CACHE_FOR_ENTITY)
    return cache;

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

407
      if (cache_for == FTFONT_CACHE_FOR_FACE)
408 409 410 411
	{
	  if (! ft_library
	      && FT_Init_FreeType (&ft_library) != 0)
	    return Qnil;
412
	  if (FT_New_Face (ft_library, filename, idx, &cache_data->ft_face)
413 414 415 416 417
	      != 0)
	    return Qnil;
	}
      else
	{
Kenichi Handa's avatar
Kenichi Handa committed
418 419 420 421
	  FcPattern *pat = NULL;
	  FcFontSet *fontset = NULL;
	  FcObjectSet *objset = NULL;
	  FcCharSet *charset = NULL;
422 423

	  pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename,
424
				FC_INDEX, FcTypeInteger, idx, NULL);
Kenichi Handa's avatar
Kenichi Handa committed
425 426 427 428 429
	  if (! pat)
	    goto finish;
	  objset = FcObjectSetBuild (FC_CHARSET, FC_STYLE, NULL);
	  if (! objset)
	    goto finish;
430
	  fontset = FcFontList (NULL, pat, objset);
Kenichi Handa's avatar
Kenichi Handa committed
431 432
	  if (! fontset)
	    goto finish;
433 434
	  if (fontset && fontset->nfont > 0
	      && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
435
				       &charset)
436 437
		  == FcResultMatch))
	    cache_data->fc_charset = FcCharSetCopy (charset);
438 439
	  else
	    cache_data->fc_charset = FcCharSetCreate ();
Kenichi Handa's avatar
Kenichi Handa committed
440 441 442 443 444 445 446 447

	finish:
	  if (fontset)
	    FcFontSetDestroy (fontset);
	  if (objset)
	    FcObjectSetDestroy (objset);
	  if (pat)
	    FcPatternDestroy (pat);
448
	}
Kenichi Handa's avatar
Kenichi Handa committed
449 450 451 452
    }
  return cache;
}

453
FcCharSet *
454
ftfont_get_fc_charset (Lisp_Object entity)
455 456 457 458
{
  Lisp_Object val, cache;
  struct ftfont_cache_data *cache_data;

459
  cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
460
  val = XCDR (cache);
461
  cache_data = XSAVE_POINTER (val, 0);
462 463 464 465 466
  return cache_data->fc_charset;
}

#ifdef HAVE_LIBOTF
static OTF *
Andreas Schwab's avatar
Andreas Schwab committed
467
ftfont_get_otf (struct ftfont_info *ftfont_info)
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
{
  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 */

Dmitry Antipov's avatar
Dmitry Antipov committed
488
static Lisp_Object ftfont_get_cache (struct frame *);
489 490 491
static Lisp_Object ftfont_list (struct frame *, Lisp_Object);
static Lisp_Object ftfont_match (struct frame *, Lisp_Object);
static Lisp_Object ftfont_list_family (struct frame *);
Dmitry Antipov's avatar
Dmitry Antipov committed
492
static Lisp_Object ftfont_open (struct frame *, Lisp_Object, int);
493
static void ftfont_close (struct font *);
494 495
static int ftfont_has_char (Lisp_Object, int);
static unsigned ftfont_encode_char (struct font *, int);
496 497
static void ftfont_text_extents (struct font *, unsigned *, int,
				 struct font_metrics *);
498 499 500 501
static int ftfont_get_bitmap (struct font *, unsigned,
                              struct font_bitmap *, int);
static int ftfont_anchor_point (struct font *, unsigned, int,
                                int *, int *);
502
#ifdef HAVE_LIBOTF
503
static Lisp_Object ftfont_otf_capability (struct font *);
504
# ifdef HAVE_M17N_FLT
505
static Lisp_Object ftfont_shape (Lisp_Object);
506 507
# endif
#endif
508 509

#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
510 511
static int ftfont_variation_glyphs (struct font *, int c,
                                    unsigned variations[256]);
512
#endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
Kenichi Handa's avatar
Kenichi Handa committed
513 514 515

struct font_driver ftfont_driver =
  {
516
    LISP_INITIALLY_ZERO,	/* Qfreetype */
517
    0,				/* case insensitive */
Kenichi Handa's avatar
Kenichi Handa committed
518 519
    ftfont_get_cache,
    ftfont_list,
520
    ftfont_match,
Kenichi Handa's avatar
Kenichi Handa committed
521
    ftfont_list_family,
522
    NULL,			/* free_entity */
Kenichi Handa's avatar
Kenichi Handa committed
523 524 525
    ftfont_open,
    ftfont_close,
    /* We can't draw a text without device dependent functions.  */
526 527
    NULL,			/* prepare_face */
    NULL,			/* done_face */
Kenichi Handa's avatar
Kenichi Handa committed
528 529 530 531
    ftfont_has_char,
    ftfont_encode_char,
    ftfont_text_extents,
    /* We can't draw a text without device dependent functions.  */
532
    NULL,			/* draw */
Kenichi Handa's avatar
Kenichi Handa committed
533
    ftfont_get_bitmap,
534
    NULL,			/* free_bitmap */
Kenichi Handa's avatar
Kenichi Handa committed
535
    ftfont_anchor_point,
536 537 538
#ifdef HAVE_LIBOTF
    ftfont_otf_capability,
#else  /* not HAVE_LIBOTF */
Kenichi Handa's avatar
Kenichi Handa committed
539
    NULL,
540
#endif	/* not HAVE_LIBOTF */
541 542 543
    NULL,			/* otf_drive */
    NULL,			/* start_for_frame */
    NULL,			/* end_for_frame */
544
#if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
545
    ftfont_shape,
546
#else  /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
547
    NULL,
548
#endif	/* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
549
    NULL,			/* check */
550

551
#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
552
    ftfont_variation_glyphs,
553
#else
554
    NULL,
555
#endif
556 557

    ftfont_filter_properties, /* filter_properties */
Kenichi Handa's avatar
Kenichi Handa committed
558 559 560
  };

static Lisp_Object
Dmitry Antipov's avatar
Dmitry Antipov committed
561
ftfont_get_cache (struct frame *f)
Kenichi Handa's avatar
Kenichi Handa committed
562 563 564 565
{
  return freetype_font_cache;
}

Kenichi Handa's avatar
Kenichi Handa committed
566
static int
567
ftfont_get_charset (Lisp_Object registry)
Kenichi Handa's avatar
Kenichi Handa committed
568
{
569
  char *str = SSDATA (SYMBOL_NAME (registry));
570 571
  USE_SAFE_ALLOCA;
  char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
572
  Lisp_Object regexp;
Kenichi Handa's avatar
Kenichi Handa committed
573 574
  int i, j;

575 576 577 578 579 580 581 582 583 584 585 586
  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';
  regexp = make_unibyte_string (re, j);
587
  SAFE_FREE ();
Kenichi Handa's avatar
Kenichi Handa committed
588
  for (i = 0; fc_charset_table[i].name; i++)
589 590 591
    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
592 593 594 595 596
      break;
  if (! fc_charset_table[i].name)
    return -1;
  if (! fc_charset_table[i].fc_charset)
    {
597 598
      FcCharSet *charset = FcCharSetCreate ();
      int *uniquifier = fc_charset_table[i].uniquifier;
Kenichi Handa's avatar
Kenichi Handa committed
599

600 601 602 603 604 605
      if (! charset)
	return -1;
      for (j = 0; uniquifier[j]; j++)
	if (! FcCharSetAddChar (charset, uniquifier[j]))
	  {
	    FcCharSetDestroy (charset);
Kenichi Handa's avatar
Kenichi Handa committed
606
	    return -1;
607 608
	  }
      fc_charset_table[i].fc_charset = charset;
Kenichi Handa's avatar
Kenichi Handa committed
609 610 611 612
    }
  return i;
}

613 614
struct OpenTypeSpec
{
615 616
  Lisp_Object script;
  unsigned int script_tag, langsys_tag;
617 618 619 620
  int nfeatures[2];
  unsigned int *features[2];
};

621
#define OTF_SYM_TAG(SYM, TAG)					\
622
  do {								\
623 624
    unsigned char *p = SDATA (SYMBOL_NAME (SYM));		\
    TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];	\
625 626
  } while (0)

627
#define OTF_TAG_STR(TAG, P)			\
628
  do {						\
629 630 631 632
    (P)[0] = (char) (TAG >> 24);		\
    (P)[1] = (char) ((TAG >> 16) & 0xFF);	\
    (P)[2] = (char) ((TAG >> 8) & 0xFF);	\
    (P)[3] = (char) (TAG & 0xFF);		\
633
    (P)[4] = '\0';				\
634 635
  } while (0)

636
#ifdef HAVE_LIBOTF
637 638 639 640 641 642 643
#define OTF_TAG_SYM(SYM, TAG)			\
  do {						\
    char str[5];				\
    						\
    OTF_TAG_STR (TAG, str);			\
    (SYM) = font_intern_prop (str, 4, 1);	\
  } while (0)
644
#endif
645 646


647 648 649
static struct OpenTypeSpec *
ftfont_get_open_type_spec (Lisp_Object otf_spec)
{
650
  struct OpenTypeSpec *spec = malloc (sizeof *spec);
651
  Lisp_Object val;
652 653
  int i, j;
  bool negative;
654 655 656

  if (! spec)
    return NULL;
657
  spec->script = XCAR (otf_spec);
658
  if (! NILP (spec->script))
659 660 661 662 663 664 665 666
    {
      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;
    }
667
  else
668
    spec->script_tag = 0x44464C54; 	/* "DFLT" */
669
  otf_spec = XCDR (otf_spec);
Kenichi Handa's avatar
Kenichi Handa committed
670 671 672 673 674 675 676 677
  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);
    }
678
  spec->nfeatures[0] = spec->nfeatures[1] = 0;
Kenichi Handa's avatar
Kenichi Handa committed
679
  for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
680 681 682 683 684 685 686
    {
      Lisp_Object len;

      val = XCAR (otf_spec);
      if (NILP (val))
	continue;
      len = Flength (val);
687 688 689
      spec->features[i] =
	(min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
	 ? 0
690
	 : malloc (XINT (len) * sizeof *spec->features[i]));
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
      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;
}

715
static FcPattern *
716
ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **otspec, const char **langname)
Kenichi Handa's avatar
Kenichi Handa committed
717
{
Kenichi Handa's avatar
Kenichi Handa committed
718
  Lisp_Object tmp, extra;
Kenichi Handa's avatar
Kenichi Handa committed
719 720 721
  FcPattern *pattern = NULL;
  FcCharSet *charset = NULL;
  FcLangSet *langset = NULL;
722 723
  int n;
  int dpi = -1;
724
  int scalable = -1;
725
  Lisp_Object script = Qnil;
Kenichi Handa's avatar
Kenichi Handa committed
726
  Lisp_Object registry;
727
  int fc_charset_idx;
Kenichi Handa's avatar
Kenichi Handa committed
728

729 730
  if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
      && n < 100)
Paul Eggert's avatar
Paul Eggert committed
731
    /* Fontconfig doesn't support reverse-italic/oblique.  */
732 733 734 735 736 737 738
    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;
739

Kenichi Handa's avatar
Kenichi Handa committed
740 741
  registry = AREF (spec, FONT_REGISTRY_INDEX);
  if (NILP (registry)
742
      || EQ (registry, Qascii_0)
Kenichi Handa's avatar
Kenichi Handa committed
743
      || EQ (registry, Qiso10646_1)
744
      || EQ (registry, Qunicode_bmp))
745
    fc_charset_idx = -1;
Kenichi Handa's avatar
Kenichi Handa committed
746
  else
Kenichi Handa's avatar
Kenichi Handa committed
747
    {
748 749
      FcChar8 *lang;

750 751
      fc_charset_idx = ftfont_get_charset (registry);
      if (fc_charset_idx < 0)
752
	return NULL;
753
      charset = fc_charset_table[fc_charset_idx].fc_charset;
754 755
      *langname = fc_charset_table[fc_charset_idx].lang;
      lang = (FcChar8 *) *langname;
756 757 758 759 760 761 762
      if (lang)
	{
	  langset = FcLangSetCreate ();
	  if (! langset)
	    goto err;
	  FcLangSetAdd (langset, lang);
	}
Kenichi Handa's avatar
Kenichi Handa committed
763 764
    }

765
  otlayout[0] = '\0';
766 767
  for (extra = AREF (spec, FONT_EXTRA_INDEX);
       CONSP (extra); extra = XCDR (extra))
Kenichi Handa's avatar
Kenichi Handa committed
768
    {
769 770
      Lisp_Object key, val;

771 772
      key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
      if (EQ (key, QCdpi))
773 774 775 776
	{
	  if (INTEGERP (val))
	    dpi = XINT (val);
	}
777
      else if (EQ (key, QClang))
Kenichi Handa's avatar
Kenichi Handa committed
778
	{
779 780
	  if (! langset)
	    langset = FcLangSetCreate ();
Kenichi Handa's avatar
Kenichi Handa committed
781 782
	  if (! langset)
	    goto err;
783
	  if (SYMBOLP (val))
Kenichi Handa's avatar
Kenichi Handa committed
784
	    {
785
	      if (! FcLangSetAdd (langset, SYMBOL_FcChar8 (val)))
Kenichi Handa's avatar
Kenichi Handa committed
786 787 788
		goto err;
	    }
	  else
789 790 791 792
	    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
793
	}
794 795
      else if (EQ (key, QCotf))
	{
796 797 798 799 800
	  if (CONSP (val))
	    {
	      *otspec = ftfont_get_open_type_spec (val);
	      if (! *otspec)
		return NULL;
801
	      strcpy (otlayout, "otlayout:");
802 803 804
	      OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
	      script = (*otspec)->script;
	    }
805
	}
806 807 808 809 810
      else if (EQ (key, QCscript))
	script = val;
      else if (EQ (key, QCscalable))
	scalable = ! NILP (val);
    }
Kenichi Handa's avatar
Kenichi Handa committed
811

812 813 814 815
  if (! NILP (script) && ! charset)
    {
      Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);

816
      if (CONSP (chars) && CONSP (CDR (chars)))
817 818 819 820 821 822
	{
	  charset = FcCharSetCreate ();
	  if (! charset)
	    goto err;
	  for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
	    if (CHARACTERP (XCAR (chars))
823
		&& ! FcCharSetAddChar (charset, XFASTINT (XCAR (chars))))
824
	      goto err;
Kenichi Handa's avatar
Kenichi Handa committed
825 826 827
	}
    }

828
  pattern = FcPatternCreate ();
829 830 831
  if (! pattern)
    goto err;
  tmp = AREF (spec, FONT_FOUNDRY_INDEX);
832
  if (! NILP (tmp)
833 834
      && ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
    goto err;
835 836 837 838
  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
839 840 841 842 843 844
  if (charset
      && ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
    goto err;
  if (langset
      && ! FcPatternAddLangSet (pattern, FC_LANG, langset))
    goto err;
845 846 847 848
  if (dpi >= 0
      && ! FcPatternAddDouble (pattern, FC_DPI, dpi))
    goto err;
  if (scalable >= 0
Kenichi Handa's avatar
Kenichi Handa committed
849
      && ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
850
    goto err;
851

852
  goto finish;
Kenichi Handa's avatar
Kenichi Handa committed
853

854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
 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);
874
  if (charset && fc_charset_idx < 0) FcCharSetDestroy (charset);
875 876 877 878
  return pattern;
}

static Lisp_Object
879
ftfont_list (struct frame *f, Lisp_Object spec)
880
{
Kenichi Handa's avatar
Kenichi Handa committed
881
  Lisp_Object val = Qnil, family, adstyle;
882 883 884 885
  int i;
  FcPattern *pattern;
  FcFontSet *fontset = NULL;
  FcObjectSet *objset = NULL;
886 887
  FcCharSet *charset;
  Lisp_Object chars = Qnil;
888 889
  char otlayout[15];		/* For "otlayout:XXXX" */
  struct OpenTypeSpec *otspec = NULL;
890
  int spacing = -1;
891
  const char *langname = NULL;
Juanma Barranquero's avatar
Juanma Barranquero committed
892