ftfont.c 72.7 KB
Newer Older
Kenichi Handa's avatar
Kenichi Handa committed
1
/* ftfont.c -- FreeType font driver.
2
   Copyright (C) 2006-2011 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

#include <config.h>
#include <stdio.h>
24
#include <setjmp.h>
Kenichi Handa's avatar
Kenichi Handa committed
25 26 27 28 29 30 31 32 33 34 35

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

#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

41
/* Symbolic type of this font-driver.  */
42
static Lisp_Object Qfreetype;
Kenichi Handa's avatar
Kenichi Handa committed
43

44 45 46
/* Fontconfig's generic families and their aliases.  */
static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;

Juanma Barranquero's avatar
Juanma Barranquero committed
47
/* Flag to tell if FcInit is already called or not.  */
Kenichi Handa's avatar
Kenichi Handa committed
48
static int fc_initialized;
49 50

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

53
/* Cache for FreeType fonts.  */
Kenichi Handa's avatar
Kenichi Handa committed
54 55
static Lisp_Object freetype_font_cache;

56
/* Cache for FT_Face and FcCharSet. */
Kenichi Handa's avatar
Kenichi Handa committed
57
static Lisp_Object ft_face_cache;
Kenichi Handa's avatar
Kenichi Handa committed
58 59 60 61 62 63 64

/* The actual structure for FreeType font that can be casted to struct
   font.  */

struct ftfont_info
{
  struct font font;
65
#ifdef HAVE_LIBOTF
66
  /* The following four members must be here in this order to be
67
     compatible with struct xftfont_info (in xftfont.c).  */
68 69 70
  int maybe_otf;	/* Flag to tell if this may be OTF or not.  */
  OTF *otf;
#endif	/* HAVE_LIBOTF */
71 72
  FT_Size ft_size;
  int index;
73
  FT_Matrix matrix;
Kenichi Handa's avatar
Kenichi Handa committed
74 75
};

76 77 78 79 80 81 82
enum ftfont_cache_for
  {
    FTFONT_CACHE_FOR_FACE,
    FTFONT_CACHE_FOR_CHARSET,
    FTFONT_CACHE_FOR_ENTITY
  };

83
static Lisp_Object ftfont_pattern_entity (FcPattern *, Lisp_Object);
Kenichi Handa's avatar
Kenichi Handa committed
84

85 86 87 88
static Lisp_Object ftfont_resolve_generic_family (Lisp_Object,
                                                  FcPattern *);
static Lisp_Object ftfont_lookup_cache (Lisp_Object,
                                        enum ftfont_cache_for);
89

90
static void ftfont_filter_properties (Lisp_Object font, Lisp_Object alist);
91

92
Lisp_Object ftfont_font_format (FcPattern *, Lisp_Object);
93 94 95

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

Kenichi Handa's avatar
Kenichi Handa committed
96
static struct
Kenichi Handa's avatar
Kenichi Handa committed
97
{
98
  /* registry name */
99
  const char *name;
Kenichi Handa's avatar
Kenichi Handa committed
100 101
  /* characters to distinguish the charset from the others */
  int uniquifier[6];
102
  /* additional constraint by language */
103
  const char *lang;
Kenichi Handa's avatar
Kenichi Handa committed
104 105 106
  /* set on demand */
  FcCharSet *fc_charset;
} fc_charset_table[] =
107
  { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    { "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"},
140 141
    { "windows-1251", { 0x0401, 0x0490 }, "ru"},
    { "koi8-r", { 0x0401, 0x2219 }, "ru"},
142
    { "mulelao-1", { 0x0E81 }, "lo"},
143
    { "unicode-sip", { 0x20000 }},
Kenichi Handa's avatar
Kenichi Handa committed
144 145
    { NULL }
  };
Kenichi Handa's avatar
Kenichi Handa committed
146

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

167 168 169 170 171 172 173
#ifdef FC_FONTFORMAT
  if ((FcPatternGetString (p, FC_FONTFORMAT, 0, &fcstr) == FcResultMatch)
      && (xstrcasecmp ((char *) fcstr, "bdf") != 0
	  || xstrcasecmp ((char *) fcstr, "pcf") != 0))
    /* Not a BDF nor PCF font.  */
    return Qnil;
#endif
174
  if (FcPatternGetString (p, FC_STYLE, 0, &fcstr) != FcResultMatch)
