ftfont.c 72.4 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
  if (FcPatternGetString (p, FC_STYLE, 0, &fcstr) != FcResultMatch)
Kenichi Handa's avatar
Kenichi Handa committed
168
    return Qnil;
169
  str = (char *) fcstr;
Kenichi Handa's avatar
Kenichi Handa committed
170 171 172
  for (end = str; *end && *end != ' '; end++);
  if (*end)
    {
173 174 175 176 177
      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
178 179 180 181 182 183
    }
  if (xstrcasecmp (str, "Regular") == 0
      || xstrcasecmp (str, "Bold") == 0
      || xstrcasecmp (str, "Oblique") == 0
      || xstrcasecmp (str, "Italic") == 0)
    return Qnil;
184
  adstyle = font_intern_prop (str, end - str, 1);
Kenichi Handa's avatar
Kenichi Handa committed
185 186 187 188 189
  if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
    return Qnil;
  return adstyle;
}

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

201
  if (FcPatternGetString (p, FC_FILE, 0, &str) != FcResultMatch)
202
    return Qnil;
203
  if (FcPatternGetInteger (p, FC_INDEX, 0, &idx) != FcResultMatch)
204
    return Qnil;
205

206 207
  file = (char *) str;
  key = Fcons (make_unibyte_string (file, strlen (file)), make_number (idx));
208 209 210
  cache = ftfont_lookup_cache (key, FTFONT_CACHE_FOR_ENTITY);
  entity = XCAR (cache);
  if (! NILP (entity))
211 212 213 214 215 216 217 218
    {
      Lisp_Object val = font_make_entity ();
      int i;

      for (i = 0; i < FONT_OBJLIST_INDEX; i++)
	ASET (val, i, AREF (entity, i));
      return val;
    }
219
  entity = font_make_entity ();
220
  XSETCAR (cache, entity);
221 222

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

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

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

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

293

294 295 296
static Lisp_Object ftfont_generic_family_list;

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

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

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

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

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

Kenichi Handa's avatar
Kenichi Handa committed
360 361 362 363 364 365 366 367 368 369
  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;

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

	  args[0] = QCtest;
	  args[1] = Qequal;
	  ft_face_cache = Fmake_hash_table (2, args);
	}
384 385 386
      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
387
      val = make_save_value (NULL, 0);
388 389
      XSAVE_VALUE (val)->integer = 0;
      XSAVE_VALUE (val)->pointer = cache_data;
390 391
      cache = Fcons (Qnil, val);
      Fputhash (key, cache, ft_face_cache);
Kenichi Handa's avatar
Kenichi Handa committed
392 393 394
    }
  else
    {
395 396 397
      val = XCDR (cache);
      cache_data = XSAVE_VALUE (val)->pointer;
    }
398 399 400 401 402 403

  if (cache_for == FTFONT_CACHE_FOR_ENTITY)
    return cache;

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

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

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

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

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

460
  cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
461 462 463 464 465 466 467
  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
468
ftfont_get_otf (struct ftfont_info *ftfont_info)
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
{
  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 */

489 490 491 492 493 494 495 496 497 498 499 500 501 502
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 *);
503
#ifdef HAVE_LIBOTF
504
static Lisp_Object ftfont_otf_capability (struct font *);
505
# ifdef HAVE_M17N_FLT
506
static Lisp_Object ftfont_shape (Lisp_Object);
507 508
# endif
#endif
509 510

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

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

554
#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
555
    ftfont_variation_glyphs,
556
#else
557
    NULL,
558
#endif
559 560

    ftfont_filter_properties, /* filter_properties */
Kenichi Handa's avatar
Kenichi Handa committed
561 562 563
  };

static Lisp_Object
564
ftfont_get_cache (FRAME_PTR f)
Kenichi Handa's avatar
Kenichi Handa committed
565 566 567 568
{
  return freetype_font_cache;
}

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

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

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

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

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

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

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


646 647 648 649 650 651 652 653 654
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;
655
  spec->script = XCAR (otf_spec);
656
  if (! NILP (spec->script))
657 658 659 660 661 662 663 664
    {
      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;
    }
665
  else
666
    spec->script_tag = 0x44464C54; 	/* "DFLT" */
667
  otf_spec = XCDR (otf_spec);
Kenichi Handa's avatar
Kenichi Handa committed
668 669 670 671 672 673 674 675
  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);
    }
676
  spec->nfeatures[0] = spec->nfeatures[1] = 0;
Kenichi Handa's avatar
Kenichi Handa committed
677
  for (i = 0; i < 2 && ! NILP (otf_spec); i++, otf_spec = XCDR (otf_spec))
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
    {
      Lisp_Object len;

      val = XCAR (otf_spec);
      if (NILP (val))
	continue;
      len = Flength (val);
      spec->features[i] = malloc (sizeof (int) * XINT (len));
      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;
}

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

