aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa2008-05-19 07:21:25 +0000
committerKenichi Handa2008-05-19 07:21:25 +0000
commit21988a0804b92c2130fe780ef0c9d7a66ff3ad45 (patch)
treea85e04ddc8df0dfc9594c1540cb541935edd84a2 /src
parent686ee703662283c9f84e9a72b8d8fb8a86d6c48c (diff)
downloademacs-21988a0804b92c2130fe780ef0c9d7a66ff3ad45.tar.gz
emacs-21988a0804b92c2130fe780ef0c9d7a66ff3ad45.zip
(cs_iso8859_1): Deleted.
(ft_face_cache): New variable. (struct ftfont_info): New member fc_charset_idx; (ftfont_build_basic_charsets): Deleted. (fc_charset_table): New variable. (ftfont_pattern_entity): New arg fc_charset_idx. Store (FILENAME . FC_CHARSET_IDX) as :font-entity property in the font entity. Callers changed. (ftfont_lookup_cache, ftfont_get_charset): New funcitons. (ftfont_spec_pattern): New argument fc_charset_idx. Check registry more rigidly. Callers changed. (ftfont_open, ftfont_close, ftfont_has_char): Adjustd for the change of :font-entity property of the font.
Diffstat (limited to 'src')
-rw-r--r--src/ftfont.c341
1 files changed, 205 insertions, 136 deletions
diff --git a/src/ftfont.c b/src/ftfont.c
index e11de08259b..6c86a7872e9 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -51,9 +51,8 @@ static FT_Library ft_library;
51/* Cache for FreeType fonts. */ 51/* Cache for FreeType fonts. */
52static Lisp_Object freetype_font_cache; 52static Lisp_Object freetype_font_cache;
53 53
54/* Fontconfig's charset used for finding fonts of registry 54/* Cache for FT_Face */
55 "iso8859-1". */ 55static Lisp_Object ft_face_cache;
56static FcCharSet *cs_iso8859_1;
57 56
58/* The actual structure for FreeType font that can be casted to struct 57/* The actual structure for FreeType font that can be casted to struct
59 font. */ 58 font. */
@@ -62,71 +61,95 @@ struct ftfont_info
62{ 61{
63 struct font font; 62 struct font font;
64 FT_Size ft_size; 63 FT_Size ft_size;
64 int fc_charset_idx;
65#ifdef HAVE_LIBOTF 65#ifdef HAVE_LIBOTF
66 int maybe_otf; /* Flag to tell if this may be OTF or not. */ 66 int maybe_otf; /* Flag to tell if this may be OTF or not. */
67 OTF *otf; 67 OTF *otf;
68#endif /* HAVE_LIBOTF */ 68#endif /* HAVE_LIBOTF */
69}; 69};
70 70
71static int ftfont_build_basic_charsets P_ ((void)); 71static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object, int));
72static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object)); 72
73static Lisp_Object ftfont_list_generic_family P_ ((Lisp_Object)); 73static Lisp_Object ftfont_list_generic_family P_ ((Lisp_Object));
74Lisp_Object ftfont_font_format P_ ((FcPattern *)); 74Lisp_Object ftfont_font_format P_ ((FcPattern *));
75 75
76#define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM)) 76#define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
77 77
78static int 78static struct
79ftfont_build_basic_charsets ()
80{ 79{
81 FcChar32 c; 80 /* charset name */
82 81 char *name;
83 cs_iso8859_1 = FcCharSetCreate (); 82 /* characters to distinguish the charset from the others */
84 if (! cs_iso8859_1) 83 int uniquifier[6];
85 return -1; 84 /* set in syms_of_ftfont */
86 for (c = ' '; c < 127; c++) 85 int charset_id;
87 if (! FcCharSetAddChar (cs_iso8859_1, c)) 86 /* set on demand */
88 return -1; 87 FcCharSet *fc_charset;
89#if 0 88} fc_charset_table[] =
90 /* This part is currently disabled. Should be fixed later. */ 89 { { "iso-8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 }, -1 },
91 for (c = 192; c < 256; c++) 90 { "iso-8859-2", { 0x00A0, 0x010E }},
92 if (! FcCharSetAddChar (cs_iso8859_1, c)) 91 { "iso-8859-3", { 0x00A0, 0x0108 }},
93 return -1; 92 { "iso-8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
94#endif 93 { "iso-8859-5", { 0x00A0, 0x0401 }},
95 return 0; 94 { "iso-8859-6", { 0x00A0, 0x060C }},
96} 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 };
97 127
98extern Lisp_Object Qc, Qm, Qp, Qd; 128extern Lisp_Object Qc, Qm, Qp, Qd;
99 129
100static Lisp_Object 130static Lisp_Object
101ftfont_pattern_entity (p, registry) 131ftfont_pattern_entity (p, registry, fc_charset_idx)
102 FcPattern *p; 132 FcPattern *p;
103 Lisp_Object registry; 133 Lisp_Object registry;
134 int fc_charset_idx;
104{ 135{
105 Lisp_Object entity; 136 Lisp_Object entity;
106 FcChar8 *file, *fontformat; 137 char *file, *str;
107 FcCharSet *charset;
108 FcChar8 *str;
109 int numeric; 138 int numeric;
110 double dbl; 139 double dbl;
111 FcBool b; 140 FcBool b;
112 141
113 if (FcPatternGetString (p, FC_FILE, 0, &file) != FcResultMatch) 142 if (FcPatternGetString (p, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
114 return Qnil; 143 return Qnil;
115 if (FcPatternGetCharSet (p, FC_CHARSET, 0, &charset) != FcResultMatch)
116 charset = NULL;
117#ifdef FC_FONTFORMAT
118 if (FcPatternGetString (p, FC_FONTFORMAT, 0, &fontformat) != FcResultMatch)
119#endif /* FC_FONTFORMAT */
120 fontformat = NULL;
121 144
122 entity = font_make_entity (); 145 entity = font_make_entity ();
123 146
124 ASET (entity, FONT_TYPE_INDEX, Qfreetype); 147 ASET (entity, FONT_TYPE_INDEX, Qfreetype);
125 ASET (entity, FONT_REGISTRY_INDEX, registry); 148 ASET (entity, FONT_REGISTRY_INDEX, registry);
126 149
127 if (FcPatternGetString (p, FC_FOUNDRY, 0, &str) == FcResultMatch) 150 if (FcPatternGetString (p, FC_FOUNDRY, 0, (FcChar8 **) &str) == FcResultMatch)
128 ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (str, strlen (str))); 151 ASET (entity, FONT_FOUNDRY_INDEX, font_intern_prop (str, strlen (str)));
129 if (FcPatternGetString (p, FC_FAMILY, 0, &str) == FcResultMatch) 152 if (FcPatternGetString (p, FC_FAMILY, 0, (FcChar8 **) &str) == FcResultMatch)
130 ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (str, strlen (str))); 153 ASET (entity, FONT_FAMILY_INDEX, font_intern_prop (str, strlen (str)));
131 if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch) 154 if (FcPatternGetInteger (p, FC_WEIGHT, 0, &numeric) == FcResultMatch)
132 { 155 {
@@ -158,26 +181,10 @@ ftfont_pattern_entity (p, registry)
158 && b == FcTrue) 181 && b == FcTrue)
159 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0)); 182 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
160 183
161 file = FcStrCopy (file); 184 font_put_extra (entity, QCfont_entity,
162 if (! file) 185 Fcons (make_unibyte_string ((char *) file,
163 return Qnil; 186 strlen ((char *) file)),
164 p = FcPatternCreate (); 187 make_number (fc_charset_idx)));
165 if (! p)
166 return Qnil;
167
168 if (FcPatternAddString (p, FC_FILE, file) == FcFalse
169 || (charset
170 && FcPatternAddCharSet (p, FC_CHARSET, charset) == FcFalse)
171#ifdef FC_FONTFORMAT
172 || (fontformat
173 && FcPatternAddString (p, FC_FONTFORMAT, fontformat) == FcFalse)
174#endif /* FC_FONTFORMAT */
175 )
176 {
177 FcPatternDestroy (p);
178 return Qnil;
179 }
180 font_put_extra (entity, QCfont_entity, make_save_value (p, 0));
181 return entity; 188 return entity;
182} 189}
183 190
@@ -188,12 +195,12 @@ static Lisp_Object
188ftfont_list_generic_family (family) 195ftfont_list_generic_family (family)
189 Lisp_Object family; 196 Lisp_Object family;
190{ 197{
191 Lisp_Object slot, list, val; 198 Lisp_Object slot, list;
192 FcObjectSet *objset = NULL; 199 FcObjectSet *objset = NULL;
193 FcPattern *pattern = NULL, *pat = NULL; 200 FcPattern *pattern = NULL, *pat = NULL;
194 FcFontSet *fontset = NULL; 201 FcFontSet *fontset = NULL;
195 FcChar8 *fam; 202 FcChar8 *fam;
196 int i, j; 203 int i;
197 204
198 if (EQ (family, Qmono)) 205 if (EQ (family, Qmono))
199 family = Qmonospace; 206 family = Qmonospace;
@@ -243,6 +250,35 @@ ftfont_list_generic_family (family)
243 return list; 250 return list;
244} 251}
245 252
253Lisp_Object
254ftfont_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
246static Lisp_Object ftfont_get_cache P_ ((FRAME_PTR)); 282static Lisp_Object ftfont_get_cache P_ ((FRAME_PTR));
247static Lisp_Object ftfont_list P_ ((Lisp_Object, Lisp_Object)); 283static Lisp_Object ftfont_list P_ ((Lisp_Object, Lisp_Object));
248static Lisp_Object ftfont_match P_ ((Lisp_Object, Lisp_Object)); 284static Lisp_Object ftfont_match P_ ((Lisp_Object, Lisp_Object));
@@ -303,6 +339,50 @@ ftfont_get_cache (f)
303 return freetype_font_cache; 339 return freetype_font_cache;
304} 340}
305 341
342static int
343ftfont_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
306struct OpenTypeSpec 386struct OpenTypeSpec
307{ 387{
308 Lisp_Object script; 388 Lisp_Object script;
@@ -390,14 +470,17 @@ ftfont_get_open_type_spec (Lisp_Object otf_spec)
390 return spec; 470 return spec;
391} 471}
392 472
473static FcPattern *ftfont_spec_pattern P_ ((Lisp_Object, int *, char *,
474 struct OpenTypeSpec **));
475
393static FcPattern * 476static FcPattern *
394ftfont_spec_pattern (spec, otlayout, otspec) 477ftfont_spec_pattern (spec, fc_charset_idx, otlayout, otspec)
395 Lisp_Object spec; 478 Lisp_Object spec;
479 int *fc_charset_idx;
396 char *otlayout; 480 char *otlayout;
397 struct OpenTypeSpec **otspec; 481 struct OpenTypeSpec **otspec;
398{ 482{
399 Lisp_Object val, tmp, extra; 483 Lisp_Object tmp, extra;
400 int i;
401 FcPattern *pattern = NULL; 484 FcPattern *pattern = NULL;
402 FcCharSet *charset = NULL; 485 FcCharSet *charset = NULL;
403 FcLangSet *langset = NULL; 486 FcLangSet *langset = NULL;
@@ -407,7 +490,7 @@ ftfont_spec_pattern (spec, otlayout, otspec)
407 int scalable = -1; 490 int scalable = -1;
408 Lisp_Object name = Qnil; 491 Lisp_Object name = Qnil;
409 Lisp_Object script = Qnil; 492 Lisp_Object script = Qnil;
410 Lisp_Object registry = Qunicode_bmp; 493 Lisp_Object registry;
411 494
412 if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX)) 495 if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX))
413 && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0) 496 && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0)
@@ -426,20 +509,18 @@ ftfont_spec_pattern (spec, otlayout, otspec)
426 && XINT (AREF (spec, FONT_AVGWIDTH_INDEX)) == 0) 509 && XINT (AREF (spec, FONT_AVGWIDTH_INDEX)) == 0)
427 scalable = 1; 510 scalable = 1;
428 511
429 if (! NILP (AREF (spec, FONT_REGISTRY_INDEX))) 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
430 { 519 {
431 registry = AREF (spec, FONT_REGISTRY_INDEX); 520 *fc_charset_idx = ftfont_get_charset (registry);
432 if (EQ (registry, Qiso8859_1)) 521 if (*fc_charset_idx < 0)
433 {
434 if (! cs_iso8859_1
435 && ftfont_build_basic_charsets () < 0)
436 return NULL;
437 charset = cs_iso8859_1;
438 }
439 else if (! EQ (registry, Qiso10646_1)
440 && ! EQ (registry, Qunicode_bmp)
441 && ! EQ (registry, Qunicode_sip))
442 return NULL; 522 return NULL;
523 charset = fc_charset_table[*fc_charset_idx].fc_charset;
443 } 524 }
444 525
445 otlayout[0] = '\0'; 526 otlayout[0] = '\0';
@@ -547,7 +628,6 @@ ftfont_spec_pattern (spec, otlayout, otspec)
547 } 628 }
548 629
549 finish: 630 finish:
550 if (charset && charset != cs_iso8859_1) FcCharSetDestroy (charset);
551 if (langset) FcLangSetDestroy (langset); 631 if (langset) FcLangSetDestroy (langset);
552 return pattern; 632 return pattern;
553} 633}
@@ -556,16 +636,12 @@ static Lisp_Object
556ftfont_list (frame, spec) 636ftfont_list (frame, spec)
557 Lisp_Object frame, spec; 637 Lisp_Object frame, spec;
558{ 638{
559 Lisp_Object val, tmp, registry, family, family_list; 639 Lisp_Object val, registry, family, family_list;
560 int i; 640 int i;
561 FcPattern *pattern; 641 FcPattern *pattern;
562 FcFontSet *fontset = NULL; 642 FcFontSet *fontset = NULL;
563 FcObjectSet *objset = NULL; 643 FcObjectSet *objset = NULL;
564 double pixel_size = 0; 644 int fc_charset_idx;
565 int weight = -1, slant = -1, width = -1;
566 double dpi = -1;
567 int spacing = -1;
568 int scalable = -1;
569 char otlayout[15]; /* For "otlayout:XXXX" */ 645 char otlayout[15]; /* For "otlayout:XXXX" */
570 struct OpenTypeSpec *otspec = NULL; 646 struct OpenTypeSpec *otspec = NULL;
571 647
@@ -575,7 +651,7 @@ ftfont_list (frame, spec)
575 fc_initialized = 1; 651 fc_initialized = 1;
576 } 652 }
577 653
578 pattern = ftfont_spec_pattern (spec, otlayout, &otspec); 654 pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec);
579 if (! pattern) 655 if (! pattern)
580 return Qnil; 656 return Qnil;
581 objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT, 657 objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT,
@@ -584,9 +660,6 @@ ftfont_list (frame, spec)
584#ifdef FC_CAPABILITY 660#ifdef FC_CAPABILITY
585 FC_CAPABILITY, 661 FC_CAPABILITY,
586#endif /* FC_CAPABILITY */ 662#endif /* FC_CAPABILITY */
587#ifdef FC_FONTFORMAT
588 FC_FONTFORMAT,
589#endif /* FC_FONTFORMAT */
590 NULL); 663 NULL);
591 if (! objset) 664 if (! objset)
592 goto err; 665 goto err;
@@ -618,8 +691,6 @@ ftfont_list (frame, spec)
618 for (i = 0; i < fontset->nfont; i++) 691 for (i = 0; i < fontset->nfont; i++)
619 { 692 {
620 Lisp_Object entity; 693 Lisp_Object entity;
621 int n;
622 double dbl;
623 694
624#ifdef FC_CAPABILITY 695#ifdef FC_CAPABILITY
625 if (otlayout[0]) 696 if (otlayout[0])
@@ -655,7 +726,8 @@ ftfont_list (frame, spec)
655 continue; 726 continue;
656 } 727 }
657#endif /* HAVE_LIBOTF */ 728#endif /* HAVE_LIBOTF */
658 entity = ftfont_pattern_entity (fontset->fonts[i], registry); 729 entity = ftfont_pattern_entity (fontset->fonts[i], registry,
730 fc_charset_idx);
659 if (! NILP (entity)) 731 if (! NILP (entity))
660 val = Fcons (entity, val); 732 val = Fcons (entity, val);
661 } 733 }
@@ -680,11 +752,12 @@ static Lisp_Object
680ftfont_match (frame, spec) 752ftfont_match (frame, spec)
681 Lisp_Object frame, spec; 753 Lisp_Object frame, spec;
682{ 754{
683 Lisp_Object extra, val, entity; 755 Lisp_Object entity;
684 FcPattern *pattern, *match = NULL; 756 FcPattern *pattern, *match = NULL;
685 FcResult result; 757 FcResult result;
686 char otlayout[15]; /* For "otlayout:XXXX" */ 758 char otlayout[15]; /* For "otlayout:XXXX" */
687 struct OpenTypeSpec *otspec = NULL; 759 struct OpenTypeSpec *otspec = NULL;
760 int fc_charset_idx;
688 761
689 if (! fc_initialized) 762 if (! fc_initialized)
690 { 763 {
@@ -692,7 +765,7 @@ ftfont_match (frame, spec)
692 fc_initialized = 1; 765 fc_initialized = 1;
693 } 766 }
694 767
695 pattern = ftfont_spec_pattern (spec, otlayout, &otspec); 768 pattern = ftfont_spec_pattern (spec, &fc_charset_idx, otlayout, &otspec);
696 if (! pattern) 769 if (! pattern)
697 return Qnil; 770 return Qnil;
698 771
@@ -710,7 +783,7 @@ ftfont_match (frame, spec)
710 match = FcFontMatch (NULL, pattern, &result); 783 match = FcFontMatch (NULL, pattern, &result);
711 if (match) 784 if (match)
712 { 785 {
713 entity = ftfont_pattern_entity (match, Qunicode_bmp); 786 entity = ftfont_pattern_entity (match, Qunicode_bmp, fc_charset_idx);
714 FcPatternDestroy (match); 787 FcPatternDestroy (match);
715 if (! NILP (AREF (spec, FONT_FAMILY_INDEX)) 788 if (! NILP (AREF (spec, FONT_FAMILY_INDEX))
716 && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX), 789 && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX),
@@ -781,10 +854,10 @@ ftfont_open (f, entity, pixel_size)
781 FT_Face ft_face; 854 FT_Face ft_face;
782 FT_Size ft_size; 855 FT_Size ft_size;
783 FT_UInt size; 856 FT_UInt size;
784 Lisp_Object val, font_object; 857 Lisp_Object val, filename, cache, font_object;
858 int fc_charset_idx;
785 FcPattern *pattern; 859 FcPattern *pattern;
786 FcChar8 *file = NULL, *fmt = NULL; 860 int scalable;
787 FcBool scalable;
788 int spacing; 861 int spacing;
789 char name[256]; 862 char name[256];
790 int i, len; 863 int i, len;
@@ -794,26 +867,17 @@ ftfont_open (f, entity, pixel_size)
794 if (! CONSP (val)) 867 if (! CONSP (val))
795 return Qnil; 868 return Qnil;
796 val = XCDR (val); 869 val = XCDR (val);
797 pattern = XSAVE_VALUE (val)->pointer; 870 filename = XCAR (val);
798 if (XSAVE_VALUE (val)->integer == 0) 871 fc_charset_idx = XINT (XCDR (val));
799 { 872 cache = ftfont_lookup_cache (filename);
800 /* We have not yet created FT_Face for this font. */ 873 if (NILP (cache))
801 if (! ft_library 874 return Qnil;
802 && FT_Init_FreeType (&ft_library) != 0) 875 filename = XCAR (cache);
803 return Qnil; 876 val = XCDR (cache);
804 if (FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch) 877 ft_face = XSAVE_VALUE (val)->pointer;
805 return Qnil; 878 if (XSAVE_VALUE (val)->integer > 0)
806 if (FT_New_Face (ft_library, (char *) file, 0, &ft_face) != 0)
807 return Qnil;
808 FcPatternAddFTFace (pattern, FC_FT_FACE, ft_face);
809 ft_size = ft_face->size;
810 XSAVE_VALUE (val)->integer++;
811 }
812 else
813 { 879 {
814 if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &ft_face) 880 /* FT_Face in this cache is already used by the different size. */
815 != FcResultMatch)
816 return Qnil;
817 if (FT_New_Size (ft_face, &ft_size) != 0) 881 if (FT_New_Size (ft_face, &ft_size) != 0)
818 return Qnil; 882 return Qnil;
819 if (FT_Activate_Size (ft_size) != 0) 883 if (FT_Activate_Size (ft_size) != 0)
@@ -821,8 +885,8 @@ ftfont_open (f, entity, pixel_size)
821 FT_Done_Size (ft_size); 885 FT_Done_Size (ft_size);
822 return Qnil; 886 return Qnil;
823 } 887 }
824 } 888 }
825 889 XSAVE_VALUE (val)->integer++;
826 size = XINT (AREF (entity, FONT_SIZE_INDEX)); 890 size = XINT (AREF (entity, FONT_SIZE_INDEX));
827 if (size == 0) 891 if (size == 0)
828 size = pixel_size; 892 size = pixel_size;
@@ -847,15 +911,12 @@ ftfont_open (f, entity, pixel_size)
847 else 911 else
848 ASET (font_object, FONT_FULLNAME_INDEX, 912 ASET (font_object, FONT_FULLNAME_INDEX,
849 AREF (font_object, FONT_NAME_INDEX)); 913 AREF (font_object, FONT_NAME_INDEX));
850 if (! file 914 ASET (font_object, FONT_FILE_INDEX, filename);
851 && ! FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch)
852 return Qnil;
853 ASET (font_object, FONT_FILE_INDEX,
854 make_unibyte_string ((char *) file, strlen ((char *) file)));
855 ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (pattern)); 915 ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (pattern));
856 font = XFONT_OBJECT (font_object); 916 font = XFONT_OBJECT (font_object);
857 ftfont_info = (struct ftfont_info *) font; 917 ftfont_info = (struct ftfont_info *) font;
858 ftfont_info->ft_size = ft_size; 918 ftfont_info->ft_size = ft_face->size;
919 ftfont_info->fc_charset_idx = fc_charset_idx;
859#ifdef HAVE_LIBOTF 920#ifdef HAVE_LIBOTF
860 ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT; 921 ftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
861 ftfont_info->otf = NULL; 922 ftfont_info->otf = NULL;
@@ -865,8 +926,8 @@ ftfont_open (f, entity, pixel_size)
865 font->encoding_charset = font->repertory_charset = -1; 926 font->encoding_charset = font->repertory_charset = -1;
866 927
867 upEM = ft_face->units_per_EM; 928 upEM = ft_face->units_per_EM;
868 if (! FcPatternGetBool (pattern, FC_SCALABLE, 0, &scalable) == FcResultMatch) 929 scalable = (INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
869 scalable = FcFalse; 930 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0);
870 if (scalable) 931 if (scalable)
871 { 932 {
872 font->ascent = ft_face->ascender * size / upEM; 933 font->ascent = ft_face->ascender * size / upEM;
@@ -879,7 +940,9 @@ ftfont_open (f, entity, pixel_size)
879 font->descent = - ft_face->size->metrics.descender >> 6; 940 font->descent = - ft_face->size->metrics.descender >> 6;
880 font->height = ft_face->size->metrics.height >> 6; 941 font->height = ft_face->size->metrics.height >> 6;
881 } 942 }
882 if (FcPatternGetInteger (pattern, FC_SPACING, 0, &spacing) != FcResultMatch) 943 if (INTEGERP (AREF (entity, FONT_SPACING_INDEX)))
944 spacing = XINT (AREF (entity, FONT_SPACING_INDEX));
945 else
883 spacing = FC_PROPORTIONAL; 946 spacing = FC_PROPORTIONAL;
884 if (spacing != FC_PROPORTIONAL) 947 if (spacing != FC_PROPORTIONAL)
885 font->min_width = font->average_width = font->space_width 948 font->min_width = font->average_width = font->space_width
@@ -931,18 +994,21 @@ ftfont_close (f, font)
931 struct font *font; 994 struct font *font;
932{ 995{
933 struct ftfont_info *ftfont_info = (struct ftfont_info *) font; 996 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
934 Lisp_Object val; 997 Lisp_Object val, cache;
935 998
936 val = assq_no_quit (QCfont_entity, font->props[FONT_EXTRA_INDEX]); 999 cache = ftfont_lookup_cache (font->props[FONT_FILE_INDEX]);
937 val = XCDR (val); 1000 val = XCDR (cache);
938 (XSAVE_VALUE (val)->integer)--; 1001 (XSAVE_VALUE (val)->integer)--;
939 if (XSAVE_VALUE (val)->integer == 0) 1002 if (XSAVE_VALUE (val)->integer == 0)
940 { 1003 {
941 FT_Done_Face (ftfont_info->ft_size->face); 1004 FT_Face ft_face = XSAVE_VALUE (val)->pointer;
1005
1006 FT_Done_Face (ft_face);
942#ifdef HAVE_LIBOTF 1007#ifdef HAVE_LIBOTF
943 if (ftfont_info->otf) 1008 if (ftfont_info->otf)
944 OTF_close (ftfont_info->otf); 1009 OTF_close (ftfont_info->otf);
945#endif 1010#endif
1011 XSAVE_VALUE (val)->pointer = NULL;
946 } 1012 }
947 else 1013 else
948 FT_Done_Size (ftfont_info->ft_size); 1014 FT_Done_Size (ftfont_info->ft_size);
@@ -954,15 +1020,15 @@ ftfont_has_char (entity, c)
954 int c; 1020 int c;
955{ 1021{
956 Lisp_Object val; 1022 Lisp_Object val;
957 FcPattern *pattern; 1023 int fc_charset_idx;
958 FcCharSet *charset; 1024 struct charset *charset;
959 1025
960 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); 1026 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
961 val = XCDR (val); 1027 fc_charset_idx = XINT (XCDR (XCDR (val)));
962 pattern = XSAVE_VALUE (val)->pointer; 1028 if (fc_charset_idx < 0)
963 if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
964 return -1; 1029 return -1;
965 return (FcCharSetHasChar (charset, (FcChar32) c) == FcTrue); 1030 charset = CHARSET_FROM_ID (fc_charset_table[fc_charset_idx].charset_id);
1031 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset));
966} 1032}
967 1033
968static unsigned 1034static unsigned
@@ -1316,7 +1382,6 @@ ftfont_drive_otf (font, spec, in, from, to, out, adjustment)
1316 return -2; 1382 return -2;
1317 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; ) 1383 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
1318 { 1384 {
1319 OTF_Glyph *endg;
1320 MFLTGlyph *g; 1385 MFLTGlyph *g;
1321 int min_from, max_to; 1386 int min_from, max_to;
1322 int j; 1387 int j;
@@ -1550,7 +1615,8 @@ ftfont_shape_by_flt (lgstring, font, ft_face, otf)
1550 if (NILP (family)) 1615 if (NILP (family))
1551 flt_font_ft.flt_font.family = Mnil; 1616 flt_font_ft.flt_font.family = Mnil;
1552 else 1617 else
1553 flt_font_ft.flt_font.family = msymbol (SDATA (SYMBOL_NAME (family))); 1618 flt_font_ft.flt_font.family
1619 = msymbol ((char *) SDATA (SYMBOL_NAME (family)));
1554 } 1620 }
1555 flt_font_ft.flt_font.x_ppem = ft_face->size->metrics.x_ppem; 1621 flt_font_ft.flt_font.x_ppem = ft_face->size->metrics.x_ppem;
1556 flt_font_ft.flt_font.y_ppem = ft_face->size->metrics.y_ppem; 1622 flt_font_ft.flt_font.y_ppem = ft_face->size->metrics.y_ppem;
@@ -1699,6 +1765,9 @@ syms_of_ftfont ()
1699 Fcons (Fcons (Qsans_serif, Qt), 1765 Fcons (Fcons (Qsans_serif, Qt),
1700 Fcons (Fcons (Qsans, Qt), Qnil))); 1766 Fcons (Fcons (Qsans, Qt), Qnil)));
1701 1767
1768 staticpro (&ft_face_cache);
1769 ft_face_cache = Qnil;
1770
1702 ftfont_driver.type = Qfreetype; 1771 ftfont_driver.type = Qfreetype;
1703 register_font_driver (&ftfont_driver, NULL); 1772 register_font_driver (&ftfont_driver, NULL);
1704} 1773}