Kenichi Handa's avatar
Kenichi Handa committed
175
    return Qnil;
176
  str = (char *) fcstr;
Kenichi Handa's avatar
Kenichi Handa committed
177 178 179
  for (end = str; *end && *end != ' '; end++);
  if (*end)
    {
180 181 182 183 184
      char *newstr = alloca (end - str + 1);
      memcpy (newstr, str, end - str);
      newstr[end - str] = '\0';
      end = newstr + (end - str);
      str = newstr;
Kenichi Handa's avatar
Kenichi Handa committed
185 186 187 188 189 190
    }
  if (xstrcasecmp (str, "Regular") == 0
      || xstrcasecmp (str, "Bold") == 0
      || xstrcasecmp (str, "Oblique") == 0
      || xstrcasecmp (str, "Italic") == 0)
    return Qnil;
191
  adstyle = font_intern_prop (str, end - str, 1);
Kenichi Handa's avatar
Kenichi Handa committed
192 193 194 195 196
  if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
    return Qnil;
  return adstyle;
}

197
static Lisp_Object
198
ftfont_pattern_entity (FcPattern *p, Lisp_Object extra)
199
{
200
  Lisp_Object key, cache, entity;
201 202
  FcChar8 *str;
  char *file;
203
  int idx;
204 205
  int numeric;
  double dbl;
206
  FcBool b;
207

208
  if (FcPatternGetString (p, FC_FILE, 0, &str) != FcResultMatch)
209
    return Qnil;
210
  if (FcPatternGetInteger (p, FC_INDEX, 0, &idx) != FcResultMatch)
211
    return Qnil;
212

213 214
  file = (char *) str;
  key = Fcons (make_unibyte_string (file, strlen (file)), make_number (idx));
215 216 217
  cache = ftfont_lookup_cache (key, FTFONT_CACHE_FOR_ENTITY);
  entity = XCAR (cache);
  if (! NILP (entity))
218 219 220 221 222 223
    {
      Lisp_Object val = font_make_entity ();
      int i;

      for (i = 0; i < FONT_OBJLIST_INDEX; i++)
	ASET (val, i, AREF (entity, i));
224 225 226 227

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

228 229
      return val;
    }
230
  entity = font_make_entity ();
231
  XSETCAR (cache, entity);
232 233

  ASET (entity, FONT_TYPE_INDEX, Qfreetype);
234
  ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
235

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

      ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
      if ((ft_library || FT_Init_FreeType (&ft_library) == 0)
288
	  && FT_New_Face (ft_library, file, idx, &ft_face) == 0)
289 290 291 292 293 294 295 296 297
	{
	  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);
	}
    }
298

299
  ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
300
  font_put_extra (entity, QCfont_entity, key);
301 302 303
  return entity;
}

304

305 306 307
static Lisp_Object ftfont_generic_family_list;

static Lisp_Object
308
ftfont_resolve_generic_family (Lisp_Object family, FcPattern *pattern)
309
{
310
  Lisp_Object slot;
311
  FcPattern *match;
312
  FcResult result;
Kenichi Handa's avatar
Kenichi Handa committed
313
  FcLangSet *langset;
314

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

      if (FcPatternGetString (match, FC_FAMILY, 0, &fam) == FcResultMatch)
	family = intern ((char *) fam);
349
    }
350 351 352 353
  else
    family = Qnil;
  XSETCDR (slot, family);
  if (match) FcPatternDestroy (match);
354
 err:
355
  if (pattern) FcPatternDestroy (pattern);
356
  return family;
357 358
}

359 360 361 362 363 364 365
struct ftfont_cache_data
{
  FT_Face ft_face;
  FcCharSet *fc_charset;
};

