ftfont.c 48.1 KB
Newer Older
Kenichi Handa's avatar
Kenichi Handa committed
1
/* ftfont.c -- FreeType font driver.
2 3
   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
   Copyright (C) 2006, 2007, 2008
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 27 28 29 30 31 32 33 34 35 36

#include <config.h>
#include <stdio.h>

#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"
#include "fontset.h"
#include "font.h"
37
#include "ftfont.h"
Kenichi Handa's avatar
Kenichi Handa committed
38

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

42 43 44
/* 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
45
/* Flag to tell if FcInit is already called or not.  */
Kenichi Handa's avatar
Kenichi Handa committed
46
static int fc_initialized;
47 48

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

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

Kenichi Handa's avatar
Kenichi Handa committed
54 55
/* Cache for FT_Face */
static Lisp_Object ft_face_cache;
Kenichi Handa's avatar
Kenichi Handa committed
56 57 58 59 60 61 62 63

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

struct ftfont_info
{
  struct font font;
  FT_Size ft_size;
Kenichi Handa's avatar
Kenichi Handa committed
64
  int fc_charset_idx;
65 66 67 68
#ifdef HAVE_LIBOTF
  int maybe_otf;	/* Flag to tell if this may be OTF or not.  */
  OTF *otf;
#endif	/* HAVE_LIBOTF */
Kenichi Handa's avatar
Kenichi Handa committed
69 70
};

71 72
static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object,
					      Lisp_Object, int));
Kenichi Handa's avatar
Kenichi Handa committed
73

74 75 76
static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object,
						      FcPattern *));
Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
77 78 79

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

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

132 133
extern Lisp_Object Qc, Qm, Qp, Qd;

134
static Lisp_Object
135
ftfont_pattern_entity (p, registry, extra, fc_charset_idx)
136
     FcPattern *p;
137
     Lisp_Object registry, extra;
Kenichi Handa's avatar
Kenichi Handa committed
138
     int fc_charset_idx;
139 140
{
  Lisp_Object entity;
Kenichi Handa's avatar
Kenichi Handa committed
141
  char *file, *str;
142 143
  int numeric;
  double dbl;
144
  FcBool b;
145

Kenichi Handa's avatar
Kenichi Handa committed
146
  if (FcPatternGetString (p, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
147 148
    return Qnil;

149
  entity = font_make_entity ();
150 151 152 153

  ASET (entity, FONT_TYPE_INDEX, Qfreetype);
  ASET (entity, FONT_REGISTRY_INDEX, registry);

Kenichi Handa's avatar
Kenichi Handa committed
154
  if (FcPatternGetString (p, FC_FOUNDRY, 0, (FcChar8 **) &str) == FcResultMatch)
155
    ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (str, strlen (str), 1));
Kenichi Handa's avatar
Kenichi Handa committed
156
  if (FcPatternGetString (p, FC_FAMILY, 0, (FcChar8 **) &str) == FcResultMatch)
157
    ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (str, strlen (str), 1));
158
  if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
159
    {
160 161 162
      if (numeric >= FC_WEIGHT_REGULAR && numeric < FC_WEIGHT_MEDIUM)
	numeric = FC_WEIGHT_MEDIUM;
      FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, make_number (numeric));
163
    }
164
  if (FcPatternGetInteger (p, FC_SLANT, 0, &numeric) == FcResultMatch)
165 166 167 168
    {
      numeric += 100;
      FONT_SET_STYLE (entity, FONT_SLANT_INDEX, make_number (numeric));
    }
169
  if (FcPatternGetInteger (p, FC_WIDTH, 0, &numeric) == FcResultMatch)
170 171 172
    {
      FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric));
    }
173 174 175 176
  if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
    ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
  else
    ASET (entity, FONT_SIZE_INDEX, make_number (0));
177 178 179 180 181 182 183 184 185 186
  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)
    ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
187

188
  ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
Kenichi Handa's avatar
Kenichi Handa committed
189 190 191 192
  font_put_extra (entity, QCfont_entity,
		  Fcons (make_unibyte_string ((char *) file,
					      strlen ((char *) file)),
			 make_number (fc_charset_idx)));
193 194 195
  return entity;
}

196

197 198 199
static Lisp_Object ftfont_generic_family_list;

