diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ftfont.c | 179 |
1 files changed, 93 insertions, 86 deletions
diff --git a/src/ftfont.c b/src/ftfont.c index f2fa877c554..8b0bb06a886 100644 --- a/src/ftfont.c +++ b/src/ftfont.c | |||
| @@ -44,7 +44,7 @@ Lisp_Object Qfreetype; | |||
| 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; |
| @@ -74,11 +74,19 @@ struct ftfont_info | |||
| 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 | ||
| @@ -95,7 +103,7 @@ static struct | |||
| 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 }}, |
| @@ -135,29 +143,6 @@ static struct | |||
| 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. |
| @@ -206,7 +191,7 @@ 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; |
| @@ -218,7 +203,14 @@ ftfont_pattern_entity (p, extra) | |||
| 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); |
| @@ -244,12 +236,7 @@ ftfont_pattern_entity (p, extra) | |||
| 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)); |
| @@ -262,13 +249,31 @@ ftfont_pattern_entity (p, extra) | |||
| 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 | ||
| @@ -335,9 +340,9 @@ struct ftfont_cache_data | |||
| 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; |
| @@ -352,29 +357,45 @@ ftfont_lookup_cache (key, for_face) | |||
| 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) |
| @@ -400,31 +421,11 @@ ftfont_lookup_cache (key, for_face) | |||
| 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 | ||
| @@ -447,7 +448,7 @@ ftfont_get_fc_charset (entity) | |||
| 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; |
| @@ -582,23 +583,18 @@ ftfont_get_charset (registry) | |||
| 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 | { | ||
| 589 | FcCharSet *charset = FcCharSetCreate (); | ||
| 590 | int *uniquifier = fc_charset_table[i].uniquifier; | ||
| 591 | 588 | ||
| 592 | if (! charset) | 589 | if (! charset) |
| 590 | return -1; | ||
| 591 | for (j = 0; uniquifier[j]; j++) | ||
| 592 | if (! FcCharSetAddChar (charset, uniquifier[j])) | ||
| 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 | } |
| @@ -1170,7 +1166,7 @@ ftfont_open (f, entity, pixel_size) | |||
| 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); |
| @@ -1297,7 +1293,7 @@ ftfont_close (f, 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)--; |
| @@ -1321,6 +1317,17 @@ 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); |