X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffcmatch.c;h=7e3353b3d42e610b1e5ba6a387eee20aeb08de76;hb=7ce196733129b0e664c1bdc20f973f15167292f7;hp=a359a8b883b96b5d1fee4937e387b1b581290a51;hpb=67accef4d3e245c1dea341e633d82b14aa03432a;p=fontconfig.git diff --git a/src/fcmatch.c b/src/fcmatch.c index a359a8b..7e3353b 100644 --- a/src/fcmatch.c +++ b/src/fcmatch.c @@ -22,13 +22,13 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include "fcint.h" #include #include -#include "fcint.h" #include static double -FcCompareNumber (const char *object, FcValue *value1, FcValue *value2) +FcCompareNumber (FcValue *value1, FcValue *value2) { double v1, v2, v; @@ -55,29 +55,31 @@ FcCompareNumber (const char *object, FcValue *value1, FcValue *value2) v = v2 - v1; if (v < 0) v = -v; - return (double) v; + return v; } static double -FcCompareString (const char *object, FcValue *v1, FcValue *v2) +FcCompareString (FcValue *v1, FcValue *v2) { - FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2); - if (value2.type != FcTypeString || value1.type != FcTypeString) - return -1.0; - return (double) FcStrCmpIgnoreCase (value1.u.s, value2.u.s) != 0; + return (double) FcStrCmpIgnoreCase (fc_value_string(v1), fc_value_string(v2)) != 0; } static double -FcCompareFamily (const char *object, FcValue *v1, FcValue *v2) +FcCompareFamily (FcValue *v1, FcValue *v2) { - FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2); - if (value2.type != FcTypeString || value1.type != FcTypeString) - return -1.0; - return (double) FcStrCmpIgnoreBlanksAndCase (value1.u.s, value2.u.s) != 0; + /* rely on the guarantee in FcPatternAddWithBinding that + * families are always FcTypeString. */ + const FcChar8* v1_string = fc_value_string(v1); + const FcChar8* v2_string = fc_value_string(v2); + + if (FcToLower(*v1_string) != FcToLower(*v2_string)) + return 1.0; + + return (double) FcStrCmpIgnoreBlanksAndCase (v1_string, v2_string) != 0; } static double -FcCompareLang (const char *object, FcValue *v1, FcValue *v2) +FcCompareLang (FcValue *v1, FcValue *v2) { FcLangResult result; FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2); @@ -124,25 +126,21 @@ FcCompareLang (const char *object, FcValue *v1, FcValue *v2) } static double -FcCompareBool (const char *object, FcValue *value1, FcValue *value2) +FcCompareBool (FcValue *v1, FcValue *v2) { - if (value2->type != FcTypeBool || value1->type != FcTypeBool) + if (fc_storage_type(v2) != FcTypeBool || fc_storage_type(v1) != FcTypeBool) return -1.0; - return (double) value2->u.b != value1->u.b; + return (double) v2->u.b != v1->u.b; } static double -FcCompareCharSet (const char *object, FcValue *v1, FcValue *v2) +FcCompareCharSet (FcValue *v1, FcValue *v2) { - FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2); - - if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet) - return -1.0; - return (double) FcCharSetSubtractCount (value1.u.c, value2.u.c); + return (double) FcCharSetSubtractCount (fc_value_charset(v1), fc_value_charset(v2)); } static double -FcCompareSize (const char *object, FcValue *value1, FcValue *value2) +FcCompareSize (FcValue *value1, FcValue *value2) { double v1, v2, v; @@ -175,8 +173,8 @@ FcCompareSize (const char *object, FcValue *value1, FcValue *value2) } typedef struct _FcMatcher { - const char *object; - double (*compare) (const char *object, FcValue *value1, FcValue *value2); + FcObject object; + double (*compare) (FcValue *value1, FcValue *value2); int strong, weak; } FcMatcher; @@ -186,180 +184,151 @@ typedef struct _FcMatcher { * later values */ static FcMatcher _FcMatchers [] = { - { FC_FOUNDRY, FcCompareString, 0, 0 }, + { FC_FOUNDRY_OBJECT, FcCompareString, 0, 0 }, #define MATCH_FOUNDRY 0 #define MATCH_FOUNDRY_INDEX 0 - { FC_CHARSET, FcCompareCharSet, 1, 1 }, + { FC_CHARSET_OBJECT, FcCompareCharSet, 1, 1 }, #define MATCH_CHARSET 1 #define MATCH_CHARSET_INDEX 1 - { FC_FAMILY, FcCompareFamily, 2, 4 }, + { FC_FAMILY_OBJECT, FcCompareFamily, 2, 4 }, #define MATCH_FAMILY 2 #define MATCH_FAMILY_STRONG_INDEX 2 #define MATCH_FAMILY_WEAK_INDEX 4 - { FC_LANG, FcCompareLang, 3, 3 }, + { FC_LANG_OBJECT, FcCompareLang, 3, 3 }, #define MATCH_LANG 3 #define MATCH_LANG_INDEX 3 - { FC_SPACING, FcCompareNumber, 5, 5 }, + { FC_SPACING_OBJECT, FcCompareNumber, 5, 5 }, #define MATCH_SPACING 4 #define MATCH_SPACING_INDEX 5 - { FC_PIXEL_SIZE, FcCompareSize, 6, 6 }, + { FC_PIXEL_SIZE_OBJECT, FcCompareSize, 6, 6 }, #define MATCH_PIXEL_SIZE 5 #define MATCH_PIXEL_SIZE_INDEX 6 - { FC_STYLE, FcCompareString, 7, 7 }, + { FC_STYLE_OBJECT, FcCompareString, 7, 7 }, #define MATCH_STYLE 6 #define MATCH_STYLE_INDEX 7 - { FC_SLANT, FcCompareNumber, 8, 8 }, + { FC_SLANT_OBJECT, FcCompareNumber, 8, 8 }, #define MATCH_SLANT 7 #define MATCH_SLANT_INDEX 8 - { FC_WEIGHT, FcCompareNumber, 9, 9 }, + { FC_WEIGHT_OBJECT, FcCompareNumber, 9, 9 }, #define MATCH_WEIGHT 8 #define MATCH_WEIGHT_INDEX 9 - { FC_WIDTH, FcCompareNumber, 10, 10 }, + { FC_WIDTH_OBJECT, FcCompareNumber, 10, 10 }, #define MATCH_WIDTH 9 #define MATCH_WIDTH_INDEX 10 - { FC_ANTIALIAS, FcCompareBool, 11, 11 }, + { FC_ANTIALIAS_OBJECT, FcCompareBool, 11, 11 }, #define MATCH_ANTIALIAS 10 #define MATCH_ANTIALIAS_INDEX 11 - { FC_RASTERIZER, FcCompareString, 12, 12 }, + { FC_RASTERIZER_OBJECT, FcCompareString, 12, 12 }, #define MATCH_RASTERIZER 11 #define MATCH_RASTERIZER_INDEX 12 - { FC_OUTLINE, FcCompareBool, 13, 13 }, + { FC_OUTLINE_OBJECT, FcCompareBool, 13, 13 }, #define MATCH_OUTLINE 12 #define MATCH_OUTLINE_INDEX 13 - { FC_FONTVERSION, FcCompareNumber, 14, 14 }, + { FC_FONTVERSION_OBJECT, FcCompareNumber, 14, 14 }, #define MATCH_FONTVERSION 13 #define MATCH_FONTVERSION_INDEX 14 }; #define NUM_MATCH_VALUES 15 -static FcBool -FcCompareValueList (const char *object, - FcValueListPtr v1orig, /* pattern */ - FcValueListPtr v2orig, /* target */ - FcValue *bestValue, - double *value, - FcResult *result) +static FcMatcher* +FcObjectToMatcher (FcObject object) { - FcValueListPtr v1, v2; - double v, best, bestStrong, bestWeak; - int i; - int j; - - /* - * Locate the possible matching entry by examining the - * first few characters in object - */ + int i; + i = -1; - switch (FcToLower (object[0])) { - case 'f': - switch (FcToLower (object[1])) { - case 'o': - switch (FcToLower (object[2])) { - case 'u': - i = MATCH_FOUNDRY; break; - case 'n': - i = MATCH_FONTVERSION; break; - } - break; - case 'a': - i = MATCH_FAMILY; break; - } - break; - case 'c': + switch (object) { + case FC_FOUNDRY_OBJECT: + i = MATCH_FOUNDRY; break; + case FC_FONTVERSION_OBJECT: + i = MATCH_FONTVERSION; break; + case FC_FAMILY_OBJECT: + i = MATCH_FAMILY; break; + case FC_CHARSET_OBJECT: i = MATCH_CHARSET; break; - case 'a': + case FC_ANTIALIAS_OBJECT: i = MATCH_ANTIALIAS; break; - case 'l': + case FC_LANG_OBJECT: i = MATCH_LANG; break; - case 's': - switch (FcToLower (object[1])) { - case 'p': - i = MATCH_SPACING; break; - case 't': - i = MATCH_STYLE; break; - case 'l': - i = MATCH_SLANT; break; - } - break; - case 'p': + case FC_SPACING_OBJECT: + i = MATCH_SPACING; break; + case FC_STYLE_OBJECT: + i = MATCH_STYLE; break; + case FC_SLANT_OBJECT: + i = MATCH_SLANT; break; + case FC_PIXEL_SIZE_OBJECT: i = MATCH_PIXEL_SIZE; break; - case 'w': - switch (FcToLower (object[1])) { - case 'i': - i = MATCH_WIDTH; break; - case 'e': - i = MATCH_WEIGHT; break; - } - break; - case 'r': + case FC_WIDTH_OBJECT: + i = MATCH_WIDTH; break; + case FC_WEIGHT_OBJECT: + i = MATCH_WEIGHT; break; + case FC_RASTERIZER_OBJECT: i = MATCH_RASTERIZER; break; - case 'o': + case FC_OUTLINE_OBJECT: i = MATCH_OUTLINE; break; } - if (i == -1 || - FcStrCmpIgnoreCase ((FcChar8 *) _FcMatchers[i].object, - (FcChar8 *) object) != 0) - { - if (bestValue) - *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2orig)->value); - return FcTrue; - } -#if 0 - for (i = 0; i < NUM_MATCHER; i++) - { - if (!FcStrCmpIgnoreCase ((FcChar8 *) _FcMatchers[i].object, - (FcChar8 *) object)) - break; - } - if (i == NUM_MATCHER) + + if (i < 0) + return NULL; + + return _FcMatchers+i; +} + +static FcBool +FcCompareValueList (FcObject object, + FcValueListPtr v1orig, /* pattern */ + FcValueListPtr v2orig, /* target */ + FcValue *bestValue, + double *value, + FcResult *result) +{ + FcValueListPtr v1, v2; + double v, best, bestStrong, bestWeak; + int j; + FcMatcher *match = FcObjectToMatcher(object); + + if (!match) { if (bestValue) - *bestValue = v2orig->value; + *bestValue = FcValueCanonicalize(&v2orig->value); return FcTrue; } -#endif + best = 1e99; bestStrong = 1e99; bestWeak = 1e99; j = 0; - for (v1 = v1orig; FcValueListPtrU(v1); - v1 = FcValueListPtrU(v1)->next) + for (v1 = v1orig; v1; v1 = FcValueListNext(v1)) { - for (v2 = v2orig; FcValueListPtrU(v2); - v2 = FcValueListPtrU(v2)->next) + for (v2 = v1orig; v2; v2 = FcValueListNext(v2)) { - v = (*_FcMatchers[i].compare) (_FcMatchers[i].object, - &FcValueListPtrU(v1)->value, - &FcValueListPtrU(v2)->value); + v = (match->compare) (&v1->value, &v2->value); if (v < 0) { *result = FcResultTypeMismatch; return FcFalse; } - if (FcDebug () & FC_DBG_MATCHV) - printf (" v %g j %d ", v, j); v = v * 100 + j; if (v < best) { if (bestValue) - *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2)->value); + *bestValue = FcValueCanonicalize(&v2->value); best = v; } - if (FcValueListPtrU(v1)->binding == FcValueBindingStrong) + if (v1->binding == FcValueBindingStrong) { if (v < bestStrong) bestStrong = v; @@ -374,7 +343,7 @@ FcCompareValueList (const char *object, } if (FcDebug () & FC_DBG_MATCHV) { - printf (" %s: %g ", object, best); + printf (" %s: %g ", FcObjectName (object), best); FcValueListPrint (v1orig); printf (", "); FcValueListPrint (v2orig); @@ -382,8 +351,8 @@ FcCompareValueList (const char *object, } if (value) { - int weak = _FcMatchers[i].weak; - int strong = _FcMatchers[i].strong; + int weak = match->weak; + int strong = match->strong; if (weak == strong) value[strong] += best; else @@ -415,39 +384,26 @@ FcCompare (FcPattern *pat, i2 = 0; while (i1 < pat->num && i2 < fnt->num) { - i = FcObjectPtrCompare((FcPatternEltU(pat->elts)+i1)->object, - (FcPatternEltU(fnt->elts)+i2)->object); + FcPatternElt *elt_i1 = &FcPatternElts(pat)[i1]; + FcPatternElt *elt_i2 = &FcPatternElts(fnt)[i2]; + + i = FcObjectCompare(elt_i1->object, elt_i2->object); if (i > 0) i2++; else if (i < 0) i1++; else { - if (!FcCompareValueList (FcObjectPtrU((FcPatternEltU(pat->elts)+i1)->object), - (FcPatternEltU(pat->elts)+i1)->values, - (FcPatternEltU(fnt->elts)+i2)->values, - 0, - value, - result)) + if (!FcCompareValueList (elt_i1->object, + FcPatternEltValues(elt_i1), + FcPatternEltValues(elt_i2), + 0, value, result)) return FcFalse; i1++; i2++; } } return FcTrue; -#if 0 - for (i1 = 0; i1 < pat->num; i1++) - { - for (i2 = 0; i2 < fnt->num; i2++) - { - if (!strcmp (pat->elts[i1].object, fnt->elts[i2].object)) - { - break; - } - } - } - return FcTrue; -#endif } FcPattern * @@ -466,29 +422,32 @@ FcFontRenderPrepare (FcConfig *config, return 0; for (i = 0; i < font->num; i++) { - fe = FcPatternEltU(font->elts)+i; - pe = FcPatternFindElt (pat, FcObjectPtrU(fe->object)); + fe = &FcPatternElts(font)[i]; + pe = FcPatternObjectFindElt (pat, fe->object); if (pe) { - if (!FcCompareValueList (FcObjectPtrU(pe->object), pe->values, - fe->values, &v, 0, &result)) + if (!FcCompareValueList (pe->object, FcPatternEltValues(pe), + FcPatternEltValues(fe), &v, 0, &result)) { FcPatternDestroy (new); return 0; } } else - v = FcValueCanonicalize(&FcValueListPtrU(fe->values)->value); - FcPatternAdd (new, FcObjectPtrU(fe->object), v, FcFalse); + v = FcValueCanonicalize(&FcPatternEltValues (fe)->value); + FcPatternObjectAdd (new, fe->object, v, FcFalse); } for (i = 0; i < pat->num; i++) { - pe = FcPatternEltU(pat->elts)+i; - fe = FcPatternFindElt (font, FcObjectPtrU(pe->object)); + pe = &FcPatternElts(pat)[i]; + fe = FcPatternObjectFindElt (font, pe->object); if (!fe) - FcPatternAdd (new, FcObjectPtrU(pe->object), - FcValueCanonicalize(&FcValueListPtrU(pe->values)->value), FcTrue); + { + v = FcValueCanonicalize(&FcPatternEltValues(pe)->value); + FcPatternObjectAdd (new, pe->object, v, FcTrue); + } } + FcConfigSubstituteWithPat (config, new, pat, FcMatchFont); return new; } @@ -519,10 +478,7 @@ FcFontSetMatch (FcConfig *config, { config = FcConfigGetCurrent (); if (!config) - { - *result = FcResultOutOfMemory; return 0; - } } for (set = 0; set < nsets; set++) { @@ -620,7 +576,7 @@ FcSortCompare (const void *aa, const void *ab) } static FcBool -FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool trim) +FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool trim, FcBool build_cs) { FcCharSet *ncs; FcSortNode *node; @@ -637,16 +593,20 @@ FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool tri */ if (!trim || !*cs || !FcCharSetIsSubset (ncs, *cs)) { - if (*cs) - { - ncs = FcCharSetUnion (ncs, *cs); - if (!ncs) - return FcFalse; - FcCharSetDestroy (*cs); - } - else - ncs = FcCharSetCopy (ncs); - *cs = ncs; + if (trim || build_cs) + { + if (*cs) + { + ncs = FcCharSetUnion (ncs, *cs); + if (!ncs) + return FcFalse; + FcCharSetDestroy (*cs); + } + else + ncs = FcCharSetCopy (ncs); + *cs = ncs; + } + FcPatternReference (node->pattern); if (FcDebug () & FC_DBG_MATCH) { @@ -780,8 +740,7 @@ FcFontSetSort (FcConfig *config, FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch && FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == FcResultMatch) { - double compare = FcCompareLang (FC_LANG, &patternLang, - &nodeLang); + double compare = FcCompareLang (&patternLang, &nodeLang); if (compare >= 0 && compare < 2) { if (FcDebug () & FC_DBG_MATCHV) @@ -816,13 +775,16 @@ FcFontSetSort (FcConfig *config, cs = 0; - if (!FcSortWalk (nodeps, nnodes, ret, &cs, trim)) + if (!FcSortWalk (nodeps, nnodes, ret, &cs, trim, (csp!=0))) goto bail2; if (csp) *csp = cs; else - FcCharSetDestroy (cs); + { + if (cs) + FcCharSetDestroy (cs); + } free (nodes);