static Lisp_Object
200
ftfont_resolve_generic_family (family, pattern)
201
     Lisp_Object family;
202
     FcPattern *pattern;
203
{
204
  Lisp_Object slot;
205
  FcPattern *match;
206
  FcResult result;
207

208
  family = Fintern (Fdowncase (SYMBOL_NAME (family)), Qnil);
209 210 211 212 213 214
  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))
215
    return Qnil;
216 217
  if (! EQ (XCDR (slot), Qt))
    return XCDR (slot);
218
  pattern = FcPatternDuplicate (pattern);
219 220
  if (! pattern)
    goto err;
221 222
  FcPatternDel (pattern, FC_FAMILY);
  FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (family));
223
  FcConfigSubstitute (NULL, pattern, FcMatchPattern);
224 225 226
  FcDefaultSubstitute (pattern);
  match = FcFontMatch (NULL, pattern, &result);
  if (match)
227
    {
228 229 230 231
      FcChar8 *fam;

      if (FcPatternGetString (match, FC_FAMILY, 0, &fam) == FcResultMatch)
	family = intern ((char *) fam);
232
    }
233 234 235
  else
    family = Qnil;
  XSETCDR (slot, family);
236
 err:
237
  if (match) FcPatternDestroy (match);
238
  if (pattern) FcPatternDestroy (pattern);
239
  return family;
240 241
}

Kenichi Handa's avatar
Kenichi Handa committed
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
Lisp_Object
ftfont_lookup_cache (filename)
     Lisp_Object filename;
{
  Lisp_Object cache, val;

  cache = assoc_no_quit (filename, ft_face_cache);
  if (NILP (cache))
    {
      val = make_save_value (NULL, 0);
      cache = Fcons (filename, val);
      ft_face_cache = Fcons (cache, ft_face_cache);
    }
  else
    val = XCDR (cache);
  if (! XSAVE_VALUE (val)->pointer)
    {
      FT_Face ft_face;

      if (! ft_library
	  && FT_Init_FreeType (&ft_library) != 0)
	return Qnil;
      if (FT_New_Face (ft_library, (char *) SDATA (filename), 0, &ft_face) != 0)
	return Qnil;
      XSAVE_VALUE (val)->pointer = ft_face;
    }
  return cache;
}

271
static Lisp_Object ftfont_get_cache P_ ((FRAME_PTR));
Kenichi Handa's avatar
Kenichi Handa committed
272
static Lisp_Object ftfont_list P_ ((Lisp_Object, Lisp_Object));
273
static Lisp_Object ftfont_match P_ ((Lisp_Object, Lisp_Object));
Kenichi Handa's avatar
Kenichi Handa committed
274
static Lisp_Object ftfont_list_family P_ ((Lisp_Object));
275
static Lisp_Object ftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
Kenichi Handa's avatar
Kenichi Handa committed
276 277 278 279 280 281 282 283 284
static void ftfont_close P_ ((FRAME_PTR, struct font *));
static int ftfont_has_char P_ ((Lisp_Object, int));
static unsigned ftfont_encode_char P_ ((struct font *, int));
static int ftfont_text_extents P_ ((struct font *, unsigned *, int,
				    struct font_metrics *));
static int ftfont_get_bitmap P_ ((struct font *, unsigned,
				  struct font_bitmap *, int));
static int ftfont_anchor_point P_ ((struct font *, unsigned, int,
				    int *, int *));
285
static Lisp_Object ftfont_shape P_ ((Lisp_Object));
Kenichi Handa's avatar
Kenichi Handa committed
286 287 288

struct font_driver ftfont_driver =
  {
289
    0,				/* Qfreetype */
290
    0,				/* case insensitive */
Kenichi Handa's avatar
Kenichi Handa committed
291 292
    ftfont_get_cache,
    ftfont_list,
293
    ftfont_match,
Kenichi Handa's avatar
Kenichi Handa committed
294
    ftfont_list_family,
295
    NULL,
Kenichi Handa's avatar
Kenichi Handa committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
    ftfont_open,
    ftfont_close,
    /* We can't draw a text without device dependent functions.  */
    NULL,
    NULL,
    ftfont_has_char,
    ftfont_encode_char,
    ftfont_text_extents,
    /* We can't draw a text without device dependent functions.  */
    NULL,
    ftfont_get_bitmap,
    NULL,
    NULL,
    NULL,
    ftfont_anchor_point,
    NULL,
    NULL,
313 314
    NULL,
    NULL,
315
#if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
316
    ftfont_shape
317
#else  /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
Kenichi Handa's avatar
Kenichi Handa committed
318
    NULL
319
#endif	/* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
Kenichi Handa's avatar
Kenichi Handa committed
320 321 322 323 324
  };

