Mercurial > emacs
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); |