comparison src/ftfont.c @ 102991:18e317a87f12

(Qja, Qko): Don't make them static. (enum ftfont_cache_for): New enum. (fc_charset_table): Undo the previous change. (ftfont_get_latin1_charset): Delete it. (ftfont_pattern_entity): Check cache by ftfont_lookup_cache. Set FONT_SIZE_INDEX of the entity to 0 for a scalable font. For a non-scarable font, try to get AVERAGE_WIDTH. (ftfont_lookup_cache): Argument FOR-FACE is changed to CACHE_FOR. Change ft_face_cache from a list of a hash-table. Don't check `ja' and `ko' adstyle here. (ftfont_get_fc_charset): Call ftfont_lookup_cache with FTFONT_CACHE_FOR_CHARET. (ftfont_get_charset): Undo the previous change. (ftfont_open): Call ftfont_lookup_cache with FTFONT_CACHE_FOR_FACE. (ftfont_close): Likewise. (ftfont_has_char): Special handling of `ja' and `ko' adstyle.
author Kenichi Handa <handa@m17n.org>
date Thu, 16 Apr 2009 01:38:07 +0000
parents f623dc25d37e
children bf88e5d2f4af
comparison
equal deleted inserted replaced
102990:a706504f064e 102991:18e317a87f12
42 42
43 /* Fontconfig's generic families and their aliases. */ 43 /* Fontconfig's generic families and their aliases. */
44 static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif; 44 static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
45 45
46 /* Special ADSTYLE properties to avoid fonts used for Latin characters. */ 46 /* Special ADSTYLE properties to avoid fonts used for Latin characters. */
47 static Lisp_Object Qja, Qko; 47 Lisp_Object Qja, Qko;
48 48
49 /* Flag to tell if FcInit is already called or not. */ 49 /* Flag to tell if FcInit is already called or not. */
50 static int fc_initialized; 50 static int fc_initialized;
51 51
52 /* Handle to a FreeType library instance. */ 52 /* Handle to a FreeType library instance. */
72 #endif /* HAVE_LIBOTF */ 72 #endif /* HAVE_LIBOTF */
73 FT_Size ft_size; 73 FT_Size ft_size;
74 int index; 74 int index;
75 }; 75 };
76 76
77 enum ftfont_cache_for
78 {
79 FTFONT_CACHE_FOR_FACE,
80 FTFONT_CACHE_FOR_CHARSET,
81 FTFONT_CACHE_FOR_ENTITY
82 };
83
77 static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object)); 84 static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object));
78 85
79 static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object, 86 static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object,
80 FcPattern *)); 87 FcPattern *));
81 static Lisp_Object ftfont_lookup_cache P_ ((Lisp_Object, int)); 88 static Lisp_Object ftfont_lookup_cache P_ ((Lisp_Object,
89 enum ftfont_cache_for));
82 90
83 Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object)); 91 Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
84 92
85 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM)) 93 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
86 94
93 /* additional constraint by language */ 101 /* additional constraint by language */
94 char *lang; 102 char *lang;
95 /* set on demand */ 103 /* set on demand */
96 FcCharSet *fc_charset; 104 FcCharSet *fc_charset;
97 } fc_charset_table[] = 105 } fc_charset_table[] =
98 { { "iso8859-1", { } }, /* ftfont_get_latin1_charset handles it. */ 106 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
99 { "iso8859-2", { 0x00A0, 0x010E }}, 107 { "iso8859-2", { 0x00A0, 0x010E }},
100 { "iso8859-3", { 0x00A0, 0x0108 }}, 108 { "iso8859-3", { 0x00A0, 0x0108 }},
101 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }}, 109 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
102 { "iso8859-5", { 0x00A0, 0x0401 }}, 110 { "iso8859-5", { 0x00A0, 0x0401 }},
103 { "iso8859-6", { 0x00A0, 0x060C }}, 111 { "iso8859-6", { 0x00A0, 0x060C }},
133 { "mulelao-1", { 0x0E81 }, "lo"}, 141 { "mulelao-1", { 0x0E81 }, "lo"},
134 { "unicode-sip", { 0x20000 }}, 142 { "unicode-sip", { 0x20000 }},
135 { NULL } 143 { NULL }
136 }; 144 };
137 145
138 /* Return a FcCharSet for iso8859-1 from fc_charset_table[0]. If the
139 charset is not yet ready, create it. */
140 static FcCharSet *
141 ftfont_get_latin1_charset ()
142 {
143 FcCharSet *cs;
144 FcChar32 c;
145
146 if (fc_charset_table[0].fc_charset)
147 return fc_charset_table[0].fc_charset;
148 cs = FcCharSetCreate ();
149 if (! cs)
150 return NULL;
151 for (c = 33; c <= 0xFF; c++)
152 {
153 FcCharSetAddChar (cs, c);
154 if (c == 0x7E)
155 c = 0xA0;
156 }
157 fc_charset_table[0].fc_charset = cs;
158 return cs;
159 }
160
161 extern Lisp_Object Qc, Qm, Qp, Qd; 146 extern Lisp_Object Qc, Qm, Qp, Qd;
162 147
163 /* Dirty hack for handing ADSTYLE property. 148 /* Dirty hack for handing ADSTYLE property.
164 149
165 Fontconfig (actually the underlying FreeType) gives such ADSTYLE 150 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
204 static Lisp_Object 189 static Lisp_Object
205 ftfont_pattern_entity (p, extra) 190 ftfont_pattern_entity (p, extra)
206 FcPattern *p; 191 FcPattern *p;
207 Lisp_Object extra; 192 Lisp_Object extra;
208 { 193 {
209 Lisp_Object entity; 194 Lisp_Object key, cache, entity;
210 char *file, *str; 195 char *file, *str;
211 int index; 196 int index;
212 int numeric; 197 int numeric;
213 double dbl; 198 double dbl;
214 FcBool b; 199 FcBool b;
216 if (FcPatternGetString (p, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch) 201 if (FcPatternGetString (p, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
217 return Qnil; 202 return Qnil;
218 if (FcPatternGetInteger (p, FC_INDEX, 0, &index) != FcResultMatch) 203 if (FcPatternGetInteger (p, FC_INDEX, 0, &index) != FcResultMatch)
219 return Qnil; 204 return Qnil;
220 205
206 key = Fcons (make_unibyte_string ((char *) file, strlen ((char *) file)),
207 make_number (index));
208 cache = ftfont_lookup_cache (key, FTFONT_CACHE_FOR_ENTITY);
209 entity = XCAR (cache);
210 if (! NILP (entity))
211 return entity;
221 entity = font_make_entity (); 212 entity = font_make_entity ();
213 XSETCAR (cache, entity);
222 214
223 ASET (entity, FONT_TYPE_INDEX, Qfreetype); 215 ASET (entity, FONT_TYPE_INDEX, Qfreetype);
224 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1); 216 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
225 217
226 if (FcPatternGetString (p, FC_FOUNDRY, 0, (FcChar8 **) &str) == FcResultMatch) 218 if (FcPatternGetString (p, FC_FOUNDRY, 0, (FcChar8 **) &str) == FcResultMatch)
242 { 234 {
243 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric)); 235 FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric));
244 } 236 }
245 if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch) 237 if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
246 { 238 {
247 Lisp_Object adstyle;
248
249 ASET (entity, FONT_SIZE_INDEX, make_number (dbl)); 239 ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
250 /* As this font has PIXEL_SIZE property, parhaps this is a BDF
251 or PCF font. */
252 ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
253 } 240 }
254 else 241 else
255 ASET (entity, FONT_SIZE_INDEX, make_number (0)); 242 ASET (entity, FONT_SIZE_INDEX, make_number (0));
256 if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch) 243 if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch)
257 ASET (entity, FONT_SPACING_INDEX, make_number (numeric)); 244 ASET (entity, FONT_SPACING_INDEX, make_number (numeric));
260 int dpi = dbl; 247 int dpi = dbl;
261 ASET (entity, FONT_DPI_INDEX, make_number (dpi)); 248 ASET (entity, FONT_DPI_INDEX, make_number (dpi));
262 } 249 }
263 if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch 250 if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
264 && b == FcTrue) 251 && b == FcTrue)
265 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0)); 252 {
253 ASET (entity, FONT_SIZE_INDEX, make_number (0));
254 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
255 }
256 else
257 {
258 /* As this font is not scalable, parhaps this is a BDF or PCF
259 font. */
260 FT_Face ft_face;
261
262 ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
263 if ((ft_library || FT_Init_FreeType (&ft_library) == 0)
264 && FT_New_Face (ft_library, file, index, &ft_face) == 0)
265 {
266 BDF_PropertyRec rec;
267
268 if (FT_Get_BDF_Property (ft_face, "AVERAGE_WIDTH", &rec) == 0
269 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
270 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (rec.u.integer));
271 FT_Done_Face (ft_face);
272 }
273 }
266 274
267 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra)); 275 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
268 font_put_extra (entity, QCfont_entity, 276 font_put_extra (entity, QCfont_entity, key);
269 Fcons (make_unibyte_string ((char *) file,
270 strlen ((char *) file)),
271 make_number (index)));
272 return entity; 277 return entity;
273 } 278 }
274 279
275 280
276 static Lisp_Object ftfont_generic_family_list; 281 static Lisp_Object ftfont_generic_family_list;
333 FT_Face ft_face; 338 FT_Face ft_face;
334 FcCharSet *fc_charset; 339 FcCharSet *fc_charset;
335 }; 340 };
336 341
337 static Lisp_Object 342 static Lisp_Object
338 ftfont_lookup_cache (key, for_face) 343 ftfont_lookup_cache (key, cache_for)
339 Lisp_Object key; 344 Lisp_Object key;
340 int for_face; 345 enum ftfont_cache_for cache_for;
341 { 346 {
342 Lisp_Object cache, val, entity; 347 Lisp_Object cache, val, entity;
343 struct ftfont_cache_data *cache_data; 348 struct ftfont_cache_data *cache_data;
344 349
345 if (FONT_ENTITY_P (key)) 350 if (FONT_ENTITY_P (key))
350 key = XCDR (val); 355 key = XCDR (val);
351 } 356 }
352 else 357 else
353 entity = Qnil; 358 entity = Qnil;
354 359
355 cache = assoc_no_quit (key, ft_face_cache); 360 if (NILP (ft_face_cache))
361 cache = Qnil;
362 else
363 cache = Fgethash (key, ft_face_cache, Qnil);
356 if (NILP (cache)) 364 if (NILP (cache))
357 { 365 {
366 if (NILP (ft_face_cache))
367 {
368 Lisp_Object args[2];
369
370 args[0] = QCtest;
371 args[1] = Qequal;
372 ft_face_cache = Fmake_hash_table (2, args);
373 }
358 cache_data = xmalloc (sizeof (struct ftfont_cache_data)); 374 cache_data = xmalloc (sizeof (struct ftfont_cache_data));
359 cache_data->ft_face = NULL; 375 cache_data->ft_face = NULL;
360 cache_data->fc_charset = NULL; 376 cache_data->fc_charset = NULL;
361 val = make_save_value (NULL, 0); 377 val = make_save_value (NULL, 0);
362 XSAVE_VALUE (val)->integer = 0; 378 XSAVE_VALUE (val)->integer = 0;
363 XSAVE_VALUE (val)->pointer = cache_data; 379 XSAVE_VALUE (val)->pointer = cache_data;
364 cache = Fcons (key, val); 380 cache = Fcons (Qnil, val);
365 ft_face_cache = Fcons (cache, ft_face_cache); 381 Fputhash (key, cache, ft_face_cache);
366 } 382 }
367 else 383 else
368 { 384 {
369 val = XCDR (cache); 385 val = XCDR (cache);
370 cache_data = XSAVE_VALUE (val)->pointer; 386 cache_data = XSAVE_VALUE (val)->pointer;
371 } 387 }
372 if (for_face ? ! cache_data->ft_face : ! cache_data->fc_charset) 388
389 if (cache_for == FTFONT_CACHE_FOR_ENTITY)
390 return cache;
391
392 if (cache_for == FTFONT_CACHE_FOR_FACE
393 ? ! cache_data->ft_face : ! cache_data->fc_charset)
373 { 394 {
374 char *filename = (char *) SDATA (XCAR (key)); 395 char *filename = (char *) SDATA (XCAR (key));
375 int index = XINT (XCDR (key)); 396 int index = XINT (XCDR (key));
376 397
377 if (for_face) 398 if (cache_for == FTFONT_CACHE_FOR_FACE)
378 { 399 {
379 if (! ft_library 400 if (! ft_library
380 && FT_Init_FreeType (&ft_library) != 0) 401 && FT_Init_FreeType (&ft_library) != 0)
381 return Qnil; 402 return Qnil;
382 if (FT_New_Face (ft_library, filename, index, &cache_data->ft_face) 403 if (FT_New_Face (ft_library, filename, index, &cache_data->ft_face)
398 if (! objset) 419 if (! objset)
399 goto finish; 420 goto finish;
400 fontset = FcFontList (NULL, pat, objset); 421 fontset = FcFontList (NULL, pat, objset);
401 if (! fontset) 422 if (! fontset)
402 goto finish; 423 goto finish;
403 if (fontset && fontset->nfont > 0) 424 if (fontset && fontset->nfont > 0
404 { 425 && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
405 if (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
406 &charset) 426 &charset)
407 == FcResultMatch) 427 == FcResultMatch))
408 { 428 cache_data->fc_charset = FcCharSetCopy (charset);
409 /* Dirty hack. Fonts of "ja" and "ko" adstyle are
410 not suitable for Latin characters. */
411 if (! NILP (entity)
412 && (EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qja)
413 || EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qko)))
414 {
415 FcCharSet *latin1 = ftfont_get_latin1_charset ();
416
417 if (! latin1)
418 goto finish;
419 cache_data->fc_charset = FcCharSetSubtract (charset,
420 latin1);
421 }
422 else
423 cache_data->fc_charset = FcCharSetCopy (charset);
424 }
425 else
426 cache_data->fc_charset = FcCharSetCreate ();
427 }
428 else 429 else
429 cache_data->fc_charset = FcCharSetCreate (); 430 cache_data->fc_charset = FcCharSetCreate ();
430 431
431 finish: 432 finish:
432 if (fontset) 433 if (fontset)
445 Lisp_Object entity; 446 Lisp_Object entity;
446 { 447 {
447 Lisp_Object val, cache; 448 Lisp_Object val, cache;
448 struct ftfont_cache_data *cache_data; 449 struct ftfont_cache_data *cache_data;
449 450
450 cache = ftfont_lookup_cache (entity, 0); 451 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
451 val = XCDR (cache); 452 val = XCDR (cache);
452 cache_data = XSAVE_VALUE (val)->pointer; 453 cache_data = XSAVE_VALUE (val)->pointer;
453 return cache_data->fc_charset; 454 return cache_data->fc_charset;
454 } 455 }
455 456
580 break; 581 break;
581 if (! fc_charset_table[i].name) 582 if (! fc_charset_table[i].name)
582 return -1; 583 return -1;
583 if (! fc_charset_table[i].fc_charset) 584 if (! fc_charset_table[i].fc_charset)
584 { 585 {
585 if (i == 0) 586 FcCharSet *charset = FcCharSetCreate ();
586 ftfont_get_latin1_charset (); 587 int *uniquifier = fc_charset_table[i].uniquifier;
587 else 588
588 { 589 if (! charset)
589 FcCharSet *charset = FcCharSetCreate (); 590 return -1;
590 int *uniquifier = fc_charset_table[i].uniquifier; 591 for (j = 0; uniquifier[j]; j++)
591 592 if (! FcCharSetAddChar (charset, uniquifier[j]))
592 if (! charset) 593 {
594 FcCharSetDestroy (charset);
593 return -1; 595 return -1;
594 for (j = 0; uniquifier[j]; j++) 596 }
595 if (! FcCharSetAddChar (charset, uniquifier[j])) 597 fc_charset_table[i].fc_charset = charset;
596 {
597 FcCharSetDestroy (charset);
598 return -1;
599 }
600 fc_charset_table[i].fc_charset = charset;
601 }
602 } 598 }
603 return i; 599 return i;
604 } 600 }
605 601
606 struct OpenTypeSpec 602 struct OpenTypeSpec
1168 1164
1169 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); 1165 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
1170 if (! CONSP (val)) 1166 if (! CONSP (val))
1171 return Qnil; 1167 return Qnil;
1172 val = XCDR (val); 1168 val = XCDR (val);
1173 cache = ftfont_lookup_cache (entity, 1); 1169 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_FACE);
1174 if (NILP (cache)) 1170 if (NILP (cache))
1175 return Qnil; 1171 return Qnil;
1176 filename = XCAR (val); 1172 filename = XCAR (val);
1177 index = XCDR (val); 1173 index = XCDR (val);
1178 val = XCDR (cache); 1174 val = XCDR (cache);
1295 { 1291 {
1296 struct ftfont_info *ftfont_info = (struct ftfont_info *) font; 1292 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1297 Lisp_Object val, cache; 1293 Lisp_Object val, cache;
1298 1294
1299 val = Fcons (font->props[FONT_FILE_INDEX], make_number (ftfont_info->index)); 1295 val = Fcons (font->props[FONT_FILE_INDEX], make_number (ftfont_info->index));
1300 cache = ftfont_lookup_cache (val, 1); 1296 cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE);
1301 xassert (CONSP (cache)); 1297 xassert (CONSP (cache));
1302 val = XCDR (cache); 1298 val = XCDR (cache);
1303 (XSAVE_VALUE (val)->integer)--; 1299 (XSAVE_VALUE (val)->integer)--;
1304 if (XSAVE_VALUE (val)->integer == 0) 1300 if (XSAVE_VALUE (val)->integer == 0)
1305 { 1301 {
1319 static int 1315 static int
1320 ftfont_has_char (font, c) 1316 ftfont_has_char (font, c)
1321 Lisp_Object font; 1317 Lisp_Object font;
1322 int c; 1318 int c;
1323 { 1319 {
1320 struct charset *cs = NULL;
1321
1322 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
1323 && charset_jisx0208 >= 0)
1324 cs = CHARSET_FROM_ID (charset_jisx0208);
1325 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
1326 && charset_ksc5601 >= 0)
1327 cs = CHARSET_FROM_ID (charset_ksc5601);
1328 if (cs)
1329 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
1330
1324 if (FONT_ENTITY_P (font)) 1331 if (FONT_ENTITY_P (font))
1325 { 1332 {
1326 FcCharSet *charset = ftfont_get_fc_charset (font); 1333 FcCharSet *charset = ftfont_get_fc_charset (font);
1327 1334
1328 return (FcCharSetHasChar (charset, c) == FcTrue); 1335 return (FcCharSetHasChar (charset, c) == FcTrue);