extern Lisp_Object QCname;

static Lisp_Object
325 326
ftfont_get_cache (f)
     FRAME_PTR f;
Kenichi Handa's avatar
Kenichi Handa committed
327 328 329 330
{
  return freetype_font_cache;
}

Kenichi Handa's avatar
Kenichi Handa committed
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
static int
ftfont_get_charset (registry)
     Lisp_Object registry;
{
  struct charset *encoding;
  int i, j;

  if (font_registry_charsets (registry, &encoding, NULL) < 0)
    return -1;
  if (fc_charset_table[0].charset_id < 0)
    /* Setup charset_id field of all elements.  */
    for (i = 0; fc_charset_table[i].name; i++)
      {
	Lisp_Object sym = intern (fc_charset_table[i].name);

	if (CHARSETP (sym))
	  fc_charset_table[i].charset_id = XINT (CHARSET_SYMBOL_ID (sym));
	else
	  fc_charset_table[i].charset_id = -1;
      }

  for (i = 0; fc_charset_table[i].name; i++)
    if (encoding->id == fc_charset_table[i].charset_id)
      break;
  if (! fc_charset_table[i].name)
    return -1;
  if (! fc_charset_table[i].fc_charset)
    {
      FcCharSet *charset = FcCharSetCreate ();
      int *uniquifier = fc_charset_table[i].uniquifier;

      if (! charset)
	return -1;
      for (j = 0; uniquifier[j]; j++)
	if (! FcCharSetAddChar (charset, uniquifier[j]))
	  {
	    FcCharSetDestroy (charset);
	    return -1;
	  }
Juanma Barranquero's avatar
Juanma Barranquero committed
370
      fc_charset_table[i].fc_charset = charset;
Kenichi Handa's avatar
Kenichi Handa committed
371 372 373 374
    }
  return i;
}

375 376
struct OpenTypeSpec
{
377 378
  Lisp_Object script;
  unsigned int script_tag, langsys_tag;
379 380 381 382
  int nfeatures[2];
  unsigned int *features[2];
};

383
#define OTF_SYM_TAG(SYM, TAG)					\
384
  do {								\
385 386
    unsigned char *p = SDATA (SYMBOL_NAME (SYM));		\
    TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];	\
387 388
  } while (0)

389
#define OTF_TAG_STR(TAG, P)			\
390
  do {						\
391 392 393 394
    (P)[0] = (char) (TAG >> 24);		\
    (P)[1] = (char) ((TAG >> 16) & 0xFF);	\
    (P)[2] = (char) ((TAG >> 8) & 0xFF);	\
    (P)[3] = (char) (TAG & 0xFF);		\
395
    (P)[4] = '\0';				\
396 397 398 399 400 401 402 403 404 405 406
  } while (0)

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;
407
  spec->script = XCAR (otf_spec);
408
  if (! NILP (spec->script))
409 410 411 412 413 414 415 416
    {
      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;
    }
417
  else
418
    spec->script_tag = 0x44464C54; 	/* "DFLT" */
419 420 421
  otf_spec = XCDR (otf_spec);
  val = XCAR (otf_spec);
  if (! NILP (val))
422
    OTF_SYM_TAG (val, spec->langsys_tag);
423
  else
424
    spec->langsys_tag = 0;
425 426 427 428 429
  spec->nfeatures[0] = spec->nfeatures[1] = 0;
  for (i = 0; i < 2; i++)
    {
      Lisp_Object len;

Juanma Barranquero's avatar
Juanma Barranquero committed
430
      otf_spec = XCDR (otf_spec);
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
      if (NILP (otf_spec))
	break;
      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;
}

Kenichi Handa's avatar
Kenichi Handa committed
462 463 464
static FcPattern *ftfont_spec_pattern P_ ((Lisp_Object, int *, char *,
					   struct OpenTypeSpec **));

