[Fontconfig] fontconfig: Branch 'master' - 4 commits
Akira TAGOH
tagoh at kemper.freedesktop.org
Fri Jun 8 00:05:23 PDT 2012
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;
More information about the Fontconfig
mailing list