diff options
Diffstat (limited to 'fontconfig')
-rw-r--r-- | fontconfig/doc/fclangset.fncs | 9 | ||||
-rw-r--r-- | fontconfig/fc-lang/fc-lang.c | 6 | ||||
-rw-r--r-- | fontconfig/fontconfig/fontconfig.h | 3 | ||||
-rw-r--r-- | fontconfig/src/fccfg.c | 17 | ||||
-rw-r--r-- | fontconfig/src/fcdefault.c | 106 | ||||
-rw-r--r-- | fontconfig/src/fcfreetype.c | 15 | ||||
-rw-r--r-- | fontconfig/src/fcint.h | 6 | ||||
-rw-r--r-- | fontconfig/src/fclang.c | 159 | ||||
-rw-r--r-- | fontconfig/src/fcstr.c | 44 |
9 files changed, 291 insertions, 74 deletions
diff --git a/fontconfig/doc/fclangset.fncs b/fontconfig/doc/fclangset.fncs index 0a44b38c2..e2a40b854 100644 --- a/fontconfig/doc/fclangset.fncs +++ b/fontconfig/doc/fclangset.fncs @@ -154,6 +154,15 @@ has no matching language, this function returns FcLangDifferentLang. @@ @RET@ FcStrSet * +@FUNC@ FcGetDefaultLangs +@TYPE1@ void +@PURPOSE@ Get the default languages list +@DESC@ +Returns a string set of the default languages according to the environment variables on the system. +This function looks for them in order of FC_LANG, LC_ALL, LC_CTYPE and LANG then. +If there are no valid values in those environment variables, "en" will be set as fallback. + +@RET@ FcStrSet * @FUNC@ FcLangSetGetLangs @TYPE1@ const FcLangSet * @ARG1@ ls @PURPOSE@ get the list of languages in the langset diff --git a/fontconfig/fc-lang/fc-lang.c b/fontconfig/fc-lang/fc-lang.c index 51717f952..93200c4e0 100644 --- a/fontconfig/fc-lang/fc-lang.c +++ b/fontconfig/fc-lang/fc-lang.c @@ -57,6 +57,12 @@ FcCacheObjectDereference (void *object) { } +FcPrivate FcChar8 * +FcLangNormalize (const FcChar8 *lang) +{ + return NULL; +} + int FcDebugVal; FcChar8 * diff --git a/fontconfig/fontconfig/fontconfig.h b/fontconfig/fontconfig/fontconfig.h index 2671da78d..21a476a02 100644 --- a/fontconfig/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig/fontconfig.h @@ -497,6 +497,9 @@ FcPublic void FcFontSetPrint (const FcFontSet *s); /* fcdefault.c */ +FcPublic FcStrSet * +FcGetDefaultLangs (void); + FcPublic void FcDefaultSubstitute (FcPattern *pattern); diff --git a/fontconfig/src/fccfg.c b/fontconfig/src/fccfg.c index b45d74a23..3f1fa73df 100644 --- a/fontconfig/src/fccfg.c +++ b/fontconfig/src/fccfg.c @@ -1407,6 +1407,7 @@ FcConfigSubstituteWithPat (FcConfig *config, FcEdit *e; FcValueList *l; FcPattern *m; + FcStrSet *strs; if (!config) { @@ -1418,6 +1419,22 @@ FcConfigSubstituteWithPat (FcConfig *config, switch (kind) { case FcMatchPattern: s = config->substPattern; + strs = FcGetDefaultLangs (); + if (strs) + { + FcStrList *l = FcStrListCreate (strs); + FcChar8 *lang; + FcValue v; + + FcStrSetDestroy (strs); + while (l && (lang = FcStrListNext (l))) + { + v.type = FcTypeString; + v.u.s = lang; + FcPatternObjectAddWithBinding (p, FC_LANG_OBJECT, v, FcValueBindingWeak, FcTrue); + } + FcStrListDone (l); + } break; case FcMatchFont: s = config->substFont; diff --git a/fontconfig/src/fcdefault.c b/fontconfig/src/fcdefault.c index 170a8a4d8..c6b5669ed 100644 --- a/fontconfig/src/fcdefault.c +++ b/fontconfig/src/fcdefault.c @@ -23,7 +23,7 @@ */ #include "fcint.h" -#include <locale.h> +#include <string.h> static const struct { FcObject field; @@ -39,81 +39,45 @@ static const struct { #define NUM_FC_BOOL_DEFAULTS (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0]) -FcChar8 * -FcGetDefaultLang (void) +FcStrSet * +FcGetDefaultLangs (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")) + FcStrSet *result = FcStrSetCreate (); + char *langs; + + langs = getenv ("FC_LANG"); + if (!langs || !langs[0]) + langs = getenv ("LC_ALL"); + if (!langs || !langs[0]) + langs = getenv ("LC_CTYPE"); + if (!langs || !langs[0]) + langs = getenv ("LANG"); + if (langs && langs[0]) { - ctype = getenv ("LC_ALL"); - if (!ctype) - { - ctype = getenv ("LC_CTYPE"); - if (!ctype) - ctype = getenv ("LANG"); - } + if (!FcStrSetAddLangs (result, langs)) + FcStrSetAdd (result, (const FcChar8 *) "en"); } + else + FcStrSetAdd (result, (const FcChar8 *) "en"); - /* ignore missing or empty ctype */ - if (ctype && *ctype != '\0') + return result; +} + +FcChar8 * +FcGetDefaultLang (void) +{ + static FcChar8 lang_local[128] = {0}; + FcStrSet *langs; + + if (!lang_local[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'; - } - } - else - { - after = strchr (ctype, '.'); - if (!after) - { - after = strchr (ctype, '@'); - if (!after) - after = ctype + strlen (ctype); - } - lang_len = after - ctype; - if (lang_len + 1 <= (int) sizeof (lang_local)) - { - strncpy (lang_local, ctype, lang_len); - lang_local[lang_len] = '\0'; - } - } + langs = FcGetDefaultLangs (); + strncpy ((char *)lang_local, (const char *)langs->strs[0], 127); + lang_local[127] = 0; + FcStrSetDestroy (langs); } - /* set default lang to en */ - if (!lang_local [0]) - strcpy (lang_local, "en"); - - return (FcChar8 *) lang_local; + return lang_local; } void @@ -162,10 +126,6 @@ FcDefaultSubstitute (FcPattern *pattern) FcPatternObjectAddDouble (pattern, FC_PIXEL_SIZE_OBJECT, size); } - if (FcPatternObjectGet (pattern, FC_LANG_OBJECT, 0, &v) == FcResultNoMatch) - { - FcPatternObjectAddString (pattern, FC_LANG_OBJECT, FcGetDefaultLang ()); - } if (FcPatternObjectGet (pattern, FC_FONTVERSION_OBJECT, 0, &v) == FcResultNoMatch) { FcPatternObjectAddInteger (pattern, FC_FONTVERSION_OBJECT, 0x7fffffff); diff --git a/fontconfig/src/fcfreetype.c b/fontconfig/src/fcfreetype.c index ce7dc836c..fb2b0f2f9 100644 --- a/fontconfig/src/fcfreetype.c +++ b/fontconfig/src/fcfreetype.c @@ -1179,10 +1179,11 @@ FcFreeTypeQueryFace (const FT_Face face, for (snamei = 0; snamei < snamec; snamei++) { - FcChar8 *utf8; + FcChar8 *utf8, *pp; const FcChar8 *lang; const char *elt = 0, *eltlang = 0; int *np = 0, *nlangp = 0; + size_t len; if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0) continue; @@ -1253,6 +1254,18 @@ FcFreeTypeQueryFace (const FT_Face face, #endif case TT_NAME_ID_PREFERRED_SUBFAMILY: case TT_NAME_ID_FONT_SUBFAMILY: + if (utf8) + { + pp = utf8; + while (*pp == ' ') + pp++; + len = strlen ((const char *) pp); + memmove (utf8, pp, len + 1); + pp = utf8 + len - 1; + while (*pp == ' ') + pp--; + *(pp + 1) = 0; + } if (FcDebug () & FC_DBG_SCANV) printf ("found style (n %2d p %d e %d l 0x%04x) %s\n", sname.name_id, sname.platform_id, diff --git a/fontconfig/src/fcint.h b/fontconfig/src/fcint.h index 3d06fc6eb..7cc4ed2d8 100644 --- a/fontconfig/src/fcint.h +++ b/fontconfig/src/fcint.h @@ -816,6 +816,9 @@ FcPrivate FcLangSet * FcFreeTypeLangSet (const FcCharSet *charset, const FcChar8 *exclusiveLang); +FcPrivate FcChar8 * +FcLangNormalize (const FcChar8 *lang); + FcPrivate FcLangResult FcLangCompare (const FcChar8 *s1, const FcChar8 *s2); @@ -1039,6 +1042,9 @@ FcPrivate FcBool FcIsFsMtimeBroken (const FcChar8 *dir); /* fcstr.c */ +FcPrivate FcBool +FcStrSetAddLangs (FcStrSet *strs, const char *languages); + FcPrivate void FcStrSetSort (FcStrSet * set); diff --git a/fontconfig/src/fclang.c b/fontconfig/src/fclang.c index be42b58c4..b7e70fcfb 100644 --- a/fontconfig/src/fclang.c +++ b/fontconfig/src/fclang.c @@ -22,6 +22,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include <string.h> #include "fcint.h" #include "fcftint.h" @@ -43,6 +44,9 @@ struct _FcLangSet { FcChar32 map[NUM_LANG_SET_MAP]; }; +static int FcLangSetIndex (const FcChar8 *lang); + + static void FcLangSetBitSet (FcLangSet *ls, unsigned int id) @@ -173,6 +177,161 @@ FcFreeTypeLangSet (const FcCharSet *charset, return ls; } +FcChar8 * +FcLangNormalize (const FcChar8 *lang) +{ + FcChar8 *result = NULL, *s, *orig; + char *territory, *encoding, *modifier; + size_t llen, tlen = 0, mlen = 0; + + if (!lang || !*lang) + return NULL; + + if (FcStrCmpIgnoreCase (lang, (const FcChar8 *)"C") == 0 || + FcStrCmpIgnoreCase (lang, (const FcChar8 *)"POSIX") == 0) + { + result = FcStrCopy ((const FcChar8 *)"en"); + goto bail; + } + + s = FcStrCopy (lang); + if (!s) + goto bail; + + /* from the comments in glibc: + * + * LOCALE can consist of up to four recognized parts for the XPG syntax: + * + * language[_territory[.codeset]][@modifier] + * + * Beside the first all of them are allowed to be missing. If the + * full specified locale is not found, the less specific one are + * looked for. The various part will be stripped off according to + * the following order: + * (1) codeset + * (2) normalized codeset + * (3) territory + * (4) modifier + * + * So since we don't take care of the codeset part here, what patterns + * we need to deal with is: + * + * 1. language_territory@modifier + * 2. language@modifier + * 3. language + * + * then. and maybe no need to try language_territory here. + */ + modifier = strchr ((const char *) s, '@'); + if (modifier) + { + *modifier = 0; + modifier++; + mlen = strlen (modifier); + } + encoding = strchr ((const char *) s, '.'); + if (encoding) + { + *encoding = 0; + encoding++; + if (modifier) + { + memmove (encoding, modifier, mlen + 1); + modifier = encoding; + } + } + territory = strchr ((const char *) s, '_'); + if (!territory) + territory = strchr ((const char *) s, '-'); + if (territory) + { + *territory = 0; + territory++; + tlen = strlen (territory); + } + llen = strlen ((const char *) s); + if (llen < 2 || llen > 3) + { + fprintf (stderr, "Fontconfig warning: ignoring %s: not a valid language tag\n", + lang); + goto bail0; + } + if (territory && (tlen < 2 || tlen > 3)) + { + fprintf (stderr, "Fontconfig warning: ignoring %s: not a valid region tag\n", + lang); + goto bail0; + } + if (territory) + territory[-1] = '-'; + if (modifier) + modifier[-1] = '@'; + orig = FcStrDowncase (s); + if (!orig) + goto bail0; + if (territory) + { + if (FcDebug () & FC_DBG_LANGSET) + printf("Checking the existence of %s.orth\n", s); + if (FcLangSetIndex (s) < 0) + { + memmove (territory - 1, territory + tlen, (mlen > 0 ? mlen + 1 : 0) + 1); + if (modifier) + modifier = territory; + } + else + { + result = s; + s = NULL; + goto bail1; + } + } + if (modifier) + { + if (FcDebug () & FC_DBG_LANGSET) + printf("Checking the existence of %s.orth\n", s); + if (FcLangSetIndex (s) < 0) + modifier[-1] = 0; + else + { + result = s; + s = NULL; + goto bail1; + } + } + if (FcDebug () & FC_DBG_LANGSET) + printf("Checking the existence of %s.orth\n", s); + if (FcLangSetIndex (s) < 0) + { + /* there seems no languages matched in orth. + * add the language as is for fallback. + */ + result = orig; + orig = NULL; + } + else + { + result = s; + s = NULL; + } + bail1: + if (orig) + free (orig); + bail0: + if (s) + free (s); + bail: + if (FcDebug () & FC_DBG_LANGSET) + { + if (result) + printf ("normalized: %s -> %s\n", lang, result); + else + printf ("Unable to normalize %s\n", lang); + } + + return result; +} + #define FcLangEnd(c) ((c) == '-' || (c) == '\0') FcLangResult diff --git a/fontconfig/src/fcstr.c b/fontconfig/src/fcstr.c index e372af080..c446bcd8e 100644 --- a/fontconfig/src/fcstr.c +++ b/fontconfig/src/fcstr.c @@ -1177,6 +1177,50 @@ FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s) } FcBool +FcStrSetAddLangs (FcStrSet *strs, const char *languages) +{ + const char *p = languages, *next; + FcChar8 lang[128] = {0}, *normalized_lang; + size_t len; + FcBool ret = FcFalse; + + if (!languages) + return FcFalse; + + while ((next = strchr (p, ':'))) + { + len = next - p; + len = FC_MIN (len, 128); + strncpy ((char *) lang, p, len); + lang[len] = 0; + /* ignore an empty item */ + if (*lang) + { + normalized_lang = FcLangNormalize ((const FcChar8 *) lang); + if (normalized_lang) + { + FcStrSetAdd (strs, normalized_lang); + free (normalized_lang); + ret = FcTrue; + } + } + p = next + 1; + } + if (*p) + { + normalized_lang = FcLangNormalize ((const FcChar8 *) p); + if (normalized_lang) + { + FcStrSetAdd (strs, normalized_lang); + free (normalized_lang); + ret = FcTrue; + } + } + + return ret; +} + +FcBool FcStrSetDel (FcStrSet *set, const FcChar8 *s) { int i; |