465
static FcPattern *
Kenichi Handa's avatar
Kenichi Handa committed
466
ftfont_spec_pattern (spec, fc_charset_idx, otlayout, otspec)
467
     Lisp_Object spec;
Kenichi Handa's avatar
Kenichi Handa committed
468
     int *fc_charset_idx;
469 470
     char *otlayout;
     struct OpenTypeSpec **otspec;
Kenichi Handa's avatar
Kenichi Handa committed
471
{
Kenichi Handa's avatar
Kenichi Handa committed
472
  Lisp_Object tmp, extra;
Kenichi Handa's avatar
Kenichi Handa committed
473 474 475
  FcPattern *pattern = NULL;
  FcCharSet *charset = NULL;
  FcLangSet *langset = NULL;
476 477
  int n;
  int dpi = -1;
478
  int scalable = -1;
479
  Lisp_Object script = Qnil;
Kenichi Handa's avatar
Kenichi Handa committed
480
  Lisp_Object registry;
Kenichi Handa's avatar
Kenichi Handa committed
481

482
  if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX))
483 484 485 486 487
      && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0)
    /* Fontconfig doesn't support adstyle property.  */
    return NULL;
  if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
      && n < 100)
488
    /* Fontconfig doesn't support reverse-italic/obligue.  */
489 490 491 492 493 494 495
    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;
496

Kenichi Handa's avatar
Kenichi Handa committed
497 498
  registry = AREF (spec, FONT_REGISTRY_INDEX);
  if (NILP (registry)
499
      || EQ (registry, Qascii_0)
Kenichi Handa's avatar
Kenichi Handa committed
500 501 502 503 504
      || EQ (registry, Qiso10646_1)
      || EQ (registry, Qunicode_bmp)
      || EQ (registry, Qunicode_sip))
    *fc_charset_idx = -1;
  else
Kenichi Handa's avatar
Kenichi Handa committed
505
    {
506 507
      FcChar8 *lang;

Kenichi Handa's avatar
Kenichi Handa committed
508 509
      *fc_charset_idx = ftfont_get_charset (registry);
      if (*fc_charset_idx < 0)
510
	return NULL;
Kenichi Handa's avatar
Kenichi Handa committed
511
      charset = fc_charset_table[*fc_charset_idx].fc_charset;
512 513 514 515 516 517 518 519
      lang = (FcChar8 *) fc_charset_table[*fc_charset_idx].lang;
      if (lang)
	{
	  langset = FcLangSetCreate ();
	  if (! langset)
	    goto err;
	  FcLangSetAdd (langset, lang);
	}
Kenichi Handa's avatar
Kenichi Handa committed
520 521
    }

522
  otlayout[0] = '\0';
523 524
  for (extra = AREF (spec, FONT_EXTRA_INDEX);
       CONSP (extra); extra = XCDR (extra))
Kenichi Handa's avatar
Kenichi Handa committed
525
    {
526 527
      Lisp_Object key, val;

528 529 530 531
      key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
      if (EQ (key, QCdpi))
	dpi = XINT (val);
      else if (EQ (key, QClang))
Kenichi Handa's avatar
Kenichi Handa committed
532
	{
533 534
	  if (! langset)
	    langset = FcLangSetCreate ();
Kenichi Handa's avatar
Kenichi Handa committed
535 536
	  if (! langset)
	    goto err;
537
	  if (SYMBOLP (val))
Kenichi Handa's avatar
Kenichi Handa committed
538
	    {
539
	      if (! FcLangSetAdd (langset, SYMBOL_FcChar8 (val)))
Kenichi Handa's avatar
Kenichi Handa committed
540 541 542
		goto err;
	    }
	  else
543 544 545 546
	    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
547
	}
548 549 550 551 552 553 554 555 556
      else if (EQ (key, QCotf))
	{
	  *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;
	}
557 558 559 560 561
      else if (EQ (key, QCscript))
	script = val;
      else if (EQ (key, QCscalable))
	scalable = ! NILP (val);
    }
Kenichi Handa's avatar
Kenichi Handa committed
562

563 564 565 566 567 568 569 570 571 572 573 574 575
  if (! NILP (script) && ! charset)
    {
      Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);

      if (CONSP (chars))
	{
	  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
576 577 578
	}
    }

