# HG changeset patch # User Kenichi Handa # Date 1239625993 0 # Node ID 44a517fa4d12ef53f8361f334b065b46a457e890 # Parent 67e0d4d902b4d5feb10b8298cffa3dd55a116feb (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. diff -r 67e0d4d902b4 -r 44a517fa4d12 src/ftfont.c --- a/src/ftfont.c Mon Apr 13 12:33:02 2009 +0000 +++ b/src/ftfont.c Mon Apr 13 12:33:13 2009 +0000 @@ -43,6 +43,9 @@ /* Fontconfig's generic families and their aliases. */ static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif; +/* Special ADSTYLE properties to avoid fonts used for Latin characters. */ +static Lisp_Object Qja, Qko; + /* Flag to tell if FcInit is already called or not. */ static int fc_initialized; @@ -92,7 +95,7 @@ /* set on demand */ FcCharSet *fc_charset; } fc_charset_table[] = - { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } }, + { { "iso8859-1", { } }, /* ftfont_get_latin1_charset handles it. */ { "iso8859-2", { 0x00A0, 0x010E }}, { "iso8859-3", { 0x00A0, 0x0108 }}, { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }}, @@ -132,8 +135,71 @@ { NULL } }; +/* Return a FcCharSet for iso8859-1 from fc_charset_table[0]. If the + charset is not yet ready, create it. */ +static FcCharSet * +ftfont_get_latin1_charset () +{ + FcCharSet *cs; + FcChar32 c; + + if (fc_charset_table[0].fc_charset) + return fc_charset_table[0].fc_charset; + cs = FcCharSetCreate (); + if (! cs) + return NULL; + for (c = 33; c <= 0xFF; c++) + { + FcCharSetAddChar (cs, c); + if (c == 0x7E) + c = 0xA0; + } + fc_charset_table[0].fc_charset = cs; + return cs; +} + extern Lisp_Object Qc, Qm, Qp, Qd; +/* Dirty hack for handing ADSTYLE property. + + Fontconfig (actually the underlying FreeType) gives such ADSTYLE + font property of PCF/BDF fonts in FC_STYLE. And, "Bold", + "Oblique", "Italic", or any non-normal SWIDTH property names + (e.g. SemiCondensed) are appended. In addition, if there's no + ADSTYLE property nor non-normal WEIGHT/SLANT/SWIDTH properties, + "Regular" is used for FC_STYLE (see the function + pcf_interpret_style in src/pcf/pcfread.c of FreeType). + + Unfortunately this behavior is not documented, so the following + code may fail if FreeType changes the behavior in the future. */ + +static Lisp_Object +get_adstyle_property (FcPattern *p) +{ + char *str, *end; + Lisp_Object adstyle; + + if (FcPatternGetString (p, FC_STYLE, 0, (FcChar8 **) &str) != FcResultMatch) + return Qnil; + for (end = str; *end && *end != ' '; end++); + if (*end) + { + char *p = alloca (end - str + 1); + memcpy (p, str, end - str); + p[end - str] = '\0'; + str = p; + } + if (xstrcasecmp (str, "Regular") == 0 + || xstrcasecmp (str, "Bold") == 0 + || xstrcasecmp (str, "Oblique") == 0 + || xstrcasecmp (str, "Italic") == 0) + return Qnil; + adstyle = font_intern_prop (str, end - str, 0); + if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0) + return Qnil; + return adstyle; +} + static Lisp_Object ftfont_pattern_entity (p, extra) FcPattern *p; @@ -176,7 +242,14 @@ FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, make_number (numeric)); } if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch) - ASET (entity, FONT_SIZE_INDEX, make_number (dbl)); + { + Lisp_Object adstyle; + + ASET (entity, FONT_SIZE_INDEX, make_number (dbl)); + /* As this font has PIXEL_SIZE property, parhaps this is a BDF + or PCF font. */ + ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p)); + } else ASET (entity, FONT_SIZE_INDEX, make_number (0)); if (FcPatternGetInteger (p, FC_SPACING, 0, &numeric) == FcResultMatch) @@ -265,9 +338,19 @@ Lisp_Object key; int for_face; { - Lisp_Object cache, val; + Lisp_Object cache, val, entity; struct ftfont_cache_data *cache_data; + if (FONT_ENTITY_P (key)) + { + entity = key; + val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); + xassert (CONSP (val)); + key = XCDR (val); + } + else + entity = Qnil; + cache = assoc_no_quit (key, ft_face_cache); if (NILP (cache)) { @@ -301,25 +384,56 @@ } else { - FcPattern *pat; - FcFontSet *fontset; - FcObjectSet *objset; - FcCharSet *charset; + FcPattern *pat = NULL; + FcFontSet *fontset = NULL; + FcObjectSet *objset = NULL; + FcCharSet *charset = NULL; pat = FcPatternBuild (0, FC_FILE, FcTypeString, (FcChar8 *) filename, FC_INDEX, FcTypeInteger, index, NULL); - objset = FcObjectSetBuild (FC_CHARSET, NULL); + if (! pat) + goto finish; + objset = FcObjectSetBuild (FC_CHARSET, FC_STYLE, NULL); + if (! objset) + goto finish; fontset = FcFontList (NULL, pat, objset); - if (fontset && fontset->nfont > 0 - && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0, + if (! fontset) + goto finish; + if (fontset && fontset->nfont > 0) + { + if (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0, &charset) - == FcResultMatch)) - cache_data->fc_charset = FcCharSetCopy (charset); + == FcResultMatch) + { + /* Dirty hack. Fonts of "ja" and "ko" adstyle are + not suitable for Latin characters. */ + if (! NILP (entity) + && (EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qja) + || EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qko))) + { + FcCharSet *latin1 = ftfont_get_latin1_charset (); + + if (! latin1) + goto finish; + cache_data->fc_charset = FcCharSetSubtract (charset, + latin1); + } + else + cache_data->fc_charset = FcCharSetCopy (charset); + } + else + cache_data->fc_charset = FcCharSetCreate (); + } else cache_data->fc_charset = FcCharSetCreate (); - FcFontSetDestroy (fontset); - FcObjectSetDestroy (objset); - FcPatternDestroy (pat); + + finish: + if (fontset) + FcFontSetDestroy (fontset); + if (objset) + FcObjectSetDestroy (objset); + if (pat) + FcPatternDestroy (pat); } } return cache; @@ -332,10 +446,7 @@ Lisp_Object val, cache; struct ftfont_cache_data *cache_data; - val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); - xassert (CONSP (val)); - val = XCDR (val); - cache = ftfont_lookup_cache (val, 0); + cache = ftfont_lookup_cache (entity, 0); val = XCDR (cache); cache_data = XSAVE_VALUE (val)->pointer; return cache_data->fc_charset; @@ -470,18 +581,23 @@ return -1; if (! fc_charset_table[i].fc_charset) { - FcCharSet *charset = FcCharSetCreate (); - int *uniquifier = fc_charset_table[i].uniquifier; + if (i == 0) + ftfont_get_latin1_charset (); + else + { + FcCharSet *charset = FcCharSetCreate (); + int *uniquifier = fc_charset_table[i].uniquifier; - if (! charset) - return -1; - for (j = 0; uniquifier[j]; j++) - if (! FcCharSetAddChar (charset, uniquifier[j])) - { - FcCharSetDestroy (charset); + if (! charset) return -1; - } - fc_charset_table[i].fc_charset = charset; + for (j = 0; uniquifier[j]; j++) + if (! FcCharSetAddChar (charset, uniquifier[j])) + { + FcCharSetDestroy (charset); + return -1; + } + fc_charset_table[i].fc_charset = charset; + } } return i; } @@ -602,10 +718,6 @@ Lisp_Object registry; int fc_charset_idx; - if (! NILP (AREF (spec, FONT_ADSTYLE_INDEX)) - && SBYTES (SYMBOL_NAME (AREF (spec, FONT_ADSTYLE_INDEX))) > 0) - /* Fontconfig doesn't support adstyle property. */ - return NULL; if ((n = FONT_SLANT_NUMERIC (spec)) >= 0 && n < 100) /* Fontconfig doesn't support reverse-italic/obligue. */ @@ -752,7 +864,7 @@ ftfont_list (frame, spec) Lisp_Object frame, spec; { - Lisp_Object val = Qnil, family; + Lisp_Object val = Qnil, family, adstyle; int i; FcPattern *pattern; FcFontSet *fontset = NULL; @@ -800,10 +912,12 @@ goto err; } } - + adstyle = AREF (spec, FONT_ADSTYLE_INDEX); + if (! NILP (adstyle) && SBYTES (SYMBOL_NAME (adstyle)) == 0) + adstyle = Qnil; objset = FcObjectSetBuild (FC_FOUNDRY, FC_FAMILY, FC_WEIGHT, FC_SLANT, FC_WIDTH, FC_PIXEL_SIZE, FC_SPACING, FC_SCALABLE, - FC_FILE, FC_INDEX, + FC_STYLE, FC_FILE, FC_INDEX, #ifdef FC_CAPABILITY FC_CAPABILITY, #endif /* FC_CAPABILITY */ @@ -908,6 +1022,15 @@ if (j == ASIZE (chars)) continue; } + if (! NILP (adstyle)) + { + Lisp_Object this_adstyle = get_adstyle_property (fontset->fonts[i]); + + if (NILP (this_adstyle) + || xstrcasecmp (SDATA (SYMBOL_NAME (adstyle)), + SDATA (SYMBOL_NAME (this_adstyle))) != 0) + continue; + } entity = ftfont_pattern_entity (fontset->fonts[i], AREF (spec, FONT_EXTRA_INDEX)); if (! NILP (entity)) @@ -1046,7 +1169,7 @@ if (! CONSP (val)) return Qnil; val = XCDR (val); - cache = ftfont_lookup_cache (val, 1); + cache = ftfont_lookup_cache (entity, 1); if (NILP (cache)) return Qnil; filename = XCAR (val); @@ -2091,6 +2214,8 @@ DEFSYM (Qmono, "mono"); DEFSYM (Qsans, "sans"); DEFSYM (Qsans__serif, "sans serif"); + DEFSYM (Qja, "ja"); + DEFSYM (Qko, "ko"); staticpro (&freetype_font_cache); freetype_font_cache = Fcons (Qt, Qnil);