724 725
  if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
      && n < 100)
726
    /* Fontconfig doesn't support reverse-italic/obligue.  */
727 728 729 730 731 732 733
    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;
734

Kenichi Handa's avatar
Kenichi Handa committed
735 736
  registry = AREF (spec, FONT_REGISTRY_INDEX);
  if (NILP (registry)
737
      || EQ (registry, Qascii_0)
Kenichi Handa's avatar
Kenichi Handa committed
738
      || EQ (registry, Qiso10646_1)
739
      || EQ (registry, Qunicode_bmp))
740
    fc_charset_idx = -1;
Kenichi Handa's avatar
Kenichi Handa committed
741
  else
Kenichi Handa's avatar
Kenichi Handa committed
742
    {
743 744
      FcChar8 *lang;

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

760
  otlayout[0] = '\0';
761 762
  for (extra = AREF (spec, FONT_EXTRA_INDEX);
       CONSP (extra); extra = XCDR (extra))
Kenichi Handa's avatar
Kenichi Handa committed
763
    {
764 765
      Lisp_Object key, val;

766 767
      key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
      if (EQ (key, QCdpi))
768 769 770 771
	{
	  if (INTEGERP (val))
	    dpi = XINT (val);
	}
772
      else if (EQ (key, QClang))
Kenichi Handa's avatar
Kenichi Handa committed
773
	{
774 775
	  if (! langset)
	    langset = FcLangSetCreate ();
Kenichi Handa's avatar
Kenichi Handa committed
776 777
	  if (! langset)
	    goto err;
778
	  if (SYMBOLP (val))
Kenichi Handa's avatar
Kenichi Handa committed
779
	    {
780
	      if (! FcLangSetAdd (langset, SYMBOL_FcChar8 (val)))
Kenichi Handa's avatar
Kenichi Handa committed
781 782 783
		goto err;
	    }
	  else
784 785 786 787
	    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
788
	}
789 790
      else if (EQ (key, QCotf))
	{
791 792 793 794 795 796 797 798 799
	  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;
	    }
800
	}
801 802 803 804 805
      else if (EQ (key, QCscript))
	script = val;
      else if (EQ (key, QCscalable))
	scalable = ! NILP (val);
    }
Kenichi Handa's avatar
Kenichi Handa committed
806

807 808 809 810
  if (! NILP (script) && ! charset)
    {
      Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);

811
      if (CONSP (chars) && CONSP (CDR (chars)))
812 813 814 815 816 817 818 819
	{
	  charset = FcCharSetCreate ();
	  if (! charset)
	    goto err;
	  for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
	    if (CHARACTERP (XCAR (chars))
		&& ! FcCharSetAddChar (charset, XUINT (XCAR (chars))))
	      goto err;
Kenichi Handa's avatar
Kenichi Handa committed
820 821 822
	}
    }

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

847
  goto finish;
Kenichi Handa's avatar
Kenichi Handa committed
848

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

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

888 889 890 891 892 893
  if (! fc_initialized)
    {
      FcInit ();
      fc_initialized = 1;
    }

894
  pattern = ftfont_spec_pattern (spec, otlayout, &otspec, &langname);
895 896
  if (! pattern)
    return Qnil;
897 898 899 900 901 902 903 904 905 906 907
  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;
    }
908 909
  if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
    spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
910 911 912 913 914
  family = AREF (spec, FONT_FAMILY_INDEX);
  if (! NILP (family))
    {
      Lisp_Object resolved;

915
      resolved = ftfont_resolve_generic_family (family, pattern);
916 917 918 919 920 921 922 923
      if (! NILP (resolved))
	{
	  FcPatternDel (pattern, FC_FAMILY);
	  if (! FcPatternAddString (pattern, FC_FAMILY,
				    SYMBOL_FcChar8 (resolved)))
	    goto err;
	}
    }
Kenichi Handa's avatar
Kenichi Handa committed
924 925 926
  adstyle = AREF (spec, FONT_ADSTYLE_INDEX);
  if (! NILP (adstyle) && SBYTES (SYMBOL_NAME (adstyle)) == 0)
    adstyle = Qnil;
927
  objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
928
			     FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
Kenichi Handa's avatar
Kenichi Handa committed
929
			     FC_STYLE, FC_FILE, FC_INDEX,
930 931 932
#ifdef FC_CAPABILITY
			     FC_CAPABILITY,
#endif	/* FC_CAPABILITY */
933 934 935
#ifdef FC_FONTFORMAT
			     FC_FONTFORMAT,
#endif
936
			     NULL);