579
  pattern = FcPatternCreate ();
580 581 582
  if (! pattern)
    goto err;
  tmp = AREF (spec, FONT_FOUNDRY_INDEX);
583
  if (! NILP (tmp)
584 585
      && ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
    goto err;
586 587 588 589
  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
590 591 592 593 594 595
  if (charset
      && ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
    goto err;
  if (langset
      && ! FcPatternAddLangSet (pattern, FC_LANG, langset))
    goto err;
596 597 598 599
  if (dpi >= 0
      && ! FcPatternAddDouble (pattern, FC_DPI, dpi))
    goto err;
  if (scalable >= 0
Kenichi Handa's avatar
Kenichi Handa committed
600
      && ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
601
    goto err;
602

603
  goto finish;
Kenichi Handa's avatar
Kenichi Handa committed
604

605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
 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);
625
  if (charset && *fc_charset_idx < 0) FcCharSetDestroy (charset);
626 627 628 629 630 631 632
  return pattern;
}

static Lisp_Object
ftfont_list (frame, spec)
     Lisp_Object frame, spec;
{
633
  Lisp_Object val = Qnil, registry, family;
634 635 636 637
  int i;
  FcPattern *pattern;
  FcFontSet *fontset = NULL;
  FcObjectSet *objset = NULL;
Kenichi Handa's avatar
Kenichi Handa committed
638
  int fc_charset_idx;
639 640
  char otlayout[15];		/* For "otlayout:XXXX" */
  struct OpenTypeSpec *otspec = NULL;
641
  int spacing = -1;
Juanma Barranquero's avatar
Juanma Barranquero committed
642

643 644 645 646 647 648
  if (! fc_initialized)
    {
      FcInit ();
      fc_initialized = 1;
    }

Kenichi Handa's avatar
Kenichi Handa committed
649
  pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec);
650 651
  if (! pattern)
    return Qnil;
652 653
  if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
    spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
654 655 656 657 658 659
  registry = AREF (spec, FONT_REGISTRY_INDEX);
  family = AREF (spec, FONT_FAMILY_INDEX);
  if (! NILP (family))
    {
      Lisp_Object resolved;

660
      resolved = ftfont_resolve_generic_family (family, pattern);
661 662 663 664 665 666 667 668 669
      if (! NILP (resolved))
	{
	  FcPatternDel (pattern, FC_FAMILY);
	  if (! FcPatternAddString (pattern, FC_FAMILY,
				    SYMBOL_FcChar8 (resolved)))
	    goto err;
	}
    }

670
  objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
671
			     FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
672
			     FC_FILE,
673 674 675
#ifdef FC_CAPABILITY
			     FC_CAPABILITY,
#endif	/* FC_CAPABILITY */
676 677 678
#ifdef FC_FONTFORMAT
			     FC_FONTFORMAT,
#endif
679
			     NULL);
680 681
  if (! objset)
    goto err;
682

683 684 685
  fontset = FcFontList (NULL, pattern, objset);
  if (! fontset)
    goto err;
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
#if 0
  /* Need fix because this finds any fonts.  */
  if (fontset->nfont == 0 && ! NILP (family))
    {
      /* Try maching with configuration.  For instance, the
	 configuration may specify "Nimbus Mono L" as an alias of
	 "Courier".  */
      FcPattern *pat = FcPatternBuild (0, FC_FAMILY, FcTypeString,
				       SYMBOL_FcChar8 (family), NULL);
      FcChar8 *fam;

      if (FcConfigSubstitute (NULL, pat, FcMatchPattern) == FcTrue)
	{
	  for (i = 0;
	       FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch;
	       i++)
	    {
	      FcPatternDel (pattern, FC_FAMILY);
	      FcPatternAddString (pattern, FC_FAMILY, fam);
	      FcFontSetDestroy (fontset);
	      fontset = FcFontList (NULL, pattern, objset);
	      if (fontset->nfont > 0)
		break;
	    }
	}
    }
#endif
713
  for (i = 0; i < fontset->nfont; i++)
