(cs_iso8859_1): Deleted.
[bpt/emacs.git] / src / ftfont.c
1 /* ftfont.c -- FreeType font driver.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7 This file is part of GNU Emacs.
8
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 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/>. */
21
22 #include <config.h>
23 #include <stdio.h>
24
25 #include <fontconfig/fontconfig.h>
26 #include <fontconfig/fcfreetype.h>
27
28 #include "lisp.h"
29 #include "dispextern.h"
30 #include "frame.h"
31 #include "blockinput.h"
32 #include "character.h"
33 #include "charset.h"
34 #include "coding.h"
35 #include "fontset.h"
36 #include "font.h"
37 #include "ftfont.h"
38
39 /* Symbolic type of this font-driver. */
40 Lisp_Object Qfreetype;
41
42 /* Fontconfig's generic families and their aliases. */
43 static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
44
45 /* Flag to tell if FcInit is areadly called or not. */
46 static int fc_initialized;
47
48 /* Handle to a FreeType library instance. */
49 static FT_Library ft_library;
50
51 /* Cache for FreeType fonts. */
52 static Lisp_Object freetype_font_cache;
53
54 /* Cache for FT_Face */
55 static Lisp_Object ft_face_cache;
56
57 /* The actual structure for FreeType font that can be casted to struct
58 font. */
59
60 struct ftfont_info
61 {
62 struct font font;
63 FT_Size ft_size;
64 int fc_charset_idx;
65 #ifdef HAVE_LIBOTF
66 int maybe_otf; /* Flag to tell if this may be OTF or not. */
67 OTF *otf;
68 #endif /* HAVE_LIBOTF */
69 };
70
71 static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object, int));
72
73 static Lisp_Object ftfont_list_generic_family P_ ((Lisp_Object));
74 Lisp_Object ftfont_font_format P_ ((FcPattern *));
75
76 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
77
78 static struct
79 {
80 /* charset name */
81 char *name;
82 /* characters to distinguish the charset from the others */
83 int uniquifier[6];
84 /* set in syms_of_ftfont */
85 int charset_id;
86 /* set on demand */
87 FcCharSet *fc_charset;
88 } fc_charset_table[] =
89 { { "iso-8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 }, -1 },
90 { "iso-8859-2", { 0x00A0, 0x010E }},
91 { "iso-8859-3", { 0x00A0, 0x0108 }},
92 { "iso-8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
93 { "iso-8859-5", { 0x00A0, 0x0401 }},
94 { "iso-8859-6", { 0x00A0, 0x060C }},
95 { "iso-8859-7", { 0x00A0, 0x0384 }},
96 { "iso-8859-8", { 0x00A0, 0x05D0 }},
97 { "iso-8859-9", { 0x00A0, 0x00A1, 0x00BC, 0x011E }},
98 { "iso-8859-10", { 0x00A0, 0x00D0, 0x0128, 0x2015 }},
99 { "iso-8859-11", { 0x00A0, 0x0E01 }},
100 { "iso-8859-13", { 0x00A0, 0x201C }},
101 { "iso-8859-14", { 0x00A0, 0x0174 }},
102 { "iso-8859-15", { 0x00A0, 0x00A1, 0x00D0, 0x0152 }},
103 { "iso-8859-16", { 0x00A0, 0x0218}},
104 { "chinese-gb2312", { 0x4E13 }},
105 { "big5", { 0xF6B1 }},
106 { "japanese-jisx0208", { 0x4E55 }},
107 { "korean-ksc5601", { 0xAC00 }},
108 { "chinese-cns11643-1", { 0xFE32 }},
109 { "chinese-cns11643-2", { 0x4E33, 0x7934 }},
110 { "chinese-cns11643-3", { 0x201A9 }},
111 { "chinese-cns11643-4", { 0x20057 }},
112 { "chinese-cns11643-5", { 0x20000 }},
113 { "chinese-cns11643-6", { 0x20003 }},
114 { "chinese-cns11643-7", { 0x20055 }},
115 { "chinese-gbk", { 0x4E06 }},
116 { "japanese-jisx0212", { 0x4E44 }},
117 { "japanese-jisx0213-1", { 0xFA10 }},
118 { "japanese-jisx0213-2", { 0xFA49 }},
119 { "japanese-jisx0213.2004-1", { 0x20B9F }},
120 { "viscii", { 0x1EA0, 0x1EAE, 0x1ED2 }},
121 { "tis620", { 0x0E01 }},
122 { "windows-1251", { 0x0401, 0x0490 }},
123 { "koi8-r", { 0x0401, 0x2219 }},
124 { "mule-lao", { 0x0E81 }},
125 { NULL }
126 };
127
128 extern Lisp_Object Qc, Qm, Qp, Qd;
129
130 static Lisp_Object
131 ftfont_pattern_entity (p, registry, fc_charset_idx)
132 FcPattern *p;
133 Lisp_Object registry;
134 int fc_charset_idx;
135 {
136 Lisp_Object entity;
137 char *file, *str;
138 int numeric;
139 double dbl;
140 FcBool b;
141
142 if (FcPatternGetString (p, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
143 return Qnil;
144
145 entity = font_make_entity ();
146
147 ASET (entity, FONT_TYPE_INDEX, Qfreetype);
148 ASET (entity, FONT_REGISTRY_INDEX, registry);
149
150 if (FcPatternGetString (p, FC_FOUNDRY, 0, (FcChar8 **) &str) == FcResultMatch)
151 ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (str, strlen (str)));
152 if (FcPatternGetString (p, FC_FAMILY, 0, (FcChar8 **) &str) == FcResultMatch)
153 ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (str, strlen (str)));
154 if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
155 {
156 if (numeric >= FC_WEIGHT_REGULAR && numeric < FC_WEIGHT_MEDIUM)
157 numeric = FC_WEIGHT_MEDIUM;
158 FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, make_number (numeric));
159 }
160 if (FcPatternGetInteger (p, FC_SLANT, 0, &numeric) == FcResultMatch)
161 {
162 numeric += 100;
163 FONT_SET_STYLE (entity, FONT_SLANT_INDEX, make_number (numeric));
164 }
165 if (FcPatternGetInteger (p, FC_WIDTH, 0, &numeric) == FcResultMatch)
166 {
167 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric));
168 }
169 if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
170 ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
171 else
172 ASET (entity, FONT_SIZE_INDEX, make_number (0));
173 if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch)
174 ASET (entity, FONT_SPACING_INDEX, make_number (numeric));
175 if (FcPatternGetDouble (p, FC_DPI, 0, &dbl) == FcResultMatch)
176 {
177 int dpi = dbl;
178 ASET (entity, FONT_DPI_INDEX, make_number (dpi));
179 }
180 if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
181 && b == FcTrue)
182 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
183
184 font_put_extra (entity, QCfont_entity,
185 Fcons (make_unibyte_string ((char *) file,
186 strlen ((char *) file)),
187 make_number (fc_charset_idx)));
188 return entity;
189 }
190
191
192 static Lisp_Object ftfont_generic_family_list;
193
194 static Lisp_Object
195 ftfont_list_generic_family (family)
196 Lisp_Object family;
197 {
198 Lisp_Object slot, list;
199 FcObjectSet *objset = NULL;
200 FcPattern *pattern = NULL, *pat = NULL;
201 FcFontSet *fontset = NULL;
202 FcChar8 *fam;
203 int i;
204
205 if (EQ (family, Qmono))
206 family = Qmonospace;
207 else if (EQ (family, Qsans) || EQ (family, Qsans__serif))
208 family = Qsans_serif;
209 slot = assq_no_quit (family, ftfont_generic_family_list);
210 if (! CONSP (slot))
211 return Qnil;
212 list = XCDR (slot);
213 if (! EQ (list, Qt))
214 return list;
215
216 objset = FcObjectSetBuild (FC_FAMILY, NULL);
217 if (! objset)
218 goto err;
219 pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString,
220 SYMBOL_FcChar8 (family), (char *) 0);
221 if (! pattern)
222 goto err;
223 pat = FcPatternCreate ();
224 if (! pat)
225 goto err;
226 FcConfigSubstitute (NULL, pattern, FcMatchPattern);
227 for (i = 0, list = Qnil;
228 FcPatternGetString (pattern, FC_FAMILY, i, &fam) == FcResultMatch;
229 i++)
230 {
231 if (strcmp ((char *) fam, (char *) SYMBOL_FcChar8 (family)) == 0)
232 continue;
233 if (! FcPatternAddString (pat, FC_FAMILY, fam))
234 goto err;
235 fontset = FcFontList (NULL, pat, objset);
236 if (! fontset)
237 goto err;
238 if (fontset->nfont > 0)
239 list = Fcons (intern ((char *) fam), list);
240 FcFontSetDestroy (fontset);
241 fontset = NULL;
242 FcPatternDel (pat, FC_FAMILY);
243 }
244 XSETCDR (slot, list);
245 err:
246 if (pat) FcPatternDestroy (pat);
247 if (pattern) FcPatternDestroy (pattern);
248 if (fontset) FcFontSetDestroy (fontset);
249 if (objset) FcObjectSetDestroy (objset);
250 return list;
251 }
252
253 Lisp_Object
254 ftfont_lookup_cache (filename)
255 Lisp_Object filename;
256 {
257 Lisp_Object cache, val;
258
259 cache = assoc_no_quit (filename, ft_face_cache);
260 if (NILP (cache))
261 {
262 val = make_save_value (NULL, 0);
263 cache = Fcons (filename, val);
264 ft_face_cache = Fcons (cache, ft_face_cache);
265 }
266 else
267 val = XCDR (cache);
268 if (! XSAVE_VALUE (val)->pointer)
269 {
270 FT_Face ft_face;
271
272 if (! ft_library
273 && FT_Init_FreeType (&ft_library) != 0)
274 return Qnil;
275 if (FT_New_Face (ft_library, (char *) SDATA (filename), 0, &ft_face) != 0)
276 return Qnil;
277 XSAVE_VALUE (val)->pointer = ft_face;
278 }
279 return cache;
280 }
281
282 static Lisp_Object ftfont_get_cache P_ ((FRAME_PTR));
283 static Lisp_Object ftfont_list P_ ((Lisp_Object, Lisp_Object));
284 static Lisp_Object ftfont_match P_ ((Lisp_Object, Lisp_Object));
285 static Lisp_Object ftfont_list_family P_ ((Lisp_Object));
286 static Lisp_Object ftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
287 static void ftfont_close P_ ((FRAME_PTR, struct font *));
288 static int ftfont_has_char P_ ((Lisp_Object, int));
289 static unsigned ftfont_encode_char P_ ((struct font *, int));
290 static int ftfont_text_extents P_ ((struct font *, unsigned *, int,
291 struct font_metrics *));
292 static int ftfont_get_bitmap P_ ((struct font *, unsigned,
293 struct font_bitmap *, int));
294 static int ftfont_anchor_point P_ ((struct font *, unsigned, int,
295 int *, int *));
296 static Lisp_Object ftfont_shape P_ ((Lisp_Object));
297
298 struct font_driver ftfont_driver =
299 {
300 0, /* Qfreetype */
301 0, /* case insensitive */
302 ftfont_get_cache,
303 ftfont_list,
304 ftfont_match,
305 ftfont_list_family,
306 NULL,
307 ftfont_open,
308 ftfont_close,
309 /* We can't draw a text without device dependent functions. */
310 NULL,
311 NULL,
312 ftfont_has_char,
313 ftfont_encode_char,
314 ftfont_text_extents,
315 /* We can't draw a text without device dependent functions. */
316 NULL,
317 ftfont_get_bitmap,
318 NULL,
319 NULL,
320 NULL,
321 ftfont_anchor_point,
322 NULL,
323 NULL,
324 NULL,
325 NULL,
326 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
327 ftfont_shape
328 #else /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
329 NULL
330 #endif /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
331 };
332
333 extern Lisp_Object QCname;
334
335 static Lisp_Object
336 ftfont_get_cache (f)
337 FRAME_PTR f;
338 {
339 return freetype_font_cache;
340 }
341
342 static int
343 ftfont_get_charset (registry)
344 Lisp_Object registry;
345 {
346 struct charset *encoding;
347 int i, j;
348
349 if (font_registry_charsets (registry, &encoding, NULL) < 0)
350 return -1;
351 if (fc_charset_table[0].charset_id < 0)
352 /* Setup charset_id field of all elements. */
353 for (i = 0; fc_charset_table[i].name; i++)
354 {
355 Lisp_Object sym = intern (fc_charset_table[i].name);
356
357 if (CHARSETP (sym))
358 fc_charset_table[i].charset_id = XINT (CHARSET_SYMBOL_ID (sym));
359 else
360 fc_charset_table[i].charset_id = -1;
361 }
362
363 for (i = 0; fc_charset_table[i].name; i++)
364 if (encoding->id == fc_charset_table[i].charset_id)
365 break;
366 if (! fc_charset_table[i].name)
367 return -1;
368 if (! fc_charset_table[i].fc_charset)
369 {
370 FcCharSet *charset = FcCharSetCreate ();
371 int *uniquifier = fc_charset_table[i].uniquifier;
372
373 if (! charset)
374 return -1;
375 for (j = 0; uniquifier[j]; j++)
376 if (! FcCharSetAddChar (charset, uniquifier[j]))
377 {
378 FcCharSetDestroy (charset);
379 return -1;
380 }
381 fc_charset_table[i].fc_charset = charset;
382 }
383 return i;
384 }
385
386 struct OpenTypeSpec
387 {
388 Lisp_Object script;
389 unsigned int script_tag, langsys_tag;
390 int nfeatures[2];
391 unsigned int *features[2];
392 };
393
394 #define OTF_SYM_TAG(SYM, TAG) \
395 do { \
396 unsigned char *p = SDATA (SYMBOL_NAME (SYM)); \
397 TAG = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; \
398 } while (0)
399
400 #define OTF_TAG_STR(TAG, P) \
401 do { \
402 (P)[0] = (char) (TAG >> 24); \
403 (P)[1] = (char) ((TAG >> 16) & 0xFF); \
404 (P)[2] = (char) ((TAG >> 8) & 0xFF); \
405 (P)[3] = (char) (TAG & 0xFF); \
406 (P)[4] = '\0'; \
407 } while (0)
408
409 static struct OpenTypeSpec *
410 ftfont_get_open_type_spec (Lisp_Object otf_spec)
411 {
412 struct OpenTypeSpec *spec = malloc (sizeof (struct OpenTypeSpec));
413 Lisp_Object val;
414 int i, j, negative;
415
416 if (! spec)
417 return NULL;
418 spec->script = XCAR (otf_spec);
419 if (! NILP (spec->script))
420 {
421 OTF_SYM_TAG (spec->script, spec->script_tag);
422 val = assq_no_quit (spec->script, Votf_script_alist);
423 if (CONSP (val) && SYMBOLP (XCDR (val)))
424 spec->script = XCDR (val);
425 else
426 spec->script = Qnil;
427 }
428 else
429 spec->script_tag = 0x44464C54; /* "DFLT" */
430 otf_spec = XCDR (otf_spec);
431 val = XCAR (otf_spec);
432 if (! NILP (val))
433 OTF_SYM_TAG (val, spec->langsys_tag);
434 else
435 spec->langsys_tag = 0;
436 spec->nfeatures[0] = spec->nfeatures[1] = 0;
437 for (i = 0; i < 2; i++)
438 {
439 Lisp_Object len;
440
441 otf_spec = XCDR (otf_spec);
442 if (NILP (otf_spec))
443 break;
444 val = XCAR (otf_spec);
445 if (NILP (val))
446 continue;
447 len = Flength (val);
448 spec->features[i] = malloc (sizeof (int) * XINT (len));
449 if (! spec->features[i])
450 {
451 if (i > 0 && spec->features[0])
452 free (spec->features[0]);
453 free (spec);
454 return NULL;
455 }
456 for (j = 0, negative = 0; CONSP (val); val = XCDR (val))
457 {
458 if (NILP (XCAR (val)))
459 negative = 1;
460 else
461 {
462 unsigned int tag;
463
464 OTF_SYM_TAG (XCAR (val), tag);
465 spec->features[i][j++] = negative ? tag & 0x80000000 : tag;
466 }
467 }
468 spec->nfeatures[i] = j;
469 }
470 return spec;
471 }
472
473 static FcPattern *ftfont_spec_pattern P_ ((Lisp_Object, int *, char *,
474 struct OpenTypeSpec **));
475
476 static FcPattern *
477 ftfont_spec_pattern (spec, fc_charset_idx, otlayout, otspec)
478 Lisp_Object spec;
479 int *fc_charset_idx;
480 char *otlayout;
481 struct OpenTypeSpec **otspec;
482 {
483 Lisp_Object tmp, extra;
484 FcPattern *pattern = NULL;
485 FcCharSet *charset = NULL;
486 FcLangSet *langset = NULL;
487 int n;
488 int dpi = -1;
489 int spacing = -1;
490 int scalable = -1;
491 Lisp_Object name = Qnil;
492 Lisp_Object script = Qnil;
493 Lisp_Object registry;
494
495 if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX))
496 && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0)
497 /* Fontconfig doesn't support adstyle property. */
498 return NULL;
499 if ((n = FONT_SLANT_NUMERIC (spec)) >= 0
500 && n < 100)
501 /* Fontconfig doesn't support reverse-italic/obligue. */
502 return NULL;
503
504 if (INTEGERP (AREF (spec, FONT_DPI_INDEX)))
505 dpi = XINT (AREF (spec, FONT_DPI_INDEX));
506 if (INTEGERP (AREF (spec, FONT_SPACING_INDEX)))
507 spacing = XINT (AREF (spec, FONT_SPACING_INDEX));
508 if (INTEGERP (AREF (spec, FONT_AVGWIDTH_INDEX))
509 && XINT (AREF (spec, FONT_AVGWIDTH_INDEX)) == 0)
510 scalable = 1;
511
512 registry = AREF (spec, FONT_REGISTRY_INDEX);
513 if (NILP (registry)
514 || EQ (registry, Qiso10646_1)
515 || EQ (registry, Qunicode_bmp)
516 || EQ (registry, Qunicode_sip))
517 *fc_charset_idx = -1;
518 else
519 {
520 *fc_charset_idx = ftfont_get_charset (registry);
521 if (*fc_charset_idx < 0)
522 return NULL;
523 charset = fc_charset_table[*fc_charset_idx].fc_charset;
524 }
525
526 otlayout[0] = '\0';
527 for (extra = AREF (spec, FONT_EXTRA_INDEX);
528 CONSP (extra); extra = XCDR (extra))
529 {
530 Lisp_Object key, val;
531
532 key = XCAR (XCAR (extra)), val = XCDR (XCAR (extra));
533 if (EQ (key, QCdpi))
534 dpi = XINT (val);
535 else if (EQ (key, QCfc_unknown_spec))
536 name = val;
537 else if (EQ (key, QClang))
538 {
539 langset = FcLangSetCreate ();
540 if (! langset)
541 goto err;
542 if (SYMBOLP (val))
543 {
544 if (! FcLangSetAdd (langset, SYMBOL_FcChar8 (val)))
545 goto err;
546 }
547 else
548 for (; CONSP (val); val = XCDR (val))
549 if (SYMBOLP (XCAR (val))
550 && ! FcLangSetAdd (langset, SYMBOL_FcChar8 (XCAR (val))))
551 goto err;
552 }
553 else if (EQ (key, QCname))
554 name = val;
555 else if (EQ (key, QCotf))
556 {
557 *otspec = ftfont_get_open_type_spec (val);
558 if (! *otspec)
559 return NULL;
560 strcat (otlayout, "otlayout:");
561 OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
562 script = (*otspec)->script;
563 }
564 else if (EQ (key, QCscript))
565 script = val;
566 else if (EQ (key, QCscalable))
567 scalable = ! NILP (val);
568 }
569
570 if (! NILP (script) && ! charset)
571 {
572 Lisp_Object chars = assq_no_quit (script, Vscript_representative_chars);
573
574 if (CONSP (chars))
575 {
576 charset = FcCharSetCreate ();
577 if (! charset)
578 goto err;
579 for (chars = XCDR (chars); CONSP (chars); chars = XCDR (chars))
580 if (CHARACTERP (XCAR (chars))
581 && ! FcCharSetAddChar (charset, XUINT (XCAR (chars))))
582 goto err;
583 }
584 }
585
586 pattern = NILP (name) ? FcPatternCreate () : FcNameParse (SDATA (name));
587 if (! pattern)
588 goto err;
589 FcPatternDel (pattern, FC_SIZE);
590 FcPatternDel (pattern, FC_PIXEL_SIZE);
591 tmp = AREF (spec, FONT_FOUNDRY_INDEX);
592 if (! NILP (tmp)
593 && ! FcPatternAddString (pattern, FC_FOUNDRY, SYMBOL_FcChar8 (tmp)))
594 goto err;
595 if (charset
596 && ! FcPatternAddCharSet (pattern, FC_CHARSET, charset))
597 goto err;
598 if (langset
599 && ! FcPatternAddLangSet (pattern, FC_LANG, langset))
600 goto err;
601 if (dpi >= 0
602 && ! FcPatternAddDouble (pattern, FC_DPI, dpi))
603 goto err;
604 if (spacing >= 0
605 && ! FcPatternAddInteger (pattern, FC_SPACING, spacing))
606 goto err;
607 if (scalable >= 0
608 && ! FcPatternAddBool (pattern, FC_SCALABLE, scalable ? FcTrue : FcFalse))
609 goto err;
610 goto finish;
611
612 err:
613 /* We come here because of unexpected error in fontconfig API call
614 (usually insufficient memory). */
615 if (pattern)
616 {
617 FcPatternDestroy (pattern);
618 pattern = NULL;
619 }
620 if (*otspec)
621 {
622 if ((*otspec)->nfeatures[0] > 0)
623 free ((*otspec)->features[0]);
624 if ((*otspec)->nfeatures[1] > 0)
625 free ((*otspec)->features[1]);
626 free (*otspec);
627 *otspec = NULL;
628 }
629
630 finish:
631 if (langset) FcLangSetDestroy (langset);
632 return pattern;
633 }
634
635 static Lisp_Object
636 ftfont_list (frame, spec)
637 Lisp_Object frame, spec;
638 {
639 Lisp_Object val, registry, family, family_list;
640 int i;
641 FcPattern *pattern;
642 FcFontSet *fontset = NULL;
643 FcObjectSet *objset = NULL;
644 int fc_charset_idx;
645 char otlayout[15]; /* For "otlayout:XXXX" */
646 struct OpenTypeSpec *otspec = NULL;
647
648 if (! fc_initialized)
649 {
650 FcInit ();
651 fc_initialized = 1;
652 }
653
654 pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec);
655 if (! pattern)
656 return Qnil;
657 objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
658 FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE,
659 FC_CHARSET, FC_FILE,
660 #ifdef FC_CAPABILITY
661 FC_CAPABILITY,
662 #endif /* FC_CAPABILITY */
663 NULL);
664 if (! objset)
665 goto err;
666
667 registry = AREF (spec, FONT_REGISTRY_INDEX);
668 family = AREF (spec, FONT_FAMILY_INDEX);
669 if (NILP (family))
670 family_list = Fcons (Qnil, Qnil);
671 else
672 {
673 family = Fintern (Fdowncase (SYMBOL_NAME (family)), Qnil);
674 family_list = ftfont_list_generic_family (family);
675 if (NILP (family_list))
676 family_list = Fcons (family, Qnil);
677 }
678
679 for (val = Qnil; CONSP (family_list); family_list = XCDR (family_list))
680 {
681 family = XCAR (family_list);
682 if (! NILP (family))
683 {
684 FcPatternDel (pattern, FC_FAMILY);
685 if (! FcPatternAddString (pattern, FC_FAMILY, SYMBOL_FcChar8 (family)))
686 goto err;
687 }
688 fontset = FcFontList (NULL, pattern, objset);
689 if (! fontset)
690 goto err;
691 for (i = 0; i < fontset->nfont; i++)
692 {
693 Lisp_Object entity;
694
695 #ifdef FC_CAPABILITY
696 if (otlayout[0])
697 {
698 FcChar8 *this;
699
700 if (FcPatternGetString (fontset->fonts[i], FC_CAPABILITY, 0,
701 &this) != FcResultMatch
702 || ! strstr ((char *) this, otlayout))
703 continue;
704 }
705 #endif /* FC_CAPABILITY */
706 #ifdef HAVE_LIBOTF
707 if (otspec)
708 {
709 FcChar8 *file;
710 OTF *otf;
711
712 if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file)
713 != FcResultMatch)
714 continue;
715 otf = OTF_open ((char *) file);
716 if (! otf)
717 continue;
718 if (OTF_check_features (otf, 1,
719 otspec->script_tag, otspec->langsys_tag,
720 otspec->features[0],
721 otspec->nfeatures[0]) != 1
722 || OTF_check_features (otf, 0,
723 otspec->script_tag, otspec->langsys_tag,
724 otspec->features[1],
725 otspec->nfeatures[1]) != 1)
726 continue;
727 }
728 #endif /* HAVE_LIBOTF */
729 entity = ftfont_pattern_entity (fontset->fonts[i], registry,
730 fc_charset_idx);
731 if (! NILP (entity))
732 val = Fcons (entity, val);
733 }
734 FcFontSetDestroy (fontset);
735 fontset = NULL;
736 }
737 goto finish;
738
739 err:
740 /* We come here because of unexpected error in fontconfig API call
741 (usually insufficient memory). */
742 val = Qnil;
743
744 finish:
745 if (objset) FcObjectSetDestroy (objset);
746 if (fontset) FcFontSetDestroy (fontset);
747 if (pattern) FcPatternDestroy (pattern);
748 return val;
749 }
750
751 static Lisp_Object
752 ftfont_match (frame, spec)
753 Lisp_Object frame, spec;
754 {
755 Lisp_Object entity;
756 FcPattern *pattern, *match = NULL;
757 FcResult result;
758 char otlayout[15]; /* For "otlayout:XXXX" */
759 struct OpenTypeSpec *otspec = NULL;
760 int fc_charset_idx;
761
762 if (! fc_initialized)
763 {
764 FcInit ();
765 fc_initialized = 1;
766 }
767
768 pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec);
769 if (! pattern)
770 return Qnil;
771
772 if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
773 {
774 FcValue value;
775
776 value.type = FcTypeDouble;
777 value.u.d = XINT (AREF (spec, FONT_SIZE_INDEX));
778 FcPatternAdd (pattern, FC_PIXEL_SIZE, value, FcFalse);
779 }
780 if (FcConfigSubstitute (NULL, pattern, FcMatchPattern) == FcTrue)
781 {
782 FcDefaultSubstitute (pattern);
783 match = FcFontMatch (NULL, pattern, &result);
784 if (match)
785 {
786 entity = ftfont_pattern_entity (match, Qunicode_bmp, fc_charset_idx);
787 FcPatternDestroy (match);
788 if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
789 && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
790 ftfont_generic_family_list))
791 && NILP (Fstring_equal (AREF (spec, FONT_FAMILY_INDEX),
792 AREF (entity, FONT_FAMILY_INDEX))))
793 entity = Qnil;
794 }
795 }
796 FcPatternDestroy (pattern);
797
798 return entity;
799 }
800
801 static Lisp_Object
802 ftfont_list_family (frame)
803 Lisp_Object frame;
804 {
805 Lisp_Object list;
806 FcPattern *pattern = NULL;
807 FcFontSet *fontset = NULL;
808 FcObjectSet *objset = NULL;
809 int i;
810
811 if (! fc_initialized)
812 {
813 FcInit ();
814 fc_initialized = 1;
815 }
816
817 pattern = FcPatternCreate ();
818 if (! pattern)
819 goto finish;
820 objset = FcObjectSetBuild (FC_FAMILY, NULL);
821 if (! objset)
822 goto finish;
823 fontset = FcFontList (NULL, pattern, objset);
824 if (! fontset)
825 goto finish;
826
827 list = Qnil;
828 for (i = 0; i < fontset->nfont; i++)
829 {
830 FcPattern *pat = fontset->fonts[i];
831 FcChar8 *str;
832
833 if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch)
834 list = Fcons (intern ((char *) str), list);
835 }
836
837 finish:
838 if (objset) FcObjectSetDestroy (objset);
839 if (fontset) FcFontSetDestroy (fontset);
840 if (pattern) FcPatternDestroy (pattern);
841
842 return list;
843 }
844
845
846 static Lisp_Object
847 ftfont_open (f, entity, pixel_size)
848 FRAME_PTR f;
849 Lisp_Object entity;
850 int pixel_size;
851 {
852 struct ftfont_info *ftfont_info;
853 struct font *font;
854 FT_Face ft_face;
855 FT_Size ft_size;
856 FT_UInt size;
857 Lisp_Object val, filename, cache, font_object;
858 int fc_charset_idx;
859 FcPattern *pattern;
860 int scalable;
861 int spacing;
862 char name[256];
863 int i, len;
864 int upEM;
865
866 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
867 if (! CONSP (val))
868 return Qnil;
869 val = XCDR (val);
870 filename = XCAR (val);
871 fc_charset_idx = XINT (XCDR (val));
872 cache = ftfont_lookup_cache (filename);
873 if (NILP (cache))
874 return Qnil;
875 filename = XCAR (cache);
876 val = XCDR (cache);
877 ft_face = XSAVE_VALUE (val)->pointer;
878 if (XSAVE_VALUE (val)->integer > 0)
879 {
880 /* FT_Face in this cache is already used by the different size. */
881 if (FT_New_Size (ft_face, &ft_size) != 0)
882 return Qnil;
883 if (FT_Activate_Size (ft_size) != 0)
884 {
885 FT_Done_Size (ft_size);
886 return Qnil;
887 }
888 }
889 XSAVE_VALUE (val)->integer++;
890 size = XINT (AREF (entity, FONT_SIZE_INDEX));
891 if (size == 0)
892 size = pixel_size;
893 if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
894 {
895 if (XSAVE_VALUE (val)->integer == 0)
896 FT_Done_Face (ft_face);
897 return Qnil;
898 }
899
900 font_object = font_make_object (VECSIZE (struct ftfont_info));
901 ASET (font_object, FONT_TYPE_INDEX, Qfreetype);
902 for (i = 1;i < FONT_ENTITY_MAX; i++)
903 ASET (font_object, i, AREF (entity, i));
904 ASET (font_object, FONT_SIZE_INDEX, make_number (size));
905 len = font_unparse_xlfd (entity, size, name, 256);
906 if (len > 0)
907 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
908 len = font_unparse_fcname (entity, size, name, 256);
909 if (len > 0)
910 ASET (font_object, FONT_FULLNAME_INDEX, make_unibyte_string (name, len));
911 else
912 ASET (font_object, FONT_FULLNAME_INDEX,
913 AREF (font_object, FONT_NAME_INDEX));
914 ASET (font_object, FONT_FILE_INDEX, filename);
915 ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (pattern));
916 font = XFONT_OBJECT (font_object);
917 ftfont_info = (struct ftfont_info *) font;
918 ftfont_info->ft_size = ft_face->size;
919 ftfont_info->fc_charset_idx = fc_charset_idx;
920 #ifdef HAVE_LIBOTF
921 ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
922 ftfont_info->otf = NULL;
923 #endif /* HAVE_LIBOTF */
924 font->pixel_size = size;
925 font->driver = &ftfont_driver;
926 font->encoding_charset = font->repertory_charset = -1;
927
928 upEM = ft_face->units_per_EM;
929 scalable = (INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
930 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0);
931 if (scalable)
932 {
933 font->ascent = ft_face->ascender * size / upEM;
934 font->descent = - ft_face->descender * size / upEM;
935 font->height = ft_face->height * size / upEM;
936 }
937 else
938 {
939 font->ascent = ft_face->size->metrics.ascender >> 6;
940 font->descent = - ft_face->size->metrics.descender >> 6;
941 font->height = ft_face->size->metrics.height >> 6;
942 }
943 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
944 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
945 else
946 spacing = FC_PROPORTIONAL;
947 if (spacing != FC_PROPORTIONAL)
948 font->min_width = font->average_width = font->space_width
949 = (scalable ? ft_face->max_advance_width * size / upEM
950 : ft_face->size->metrics.max_advance >> 6);
951 else
952 {
953 int n;
954
955 font->min_width = font->average_width = font->space_width = 0;
956 for (i = 32, n = 0; i < 127; i++)
957 if (FT_Load_Char (ft_face, i, FT_LOAD_DEFAULT) != 0)
958 {
959 int this_width = ft_face->glyph->metrics.horiAdvance >> 6;
960
961 if (this_width > 0
962 && (! font->min_width || font->min_width > this_width))
963 font->min_width = this_width;
964 if (i == 32)
965 font->space_width = this_width;
966 font->average_width += this_width;
967 n++;
968 }
969 if (n > 0)
970 font->average_width /= n;
971 }
972
973 font->baseline_offset = 0;
974 font->relative_compose = 0;
975 font->default_ascent = 0;
976 font->vertical_centering = 0;
977 if (scalable)
978 {
979 font->underline_position = -ft_face->underline_position * size / upEM;
980 font->underline_thickness = -ft_face->underline_thickness * size / upEM;
981 }
982 else
983 {
984 font->underline_position = -1;
985 font->underline_thickness = 0;
986 }
987
988 return font_object;
989 }
990
991 static void
992 ftfont_close (f, font)
993 FRAME_PTR f;
994 struct font *font;
995 {
996 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
997 Lisp_Object val, cache;
998
999 cache = ftfont_lookup_cache (font->props[FONT_FILE_INDEX]);
1000 val = XCDR (cache);
1001 (XSAVE_VALUE (val)->integer)--;
1002 if (XSAVE_VALUE (val)->integer == 0)
1003 {
1004 FT_Face ft_face = XSAVE_VALUE (val)->pointer;
1005
1006 FT_Done_Face (ft_face);
1007 #ifdef HAVE_LIBOTF
1008 if (ftfont_info->otf)
1009 OTF_close (ftfont_info->otf);
1010 #endif
1011 XSAVE_VALUE (val)->pointer = NULL;
1012 }
1013 else
1014 FT_Done_Size (ftfont_info->ft_size);
1015 }
1016
1017 static int
1018 ftfont_has_char (entity, c)
1019 Lisp_Object entity;
1020 int c;
1021 {
1022 Lisp_Object val;
1023 int fc_charset_idx;
1024 struct charset *charset;
1025
1026 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
1027 fc_charset_idx = XINT (XCDR (XCDR (val)));
1028 if (fc_charset_idx < 0)
1029 return -1;
1030 charset = CHARSET_FROM_ID (fc_charset_table[fc_charset_idx].charset_id);
1031 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset));
1032 }
1033
1034 static unsigned
1035 ftfont_encode_char (font, c)
1036 struct font *font;
1037 int c;
1038 {
1039 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1040 FT_Face ft_face = ftfont_info->ft_size->face;
1041 FT_ULong charcode = c;
1042 FT_UInt code = FT_Get_Char_Index (ft_face, charcode);
1043
1044 return (code > 0 ? code : FONT_INVALID_CODE);
1045 }
1046
1047 static int
1048 ftfont_text_extents (font, code, nglyphs, metrics)
1049 struct font *font;
1050 unsigned *code;
1051 int nglyphs;
1052 struct font_metrics *metrics;
1053 {
1054 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1055 FT_Face ft_face = ftfont_info->ft_size->face;
1056 int width = 0;
1057 int i;
1058
1059 if (ftfont_info->ft_size != ft_face->size)
1060 FT_Activate_Size (ftfont_info->ft_size);
1061 if (metrics)
1062 bzero (metrics, sizeof (struct font_metrics));
1063 for (i = 0; i < nglyphs; i++)
1064 {
1065 if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0)
1066 {
1067 FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
1068
1069 if (metrics)
1070 {
1071 if (metrics->lbearing > width + (m->horiBearingX >> 6))
1072 metrics->lbearing = width + (m->horiBearingX >> 6);
1073 if (metrics->rbearing
1074 < width + ((m->horiBearingX + m->width) >> 6))
1075 metrics->rbearing
1076 = width + ((m->horiBearingX + m->width) >> 6);
1077 if (metrics->ascent < (m->horiBearingY >> 6))
1078 metrics->ascent = m->horiBearingY >> 6;
1079 if (metrics->descent > ((m->horiBearingY + m->height) >> 6))
1080 metrics->descent = (m->horiBearingY + m->height) >> 6;
1081 }
1082 width += m->horiAdvance >> 6;
1083 }
1084 else
1085 {
1086 width += font->space_width;
1087 }
1088 }
1089 if (metrics)
1090 metrics->width = width;
1091
1092 return width;
1093 }
1094
1095 static int
1096 ftfont_get_bitmap (font, code, bitmap, bits_per_pixel)
1097 struct font *font;
1098 unsigned code;
1099 struct font_bitmap *bitmap;
1100 int bits_per_pixel;
1101 {
1102 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1103 FT_Face ft_face = ftfont_info->ft_size->face;
1104 FT_Int32 load_flags = FT_LOAD_RENDER;
1105
1106 if (ftfont_info->ft_size != ft_face->size)
1107 FT_Activate_Size (ftfont_info->ft_size);
1108 if (bits_per_pixel == 1)
1109 {
1110 #ifdef FT_LOAD_TARGET_MONO
1111 load_flags |= FT_LOAD_TARGET_MONO;
1112 #else
1113 load_flags |= FT_LOAD_MONOCHROME;
1114 #endif
1115 }
1116 else if (bits_per_pixel != 8)
1117 /* We don't support such a rendering. */
1118 return -1;
1119
1120 if (FT_Load_Glyph (ft_face, code, load_flags) != 0)
1121 return -1;
1122 bitmap->bits_per_pixel
1123 = (ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 1
1124 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY ? 8
1125 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD ? 8
1126 : ft_face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V ? 8
1127 : -1);
1128 if (bitmap->bits_per_pixel < 0)
1129 /* We don't suport that kind of pixel mode. */
1130 return -1;
1131 bitmap->rows = ft_face->glyph->bitmap.rows;
1132 bitmap->width = ft_face->glyph->bitmap.width;
1133 bitmap->pitch = ft_face->glyph->bitmap.pitch;
1134 bitmap->buffer = ft_face->glyph->bitmap.buffer;
1135 bitmap->left = ft_face->glyph->bitmap_left;
1136 bitmap->top = ft_face->glyph->bitmap_top;
1137 bitmap->advance = ft_face->glyph->metrics.horiAdvance >> 6;
1138 bitmap->extra = NULL;
1139
1140 return 0;
1141 }
1142
1143 static int
1144 ftfont_anchor_point (font, code, index, x, y)
1145 struct font *font;
1146 unsigned code;
1147 int index;
1148 int *x, *y;
1149 {
1150 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1151 FT_Face ft_face = ftfont_info->ft_size->face;
1152
1153 if (ftfont_info->ft_size != ft_face->size)
1154 FT_Activate_Size (ftfont_info->ft_size);
1155 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0)
1156 return -1;
1157 if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
1158 return -1;
1159 if (index >= ft_face->glyph->outline.n_points)
1160 return -1;
1161 *x = ft_face->glyph->outline.points[index].x;
1162 *y = ft_face->glyph->outline.points[index].y;
1163 return 0;
1164 }
1165
1166 #ifdef HAVE_LIBOTF
1167 #ifdef HAVE_M17N_FLT
1168
1169 struct MFLTFontFT
1170 {
1171 MFLTFont flt_font;
1172 struct font *font;
1173 FT_Face ft_face;
1174 OTF *otf;
1175 };
1176
1177 static int
1178 ftfont_get_glyph_id (font, gstring, from, to)
1179 MFLTFont *font;
1180 MFLTGlyphString *gstring;
1181 int from, to;
1182 {
1183 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1184 FT_Face ft_face = flt_font_ft->ft_face;
1185 MFLTGlyph *g;
1186
1187 for (g = gstring->glyphs + from; from < to; g++, from++)
1188 if (! g->encoded)
1189 {
1190 FT_UInt code = FT_Get_Char_Index (ft_face, g->code);
1191
1192 g->code = code > 0 ? code : FONT_INVALID_CODE;
1193 g->encoded = 1;
1194 }
1195 return 0;
1196 }
1197
1198 static int
1199 ftfont_get_metrics (font, gstring, from, to)
1200 MFLTFont *font;
1201 MFLTGlyphString *gstring;
1202 int from, to;
1203 {
1204 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1205 FT_Face ft_face = flt_font_ft->ft_face;
1206 MFLTGlyph *g;
1207
1208 for (g = gstring->glyphs + from; from < to; g++, from++)
1209 if (! g->measured)
1210 {
1211 if (g->code != FONT_INVALID_CODE)
1212 {
1213 FT_Glyph_Metrics *m;
1214
1215 if (FT_Load_Glyph (ft_face, g->code, FT_LOAD_DEFAULT) != 0)
1216 abort ();
1217 m = &ft_face->glyph->metrics;
1218
1219 g->lbearing = m->horiBearingX;
1220 g->rbearing = m->horiBearingX + m->width;
1221 g->ascent = m->horiBearingY;
1222 g->descent = m->height - m->horiBearingY;
1223 g->xadv = m->horiAdvance;
1224 }
1225 else
1226 {
1227 g->lbearing = 0;
1228 g->rbearing = g->xadv = flt_font_ft->font->space_width << 6;
1229 g->ascent = flt_font_ft->font->ascent << 6;
1230 g->descent = flt_font_ft->font->descent << 6;
1231 }
1232 g->yadv = 0;
1233 g->measured = 1;
1234 }
1235 return 0;
1236 }
1237
1238 static int
1239 ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1240 {
1241 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1242 OTF *otf = flt_font_ft->otf;
1243 OTF_Tag *tags;
1244 int i, n, negative;
1245
1246 for (i = 0; i < 2; i++)
1247 {
1248 if (! spec->features[i])
1249 continue;
1250 for (n = 0; spec->features[i][n]; n++);
1251 tags = alloca (sizeof (OTF_Tag) * n);
1252 for (n = 0, negative = 0; spec->features[i][n]; n++)
1253 {
1254 if (spec->features[i][n] == 0xFFFFFFFF)
1255 negative = 1;
1256 else if (negative)
1257 tags[n - 1] = spec->features[i][n] | 0x80000000;
1258 else
1259 tags[n] = spec->features[i][n];
1260 }
1261 if (n - negative > 0
1262 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1263 tags, n - negative) != 1)
1264 return 0;
1265 }
1266 return 1;
1267 }
1268
1269 #define DEVICE_DELTA(table, size) \
1270 (((size) >= (table).StartSize && (size) <= (table).EndSize) \
1271 ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
1272 : 0)
1273
1274 static void
1275 adjust_anchor (FT_Face ft_face, OTF_Anchor *anchor,
1276 unsigned code, int x_ppem, int y_ppem, int *x, int *y)
1277 {
1278 if (anchor->AnchorFormat == 2)
1279 {
1280 FT_Outline *outline;
1281 int ap = anchor->f.f1.AnchorPoint;
1282
1283 FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
1284 outline = &ft_face->glyph->outline;
1285 if (ap < outline->n_points)
1286 {
1287 *x = outline->points[ap].x << 6;
1288 *y = outline->points[ap].y << 6;
1289 }
1290 }
1291 else if (anchor->AnchorFormat == 3)
1292 {
1293 if (anchor->f.f2.XDeviceTable.offset)
1294 *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
1295 if (anchor->f.f2.YDeviceTable.offset)
1296 *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
1297 }
1298 }
1299
1300 static OTF_GlyphString otf_gstring;
1301
1302 static int
1303 ftfont_drive_otf (font, spec, in, from, to, out, adjustment)
1304 MFLTFont *font;
1305 MFLTOtfSpec *spec;
1306 MFLTGlyphString *in;
1307 int from, to;
1308 MFLTGlyphString *out;
1309 MFLTGlyphAdjustment *adjustment;
1310 {
1311 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1312 FT_Face ft_face = flt_font_ft->ft_face;
1313 OTF *otf = flt_font_ft->otf;
1314 int len = to - from;
1315 int i, j, gidx;
1316 OTF_Glyph *otfg;
1317 char script[5], *langsys = NULL;
1318 char *gsub_features = NULL, *gpos_features = NULL;
1319
1320 if (len == 0)
1321 return from;
1322 OTF_tag_name (spec->script, script);
1323 if (spec->langsys)
1324 {
1325 langsys = alloca (5);
1326 OTF_tag_name (spec->langsys, langsys);
1327 }
1328 for (i = 0; i < 2; i++)
1329 {
1330 char *p;
1331
1332 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
1333 {
1334 for (j = 0; spec->features[i][j]; j++);
1335 if (i == 0)
1336 p = gsub_features = alloca (6 * j);
1337 else
1338 p = gpos_features = alloca (6 * j);
1339 for (j = 0; spec->features[i][j]; j++)
1340 {
1341 if (spec->features[i][j] == 0xFFFFFFFF)
1342 *p++ = '*', *p++ = ',';
1343 else
1344 {
1345 OTF_tag_name (spec->features[i][j], p);
1346 p[4] = ',';
1347 p += 5;
1348 }
1349 }
1350 *--p = '\0';
1351 }
1352 }
1353
1354 if (otf_gstring.size == 0)
1355 {
1356 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
1357 otf_gstring.size = len;
1358 }
1359 else if (otf_gstring.size < len)
1360 {
1361 otf_gstring.glyphs = (OTF_Glyph *) realloc (otf_gstring.glyphs,
1362 sizeof (OTF_Glyph) * len);
1363 otf_gstring.size = len;
1364 }
1365 otf_gstring.used = len;
1366 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
1367 for (i = 0; i < len; i++)
1368 {
1369 otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
1370 otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code;
1371 }
1372
1373 OTF_drive_gdef (otf, &otf_gstring);
1374 gidx = out->used;
1375
1376 if (gsub_features)
1377 {
1378 if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
1379 < 0)
1380 goto simple_copy;
1381 if (out->allocated < out->used + otf_gstring.used)
1382 return -2;
1383 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
1384 {
1385 MFLTGlyph *g;
1386 int min_from, max_to;
1387 int j;
1388
1389 g = out->glyphs + out->used;
1390 *g = in->glyphs[from + otfg->f.index.from];
1391 if (g->code != otfg->glyph_id)
1392 {
1393 g->c = 0;
1394 g->code = otfg->glyph_id;
1395 g->measured = 0;
1396 }
1397 out->used++;
1398 min_from = g->from;
1399 max_to = g->to;
1400 if (otfg->f.index.from < otfg->f.index.to)
1401 {
1402 /* OTFG substitutes multiple glyphs in IN. */
1403 for (j = from + otfg->f.index.from + 1;
1404 j <= from + otfg->f.index.to; j++)
1405 {
1406 if (min_from > in->glyphs[j].from)
1407 min_from = in->glyphs[j].from;
1408 if (max_to < in->glyphs[j].to)
1409 max_to = in->glyphs[j].to;
1410 }
1411 g->from = min_from;
1412 g->to = max_to;
1413 }
1414 for (i++, otfg++; (i < otf_gstring.used
1415 && otfg->f.index.from == otfg[-1].f.index.from);
1416 i++, otfg++)
1417 {
1418 g = out->glyphs + out->used;
1419 *g = in->glyphs[from + otfg->f.index.to];
1420 if (g->code != otfg->glyph_id)
1421 {
1422 g->c = 0;
1423 g->code = otfg->glyph_id;
1424 g->measured = 0;
1425 }
1426 out->used++;
1427 }
1428 }
1429 }
1430 else
1431 {
1432 if (out->allocated < out->used + len)
1433 return -2;
1434 for (i = 0; i < len; i++)
1435 out->glyphs[out->used++] = in->glyphs[from + i];
1436 }
1437
1438 if (gpos_features)
1439 {
1440 MFLTGlyph *base = NULL, *mark = NULL, *g;
1441 int x_ppem, y_ppem, x_scale, y_scale;
1442
1443 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
1444 < 0)
1445 return to;
1446
1447 x_ppem = ft_face->size->metrics.x_ppem;
1448 y_ppem = ft_face->size->metrics.y_ppem;
1449 x_scale = ft_face->size->metrics.x_scale;
1450 y_scale = ft_face->size->metrics.y_scale;
1451
1452 for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx;
1453 i < otf_gstring.used; i++, otfg++, g++)
1454 {
1455 MFLTGlyph *prev;
1456
1457 if (! otfg->glyph_id)
1458 continue;
1459 switch (otfg->positioning_type)
1460 {
1461 case 0:
1462 break;
1463 case 1: /* Single */
1464 case 2: /* Pair */
1465 {
1466 int format = otfg->f.f1.format;
1467
1468 if (format & OTF_XPlacement)
1469 adjustment[i].xoff
1470 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
1471 if (format & OTF_XPlaDevice)
1472 adjustment[i].xoff
1473 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
1474 if (format & OTF_YPlacement)
1475 adjustment[i].yoff
1476 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
1477 if (format & OTF_YPlaDevice)
1478 adjustment[i].yoff
1479 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
1480 if (format & OTF_XAdvance)
1481 adjustment[i].xadv
1482 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
1483 if (format & OTF_XAdvDevice)
1484 adjustment[i].xadv
1485 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
1486 if (format & OTF_YAdvance)
1487 adjustment[i].yadv
1488 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
1489 if (format & OTF_YAdvDevice)
1490 adjustment[i].yadv
1491 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
1492 adjustment[i].set = 1;
1493 }
1494 break;
1495 case 3: /* Cursive */
1496 /* Not yet supported. */
1497 break;
1498 case 4: /* Mark-to-Base */
1499 case 5: /* Mark-to-Ligature */
1500 if (! base)
1501 break;
1502 prev = base;
1503 goto label_adjust_anchor;
1504 default: /* i.e. case 6 Mark-to-Mark */
1505 if (! mark)
1506 break;
1507 prev = mark;
1508
1509 label_adjust_anchor:
1510 {
1511 int base_x, base_y, mark_x, mark_y;
1512 int this_from, this_to;
1513
1514 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
1515 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
1516 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
1517 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;;
1518
1519 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
1520 adjust_anchor (ft_face, otfg->f.f4.base_anchor,
1521 prev->code, x_ppem, y_ppem, &base_x, &base_y);
1522 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
1523 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->code,
1524 x_ppem, y_ppem, &mark_x, &mark_y);
1525 adjustment[i].xoff = (base_x - mark_x);
1526 adjustment[i].yoff = - (base_y - mark_y);
1527 adjustment[i].back = (g - prev);
1528 adjustment[i].xadv = 0;
1529 adjustment[i].advance_is_absolute = 1;
1530 adjustment[i].set = 1;
1531 this_from = g->from;
1532 this_to = g->to;
1533 for (j = 0; prev + j < g; j++)
1534 {
1535 if (this_from > prev[j].from)
1536 this_from = prev[j].from;
1537 if (this_to < prev[j].to)
1538 this_to = prev[j].to;
1539 }
1540 for (; prev <= g; prev++)
1541 {
1542 prev->from = this_from;
1543 prev->to = this_to;
1544 }
1545 }
1546 }
1547 if (otfg->GlyphClass == OTF_GlyphClass0)
1548 base = mark = g;
1549 else if (otfg->GlyphClass == OTF_GlyphClassMark)
1550 mark = g;
1551 else
1552 base = g;
1553 }
1554 }
1555 return to;
1556
1557 simple_copy:
1558 if (out->allocated < out->used + len)
1559 return -2;
1560 font->get_metrics (font, in, from, to);
1561 memcpy (out->glyphs + out->used, in->glyphs + from,
1562 sizeof (MFLTGlyph) * len);
1563 out->used += len;
1564 return to;
1565 }
1566
1567 static MFLTGlyphString gstring;
1568
1569 static int m17n_flt_initialized;
1570
1571 extern Lisp_Object QCfamily;
1572
1573 Lisp_Object
1574 ftfont_shape_by_flt (lgstring, font, ft_face, otf)
1575 Lisp_Object lgstring;
1576 struct font *font;
1577 FT_Face ft_face;
1578 OTF *otf;
1579 {
1580 EMACS_UINT len = LGSTRING_LENGTH (lgstring);
1581 EMACS_UINT i;
1582 struct MFLTFontFT flt_font_ft;
1583
1584 if (! m17n_flt_initialized)
1585 {
1586 M17N_INIT ();
1587 m17n_flt_initialized = 1;
1588 }
1589
1590 for (i = 0; i < len; i++)
1591 if (NILP (LGSTRING_GLYPH (lgstring, i)))
1592 break;
1593 len = i;
1594
1595 if (gstring.allocated == 0)
1596 {
1597 gstring.allocated = len * 2;
1598 gstring.glyph_size = sizeof (MFLTGlyph);
1599 gstring.glyphs = malloc (sizeof (MFLTGlyph) * gstring.allocated);
1600 }
1601 else if (gstring.allocated < len * 2)
1602 {
1603 gstring.allocated = len * 2;
1604 gstring.glyphs = realloc (gstring.glyphs,
1605 sizeof (MFLTGlyph) * gstring.allocated);
1606 }
1607 for (i = 0; i < len; i++)
1608 gstring.glyphs[i].c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
1609 gstring.used = len;
1610 gstring.r2l = 0;
1611
1612 {
1613 Lisp_Object family = Ffont_get (LGSTRING_FONT (lgstring), QCfamily);
1614
1615 if (NILP (family))
1616 flt_font_ft.flt_font.family = Mnil;
1617 else
1618 flt_font_ft.flt_font.family
1619 = msymbol ((char *) SDATA (SYMBOL_NAME (family)));
1620 }
1621 flt_font_ft.flt_font.x_ppem = ft_face->size->metrics.x_ppem;
1622 flt_font_ft.flt_font.y_ppem = ft_face->size->metrics.y_ppem;
1623 flt_font_ft.flt_font.get_glyph_id = ftfont_get_glyph_id;
1624 flt_font_ft.flt_font.get_metrics = ftfont_get_metrics;
1625 flt_font_ft.flt_font.check_otf = ftfont_check_otf;
1626 flt_font_ft.flt_font.drive_otf = ftfont_drive_otf;
1627 flt_font_ft.flt_font.internal = NULL;
1628 flt_font_ft.font = font;
1629 flt_font_ft.ft_face = ft_face;
1630 flt_font_ft.otf = otf;
1631 for (i = 0; i < 3; i++)
1632 {
1633 int result = mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, NULL);
1634 if (result != -2)
1635 break;
1636 gstring.allocated += gstring.allocated;
1637 gstring.glyphs = realloc (gstring.glyphs,
1638 sizeof (MFLTGlyph) * gstring.allocated);
1639 }
1640 if (gstring.used > LGSTRING_LENGTH (lgstring))
1641 return Qnil;
1642 for (i = 0; i < gstring.used; i++)
1643 {
1644 MFLTGlyph *g = gstring.glyphs + i;
1645
1646 g->from = LGLYPH_FROM (LGSTRING_GLYPH (lgstring, g->from));
1647 g->to = LGLYPH_TO (LGSTRING_GLYPH (lgstring, g->to));
1648 }
1649
1650 for (i = 0; i < gstring.used; i++)
1651 {
1652 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
1653 MFLTGlyph *g = gstring.glyphs + i;
1654
1655 if (NILP (lglyph))
1656 {
1657 lglyph = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
1658 LGSTRING_SET_GLYPH (lgstring, i, lglyph);
1659 }
1660 LGLYPH_SET_FROM (lglyph, g->from);
1661 LGLYPH_SET_TO (lglyph, g->to);
1662 LGLYPH_SET_CHAR (lglyph, g->c);
1663 LGLYPH_SET_CODE (lglyph, g->code);
1664 LGLYPH_SET_WIDTH (lglyph, g->xadv >> 6);
1665 LGLYPH_SET_LBEARING (lglyph, g->lbearing >> 6);
1666 LGLYPH_SET_RBEARING (lglyph, g->rbearing >> 6);
1667 LGLYPH_SET_ASCENT (lglyph, g->ascent >> 6);
1668 LGLYPH_SET_DESCENT (lglyph, g->descent >> 6);
1669 if (g->adjusted)
1670 {
1671 Lisp_Object vec;
1672
1673 vec = Fmake_vector (make_number (3), Qnil);
1674 ASET (vec, 0, make_number (g->xoff >> 6));
1675 ASET (vec, 1, make_number (g->yoff >> 6));
1676 ASET (vec, 2, make_number (g->xadv >> 6));
1677 LGLYPH_SET_ADJUSTMENT (lglyph, vec);
1678 }
1679 }
1680 return make_number (i);
1681 }
1682
1683 Lisp_Object
1684 ftfont_shape (lgstring)
1685 Lisp_Object lgstring;
1686 {
1687 struct font *font;
1688 struct ftfont_info *ftfont_info;
1689
1690 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
1691 ftfont_info = (struct ftfont_info *) font;
1692 if (! ftfont_info->maybe_otf)
1693 return make_number (0);
1694 if (! ftfont_info->otf)
1695 {
1696 OTF *otf = OTF_open_ft_face (ftfont_info->ft_size->face);
1697
1698 if (! otf || OTF_get_table (otf, "head") < 0)
1699 {
1700 if (otf)
1701 OTF_close (otf);
1702 ftfont_info->maybe_otf = 0;
1703 return make_number (0);
1704 }
1705
1706 ftfont_info->otf = otf;
1707 }
1708
1709 return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face,
1710 ftfont_info->otf);
1711 }
1712
1713 #endif /* HAVE_M17N_FLT */
1714 #endif /* HAVE_LIBOTF */
1715
1716 Lisp_Object
1717 ftfont_font_format (FcPattern *pattern)
1718 {
1719 FcChar8 *str;
1720
1721 #ifdef FC_FONTFORMAT
1722 if (FcPatternGetString (pattern, FC_FONTFORMAT, 0, &str) != FcResultMatch)
1723 return Qnil;
1724 if (strcmp ((char *) str, "TrueType") == 0)
1725 return intern ("truetype");
1726 if (strcmp ((char *) str, "Type 1") == 0)
1727 return intern ("type1");
1728 if (strcmp ((char *) str, "PCF") == 0)
1729 return intern ("pcf");
1730 if (strcmp ((char *) str, "BDF") == 0)
1731 return intern ("bdf");
1732 #else /* not FC_FONTFORMAT */
1733 if (FcPatternGetString (pattern, FC_FILE, 0, &str) != FcResultMatch)
1734 return Qnil;
1735 if (strcasestr ((char *) str, ".ttf") == 0)
1736 return intern ("truetype");
1737 if (strcasestr ((char *) str, "pfb") == 0)
1738 return intern ("type1");
1739 if (strcasestr ((char *) str, "pcf") == 0)
1740 return intern ("pcf");
1741 if (strcasestr ((char *) str, "bdf") == 0)
1742 return intern ("bdf");
1743 #endif /* not FC_FONTFORMAT */
1744 return intern ("unknown");
1745 }
1746
1747 \f
1748 void
1749 syms_of_ftfont ()
1750 {
1751 DEFSYM (Qfreetype, "freetype");
1752 DEFSYM (Qmonospace, "monospace");
1753 DEFSYM (Qsans_serif, "sans-serif");
1754 DEFSYM (Qserif, "serif");
1755 DEFSYM (Qmono, "mono");
1756 DEFSYM (Qsans, "sans");
1757 DEFSYM (Qsans__serif, "sans serif");
1758
1759 staticpro (&freetype_font_cache);
1760 freetype_font_cache = Fcons (Qt, Qnil);
1761
1762 staticpro (&ftfont_generic_family_list);
1763 ftfont_generic_family_list
1764 = Fcons (Fcons (Qmonospace, Qt),
1765 Fcons (Fcons (Qsans_serif, Qt),
1766 Fcons (Fcons (Qsans, Qt), Qnil)));
1767
1768 staticpro (&ft_face_cache);
1769 ft_face_cache = Qnil;
1770
1771 ftfont_driver.type = Qfreetype;
1772 register_font_driver (&ftfont_driver, NULL);
1773 }
1774
1775 /* arch-tag: 7cfa432c-33a6-4988-83d2-a82ed8604aca
1776 (do not change this comment) */