From 904426816df300fad816238f0f27ef595a6a539b Mon Sep 17 00:00:00 2001 From: Patrick Lam Date: Sat, 22 Oct 2005 14:21:14 +0000 Subject: [PATCH] Support localized font family and style names. This has been reported to break old apps like xfd, but modern (gtk+/qt/mozilla) apps work fine. reviewed by: plam --- ChangeLog | 7 +++ src/fcdefault.c | 110 +++++++++++++++++++++++++++--------------------- src/fcint.h | 4 ++ src/fclist.c | 60 ++++++++++++++++++++++++-- 4 files changed, 130 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 599e298..0d45f20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2005-10-22 Zhe Su + reviewed by: plam + + Support localized font family and style names. + This has been reported to break old apps like xfd, but modern + (gtk+/qt/mozilla) apps work fine. + 2005-10-21 Patrick Lam * src/fccache.c (FcGlobalCacheLoad): diff --git a/src/fcdefault.c b/src/fcdefault.c index 5e648dc..956862c 100644 --- a/src/fcdefault.c +++ b/src/fcdefault.c @@ -37,6 +37,67 @@ static struct { #define NUM_FC_BOOL_DEFAULTS (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0]) +FcChar8 * +FcGetDefaultLang (void) +{ + static char lang_local [128] = {0}; + char *ctype; + char *territory; + char *after; + int lang_len, territory_len; + + if (lang_local [0]) + return (FcChar8 *) lang_local; + + ctype = setlocale (LC_CTYPE, NULL); + + /* + * Check if setlocale (LC_ALL, "") has been called + */ + if (!ctype || !strcmp (ctype, "C")) + { + ctype = getenv ("LC_ALL"); + if (!ctype) + { + ctype = getenv ("LC_CTYPE"); + if (!ctype) + ctype = getenv ("LANG"); + } + } + + /* ignore missing or empty ctype */ + if (ctype && *ctype != '\0') + { + territory = strchr (ctype, '_'); + if (territory) + { + lang_len = territory - ctype; + territory = territory + 1; + after = strchr (territory, '.'); + if (!after) + { + after = strchr (territory, '@'); + if (!after) + after = territory + strlen (territory); + } + territory_len = after - territory; + if (lang_len + 1 + territory_len + 1 <= (int) sizeof (lang_local)) + { + strncpy (lang_local, ctype, lang_len); + lang_local[lang_len] = '-'; + strncpy (lang_local + lang_len + 1, territory, territory_len); + lang_local[lang_len + 1 + territory_len] = '\0'; + } + } + } + + /* set default lang to en */ + if (!lang_local [0]) + strcpy (lang_local, "en"); + + return (FcChar8 *) lang_local; +} + void FcDefaultSubstitute (FcPattern *pattern) { @@ -91,54 +152,7 @@ FcDefaultSubstitute (FcPattern *pattern) if (FcPatternGet (pattern, FC_LANG, 0, &v) == FcResultNoMatch) { - char *lang; - char *territory; - char *after; - int lang_len, territory_len; - char lang_local[128]; - char *ctype = setlocale (LC_CTYPE, NULL); - - /* - * Check if setlocale (LC_ALL, "") has been called - */ - if (!ctype || !strcmp (ctype, "C")) - { - ctype = getenv ("LC_ALL"); - if (!ctype) - { - ctype = getenv ("LC_CTYPE"); - if (!ctype) - ctype = getenv ("LANG"); - } - } - if (ctype) - { - lang = ctype; - territory = strchr (ctype, '_'); - if (territory) - { - lang_len = territory - lang; - territory = territory + 1; - after = strchr (territory, '.'); - if (!after) - { - after = strchr (territory, '@'); - if (!after) - after = territory + strlen (territory); - } - territory_len = after - territory; - if (lang_len + 1 + territory_len + 1 <= (int) sizeof (lang_local)) - { - strncpy (lang_local, lang, lang_len); - lang_local[lang_len] = '-'; - strncpy (lang_local + lang_len + 1, territory, territory_len); - lang_local[lang_len + 1 + territory_len] = '\0'; - FcPatternAddString (pattern, FC_LANG, (FcChar8 *) lang_local); - } - } - else - FcPatternAddString (pattern, FC_LANG, (FcChar8 *) lang); - } + FcPatternAddString (pattern, FC_LANG, FcGetDefaultLang ()); } if (FcPatternGet (pattern, FC_FONTVERSION, 0, &v) == FcResultNoMatch) { diff --git a/src/fcint.h b/src/fcint.h index 1dec72a..4fb8905 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -574,6 +574,10 @@ FcSubstPrint (const FcSubst *subst); int FcDebug (void); +/* fcdefault.c */ +FcChar8 * +FcGetDefaultLang (void); + /* fcdir.c */ FcBool diff --git a/src/fclist.c b/src/fclist.c index 357932b..35d68ae 100644 --- a/src/fclist.c +++ b/src/fclist.c @@ -337,6 +337,34 @@ FcListHashTableCleanup (FcListHashTable *table) table->entries = 0; } +static int +FcGetDefaultObjectLangIndex (FcPattern *font, const char *object) +{ + FcChar8 *lang = FcGetDefaultLang (); + FcPatternElt *e = FcPatternFindElt (font, object); + FcValueListPtr v; + FcValue value; + int idx = -1; + int i; + + if (e) + { + for (v = e->values, i = 0; FcValueListPtrU(v); v = FcValueListPtrU(v)->next, ++i) + { + value = FcValueCanonicalize (&FcValueListPtrU (v)->value); + + if (value.type == FcTypeString) + { + FcLangResult res = FcLangCompare (value.u.s, lang); + if (res == FcLangEqual || (res == FcLangDifferentCountry && idx < 0)) + idx = i; + } + } + } + + return (idx > 0) ? idx : 0; +} + static FcBool FcListAppend (FcListHashTable *table, FcPattern *font, @@ -347,6 +375,11 @@ FcListAppend (FcListHashTable *table, FcValueListPtr v; FcChar32 hash; FcListBucket **prev, *bucket; + int familyidx = -1; + int fullnameidx = -1; + int styleidx = -1; + int defidx = 0; + int idx; hash = FcListPatternHash (font, os); for (prev = &table->buckets[hash % FC_LIST_HASH_SIZE]; @@ -368,15 +401,36 @@ FcListAppend (FcListHashTable *table, for (o = 0; o < os->nobject; o++) { + if (!strcmp (os->objects[o], FC_FAMILY) || !strcmp (os->objects[o], FC_FAMILYLANG)) + { + if (familyidx < 0) + familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG); + defidx = familyidx; + } + else if (!strcmp (os->objects[o], FC_FULLNAME) || !strcmp (os->objects[o], FC_FULLNAMELANG)) + { + if (fullnameidx < 0) + fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG); + defidx = fullnameidx; + } + else if (!strcmp (os->objects[o], FC_STYLE) || !strcmp (os->objects[o], FC_STYLELANG)) + { + if (styleidx < 0) + styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG); + defidx = styleidx; + } + else + defidx = 0; + e = FcPatternFindElt (font, os->objects[o]); if (e) { - for (v = e->values; FcValueListPtrU(v); - v = FcValueListPtrU(v)->next) + for (v = e->values, idx = 0; FcValueListPtrU(v); + v = FcValueListPtrU(v)->next, ++idx) { if (!FcPatternAdd (bucket->pattern, os->objects[o], - FcValueCanonicalize(&FcValueListPtrU(v)->value), FcTrue)) + FcValueCanonicalize(&FcValueListPtrU(v)->value), defidx != idx)) goto bail2; } } -- 2.39.5