714
    {
715
      Lisp_Object entity;
716

717 718 719 720 721 722 723 724 725 726
      if (spacing >= 0)
	{
	  int this;

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

727
#ifdef FC_CAPABILITY
728 729 730
      if (otlayout[0])
	{
	  FcChar8 *this;
731

732 733 734 735 736
	  if (FcPatternGetString (fontset->fonts[i], FC_CAPABILITY, 0,
				  &this) != FcResultMatch
	      || ! strstr ((char *) this, otlayout))
	    continue;
	}
737
#endif	/* FC_CAPABILITY */
738
#ifdef HAVE_LIBOTF
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
      if (otspec)
	{
	  FcChar8 *file;
	  OTF *otf;

	  if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file)
	      != FcResultMatch)
	    continue;
	  otf = OTF_open ((char *) file);
	  if (! otf)
	    continue;
	  if (OTF_check_features (otf, 1,
				  otspec->script_tag, otspec->langsys_tag,
				  otspec->features[0],
				  otspec->nfeatures[0]) != 1
	      || OTF_check_features (otf, 0,
				     otspec->script_tag, otspec->langsys_tag,
				     otspec->features[1],
				     otspec->nfeatures[1]) != 1)
	    continue;
Kenichi Handa's avatar
Kenichi Handa committed
759
	}
760 761
#endif	/* HAVE_LIBOTF */
      entity = ftfont_pattern_entity (fontset->fonts[i], registry,
762
				      AREF (spec, FONT_EXTRA_INDEX),
763 764 765
				      fc_charset_idx);
      if (! NILP (entity))
	val = Fcons (entity, val);
Kenichi Handa's avatar
Kenichi Handa committed
766
    }
767
  font_add_log ("ftfont-list", spec, val);
Kenichi Handa's avatar
Kenichi Handa committed
768 769 770 771
  goto finish;

 err:
  /* We come here because of unexpected error in fontconfig API call
772
     (usually insufficient memory).  */
Kenichi Handa's avatar
Kenichi Handa committed
773 774 775 776 777 778 779 780 781
  val = Qnil;

 finish:
  if (objset) FcObjectSetDestroy (objset);
  if (fontset) FcFontSetDestroy (fontset);
  if (pattern) FcPatternDestroy (pattern);
  return val;
}

782 783 784 785
static Lisp_Object
ftfont_match (frame, spec)
     Lisp_Object frame, spec;
{
Kenichi Handa's avatar
Kenichi Handa committed
786
  Lisp_Object entity;
787
  FcPattern *pattern, *match = NULL;
788
  FcResult result;
789 790
  char otlayout[15];		/* For "otlayout:XXXX" */
  struct OpenTypeSpec *otspec = NULL;
Kenichi Handa's avatar
Kenichi Handa committed
791
  int fc_charset_idx;
792 793 794 795 796 797 798

  if (! fc_initialized)
    {
      FcInit ();
      fc_initialized = 1;
    }

Kenichi Handa's avatar
Kenichi Handa committed
799
  pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec);
800
  if (! pattern)
801 802
    return Qnil;

803
  if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
804
    {
805
      FcValue value;
806

807 808 809 810 811 812 813 814 815
      value.type = FcTypeDouble;
      value.u.d = XINT (AREF (spec, FONT_SIZE_INDEX));
      FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse);
    }
  if (FcConfigSubstitute (NULL, pattern, FcMatchPattern) == FcTrue)
    {
      FcDefaultSubstitute (pattern);
      match = FcFontMatch (NULL, pattern, &result);
      if (match)
816
	{
817 818 819
	  entity = ftfont_pattern_entity (match, Qunicode_bmp,
					  AREF (spec, FONT_EXTRA_INDEX),
					  fc_charset_idx);
820 821 822 823 824 825 826
	  FcPatternDestroy (match);
	  if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
	      && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
				     ftfont_generic_family_list))
	      && NILP (Fstring_equal (AREF (spec, FONT_FAMILY_INDEX),
				      AREF (entity, FONT_FAMILY_INDEX))))
	    entity = Qnil;
827 828
	}
    }
829
  FcPatternDestroy (pattern);
830

831
  font_add_log ("ftfont-match", spec, entity);
832 833 834
  return entity;
}

