aboutsummaryrefslogtreecommitdiff
path: root/fontconfig
diff options
context:
space:
mode:
Diffstat (limited to 'fontconfig')
-rw-r--r--fontconfig/doc/fclangset.fncs9
-rw-r--r--fontconfig/fc-lang/fc-lang.c6
-rw-r--r--fontconfig/fontconfig/fontconfig.h3
-rw-r--r--fontconfig/src/fccfg.c17
-rw-r--r--fontconfig/src/fcdefault.c106
-rw-r--r--fontconfig/src/fcfreetype.c15
-rw-r--r--fontconfig/src/fcint.h6
-rw-r--r--fontconfig/src/fclang.c159
-rw-r--r--fontconfig/src/fcstr.c44
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;