static Lisp_Object
366
ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for)
Kenichi Handa's avatar
Kenichi Handa committed
367
{
Kenichi Handa's avatar
Kenichi Handa committed
368
  Lisp_Object cache, val, entity;
369
  struct ftfont_cache_data *cache_data;
Kenichi Handa's avatar
Kenichi Handa committed
370

Kenichi Handa's avatar
Kenichi Handa committed
371 372 373 374 375 376 377 378 379 380
  if (FONT_ENTITY_P (key))
    {
      entity = key;
      val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
      xassert (CONSP (val));
      key = XCDR (val);
    }
  else
    entity = Qnil;

381 382 383 384
  if (NILP (ft_face_cache))
    cache = Qnil;
  else
    cache = Fgethash (key, ft_face_cache, Qnil);
Kenichi Handa's avatar
Kenichi Handa committed
385 386
  if (NILP (cache))
    {
387 388 389 390 391 392 393 394
      if (NILP (ft_face_cache))
	{
	  Lisp_Object args[2];

	  args[0] = QCtest;
	  args[1] = Qequal;
	  ft_face_cache = Fmake_hash_table (2, args);
	}
395 396 397
      cache_data = xmalloc (sizeof (struct ftfont_cache_data));
      cache_data->ft_face = NULL;
      cache_data->fc_charset = NULL;
Kenichi Handa's avatar
Kenichi Handa committed
398
      val = make_save_value (NULL, 0);
399 400
      XSAVE_VALUE (val)->integer = 0;
      XSAVE_VALUE (val)->pointer = cache_data;
401 402
      cache = Fcons (Qnil, val);
      Fputhash (key, cache, ft_face_cache);
Kenichi Handa's avatar
Kenichi Handa committed
403 404 405
    }
  else
    {
406 407 408
      val = XCDR (cache);
      cache_data = XSAVE_VALUE (val)->pointer;
    }
409 410 411 412 413 414

  if (cache_for == FTFONT_CACHE_FOR_ENTITY)
    return cache;

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

419
      if (cache_for == FTFONT_CACHE_FOR_FACE)
420 421 422 423
	{
	  if (! ft_library
	      && FT_Init_FreeType (&ft_library) != 0)
	    return Qnil;
424
	  if (FT_New_Face (ft_library, filename, idx, &cache_data->ft_face)
425 426 427 428 429
	      != 0)
	    return Qnil;
	}
      else
	{
Kenichi Handa's avatar
Kenichi Handa committed
430 431 432 433
	  FcPattern *pat = NULL;
	  FcFontSet *fontset = NULL;
	  FcObjectSet *objset = NULL;
	  FcCharSet *charset = NULL;
434 435

	  pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename,
436
				FC_INDEX, FcTypeInteger, idx, NULL);
Kenichi Handa's avatar
Kenichi Handa committed
437 438 439 440 441
	  if (! pat)
	    goto finish;
	  objset = FcObjectSetBuild (FC_CHARSET, FC_STYLE, NULL);
	  if (! objset)
	    goto finish;
442
	  fontset = FcFontList (NULL, pat, objset);
Kenichi Handa's avatar
Kenichi Handa committed
443 444
	  if (! fontset)
	    goto finish;
445 446
	  if (fontset && fontset->nfont > 0
	      && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
447
				       &charset)
448 449
		  == FcResultMatch))
	    cache_data->fc_charset = FcCharSetCopy (charset);
450 451
	  else
	    cache_data->fc_charset = FcCharSetCreate ();
Kenichi Handa's avatar
Kenichi Handa committed
452 453 454 455 456 457 458 459

	finish:
	  if (fontset)
	    FcFontSetDestroy (fontset);
	  if (objset)
	    FcObjectSetDestroy (objset);
	  if (pat)
	    FcPatternDestroy (pat);
460
	}
Kenichi Handa's avatar
Kenichi Handa committed
461 462 463 464
    }
  return cache;
}

465
FcCharSet *
466
ftfont_get_fc_charset (Lisp_Object entity)
467 468 469 470
{
  Lisp_Object val, cache;
  struct ftfont_cache_data *cache_data;

471
  cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
472 473 474 475 476 477 478
  val = XCDR (cache);
  cache_data = XSAVE_VALUE (val)->pointer;
  return cache_data->fc_charset;
}

