aboutsummaryrefslogtreecommitdiff
path: root/fontconfig/src
diff options
context:
space:
mode:
Diffstat (limited to 'fontconfig/src')
-rw-r--r--fontconfig/src/fccache.c77
-rw-r--r--fontconfig/src/fcdefault.c37
-rw-r--r--fontconfig/src/fcint.h3
-rw-r--r--fontconfig/src/fclist.c47
-rw-r--r--fontconfig/src/fcmatch.c113
-rw-r--r--fontconfig/src/fcname.c1
6 files changed, 249 insertions, 29 deletions
diff --git a/fontconfig/src/fccache.c b/fontconfig/src/fccache.c
index d1fa7783b..22828820d 100644
--- a/fontconfig/src/fccache.c
+++ b/fontconfig/src/fccache.c
@@ -37,6 +37,21 @@
# include <unistd.h>
# include <sys/mman.h>
#endif
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_MNTENT_H
+#include <mntent.h>
+#endif
#ifndef O_BINARY
#define O_BINARY 0
@@ -144,6 +159,64 @@ FcStat (const FcChar8 *file, struct stat *statb)
#endif
+static FcBool
+FcCacheIsMmapSafe (int fd)
+{
+ FcBool retval = FcTrue;
+ static FcBool is_initialized = FcFalse;
+ static FcBool is_env_available = FcFalse;
+ static FcBool use_mmap = FcFalse;
+
+ if (!is_initialized)
+ {
+ const char *env;
+
+ env = getenv ("FONTCONFIG_USE_MMAP");
+ if (env)
+ {
+ if (FcNameBool ((const FcChar8 *)env, &use_mmap))
+ is_env_available = FcTrue;
+ }
+ is_initialized = FcTrue;
+ }
+ if (is_env_available)
+ return use_mmap;
+#if defined(HAVE_FSTATVFS) && (defined(HAVE_STRUCT_STATVFS_F_BASETYPE) || defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME))
+ struct statvfs buf;
+
+ if (fstatvfs (fd, &buf) == 0)
+ {
+ const char *p;
+#if defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
+ p = buf.f_basetype;
+#elif defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
+ p = buf.f_fstypename;
+#endif
+
+ if (strcmp (p, "nfs") == 0)
+ retval = FcFalse;
+ }
+#elif defined(HAVE_FSTATFS) && (defined(HAVE_STRUCT_STATFS_F_FLAGS) || defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || defined(__linux__))
+ struct statfs buf;
+
+ if (fstatfs (fd, &buf) == 0)
+ {
+# if defined(HAVE_STRUCT_STATFS_F_FLAGS) && defined(MNT_LOCAL)
+ if (!(buf.f_flags & MNT_LOCAL))
+# elif defined(HAVE_STRUCT_STATFS_F_FSTYPENAME)
+ if (strcmp (buf.f_fstypename, "nfs") == 0)
+# elif defined(__linux__)
+ if (buf.f_type == 0x6969) /* nfs */
+# else
+# error "BUG: No way to figure out with fstatfs()"
+# endif
+ retval = FcFalse;
+ }
+#endif
+
+ return retval;
+}
+
static const char bin2hex[] = { '0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
@@ -602,10 +675,10 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
}
/*
- * Lage cache files are mmap'ed, smaller cache files are read. This
+ * Large cache files are mmap'ed, smaller cache files are read. This
* balances the system cost of mmap against per-process memory usage.
*/
- if (fd_stat->st_size >= FC_CACHE_MIN_MMAP)
+ if (FcCacheIsMmapSafe (fd) && fd_stat->st_size >= FC_CACHE_MIN_MMAP)
{
#if defined(HAVE_MMAP) || defined(__CYGWIN__)
cache = mmap (0, fd_stat->st_size, PROT_READ, MAP_SHARED, fd, 0);
diff --git a/fontconfig/src/fcdefault.c b/fontconfig/src/fcdefault.c
index a9165facd..170a8a4d8 100644
--- a/fontconfig/src/fcdefault.c
+++ b/fontconfig/src/fcdefault.c
@@ -119,7 +119,7 @@ FcGetDefaultLang (void)
void
FcDefaultSubstitute (FcPattern *pattern)
{
- FcValue v;
+ FcValue v, namelang, v2;
int i;
if (FcPatternObjectGet (pattern, FC_WEIGHT_OBJECT, 0, &v) == FcResultNoMatch )
@@ -175,6 +175,41 @@ FcDefaultSubstitute (FcPattern *pattern)
{
FcPatternObjectAddInteger (pattern, FC_HINT_STYLE_OBJECT, FC_HINT_FULL);
}
+ if (FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternObjectAddString (pattern, FC_NAMELANG_OBJECT, FcGetDefaultLang ());
+ }
+ /* shouldn't be failed. */
+ FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &namelang);
+ /* Add a fallback to ensure the english name when the requested language
+ * isn't available. this would helps for the fonts that have non-English
+ * name at the beginning.
+ */
+ /* Set "en-us" instead of "en" to avoid giving higher score to "en".
+ * This is a hack for the case that the orth is not like ll-cc, because,
+ * if no namelang isn't explicitly set, it will has something like ll-cc
+ * according to current locale. which may causes FcLangDifferentTerritory
+ * at FcLangCompare(). thus, the English name is selected so that
+ * exact matched "en" has higher score than ll-cc.
+ */
+ v2.type = FcTypeString;
+ v2.u.s = FcSharedStr ((FcChar8 *)"en-us");
+ if (FcPatternObjectGet (pattern, FC_FAMILYLANG_OBJECT, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternObjectAdd (pattern, FC_FAMILYLANG_OBJECT, namelang, FcTrue);
+ FcPatternObjectAddWithBinding (pattern, FC_FAMILYLANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
+ }
+ if (FcPatternObjectGet (pattern, FC_STYLELANG_OBJECT, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternObjectAdd (pattern, FC_STYLELANG_OBJECT, namelang, FcTrue);
+ FcPatternObjectAddWithBinding (pattern, FC_STYLELANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
+ }
+ if (FcPatternObjectGet (pattern, FC_FULLNAMELANG_OBJECT, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue);
+ FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue);
+ }
+ FcSharedStrFree (v2.u.s);
}
#define __fcdefault__
#include "fcaliastail.h"
diff --git a/fontconfig/src/fcint.h b/fontconfig/src/fcint.h
index e45df5351..0a59f70ac 100644
--- a/fontconfig/src/fcint.h
+++ b/fontconfig/src/fcint.h
@@ -860,7 +860,8 @@ FcListPatternMatchAny (const FcPattern *p,
#define FC_EMBEDDED_BITMAP_OBJECT 39
#define FC_DECORATIVE_OBJECT 40
#define FC_LCD_FILTER_OBJECT 41
-#define FC_MAX_BASE_OBJECT FC_LCD_FILTER_OBJECT
+#define FC_NAMELANG_OBJECT 42
+#define FC_MAX_BASE_OBJECT FC_NAMELANG_OBJECT
FcPrivate FcBool
FcNameBool (const FcChar8 *v, FcBool *result);
diff --git a/fontconfig/src/fclist.c b/fontconfig/src/fclist.c
index 88025e900..331352cd8 100644
--- a/fontconfig/src/fclist.c
+++ b/fontconfig/src/fclist.c
@@ -221,7 +221,18 @@ FcListPatternMatchAny (const FcPattern *p,
for (i = 0; i < p->num; i++)
{
FcPatternElt *pe = &FcPatternElts(p)[i];
- FcPatternElt *fe = FcPatternObjectFindElt (font, pe->object);
+ FcPatternElt *fe;
+
+ if (pe->object == FC_NAMELANG_OBJECT)
+ {
+ /* "namelang" object is the alias object to change "familylang",
+ * "stylelang" and "fullnamelang" object alltogether. it won't be
+ * available on the font pattern. so checking its availability
+ * causes no results. we should ignore it here.
+ */
+ continue;
+ }
+ fe = FcPatternObjectFindElt (font, pe->object);
if (!fe)
return FcFalse;
if (!FcListValueListMatchAny (FcPatternEltValues(pe), /* pat elts */
@@ -340,13 +351,13 @@ FcListHashTableCleanup (FcListHashTable *table)
}
static int
-FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object)
+FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object, const FcChar8 *lang)
{
- FcChar8 *lang = FcGetDefaultLang ();
FcPatternElt *e = FcPatternObjectFindElt (font, object);
FcValueListPtr v;
FcValue value;
int idx = -1;
+ int defidx = -1;
int i;
if (e)
@@ -363,17 +374,27 @@ FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object)
if (res == FcLangDifferentCountry && idx < 0)
idx = i;
+ if (defidx < 0)
+ {
+ /* workaround for fonts that has non-English value
+ * at the head of values.
+ */
+ res = FcLangCompare (value.u.s, (FcChar8 *)"en");
+ if (res == FcLangEqual)
+ defidx = i;
+ }
}
}
}
- return (idx > 0) ? idx : 0;
+ return (idx > 0) ? idx : (defidx > 0) ? defidx : 0;
}
static FcBool
FcListAppend (FcListHashTable *table,
FcPattern *font,
- FcObjectSet *os)
+ FcObjectSet *os,
+ const FcChar8 *lang)
{
int o;
FcPatternElt *e;
@@ -409,19 +430,19 @@ FcListAppend (FcListHashTable *table,
if (!strcmp (os->objects[o], FC_FAMILY) || !strcmp (os->objects[o], FC_FAMILYLANG))
{
if (familyidx < 0)
- familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT);
+ familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT, lang);
defidx = familyidx;
}
else if (!strcmp (os->objects[o], FC_FULLNAME) || !strcmp (os->objects[o], FC_FULLNAMELANG))
{
if (fullnameidx < 0)
- fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT);
+ fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT, lang);
defidx = fullnameidx;
}
else if (!strcmp (os->objects[o], FC_STYLE) || !strcmp (os->objects[o], FC_STYLELANG))
{
if (styleidx < 0)
- styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT);
+ styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT, lang);
defidx = styleidx;
}
else
@@ -499,8 +520,16 @@ FcFontSetList (FcConfig *config,
for (f = 0; f < s->nfont; f++)
if (FcListPatternMatchAny (p, /* pattern */
s->fonts[f])) /* font */
- if (!FcListAppend (&table, s->fonts[f], os))
+ {
+ FcChar8 *lang;
+
+ if (FcPatternObjectGetString (p, FC_NAMELANG_OBJECT, 0, &lang) != FcResultMatch)
+ {
+ lang = FcGetDefaultLang ();
+ }
+ if (!FcListAppend (&table, s->fonts[f], os, lang))
goto bail1;
+ }
}
#if 0
{
diff --git a/fontconfig/src/fcmatch.c b/fontconfig/src/fcmatch.c
index 655e62cf5..623538bd3 100644
--- a/fontconfig/src/fcmatch.c
+++ b/fontconfig/src/fcmatch.c
@@ -240,7 +240,8 @@ static const FcMatcher _FcMatchers [] = {
#define NUM_MATCH_VALUES 17
static const FcMatcher*
-FcObjectToMatcher (FcObject object)
+FcObjectToMatcher (FcObject object,
+ FcBool include_lang)
{
int i;
@@ -278,6 +279,16 @@ FcObjectToMatcher (FcObject object)
i = MATCH_OUTLINE; break;
case FC_DECORATIVE_OBJECT:
i = MATCH_DECORATIVE; break;
+ default:
+ if (include_lang)
+ {
+ switch (object) {
+ case FC_FAMILYLANG_OBJECT:
+ case FC_STYLELANG_OBJECT:
+ case FC_FULLNAMELANG_OBJECT:
+ i = MATCH_LANG; break;
+ }
+ }
}
if (i < 0)
@@ -287,22 +298,25 @@ FcObjectToMatcher (FcObject object)
}
static FcBool
-FcCompareValueList (FcObject object,
- FcValueListPtr v1orig, /* pattern */
- FcValueListPtr v2orig, /* target */
- FcValue *bestValue,
- double *value,
- FcResult *result)
+FcCompareValueList (FcObject object,
+ const FcMatcher *match,
+ FcValueListPtr v1orig, /* pattern */
+ FcValueListPtr v2orig, /* target */
+ FcValue *bestValue,
+ double *value,
+ int *n,
+ FcResult *result)
{
FcValueListPtr v1, v2;
double v, best, bestStrong, bestWeak;
- int j;
- const FcMatcher *match = FcObjectToMatcher(object);
+ int j, k, pos = 0;
if (!match)
{
if (bestValue)
*bestValue = FcValueCanonicalize(&v2orig->value);
+ if (n)
+ *n = 0;
return FcTrue;
}
@@ -312,7 +326,7 @@ FcCompareValueList (FcObject object,
j = 1;
for (v1 = v1orig; v1; v1 = FcValueListNext(v1))
{
- for (v2 = v2orig; v2; v2 = FcValueListNext(v2))
+ for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2), k++)
{
v = (match->compare) (&v1->value, &v2->value);
if (v < 0)
@@ -326,6 +340,7 @@ FcCompareValueList (FcObject object,
if (bestValue)
*bestValue = FcValueCanonicalize(&v2->value);
best = v;
+ pos = k;
}
if (v1->binding == FcValueBindingStrong)
{
@@ -360,6 +375,9 @@ FcCompareValueList (FcObject object,
value[strong] += bestStrong;
}
}
+ if (n)
+ *n = pos;
+
return FcTrue;
}
@@ -393,10 +411,11 @@ FcCompare (FcPattern *pat,
i1++;
else
{
- if (!FcCompareValueList (elt_i1->object,
+ const FcMatcher *match = FcObjectToMatcher (elt_i1->object, FcFalse);
+ if (!FcCompareValueList (elt_i1->object, match,
FcPatternEltValues(elt_i1),
FcPatternEltValues(elt_i2),
- 0, value, result))
+ NULL, value, NULL, result))
return FcFalse;
i1++;
i2++;
@@ -412,8 +431,8 @@ FcFontRenderPrepare (FcConfig *config,
{
FcPattern *new;
int i;
- FcPatternElt *fe, *pe;
- FcValue v;
+ FcPatternElt *fe, *pe, *fel, *pel;
+ FcValue v, vl;
FcResult result;
assert (pat != NULL);
@@ -425,19 +444,81 @@ FcFontRenderPrepare (FcConfig *config,
for (i = 0; i < font->num; i++)
{
fe = &FcPatternElts(font)[i];
+ if (fe->object == FC_FAMILYLANG_OBJECT ||
+ fe->object == FC_STYLELANG_OBJECT ||
+ fe->object == FC_FULLNAMELANG_OBJECT)
+ {
+ /* ignore those objects. we need to deal with them
+ * another way */
+ continue;
+ }
+ if (fe->object == FC_FAMILY_OBJECT ||
+ fe->object == FC_STYLE_OBJECT ||
+ fe->object == FC_FULLNAME_OBJECT)
+ {
+ FC_ASSERT_STATIC ((FC_FAMILY_OBJECT + 1) == FC_FAMILYLANG_OBJECT);
+ FC_ASSERT_STATIC ((FC_STYLE_OBJECT + 1) == FC_STYLELANG_OBJECT);
+ FC_ASSERT_STATIC ((FC_FULLNAME_OBJECT + 1) == FC_FULLNAMELANG_OBJECT);
+
+ fel = FcPatternObjectFindElt (font, fe->object + 1);
+ pel = FcPatternObjectFindElt (pat, fe->object + 1);
+ }
+ else
+ {
+ fel = NULL;
+ pel = NULL;
+ }
pe = FcPatternObjectFindElt (pat, fe->object);
if (pe)
{
- if (!FcCompareValueList (pe->object, FcPatternEltValues(pe),
- FcPatternEltValues(fe), &v, 0, &result))
+ const FcMatcher *match = FcObjectToMatcher (pe->object, FcFalse);
+
+ if (!FcCompareValueList (pe->object, match,
+ FcPatternEltValues(pe),
+ FcPatternEltValues(fe), &v, NULL, NULL, &result))
{
FcPatternDestroy (new);
return 0;
}
+ if (fel && pel)
+ {
+ int n = 1, j;
+
+ match = FcObjectToMatcher (pel->object, FcTrue);
+ if (!FcCompareValueList (pel->object, match,
+ FcPatternEltValues (pel),
+ FcPatternEltValues (fel), &vl, NULL, &n, &result))
+ {
+ FcPatternDestroy (new);
+ return NULL;
+ }
+ else
+ {
+ FcValueListPtr l;
+
+ for (j = 0, l = FcPatternEltValues (fe);
+ j < n && l != NULL;
+ j++, l = FcValueListNext (l));
+ if (l)
+ v = FcValueCanonicalize (&l->value);
+ else
+ v = FcValueCanonicalize (&FcPatternEltValues (fe)->value);
+ }
+ }
+ else if (fel)
+ {
+ vl = FcValueCanonicalize (&FcPatternEltValues (fel)->value);
+ }
}
else
+ {
v = FcValueCanonicalize(&FcPatternEltValues (fe)->value);
+ if (fel)
+ vl = FcValueCanonicalize (&FcPatternEltValues (fel)->value);
+ }
FcPatternObjectAdd (new, fe->object, v, FcFalse);
+ if (fel)
+ FcPatternObjectAdd (new, fel->object, vl, FcFalse);
}
for (i = 0; i < pat->num; i++)
{
diff --git a/fontconfig/src/fcname.c b/fontconfig/src/fcname.c
index d0b1ca84c..d51307bec 100644
--- a/fontconfig/src/fcname.c
+++ b/fontconfig/src/fcname.c
@@ -76,6 +76,7 @@ static const FcObjectType _FcBaseObjectTypes[] = {
{ FC_EMBEDDED_BITMAP, FcTypeBool },
{ FC_DECORATIVE, FcTypeBool },
{ FC_LCD_FILTER, FcTypeInteger }, /* 41 */
+ { FC_NAMELANG, FcTypeString }, /* 42 */
};
#define NUM_OBJECT_TYPES (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])