[Fontconfig] fontconfig: Branch 'master' - 4 commits
Akira TAGOH
akira at tagoh.org
Fri Jun 8 00:11:54 PDT 2012
Well, please test if you didn't play with it yet.
Thanks,
On Fri, Jun 8, 2012 at 4:05 PM, Akira TAGOH
<tagoh at kemper.freedesktop.org> wrote:
> doc/fclangset.fncs | 9 ++
> fc-lang/fc-lang.c | 6 +
> fontconfig/fontconfig.h | 3
> src/fccfg.c | 18 +++++
> src/fcdefault.c | 106 +++++++++-----------------------
> src/fcint.h | 6 +
> src/fclang.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++
> src/fcstr.c | 44 +++++++++++++
> 8 files changed, 278 insertions(+), 73 deletions(-)
>
> New commits:
> commit 07e52eeb097a4e3c147e00ed7a6eb7652a611751
> Author: Akira TAGOH <akira at tagoh.org>
> Date: Fri Jun 8 15:54:48 2012 +0900
>
> fcdefault: no need to set FC_LANG in FcDefaultSubstitute() anymore
>
> diff --git a/src/fcdefault.c b/src/fcdefault.c
> index ce90a88..c6b5669 100644
> --- a/src/fcdefault.c
> +++ b/src/fcdefault.c
> @@ -126,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);
> commit 550fd49d4fb8efab33d1fa1687b1b9bd352202fe
> Author: Akira TAGOH <akira at tagoh.org>
> Date: Tue May 22 14:17:10 2012 +0900
>
> Add the default language to the pattern prior to do build the substitution
>
> the default language is referred from the FC_LANG environment variable
> or the current locale
>
> diff --git a/src/fccfg.c b/src/fccfg.c
> index b45d74a..c3d95e8 100644
> --- a/src/fccfg.c
> +++ b/src/fccfg.c
> @@ -1407,6 +1407,7 @@ FcConfigSubstituteWithPat (FcConfig *config,
> FcEdit *e;
> FcValueList *l;
> FcPattern *m;
> + FcStrSet *strs;
>
> if (!config)
> {
> @@ -1434,6 +1435,23 @@ FcConfigSubstituteWithPat (FcConfig *config,
> return FcFalse;
> FcMemAlloc (FC_MEM_SUBSTATE, config->maxObjects * sizeof (FcSubState));
>
> + 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);
> + }
> +
> if (FcDebug () & FC_DBG_EDIT)
> {
> printf ("FcConfigSubstitute ");
> commit 2261a64ce14d692f7c553f46e2158e70400dbc9c
> Author: Akira TAGOH <akira at tagoh.org>
> Date: Fri Jun 8 15:47:52 2012 +0900
>
> fcdefault: fallback if the environment variables are empty
>
> try to fallback if FC_LANG, LC_ALL, LC_CTYPE and LANG is empty
>
> diff --git a/src/fcdefault.c b/src/fcdefault.c
> index 674374c..ce90a88 100644
> --- a/src/fcdefault.c
> +++ b/src/fcdefault.c
> @@ -46,13 +46,13 @@ FcGetDefaultLangs (void)
> char *langs;
>
> langs = getenv ("FC_LANG");
> - if (!langs)
> + if (!langs || !langs[0])
> langs = getenv ("LC_ALL");
> - if (!langs)
> + if (!langs || !langs[0])
> langs = getenv ("LC_CTYPE");
> - if (!langs)
> + if (!langs || !langs[0])
> langs = getenv ("LANG");
> - if (langs)
> + if (langs && langs[0])
> {
> if (!FcStrSetAddLangs (result, langs))
> FcStrSetAdd (result, (const FcChar8 *) "en");
> commit bbc8fb5ba705e5257693f3b266fce12d2f81b50c
> Author: Akira TAGOH <akira at tagoh.org>
> Date: Thu Mar 29 20:25:20 2012 +0900
>
> Bug 32853 - Export API to get the default language
>
> Add a new API FcGetDefaultLangs() to export the string sets of the default
> languages.
>
> diff --git a/doc/fclangset.fncs b/doc/fclangset.fncs
> index 0a44b38..e2a40b8 100644
> --- a/doc/fclangset.fncs
> +++ b/doc/fclangset.fncs
> @@ -154,6 +154,15 @@ has no matching language, this function returns FcLangDifferentLang.
> @@
>
> @RET@ FcStrSet *
> + at FUNC@ FcGetDefaultLangs
> + at TYPE1@ void
> + at PURPOSE@ Get the default languages list
> + at 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.
> +
> + at RET@ FcStrSet *
> @FUNC@ FcLangSetGetLangs
> @TYPE1@ const FcLangSet * @ARG1@ ls
> @PURPOSE@ get the list of languages in the langset
> diff --git a/fc-lang/fc-lang.c b/fc-lang/fc-lang.c
> index 51717f9..93200c4 100644
> --- a/fc-lang/fc-lang.c
> +++ b/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.h b/fontconfig/fontconfig.h
> index 2671da7..21a476a 100644
> --- a/fontconfig/fontconfig.h
> +++ b/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/src/fcdefault.c b/src/fcdefault.c
> index 170a8a4..674374c 100644
> --- a/src/fcdefault.c
> +++ b/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 = getenv ("LC_ALL");
> + if (!langs)
> + langs = getenv ("LC_CTYPE");
> + if (!langs)
> + langs = getenv ("LANG");
> + if (langs)
> {
> - 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");
> +
> + return result;
> +}
>
> - /* ignore missing or empty ctype */
> - if (ctype && *ctype != '\0')
> +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
> diff --git a/src/fcint.h b/src/fcint.h
> index 3d06fc6..7cc4ed2 100644
> --- a/src/fcint.h
> +++ b/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/src/fclang.c b/src/fclang.c
> index be42b58..b7e70fc 100644
> --- a/src/fclang.c
> +++ b/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 at modifier
> + * 2. language at 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/src/fcstr.c b/src/fcstr.c
> index e372af0..c446bcd 100644
> --- a/src/fcstr.c
> +++ b/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;
> _______________________________________________
> Fontconfig mailing list
> Fontconfig at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/fontconfig
--
Akira TAGOH
More information about the Fontconfig
mailing list