#ifdef HAVE_LIBOTF
static OTF *
Andreas Schwab's avatar
Andreas Schwab committed
479
ftfont_get_otf (struct ftfont_info *ftfont_info)
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
{
  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 */

500 501 502 503 504 505 506 507 508 509 510 511 512 513
static Lisp_Object ftfont_get_cache (FRAME_PTR);
static Lisp_Object ftfont_list (Lisp_Object, Lisp_Object);
static Lisp_Object ftfont_match (Lisp_Object, Lisp_Object);
static Lisp_Object ftfont_list_family (Lisp_Object);
static Lisp_Object ftfont_open (FRAME_PTR, Lisp_Object, int);
static void ftfont_close (FRAME_PTR, struct font *);
static int ftfont_has_char (Lisp_Object, int);
static unsigned ftfont_encode_char (struct font *, int);
static int ftfont_text_extents (struct font *, unsigned *, int,
                                struct font_metrics *);
static int ftfont_get_bitmap (struct font *, unsigned,
                              struct font_bitmap *, int);
static int ftfont_anchor_point (struct font *, unsigned, int,
                                int *, int *);
514
#ifdef HAVE_LIBOTF
515
static Lisp_Object ftfont_otf_capability (struct font *);
516
# ifdef HAVE_M17N_FLT
517
static Lisp_Object ftfont_shape (Lisp_Object);
518 519
# endif
#endif
520 521

#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
522 523
static int ftfont_variation_glyphs (struct font *, int c,
                                    unsigned variations[256]);
524
#endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
Kenichi Handa's avatar
Kenichi Handa committed
525 526 527

struct font_driver ftfont_driver =
  {
528
    0,				/* Qfreetype */
529
    0,				/* case insensitive */
Kenichi Handa's avatar
Kenichi Handa committed
530 531
    ftfont_get_cache,
    ftfont_list,
532
    ftfont_match,
Kenichi Handa's avatar
Kenichi Handa committed
533
    ftfont_list_family,
534
    NULL,			/* free_entity */
Kenichi Handa's avatar
Kenichi Handa committed
535 536 537
    ftfont_open,
    ftfont_close,
    /* We can't draw a text without device dependent functions.  */
538 539
    NULL,			/* prepare_face */
    NULL,			/* done_face */
Kenichi Handa's avatar
Kenichi Handa committed
540 541 542 543
    ftfont_has_char,
    ftfont_encode_char,
    ftfont_text_extents,
    /* We can't draw a text without device dependent functions.  */
544
    NULL,			/* draw */
Kenichi Handa's avatar
Kenichi Handa committed
545
    ftfont_get_bitmap,
546 547 548
    NULL,			/* get_bitmap */
    NULL,			/* free_bitmap */
    NULL,			/* get_outline */
Kenichi Handa's avatar
Kenichi Handa committed
549
    ftfont_anchor_point,
550 551 552
#ifdef HAVE_LIBOTF
    ftfont_otf_capability,
#else  /* not HAVE_LIBOTF */
Kenichi Handa's avatar
Kenichi Handa committed
553
    NULL,
554
#endif	/* not HAVE_LIBOTF */
555 556 557
    NULL,			/* otf_drive */
    NULL,			/* start_for_frame */
    NULL,			/* end_for_frame */
558
#if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
559
    ftfont_shape,
560
#else  /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
561
    NULL,
562
#endif	/* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
563
    NULL,			/* check */
564

565
#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
566
    ftfont_variation_glyphs,
567
#else
568
    NULL,
569
#endif
570 571

    ftfont_filter_properties, /* filter_properties */
Kenichi Handa's avatar
Kenichi Handa committed
572 573 574
  };

static Lisp_Object
575
ftfont_get_cache (FRAME_PTR f)
Kenichi Handa's avatar
Kenichi Handa committed
576 577 578 579
{
  return freetype_font_cache;
}

Kenichi Handa's avatar
Kenichi Handa committed
580
static int
581
ftfont_get_charset (Lisp_Object registry)
Kenichi Handa's avatar
Kenichi Handa committed
582
{
583
  char *str = SSDATA (SYMBOL_NAME (registry));
584 585
  char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
  Lisp_Object regexp;
Kenichi Handa's avatar
Kenichi Handa committed
586 587
  int i, j;

588 589 590 591 592 593 594 595 596 597 598 599
  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);
Kenichi Handa's avatar
Kenichi Handa committed
600
  for (i = 0; fc_charset_table[i].name; i++)
601
    if (fast_c_string_match_ignore_case (regexp, fc_charset_table[i].name) >= 0)
Kenichi Handa's avatar
Kenichi Handa committed
602 603 604 605 606
      break;
  if (! fc_charset_table[i].name)
    return -1;
  if (! fc_charset_table[i].fc_charset)
    {
607 608
      FcCharSet *charset = FcCharSetCreate ();
      int *uniquifier = fc_charset_table[i].uniquifier;
Kenichi Handa's avatar
Kenichi Handa committed
609

610 611 612 613 614 615
      if (! charset)
	return -1;
      for (j = 0; uniquifier[j]; j++)
	if (! FcCharSetAddChar (charset, uniquifier[j]))
	  {
	    FcCharSetDestroy (charset);
Kenichi Handa's avatar
Kenichi Handa committed
616
	    return -1;
617 618
	  }
      fc_charset_table[i].fc_charset = charset;
Kenichi Handa's avatar
Kenichi Handa committed
619 620 621 622
    }
  return i;
}