Kenichi Handa's avatar
Kenichi Handa committed
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
static Lisp_Object
ftfont_list_family (frame)
     Lisp_Object frame;
{
  Lisp_Object list;
  FcPattern *pattern = NULL;
  FcFontSet *fontset = NULL;
  FcObjectSet *objset = NULL;
  int i;

  if (! fc_initialized)
    {
      FcInit ();
      fc_initialized = 1;
    }

  pattern = FcPatternCreate ();
  if (! pattern)
    goto finish;
854
  objset = FcObjectSetBuild (FC_FAMILY, NULL);
Kenichi Handa's avatar
Kenichi Handa committed
855 856 857 858 859 860 861 862 863 864 865 866 867
  if (! objset)
    goto finish;
  fontset = FcFontList (NULL, pattern, objset);
  if (! fontset)
    goto finish;

  list = Qnil;
  for (i = 0; i < fontset->nfont; i++)
    {
      FcPattern *pat = fontset->fonts[i];
      FcChar8 *str;

      if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
868
	list = Fcons (intern ((char *) str), list);
Kenichi Handa's avatar
Kenichi Handa committed
869 870 871 872 873 874 875 876 877 878 879
    }

 finish:
  if (objset) FcObjectSetDestroy (objset);
  if (fontset) FcFontSetDestroy (fontset);
  if (pattern) FcPatternDestroy (pattern);

  return list;
}


880
static Lisp_Object
Kenichi Handa's avatar
Kenichi Handa committed
881 882 883 884 885 886 887 888 889 890
ftfont_open (f, entity, pixel_size)
     FRAME_PTR f;
     Lisp_Object entity;
     int pixel_size;
{
  struct ftfont_info *ftfont_info;
  struct font *font;
  FT_Face ft_face;
  FT_Size ft_size;
  FT_UInt size;
Kenichi Handa's avatar
Kenichi Handa committed
891 892
  Lisp_Object val, filename, cache, font_object;
  int fc_charset_idx;
Kenichi Handa's avatar
Kenichi Handa committed
893
  FcPattern *pattern;
Kenichi Handa's avatar
Kenichi Handa committed
894
  int scalable;
Kenichi Handa's avatar
Kenichi Handa committed
895
  int spacing;
896 897 898
  char name[256];
  int i, len;
  int upEM;
Kenichi Handa's avatar
Kenichi Handa committed
899

900 901 902 903
  val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
  if (! CONSP (val))
    return Qnil;
  val = XCDR (val);
Kenichi Handa's avatar
Kenichi Handa committed
904 905 906 907 908 909 910 911 912
  filename = XCAR (val);
  fc_charset_idx = XINT (XCDR (val));
  cache = ftfont_lookup_cache (filename);
  if (NILP (cache))
    return Qnil;
  filename = XCAR (cache);
  val = XCDR (cache);
  ft_face = XSAVE_VALUE (val)->pointer;
  if (XSAVE_VALUE (val)->integer > 0)
Kenichi Handa's avatar
Kenichi Handa committed
913
    {
Kenichi Handa's avatar
Kenichi Handa committed
914
      /* FT_Face in this cache is already used by the different size.  */
Kenichi Handa's avatar
Kenichi Handa committed
915
      if (FT_New_Size (ft_face, &ft_size) != 0)
916
	return Qnil;
Kenichi Handa's avatar
Kenichi Handa committed
917 918 919
      if (FT_Activate_Size (ft_size) != 0)
	{
	  FT_Done_Size (ft_size);
920
	  return Qnil;
Kenichi Handa's avatar
Kenichi Handa committed
921
	}
Kenichi Handa's avatar
Kenichi Handa committed
922 923
    }
  XSAVE_VALUE (val)->integer++;
Kenichi Handa's avatar
Kenichi Handa committed
924 925 926 927 928 929 930
  size = XINT (AREF (entity, FONT_SIZE_INDEX));
  if (size == 0)
    size = pixel_size;
  if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
    {
      if (XSAVE_VALUE (val)->integer == 0)
	FT_Done_Face (ft_face);
931
      return Qnil;
Kenichi Handa's avatar
Kenichi Handa committed
932 933
    }

934 935 936 937 938 939 940 941 942 943 944 945 946 947
  font_object = font_make_object (VECSIZE (struct ftfont_info));
  ASET (font_object, FONT_TYPE_INDEX, Qfreetype);
  for (i = 1;i < FONT_ENTITY_MAX; i++)
    ASET (font_object, i, AREF (entity, i));
  ASET (font_object, FONT_SIZE_INDEX, make_number (size));
  len = font_unparse_xlfd (entity, size, name, 256);
  if (len > 0)
    ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
  len = font_unparse_fcname (entity, size, name, 256);
  if (len > 0)
    ASET (font_object, FONT_FULLNAME_INDEX, make_unibyte_string (name, len));
  else
    ASET (font_object, FONT_FULLNAME_INDEX,
	  AREF (font_object, FONT_NAME_INDEX));
Kenichi Handa's avatar
Kenichi Handa committed
948
  ASET (font_object, FONT_FILE_INDEX, filename);
949
  ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (NULL, filename));
