diff options
| author | Kenichi Handa | 2009-04-13 12:33:13 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2009-04-13 12:33:13 +0000 |
| commit | 99c4d65db7400d28b56494fd3671471a43acb76d (patch) | |
| tree | bad63641cc7d73546acf172a390c6960db4572bf /src | |
| parent | 7395a3b3278acf50a66294d2f799a9e62b146b2d (diff) | |
| download | emacs-99c4d65db7400d28b56494fd3671471a43acb76d.tar.gz emacs-99c4d65db7400d28b56494fd3671471a43acb76d.zip | |
(Qja, Qko): New variables.
(fc_charset_table): Delete uniquifier data for iso8859-1.
(ftfont_get_latin1_charset): New function.
(get_adstyle_property): New function.
(ftfont_pattern_entity): Set FONT_ADSTYLE_INDEX of entity for
bitmap fonts.
(ftfont_lookup_cache): Handle the case that KEY is a font-entity.
Delete iso-8859-1 range from the charset of fonts whose adstyle is
`ko' or `ja'.
(ftfont_get_fc_charset): Call ftfont_lookup_cache with ENTITY.
(ftfont_get_charset): For iso8859-1, call
ftfont_get_latin1_charset.
(ftfont_list): Don't refuse a font spec with non-nil `adstyle'
property.
(ftfont_open): Call ftfont_lookup_cache with ENTITY.
(syms_of_ftfont): DEFSYM Qja and Qko.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ftfont.c | 199 |
1 files changed, 162 insertions, 37 deletions
diff --git a/src/ftfont.c b/src/ftfont.c index 0be985e30f2..6865478bd20 100644 --- a/src/ftfont.c +++ b/src/ftfont.c | |||
| @@ -43,6 +43,9 @@ Lisp_Object Qfreetype; | |||
| 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. */ | ||
| 47 | static Lisp_Object Qja, Qko; | ||
| 48 | |||
| 46 | /* Flag to tell if FcInit is already called or not. */ | 49 | /* Flag to tell if FcInit is already called or not. */ |
| 47 | static int fc_initialized; | 50 | static int fc_initialized; |
| 48 | 51 | ||
| @@ -92,7 +95,7 @@ static struct | |||
| 92 | /* set on demand */ | 95 | /* set on demand */ |
| 93 | FcCharSet *fc_charset; | 96 | FcCharSet *fc_charset; |
| 94 | } fc_charset_table[] = | 97 | } fc_charset_table[] = |
| 95 | { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } }, | 98 | { { "iso8859-1", { } }, /* ftfont_get_latin1_charset handles it. */ |
| 96 | { "iso8859-2", { 0x00A0, 0x010E }}, | 99 | { "iso8859-2", { 0x00A0, 0x010E }}, |
| 97 | { "iso8859-3", { 0x00A0, 0x0108 }}, | 100 | { "iso8859-3", { 0x00A0, 0x0108 }}, |
| 98 | { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }}, | 101 | { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }}, |
| @@ -132,8 +135,71 @@ static struct | |||
| 132 | { NULL } | 135 | { NULL } |
| 133 | }; | 136 | }; |
| 134 | 137 | ||
| 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 | |||
| 135 | extern Lisp_Object Qc, Qm, Qp, Qd; | 161 | extern Lisp_Object Qc, Qm, Qp, Qd; |
| 136 | 162 | ||
| 163 | /* Dirty hack for handing ADSTYLE property. | ||
| 164 | |||
| 165 | Fontconfig (actually the underlying FreeType) gives such ADSTYLE | ||
| 166 | font property of PCF/BDF fonts in FC_STYLE. And, "Bold", | ||
| 167 | "Oblique", "Italic", or any non-normal SWIDTH property names | ||
| 168 | (e.g. SemiCondensed) are appended. In addition, if there's no | ||
| 169 | ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties, | ||
| 170 | "Regular" is used for FC_STYLE (see the function | ||
| 171 | pcf_interpret_style in src/pcf/pcfread.c of FreeType). | ||
| 172 | |||
| 173 | Unfortunately this behavior is not documented, so the following | ||
| 174 | code may fail if FreeType changes the behavior in the future. */ | ||
| 175 | |||
| 176 | static Lisp_Object | ||
| 177 | get_adstyle_property (FcPattern *p) | ||
| 178 | { | ||
| 179 | char *str, *end; | ||
| 180 | Lisp_Object adstyle; | ||
| 181 | |||
| 182 | if (FcPatternGetString (p, FC_STYLE, 0, (FcChar8 **) &str) != FcResultMatch) | ||
| 183 | return Qnil; | ||
| 184 | for (end = str; *end && *end != ' '; end++); | ||
| 185 | if (*end) | ||
| 186 | { | ||
| 187 | char *p = alloca (end - str + 1); | ||
| 188 | memcpy (p, str, end - str); | ||
| 189 | p[end - str] = '\0'; | ||
| 190 | str = p; | ||
| 191 | } | ||
| 192 | if (xstrcasecmp (str, "Regular") == 0 | ||
| 193 | || xstrcasecmp (str, "Bold") == 0 | ||
| 194 | || xstrcasecmp (str, "Oblique") == 0 | ||
| 195 | || xstrcasecmp (str, "Italic") == 0) | ||
| 196 | return Qnil; | ||
| 197 | adstyle = font_intern_prop (str, end - str, 0); | ||
| 198 | if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0) | ||
| 199 | return Qnil; | ||
| 200 | return adstyle; | ||
| 201 | } | ||
| 202 | |||
| 137 | static Lisp_Object | 203 | static Lisp_Object |
| 138 | ftfont_pattern_entity (p, extra) | 204 | ftfont_pattern_entity (p, extra) |
| 139 | FcPattern *p; | 205 | FcPattern *p; |
| @@ -176,7 +242,14 @@ ftfont_pattern_entity (p, extra) | |||
| 176 | FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric)); | 242 | FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric)); |
| 177 | } | 243 | } |
| 178 | if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch) | 244 | if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch) |
| 179 | ASET (entity, FONT_SIZE_INDEX, make_number (dbl)); | 245 | { |
| 246 | Lisp_Object adstyle; | ||
| 247 | |||
| 248 | ASET (entity, FONT_SIZE_INDEX, make_number (dbl)); | ||
| 249 | /* As this font has PIXEL_SIZE property, parhaps this is a BDF | ||
| 250 | or PCF font. */ | ||
| 251 | ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p)); | ||
| 252 | } | ||
| 180 | else | 253 | else |
| 181 | ASET (entity, FONT_SIZE_INDEX, make_number (0)); | 254 | ASET (entity, FONT_SIZE_INDEX, make_number (0)); |
| 182 | if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch) | 255 | if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch) |
| @@ -265,9 +338,19 @@ ftfont_lookup_cache (key, for_face) | |||
| 265 | Lisp_Object key; | 338 | Lisp_Object key; |
| 266 | int for_face; | 339 | int for_face; |
| 267 | { | 340 | { |
| 268 | Lisp_Object cache, val; | 341 | Lisp_Object cache, val, entity; |
| 269 | struct ftfont_cache_data *cache_data; | 342 | struct ftfont_cache_data *cache_data; |
| 270 | 343 | ||
| 344 | if (FONT_ENTITY_P (key)) | ||
| 345 | { | ||
| 346 | entity = key; | ||
| 347 | val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); | ||
| 348 | xassert (CONSP (val)); | ||
| 349 | key = XCDR (val); | ||
| 350 | } | ||
| 351 | else | ||
| 352 | entity = Qnil; | ||
| 353 | |||
| 271 | cache = assoc_no_quit (key, ft_face_cache); | 354 | cache = assoc_no_quit (key, ft_face_cache); |
| 272 | if (NILP (cache)) | 355 | if (NILP (cache)) |
| 273 | { | 356 | { |
| @@ -301,25 +384,56 @@ ftfont_lookup_cache (key, for_face) | |||
| 301 | } | 384 | } |
| 302 | else | 385 | else |
| 303 | { | 386 | { |
| 304 | FcPattern *pat; | 387 | FcPattern *pat = NULL; |
| 305 | FcFontSet *fontset; | 388 | FcFontSet *fontset = NULL; |
| 306 | FcObjectSet *objset; | 389 | FcObjectSet *objset = NULL; |
| 307 | FcCharSet *charset; | 390 | FcCharSet *charset = NULL; |
| 308 | 391 | ||
| 309 | pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename, | 392 | pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename, |
| 310 | FC_INDEX, FcTypeInteger, index, NULL); | 393 | FC_INDEX, FcTypeInteger, index, NULL); |
| 311 | objset = FcObjectSetBuild (FC_CHARSET, NULL); | 394 | if (! pat) |
| 395 | goto finish; | ||
| 396 | objset = FcObjectSetBuild (FC_CHARSET, FC_STYLE, NULL); | ||
| 397 | if (! objset) | ||
| 398 | goto finish; | ||
| 312 | fontset = FcFontList (NULL, pat, objset); | 399 | fontset = FcFontList (NULL, pat, objset); |
| 313 | if (fontset && fontset->nfont > 0 | 400 | if (! fontset) |
| 314 | && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0, | 401 | goto finish; |
| 402 | if (fontset && fontset->nfont > 0) | ||
| 403 | { | ||
| 404 | if (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0, | ||
| 315 | &charset) | 405 | &charset) |
| 316 | == FcResultMatch)) | 406 | == FcResultMatch) |
| 317 | cache_data->fc_charset = FcCharSetCopy (charset); | 407 | { |
| 408 | /* Dirty hack. Fonts of "ja" and "ko" adstyle are | ||
| 409 | not suitable for Latin characters. */ | ||
| 410 | if (! NILP (entity) | ||
| 411 | && (EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qja) | ||
| 412 | || EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qko))) | ||
| 413 | { | ||
| 414 | FcCharSet *latin1 = ftfont_get_latin1_charset (); | ||
| 415 | |||
| 416 | if (! latin1) | ||
| 417 | goto finish; | ||
| 418 | cache_data->fc_charset = FcCharSetSubtract (charset, | ||
| 419 | latin1); | ||
| 420 | } | ||
| 421 | else | ||
| 422 | cache_data->fc_charset = FcCharSetCopy (charset); | ||
| 423 | } | ||
| 424 | else | ||
| 425 | cache_data->fc_charset = FcCharSetCreate (); | ||
| 426 | } | ||
| 318 | else | 427 | else |
| 319 | cache_data->fc_charset = FcCharSetCreate (); | 428 | cache_data->fc_charset = FcCharSetCreate (); |
| 320 | FcFontSetDestroy (fontset); | 429 | |
| 321 | FcObjectSetDestroy (objset); | 430 | finish: |
| 322 | FcPatternDestroy (pat); | 431 | if (fontset) |
| 432 | FcFontSetDestroy (fontset); | ||
| 433 | if (objset) | ||
| 434 | FcObjectSetDestroy (objset); | ||
| 435 | if (pat) | ||
| 436 | FcPatternDestroy (pat); | ||
| 323 | } | 437 | } |
| 324 | } | 438 | } |
| 325 | return cache; | 439 | return cache; |
| @@ -332,10 +446,7 @@ ftfont_get_fc_charset (entity) | |||
| 332 | Lisp_Object val, cache; | 446 | Lisp_Object val, cache; |
| 333 | struct ftfont_cache_data *cache_data; | 447 | struct ftfont_cache_data *cache_data; |
| 334 | 448 | ||
| 335 | val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); | 449 | cache = ftfont_lookup_cache (entity, 0); |
| 336 | xassert (CONSP (val)); | ||
| 337 | val = XCDR (val); | ||
| 338 | cache = ftfont_lookup_cache (val, 0); | ||
| 339 | val = XCDR (cache); | 450 | val = XCDR (cache); |
| 340 | cache_data = XSAVE_VALUE (val)->pointer; | 451 | cache_data = XSAVE_VALUE (val)->pointer; |
| 341 | return cache_data->fc_charset; | 452 | return cache_data->fc_charset; |
| @@ -470,18 +581,23 @@ ftfont_get_charset (registry) | |||
| 470 | return -1; | 581 | return -1; |
| 471 | if (! fc_charset_table[i].fc_charset) | 582 | if (! fc_charset_table[i].fc_charset) |
| 472 | { | 583 | { |
| 473 | FcCharSet *charset = FcCharSetCreate (); | 584 | if (i == 0) |
| 474 | int *uniquifier = fc_charset_table[i].uniquifier; | 585 | ftfont_get_latin1_charset (); |
| 586 | else | ||
| 587 | { | ||
| 588 | FcCharSet *charset = FcCharSetCreate (); | ||
| 589 | int *uniquifier = fc_charset_table[i].uniquifier; | ||
| 475 | 590 | ||
| 476 | if (! charset) | 591 | if (! charset) |
| 477 | return -1; | ||
| 478 | for (j = 0; uniquifier[j]; j++) | ||
| 479 | if (! FcCharSetAddChar (charset, uniquifier[j])) | ||
| 480 | { | ||
| 481 | FcCharSetDestroy (charset); | ||
| 482 | return -1; | 592 | return -1; |
| 483 | } | 593 | for (j = 0; uniquifier[j]; j++) |
| 484 | fc_charset_table[i].fc_charset = charset; | 594 | if (! FcCharSetAddChar (charset, uniquifier[j])) |
| 595 | { | ||
| 596 | FcCharSetDestroy (charset); | ||
| 597 | return -1; | ||
| 598 | } | ||
| 599 | fc_charset_table[i].fc_charset = charset; | ||
| 600 | } | ||
| 485 | } | 601 | } |
| 486 | return i; | 602 | return i; |
| 487 | } | 603 | } |
| @@ -602,10 +718,6 @@ ftfont_spec_pattern (spec, otlayout, otspec) | |||
| 602 | Lisp_Object registry; | 718 | Lisp_Object registry; |
| 603 | int fc_charset_idx; | 719 | int fc_charset_idx; |
| 604 | 720 | ||
| 605 | if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX)) | ||
| 606 | && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0) | ||
| 607 | /* Fontconfig doesn't support adstyle property. */ | ||
| 608 | return NULL; | ||
| 609 | if ((n = FONT_SLANT_NUMERIC (spec)) >= 0 | 721 | if ((n = FONT_SLANT_NUMERIC (spec)) >= 0 |
| 610 | && n < 100) | 722 | && n < 100) |
| 611 | /* Fontconfig doesn't support reverse-italic/obligue. */ | 723 | /* Fontconfig doesn't support reverse-italic/obligue. */ |
| @@ -752,7 +864,7 @@ static Lisp_Object | |||
| 752 | ftfont_list (frame, spec) | 864 | ftfont_list (frame, spec) |
| 753 | Lisp_Object frame, spec; | 865 | Lisp_Object frame, spec; |
| 754 | { | 866 | { |
| 755 | Lisp_Object val = Qnil, family; | 867 | Lisp_Object val = Qnil, family, adstyle; |
| 756 | int i; | 868 | int i; |
| 757 | FcPattern *pattern; | 869 | FcPattern *pattern; |
| 758 | FcFontSet *fontset = NULL; | 870 | FcFontSet *fontset = NULL; |
| @@ -800,10 +912,12 @@ ftfont_list (frame, spec) | |||
| 800 | goto err; | 912 | goto err; |
| 801 | } | 913 | } |
| 802 | } | 914 | } |
| 803 | 915 | adstyle = AREF (spec, FONT_ADSTYLE_INDEX); | |
| 916 | if (! NILP (adstyle) && SBYTES (SYMBOL_NAME (adstyle)) == 0) | ||
| 917 | adstyle = Qnil; | ||
| 804 | objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT, | 918 | objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT, |
| 805 | FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE, | 919 | FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE, |
| 806 | FC_FILE, FC_INDEX, | 920 | FC_STYLE, FC_FILE, FC_INDEX, |
| 807 | #ifdef FC_CAPABILITY | 921 | #ifdef FC_CAPABILITY |
| 808 | FC_CAPABILITY, | 922 | FC_CAPABILITY, |
| 809 | #endif /* FC_CAPABILITY */ | 923 | #endif /* FC_CAPABILITY */ |
| @@ -908,6 +1022,15 @@ ftfont_list (frame, spec) | |||
| 908 | if (j == ASIZE (chars)) | 1022 | if (j == ASIZE (chars)) |
| 909 | continue; | 1023 | continue; |
| 910 | } | 1024 | } |
| 1025 | if (! NILP (adstyle)) | ||
| 1026 | { | ||
| 1027 | Lisp_Object this_adstyle = get_adstyle_property (fontset->fonts[i]); | ||
| 1028 | |||
| 1029 | if (NILP (this_adstyle) | ||
| 1030 | || xstrcasecmp (SDATA (SYMBOL_NAME (adstyle)), | ||
| 1031 | SDATA (SYMBOL_NAME (this_adstyle))) != 0) | ||
| 1032 | continue; | ||
| 1033 | } | ||
| 911 | entity = ftfont_pattern_entity (fontset->fonts[i], | 1034 | entity = ftfont_pattern_entity (fontset->fonts[i], |
| 912 | AREF (spec, FONT_EXTRA_INDEX)); | 1035 | AREF (spec, FONT_EXTRA_INDEX)); |
| 913 | if (! NILP (entity)) | 1036 | if (! NILP (entity)) |
| @@ -1046,7 +1169,7 @@ ftfont_open (f, entity, pixel_size) | |||
| 1046 | if (! CONSP (val)) | 1169 | if (! CONSP (val)) |
| 1047 | return Qnil; | 1170 | return Qnil; |
| 1048 | val = XCDR (val); | 1171 | val = XCDR (val); |
| 1049 | cache = ftfont_lookup_cache (val, 1); | 1172 | cache = ftfont_lookup_cache (entity, 1); |
| 1050 | if (NILP (cache)) | 1173 | if (NILP (cache)) |
| 1051 | return Qnil; | 1174 | return Qnil; |
| 1052 | filename = XCAR (val); | 1175 | filename = XCAR (val); |
| @@ -2091,6 +2214,8 @@ syms_of_ftfont () | |||
| 2091 | DEFSYM (Qmono, "mono"); | 2214 | DEFSYM (Qmono, "mono"); |
| 2092 | DEFSYM (Qsans, "sans"); | 2215 | DEFSYM (Qsans, "sans"); |
| 2093 | DEFSYM (Qsans__serif, "sans serif"); | 2216 | DEFSYM (Qsans__serif, "sans serif"); |
| 2217 | DEFSYM (Qja, "ja"); | ||
| 2218 | DEFSYM (Qko, "ko"); | ||
| 2094 | 2219 | ||
| 2095 | staticpro (&freetype_font_cache); | 2220 | staticpro (&freetype_font_cache); |
| 2096 | freetype_font_cache = Fcons (Qt, Qnil); | 2221 | freetype_font_cache = Fcons (Qt, Qnil); |