623 624
struct OpenTypeSpec
{
625 626
  Lisp_Object script;
  unsigned int script_tag, langsys_tag;
627 628 629 630
  int nfeatures[2];
  unsigned int *features[2];
};

631
#define OTF_SYM_TAG(SYM, TAG)					\
632
  do {								\
633 634
    unsigned char *p = SDATA (SYMBOL_NAME (SYM));		\
    TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];	\
635 636
  } while (0)

637
#define OTF_TAG_STR(TAG, P)			\
638
  do {						\
639 640 641 642
    (P)[0] = (char) (TAG >> 24);		\
    (P)[1] = (char) ((TAG >> 16) & 0xFF);	\
    (P)[2] = (char) ((TAG >> 8) & 0xFF);	\
    (P)[3] = (char) (TAG & 0xFF);		\
643
    (P)[4] = '\0';				\
644 645
  } while (0)

646
#ifdef HAVE_LIBOTF
647 648 649 650 651 652 653
#define OTF_TAG_SYM(SYM, TAG)			\
  do {						\
    char str[5];				\
    						\
    OTF_TAG_STR (TAG, str);			\
    (SYM) = font_intern_prop (str, 4, 1);	\
  } while (0)
654
#endif
655 656


657 658 659 660 661 662 663 664 665
static struct OpenTypeSpec *
ftfont_get_open_type_spec (Lisp_Object otf_spec)
{
  struct OpenTypeSpec *spec = malloc (sizeof (struct OpenTypeSpec));
  Lisp_Object val;
  int i, j, negative;

  if (! spec)
    return NULL;
666
  spec->script = XCAR (otf_spec);
667
  if (! NILP (spec->script))
668 669 670 671 672 673 674 675
    {
      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;
    }
676
  else
677
    spec->script_tag = 0x44464C54; 	/* "DFLT" */
678
  otf_spec = XCDR (otf_spec);
Kenichi Handa's avatar
Kenichi Handa committed
679 680 681 682 683 684 685 686
  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);
    }
687
  spec->nfeatures[0] = spec->nfeatures[1] = 0;
Kenichi Handa's avatar
Kenichi Handa committed
688
  for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
689 690 691 692 693 694 695
    {
      Lisp_Object len;

      val = XCAR (otf_spec);
      if (NILP (val))
	continue;
      len = Flength (val);
696 697 698 699
      spec->features[i] =
	(min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) < XINT (len)
	 ? 0
	 : malloc (sizeof (int) * XINT (len)));
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
      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;
}

724
static FcPattern *
725
ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **otspec, const char **langname)
Kenichi Handa's avatar
Kenichi Handa committed
726
{
Kenichi Handa's avatar
Kenichi Handa committed
727
  Lisp_Object tmp, extra;
Kenichi Handa's avatar
Kenichi Handa committed
728 729 730
  FcPattern *pattern = NULL;
  FcCharSet *charset = NULL;
  FcLangSet *langset = NULL;
731 732
  int n;
  int dpi = -1;
733
  int scalable = -1;
734
  Lisp_Object script = Qnil;
Kenichi Handa's avatar
Kenichi Handa committed
735
  Lisp_Object registry;
736
  int fc_charset_idx;
Kenichi Handa's avatar
Kenichi Handa committed
737

738 739
  if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
      && n < 100)
Paul Eggert's avatar
Paul Eggert committed
740
    /* Fontconfig doesn't support reverse-italic/oblique.  */
741 742 743 744 745 746 747
    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;
748

Kenichi Handa's avatar
Kenichi Handa committed
749 750
  registry = AREF (spec, FONT_REGISTRY_INDEX);
  if (NILP (registry)
751
      || EQ (registry, Qascii_0)
Kenichi Handa's avatar
Kenichi Handa committed
752
      || EQ (registry, Qiso10646_1)
753
      || EQ (registry, Qunicode_bmp))
