diff options
Diffstat (limited to 'fontconfig/src')
-rw-r--r-- | fontconfig/src/fccache.c | 77 | ||||
-rw-r--r-- | fontconfig/src/fcdefault.c | 37 | ||||
-rw-r--r-- | fontconfig/src/fcint.h | 3 | ||||
-rw-r--r-- | fontconfig/src/fclist.c | 47 | ||||
-rw-r--r-- | fontconfig/src/fcmatch.c | 113 | ||||
-rw-r--r-- | fontconfig/src/fcname.c | 1 |
6 files changed, 249 insertions, 29 deletions
diff --git a/fontconfig/src/fccache.c b/fontconfig/src/fccache.c index fbe2d5c01..882dd3eb5 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 bada32550..fb4a64b9d 100644 --- a/fontconfig/src/fcint.h +++ b/fontconfig/src/fcint.h @@ -858,7 +858,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]) |