950 951
  font = XFONT_OBJECT (font_object);
  ftfont_info = (struct ftfont_info *) font;
Kenichi Handa's avatar
Kenichi Handa committed
952 953
  ftfont_info->ft_size = ft_face->size;
  ftfont_info->fc_charset_idx = fc_charset_idx;
954
#ifdef HAVE_LIBOTF
955 956
  ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
  ftfont_info->otf = NULL;
957
#endif	/* HAVE_LIBOTF */
Kenichi Handa's avatar
Kenichi Handa committed
958 959
  font->pixel_size = size;
  font->driver = &ftfont_driver;
960
  font->encoding_charset = font->repertory_charset = -1;
961

962
  upEM = ft_face->units_per_EM;
Kenichi Handa's avatar
Kenichi Handa committed
963 964
  scalable = (INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
	      && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0);
965 966 967 968 969 970 971 972 973 974 975
  if (scalable)
    {
      font->ascent = ft_face->ascender * size / upEM;
      font->descent = - ft_face->descender * size / upEM;
      font->height = ft_face->height * size / upEM;
    }
  else
    {
      font->ascent = ft_face->size->metrics.ascender >> 6;
      font->descent = - ft_face->size->metrics.descender >> 6;
      font->height = ft_face->size->metrics.height >> 6;
976
    }
Kenichi Handa's avatar
Kenichi Handa committed
977 978 979
  if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
    spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
  else
980 981
    spacing = FC_PROPORTIONAL;
  if (spacing != FC_PROPORTIONAL)
982 983 984
    font->min_width = font->average_width = font->space_width
      = (scalable ? ft_face->max_advance_width * size / upEM
	 : ft_face->size->metrics.max_advance >> 6);
Kenichi Handa's avatar
Kenichi Handa committed
985 986
  else
    {
987
      int n;
Kenichi Handa's avatar
Kenichi Handa committed
988

989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
      font->min_width = font->average_width = font->space_width = 0;
      for (i = 32, n = 0; i < 127; i++)
	if (FT_Load_Char (ft_face, i, FT_LOAD_DEFAULT) != 0)
	  {
	    int this_width = ft_face->glyph->metrics.horiAdvance >> 6;

	    if (this_width > 0
		&& (! font->min_width || font->min_width > this_width))
	      font->min_width = this_width;
	    if (i == 32)
	      font->space_width = this_width;
	    font->average_width += this_width;
	    n++;
	  }
      if (n > 0)
	font->average_width /= n;
Kenichi Handa's avatar
Kenichi Handa committed
1005 1006
    }

1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
  font->baseline_offset = 0;
  font->relative_compose = 0;
  font->default_ascent = 0;
  font->vertical_centering = 0;
  if (scalable)
    {
      font->underline_position = -ft_face->underline_position * size / upEM;
      font->underline_thickness = -ft_face->underline_thickness * size / upEM;
    }
  else
    {
      font->underline_position = -1;
      font->underline_thickness = 0;
    }
Kenichi Handa's avatar
Kenichi Handa committed
1021

1022
  return font_object;
Kenichi Handa's avatar
Kenichi Handa committed
1023 1024 1025 1026 1027 1028 1029 1030
}

static void
ftfont_close (f, font)
     FRAME_PTR f;
     struct font *font;
{
  struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
Kenichi Handa's avatar
Kenichi Handa committed
1031
  Lisp_Object val, cache;
Kenichi Handa's avatar
Kenichi Handa committed