754
    fc_charset_idx = -1;
Kenichi Handa's avatar
Kenichi Handa committed
755
  else
Kenichi Handa's avatar
Kenichi Handa committed
756
    {
757 758
      FcChar8 *lang;

759 760
      fc_charset_idx = ftfont_get_charset (registry);
      if (fc_charset_idx < 0)
761
	return NULL;
762
      charset = fc_charset_table[fc_charset_idx].fc_charset;
763 764
      *langname = fc_charset_table[fc_charset_idx].lang;
      lang = (FcChar8 *) *langname;
765 766 767 768 769 770 771
      if (lang)
	{
	  langset = FcLangSetCreate ();
	  if (! langset)
	    goto err;
	  FcLangSetAdd (langset, lang);
	}
Kenichi Handa's avatar
Kenichi Handa committed
772 773
    }

774
  otlayout[0] = '\0';
775 776
  for (extra = AREF (spec, FONT_EXTRA_INDEX);
       CONSP (extra); extra = XCDR (extra))
Kenichi Handa's avatar
Kenichi Handa committed
777
    {
778 779
      Lisp_Object key, val;

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

821 822 823 824
  if (! NILP (script) && ! charset)
    {
      Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);

825
      if (CONSP (chars) && CONSP (CDR (chars)))
826 827 828 829 830 831
	{
	  charset = FcCharSetCreate ();
	  if (! charset)
	    goto err;
	  for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
	    if (CHARACTERP (XCAR (chars))
832
		&& ! FcCharSetAddChar (charset, XFASTINT (XCAR (chars))))
833
	      goto err;
Kenichi Handa's avatar
Kenichi Handa committed
834 835 836
	}
    }

837
  pattern = FcPatternCreate ();
838 839 840
  if (! pattern)
    goto err;
  tmp = AREF (spec, FONT_FOUNDRY_INDEX);
841
  if (! NILP (tmp)
842 843
      && ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
    goto err;
844 845 846 847
  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
848 849 850 851 852 853
  if (charset
      && ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
    goto err;
  if (langset
      && ! FcPatternAddLangSet (pattern, FC_LANG, langset))
    goto err;
854 855 856 857
  if (dpi >= 0
      && ! FcPatternAddDouble (pattern, FC_DPI, dpi))
    goto err;
  if (scalable >= 0
Kenichi Handa's avatar
Kenichi Handa committed
858
      && ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
859
    goto err;
860

861
  goto finish;
Kenichi Handa's avatar
Kenichi Handa committed
862

863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
 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);
883
  if (charset && fc_charset_idx < 0) FcCharSetDestroy (charset);
884 885 886 887
  return pattern;
}

static Lisp_Object
888
ftfont_list (Lisp_Object frame, Lisp_Object spec)
889
{
Kenichi Handa's avatar
Kenichi Handa committed
890
  Lisp_Object val = Qnil, family, adstyle;
891 892 893 894
  int i;
  FcPattern *pattern;
  FcFontSet *fontset = NULL;
  FcObjectSet *objset = NULL;
895 896
  FcCharSet *charset;
  Lisp_Object chars = Qnil;
897 898
  char otlayout[15];		/* For "otlayout:XXXX" */
  struct OpenTypeSpec *otspec = NULL;
899
  int spacing = -1;
900
  const char *langname = NULL;
Juanma Barranquero's avatar
Juanma Barranquero committed
901

902 903 904 905 906 907
  if (! fc_initialized)
    {
      FcInit ();
      fc_initialized = 1;
    }

908
  pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
909 910
  if (! pattern)
    return Qnil;
911 912 913 914 915 916 917 918 919 920 921
  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;
    }
922 923
  if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
    spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
924 925 926 927 928
  family = AREF (spec, FONT_FAMILY_INDEX);
  if (! NILP (family))
    {
      Lisp_Object resolved;

929
      resolved = ftfont_resolve_generic_family (family, pattern);
930 931 932 933 934 935 936 937
      if (! NILP (resolved))
	{
	  FcPatternDel (pattern, FC_FAMILY);
	  if (! FcPatternAddString (pattern, FC_FAMILY,
				    SYMBOL_FcChar8 (resolved)))