X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffcmatch.c;h=422bc384d2ecbabc2df33e3d10122381d985d9df;hb=a18ca17b6211f62fbd1d893811b94b8c83db4cc0;hp=8d0fbc37ffe2e1a318347f229657d96e843fc7bd;hpb=55e145b0250e5c233d9fed1f8f5efe690374cdf2;p=fontconfig.git diff --git a/src/fcmatch.c b/src/fcmatch.c index 8d0fbc3..422bc38 100644 --- a/src/fcmatch.c +++ b/src/fcmatch.c @@ -1,5 +1,5 @@ /* - * $RCSId: xc/lib/fontconfig/src/fcmatch.c,v 1.20 2002/08/31 22:17:32 keithp Exp $ + * fontconfig/src/fcmatch.c * * Copyright © 2000 Keith Packard * @@ -7,31 +7,32 @@ * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in + * documentation, and that the name of the author(s) not be used in * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no + * specific, written prior permission. The authors make no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +#include "fcint.h" +#include #include #include -#include "fcint.h" #include static double FcCompareNumber (FcValue *value1, FcValue *value2) { double v1, v2, v; - + switch (value1->type) { case FcTypeInteger: v1 = (double) value1->u.i; @@ -61,18 +62,19 @@ FcCompareNumber (FcValue *value1, FcValue *value2) static double FcCompareString (FcValue *v1, FcValue *v2) { - return (double) FcStrCmpIgnoreCase (fc_value_string(v1), fc_value_string(v2)) != 0; + return (double) FcStrCmpIgnoreCase (FcValueString(v1), FcValueString(v2)) != 0; } static double FcCompareFamily (FcValue *v1, FcValue *v2) { - /* rely on the guarantee in FcPatternAddWithBinding that + /* rely on the guarantee in FcPatternObjectAddWithBinding that * families are always FcTypeString. */ - const FcChar8* v1_string = fc_value_string(v1); - const FcChar8* v2_string = fc_value_string(v2); + const FcChar8* v1_string = FcValueString(v1); + const FcChar8* v2_string = FcValueString(v2); - if (FcToLower(*v1_string) != FcToLower(*v2_string)) + if (FcToLower(*v1_string) != FcToLower(*v2_string) && + *v1_string != ' ' && *v2_string != ' ') return 1.0; return (double) FcStrCmpIgnoreBlanksAndCase (v1_string, v2_string) != 0; @@ -83,7 +85,7 @@ FcCompareLang (FcValue *v1, FcValue *v2) { FcLangResult result; FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2); - + switch (value1.type) { case FcTypeLangSet: switch (value2.type) { @@ -91,7 +93,7 @@ FcCompareLang (FcValue *v1, FcValue *v2) result = FcLangSetCompare (value1.u.l, value2.u.l); break; case FcTypeString: - result = FcLangSetHasLang (value1.u.l, + result = FcLangSetHasLang (value1.u.l, value2.u.s); break; default: @@ -104,7 +106,7 @@ FcCompareLang (FcValue *v1, FcValue *v2) result = FcLangSetHasLang (value2.u.l, value1.u.s); break; case FcTypeString: - result = FcLangCompare (value1.u.s, + result = FcLangCompare (value1.u.s, value2.u.s); break; default: @@ -128,7 +130,7 @@ FcCompareLang (FcValue *v1, FcValue *v2) static double FcCompareBool (FcValue *v1, FcValue *v2) { - if (fc_storage_type(v2) != FcTypeBool || fc_storage_type(v1) != FcTypeBool) + if (v2->type != FcTypeBool || v1->type != FcTypeBool) return -1.0; return (double) v2->u.b != v1->u.b; } @@ -136,7 +138,7 @@ FcCompareBool (FcValue *v1, FcValue *v2) static double FcCompareCharSet (FcValue *v1, FcValue *v2) { - return (double) FcCharSetSubtractCount (fc_value_charset(v1), fc_value_charset(v2)); + return (double) FcCharSetSubtractCount (FcValueCharSet(v1), FcValueCharSet(v2)); } static double @@ -173,8 +175,7 @@ FcCompareSize (FcValue *value1, FcValue *value2) } typedef struct _FcMatcher { - const char *object; - FcObjectPtr objectPtr; + FcObject object; double (*compare) (FcValue *value1, FcValue *value2); int strong, weak; } FcMatcher; @@ -184,157 +185,89 @@ typedef struct _FcMatcher { * each value, earlier values are more significant than * later values */ -static FcMatcher _FcMatchers [] = { - { FC_FOUNDRY, 0, FcCompareString, 0, 0 }, +static const FcMatcher _FcMatchers [] = { + { FC_FOUNDRY_OBJECT, FcCompareString, 0, 0 }, #define MATCH_FOUNDRY 0 -#define MATCH_FOUNDRY_INDEX 0 - - { FC_CHARSET, 0, FcCompareCharSet, 1, 1 }, + { FC_CHARSET_OBJECT, FcCompareCharSet, 1, 1 }, #define MATCH_CHARSET 1 -#define MATCH_CHARSET_INDEX 1 - - { FC_FAMILY, 0, 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, 0, FcCompareLang, 3, 3 }, + { FC_LANG_OBJECT, FcCompareLang, 3, 3 }, #define MATCH_LANG 3 #define MATCH_LANG_INDEX 3 - - { FC_SPACING, 0, FcCompareNumber, 5, 5 }, + { FC_SPACING_OBJECT, FcCompareNumber, 5, 5 }, #define MATCH_SPACING 4 -#define MATCH_SPACING_INDEX 5 - - { FC_PIXEL_SIZE, 0, FcCompareSize, 6, 6 }, + { FC_PIXEL_SIZE_OBJECT, FcCompareSize, 6, 6 }, #define MATCH_PIXEL_SIZE 5 -#define MATCH_PIXEL_SIZE_INDEX 6 - - { FC_STYLE, 0, FcCompareString, 7, 7 }, + { FC_STYLE_OBJECT, FcCompareString, 7, 7 }, #define MATCH_STYLE 6 -#define MATCH_STYLE_INDEX 7 - - { FC_SLANT, 0, FcCompareNumber, 8, 8 }, + { FC_SLANT_OBJECT, FcCompareNumber, 8, 8 }, #define MATCH_SLANT 7 -#define MATCH_SLANT_INDEX 8 - - { FC_WEIGHT, 0, FcCompareNumber, 9, 9 }, + { FC_WEIGHT_OBJECT, FcCompareNumber, 9, 9 }, #define MATCH_WEIGHT 8 -#define MATCH_WEIGHT_INDEX 9 - - { FC_WIDTH, 0, FcCompareNumber, 10, 10 }, + { FC_WIDTH_OBJECT, FcCompareNumber, 10, 10 }, #define MATCH_WIDTH 9 -#define MATCH_WIDTH_INDEX 10 - - { FC_ANTIALIAS, 0, FcCompareBool, 11, 11 }, -#define MATCH_ANTIALIAS 10 -#define MATCH_ANTIALIAS_INDEX 11 - - { FC_RASTERIZER, 0, FcCompareString, 12, 12 }, -#define MATCH_RASTERIZER 11 -#define MATCH_RASTERIZER_INDEX 12 - - { FC_OUTLINE, 0, FcCompareBool, 13, 13 }, -#define MATCH_OUTLINE 12 -#define MATCH_OUTLINE_INDEX 13 - - { FC_FONTVERSION, 0, FcCompareNumber, 14, 14 }, -#define MATCH_FONTVERSION 13 -#define MATCH_FONTVERSION_INDEX 14 + { FC_DECORATIVE_OBJECT, FcCompareBool, 11, 11 }, +#define MATCH_DECORATIVE 10 + { FC_ANTIALIAS_OBJECT, FcCompareBool, 12, 12 }, +#define MATCH_ANTIALIAS 11 + { FC_RASTERIZER_OBJECT, FcCompareString, 13, 13 }, +#define MATCH_RASTERIZER 12 + { FC_OUTLINE_OBJECT, FcCompareBool, 14, 14 }, +#define MATCH_OUTLINE 13 + { FC_FONTVERSION_OBJECT, FcCompareNumber, 15, 15 }, +#define MATCH_FONTVERSION 14 }; -#define NUM_MATCH_VALUES 15 - -static FcBool matchObjectPtrsInit = FcFalse; - -static void -FcMatchObjectPtrsInit (void) -{ - _FcMatchers[MATCH_FOUNDRY].objectPtr = FcObjectToPtr(FC_FOUNDRY); - _FcMatchers[MATCH_CHARSET].objectPtr = FcObjectToPtr(FC_CHARSET); - _FcMatchers[MATCH_FAMILY].objectPtr = FcObjectToPtr(FC_FAMILY); - _FcMatchers[MATCH_LANG].objectPtr = FcObjectToPtr(FC_LANG); - _FcMatchers[MATCH_SPACING].objectPtr = FcObjectToPtr(FC_SPACING); - _FcMatchers[MATCH_PIXEL_SIZE].objectPtr = FcObjectToPtr(FC_PIXEL_SIZE); - _FcMatchers[MATCH_STYLE].objectPtr = FcObjectToPtr(FC_STYLE); - _FcMatchers[MATCH_SLANT].objectPtr = FcObjectToPtr(FC_SLANT); - _FcMatchers[MATCH_WEIGHT].objectPtr = FcObjectToPtr(FC_WEIGHT); - _FcMatchers[MATCH_WIDTH].objectPtr = FcObjectToPtr(FC_WIDTH); - _FcMatchers[MATCH_ANTIALIAS].objectPtr = FcObjectToPtr(FC_ANTIALIAS); - _FcMatchers[MATCH_RASTERIZER].objectPtr = FcObjectToPtr(FC_RASTERIZER); - _FcMatchers[MATCH_OUTLINE].objectPtr = FcObjectToPtr(FC_OUTLINE); - _FcMatchers[MATCH_FONTVERSION].objectPtr = FcObjectToPtr(FC_FONTVERSION); - matchObjectPtrsInit = FcTrue; -} +#define NUM_MATCH_VALUES 16 -static FcMatcher* -FcObjectPtrToMatcher (FcObjectPtr o) +static const FcMatcher* +FcObjectToMatcher (FcObject object) { int i; - const char *object = FcObjectPtrU(o); i = -1; - switch (object[0]) { - case 'f': - switch (object[1]) { - case 'o': - switch (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 (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 (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; + case FC_DECORATIVE_OBJECT: + i = MATCH_DECORATIVE; break; } if (i < 0) - return 0; - - if (!matchObjectPtrsInit) - FcMatchObjectPtrsInit(); - - if (o != _FcMatchers[i].objectPtr) - return 0; + return NULL; return _FcMatchers+i; } static FcBool -FcCompareValueList (FcObjectPtr o, +FcCompareValueList (FcObject object, FcValueListPtr v1orig, /* pattern */ FcValueListPtr v2orig, /* target */ FcValue *bestValue, @@ -342,43 +275,39 @@ FcCompareValueList (FcObjectPtr o, FcResult *result) { FcValueListPtr v1, v2; - FcValueList *v1_ptrU, *v2_ptrU; double v, best, bestStrong, bestWeak; int j; - const char *object = FcObjectPtrU(o); - FcMatcher *match = FcObjectPtrToMatcher(o); + const FcMatcher *match = FcObjectToMatcher(object); if (!match) { if (bestValue) - *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2orig)->value); + *bestValue = FcValueCanonicalize(&v2orig->value); return FcTrue; } best = 1e99; bestStrong = 1e99; bestWeak = 1e99; - j = 0; - for (v1 = v1orig, v1_ptrU = FcValueListPtrU(v1); v1_ptrU; - v1 = v1_ptrU->next, v1_ptrU = FcValueListPtrU(v1)) + j = 1; + for (v1 = v1orig; v1; v1 = FcValueListNext(v1)) { - for (v2 = v2orig, v2_ptrU = FcValueListPtrU(v2); v2_ptrU; - v2 = v2_ptrU->next, v2_ptrU = FcValueListPtrU(v2)) + for (v2 = v2orig; v2; v2 = FcValueListNext(v2)) { - v = (match->compare) (&v1_ptrU->value, &v2_ptrU->value); + v = (match->compare) (&v1->value, &v2->value); if (v < 0) { *result = FcResultTypeMismatch; return FcFalse; } - v = v * 100 + j; + v = v * 1000 + j; if (v < best) { if (bestValue) - *bestValue = FcValueCanonicalize(&v2_ptrU->value); + *bestValue = FcValueCanonicalize(&v2->value); best = v; } - if (v1_ptrU->binding == FcValueBindingStrong) + if (v1->binding == FcValueBindingStrong) { if (v < bestStrong) bestStrong = v; @@ -393,7 +322,7 @@ FcCompareValueList (FcObjectPtr o, } if (FcDebug () & FC_DBG_MATCHV) { - printf (" %s: %g ", object, best); + printf (" %s: %g ", FcObjectName (object), best); FcValueListPrint (v1orig); printf (", "); FcValueListPrint (v2orig); @@ -426,18 +355,18 @@ FcCompare (FcPattern *pat, FcResult *result) { int i, i1, i2; - + for (i = 0; i < NUM_MATCH_VALUES; i++) value[i] = 0.0; - + i1 = 0; i2 = 0; while (i1 < pat->num && i2 < fnt->num) { - FcPatternElt *elt_i1 = FcPatternEltU(pat->elts)+i1; - FcPatternElt *elt_i2 = FcPatternEltU(fnt->elts)+i2; + FcPatternElt *elt_i1 = &FcPatternElts(pat)[i1]; + FcPatternElt *elt_i2 = &FcPatternElts(fnt)[i2]; - i = FcObjectPtrCompare(elt_i1->object, elt_i2->object); + i = FcObjectCompare(elt_i1->object, elt_i2->object); if (i > 0) i2++; else if (i < 0) @@ -445,7 +374,8 @@ FcCompare (FcPattern *pat, else { if (!FcCompareValueList (elt_i1->object, - elt_i1->values, elt_i2->values, + FcPatternEltValues(elt_i1), + FcPatternEltValues(elt_i2), 0, value, result)) return FcFalse; i1++; @@ -465,278 +395,110 @@ FcFontRenderPrepare (FcConfig *config, FcPatternElt *fe, *pe; FcValue v; FcResult result; - + + assert (pat != NULL); + assert (font != NULL); + new = FcPatternCreate (); if (!new) 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 (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); + } } - if (FcPatternFindElt (font, FC_FILE)) - FcPatternTransferFullFname (new, font); - FcConfigSubstituteWithPat (config, new, pat, FcMatchFont); return new; } -FcPattern * -FcFontSetMatch (FcConfig *config, - FcFontSet **sets, - int nsets, - FcPattern *p, - FcResult *result) +static FcPattern * +FcFontSetMatchInternal (FcConfig *config, + FcFontSet **sets, + int nsets, + FcPattern *p, + FcResult *result) { - double score; - double bestscore; + double score[NUM_MATCH_VALUES], bestscore[NUM_MATCH_VALUES]; int f; FcFontSet *s; FcPattern *best; - int scoring_index; - int *sets_offset; + int i; int set; - int nfonts; - int fonts_left; - FcMatcher *matcher; - FcMatcher *strong_matchers[NUM_MATCH_VALUES]; - FcMatcher *weak_matchers[NUM_MATCH_VALUES]; - FcPatternElt *pat_elts[NUM_MATCH_VALUES]; - int pat_elt; - int *match_blocked; - int block_start; - - if (!nsets || !sets || !p) - { - *result = FcResultNoMatch; - return 0; - } + for (i = 0; i < NUM_MATCH_VALUES; i++) + bestscore[i] = 0; + best = 0; if (FcDebug () & FC_DBG_MATCH) { printf ("Match "); FcPatternPrint (p); } - if (!config) - { - config = FcConfigGetCurrent (); - if (!config) - { - *result = FcResultOutOfMemory; - return 0; - } - } - - sets_offset = (int *)calloc(nsets, sizeof (int)); - - nfonts = 0; - for (set = 0; set < nsets; ++set) - { - sets_offset[set] = nfonts; - if (sets[set]) - nfonts += sets[set]->nfont; - } - - fonts_left = nfonts; - - match_blocked = (int*)calloc(nfonts, sizeof(int)); - - /* Find out all necessary matchers first, so we don't need to find them - * in every loop. - */ - - memset(strong_matchers, 0, sizeof (FcMatcher*) * NUM_MATCH_VALUES); - memset(weak_matchers, 0, sizeof (FcMatcher*) * NUM_MATCH_VALUES); - memset(pat_elts, 0, sizeof (FcPatternElt*) * NUM_MATCH_VALUES); - - for (pat_elt = 0; pat_elt < p->num; ++pat_elt) - { - matcher = FcObjectPtrToMatcher - ((FcPatternEltU(p->elts)+pat_elt)->object); - if (matcher) - { - strong_matchers[matcher->strong] = matcher; - weak_matchers[matcher->weak] = matcher; - pat_elts [matcher->strong] = pat_elts [matcher->weak] = - (FcPatternEltU(p->elts)+pat_elt); - } - } - - /* The old algorithm checked if each font beat 'best', - * scanning all of the value lists for all of the pattern elts. */ - /* This algorithm checks each font on a element-by-element basis - * and blocks fonts that have already lost on some element from - * further consideration from being best. Basically, we've - * swapped the order of loops and short-circuited fonts that - * are out of contention right away. - * This saves a lot of time! */ - best = 0; - block_start = 0; - for (scoring_index = 0; scoring_index < NUM_MATCH_VALUES; ++scoring_index) + for (set = 0; set < nsets; set++) { - FcValueListPtr v1; - FcValueList *v1_ptrU; - int v1_offset = 0; - - if (!strong_matchers [scoring_index] && !weak_matchers [scoring_index]) + s = sets[set]; + if (!s) continue; - - for (v1 = pat_elts[scoring_index]->values, v1_ptrU = FcValueListPtrU(v1); - v1_ptrU; - v1 = v1_ptrU->next, v1_ptrU = FcValueListPtrU(v1), ++v1_offset) + for (f = 0; f < s->nfont; f++) { - matcher = (v1_ptrU->binding == FcValueBindingWeak) ? - weak_matchers[scoring_index] : strong_matchers[scoring_index]; - - if (!matcher) continue; - - bestscore = 1e99; - if (FcDebug () & FC_DBG_MATCHV) { - printf("Scoring Index %d, Value %d: %d(%d) fonts left\n", - scoring_index, v1_offset, fonts_left, nfonts); + printf ("Font %d ", f); + FcPatternPrint (s->fonts[f]); } - - for (set = 0; set < nsets; ++set) + if (!FcCompare (p, s->fonts[f], score, result)) + return 0; + if (FcDebug () & FC_DBG_MATCHV) { - s = sets[set]; - if (!s) continue; - - /* All fonts before block_start should have been knocked out. */ - for (f = (block_start > sets_offset[set]) ? (block_start - sets_offset[set]) : 0; - f < s->nfont; ++f) + printf ("Score"); + for (i = 0; i < NUM_MATCH_VALUES; i++) { - int cand_elt; - FcPatternElt *cand_elts; - - if (match_blocked[f + sets_offset[set]] == 1) - continue; - - score = 1e99; - cand_elts = FcPatternEltU(s->fonts[f]->elts); - - /* Look for the appropriate element in this candidate - * pattern 'f' and evaluate its score wrt 'p'. */ - for (cand_elt = 0; cand_elt < s->fonts[f]->num; ++cand_elt) - { - if (cand_elts[cand_elt].object == pat_elts[scoring_index]->object) - { - FcValueListPtr v2; - FcValueList *v2_ptrU; - - for (v2 = cand_elts[cand_elt].values, v2_ptrU = FcValueListPtrU(v2); - v2_ptrU; - v2 = v2_ptrU->next, v2_ptrU = FcValueListPtrU(v2)) - { - double v = (matcher->compare)(&v1_ptrU->value, &v2_ptrU->value); - - if (v < 0) - { - *result = FcResultTypeMismatch; - free (match_blocked); - free (sets_offset); - return 0; - } - - /* I'm actually kind of surprised that - * this isn't v + 100 * v1_offset. -PL */ - v = v * 100 + v1_offset; - /* The old patch said score += v, which - * seems to be wrong when you have - * multiple matchers. This takes the - * best score it can find for that font. */ - if (v < score) - score = v; - } - } - } - - /* We had no matching, just try the next one */ - if (score == 1e99) - { - match_blocked[f + sets_offset[set]] = 2; - continue; - } - match_blocked[f + sets_offset[set]] = 0; - /* If there's a previous champion, and current score - * beats previous best score, on this element, then - * knock out the previous champion and anything - * else that we would have visited previous to f; - * clearly anything previous to f would have been - * less than f on this score. */ - if (!best || score < bestscore) - { - if (best) - { - int b; - for (b = block_start; b < f + sets_offset[set]; ++b) - if (!match_blocked[b]) - { - match_blocked[b] = 1; - --fonts_left; - } - } - - bestscore = score; - best = s->fonts[f]; - /* This kills too many fonts, unfortunately. */ - /* block_start = f + sets_offset[set]; */ - } - - /* If f loses, then it's out too. */ - if (best && score > bestscore) - { - match_blocked[f + sets_offset[set]] = 1; - --fonts_left; - } - - /* If there is only 1 font left and the best is set, - * then just return this font - */ - if (fonts_left == 1 && best) - goto end; - - /* Otherwise, f is equal to best on this element. - * Carry on to next pattern element. */ + printf (" %g", score[i]); } + printf ("\n"); } - if ((FcDebug () & FC_DBG_MATCHV) && best) + for (i = 0; i < NUM_MATCH_VALUES; i++) { - printf ("Best match (scoring index %d) candidate %d ", scoring_index, block_start); - FcPatternPrint (best); + if (best && bestscore[i] < score[i]) + break; + if (!best || score[i] < bestscore[i]) + { + for (i = 0; i < NUM_MATCH_VALUES; i++) + bestscore[i] = score[i]; + best = s->fonts[f]; + break; + } } } } - -end: - free (match_blocked); - free (sets_offset); - - if ((FcDebug () & FC_DBG_MATCH) && best) + if (FcDebug () & FC_DBG_MATCH) { - printf ("Best match (scoring index %d) %d ", scoring_index, block_start); + printf ("Best score"); + for (i = 0; i < NUM_MATCH_VALUES; i++) + printf (" %g", bestscore[i]); + printf ("\n"); FcPatternPrint (best); } if (!best) @@ -744,16 +506,46 @@ end: *result = FcResultNoMatch; return 0; } - return FcFontRenderPrepare (config, p, best); + return best; +} + +FcPattern * +FcFontSetMatch (FcConfig *config, + FcFontSet **sets, + int nsets, + FcPattern *p, + FcResult *result) +{ + FcPattern *best; + + assert (sets != NULL); + assert (p != NULL); + assert (result != NULL); + + if (!config) + { + config = FcConfigGetCurrent (); + if (!config) + return 0; + } + best = FcFontSetMatchInternal (config, sets, nsets, p, result); + if (best) + return FcFontRenderPrepare (config, p, best); + else + return NULL; } FcPattern * FcFontMatch (FcConfig *config, - FcPattern *p, + FcPattern *p, FcResult *result) { FcFontSet *sets[2]; int nsets; + FcPattern *best; + + assert (p != NULL); + assert (result != NULL); if (!config) { @@ -766,7 +558,12 @@ FcFontMatch (FcConfig *config, sets[nsets++] = config->fonts[FcSetSystem]; if (config->fonts[FcSetApplication]) sets[nsets++] = config->fonts[FcSetApplication]; - return FcFontSetMatch (config, sets, nsets, p, result); + + best = FcFontSetMatchInternal (config, sets, nsets, p, result); + if (best) + return FcFontRenderPrepare (config, p, best); + else + return NULL; } typedef struct _FcSortNode { @@ -791,52 +588,71 @@ FcSortCompare (const void *aa, const void *ab) } static FcBool -FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool trim, FcBool build_cs) +FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **csp, FcBool trim) { - FcCharSet *ncs; - FcSortNode *node; + FcBool ret = FcFalse; + FcCharSet *cs; + + cs = 0; + if (trim || csp) + { + cs = FcCharSetCreate (); + if (cs == NULL) + goto bail; + } while (nnode--) { - node = *n++; - if (FcPatternGetCharSet (node->pattern, FC_CHARSET, 0, &ncs) == - FcResultMatch) + FcSortNode *node = *n++; + FcBool adds_chars = FcFalse; + + /* + * Only fetch node charset if we'd need it + */ + if (cs) + { + FcCharSet *ncs; + + if (FcPatternGetCharSet (node->pattern, FC_CHARSET, 0, &ncs) != + FcResultMatch) + continue; + + if (!FcCharSetMerge (cs, ncs, &adds_chars)) + goto bail; + } + + /* + * If this font isn't a subset of the previous fonts, + * add it to the list + */ + if (!trim || adds_chars) { - /* - * If this font isn't a subset of the previous fonts, - * add it to the list - */ - if (!trim || !*cs || !FcCharSetIsSubset (ncs, *cs)) + FcPatternReference (node->pattern); + if (FcDebug () & FC_DBG_MATCHV) { - 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) - { - printf ("Add "); - FcPatternPrint (node->pattern); - } - if (!FcFontSetAdd (fs, node->pattern)) - { - FcPatternDestroy (node->pattern); - return FcFalse; - } + printf ("Add "); + FcPatternPrint (node->pattern); + } + if (!FcFontSetAdd (fs, node->pattern)) + { + FcPatternDestroy (node->pattern); + goto bail; } } } - return FcTrue; + if (csp) + { + *csp = cs; + cs = 0; + } + + ret = FcTrue; + +bail: + if (cs) + FcCharSetDestroy (cs); + + return ret; } void @@ -860,7 +676,6 @@ FcFontSetSort (FcConfig *config, FcSortNode **nodeps, **nodep; int nnodes; FcSortNode *new; - FcCharSet *cs; int set; int f; int i; @@ -868,6 +683,19 @@ FcFontSetSort (FcConfig *config, FcBool *patternLangSat; FcValue patternLang; + assert (sets != NULL); + assert (p != NULL); + assert (result != NULL); + + /* There are some implementation that relying on the result of + * "result" to check if the return value of FcFontSetSort + * is valid or not. + * So we should initialize it to the conservative way since + * this function doesn't return NULL anymore. + */ + if (result) + *result = FcResultNoMatch; + if (FcDebug () & FC_DBG_MATCH) { printf ("Sort "); @@ -882,22 +710,22 @@ FcFontSetSort (FcConfig *config, nnodes += s->nfont; } if (!nnodes) - goto bail0; - + return FcFontSetCreate (); + for (nPatternLang = 0; FcPatternGet (p, FC_LANG, nPatternLang, &patternLang) == FcResultMatch; nPatternLang++) ; /* freed below */ - nodes = malloc (nnodes * sizeof (FcSortNode) + + nodes = malloc (nnodes * sizeof (FcSortNode) + nnodes * sizeof (FcSortNode *) + nPatternLang * sizeof (FcBool)); if (!nodes) goto bail0; nodeps = (FcSortNode **) (nodes + nnodes); patternLangSat = (FcBool *) (nodeps + nnodes); - + new = nodes; nodep = nodeps; for (set = 0; set < nsets; set++) @@ -931,13 +759,13 @@ FcFontSetSort (FcConfig *config, } nnodes = new - nodes; - + qsort (nodeps, nnodes, sizeof (FcSortNode *), FcSortCompare); - + for (i = 0; i < nPatternLang; i++) patternLangSat[i] = FcFalse; - + for (f = 0; f < nnodes; f++) { FcBool satisfies = FcFalse; @@ -945,7 +773,7 @@ FcFontSetSort (FcConfig *config, * If this node matches any language, go check * which ones and satisfy those entries */ - if (nodeps[f]->score[MATCH_LANG_INDEX] < nPatternLang) + if (nodeps[f]->score[MATCH_LANG_INDEX] < 2000) { for (i = 0; i < nPatternLang; i++) { @@ -975,7 +803,7 @@ FcFontSetSort (FcConfig *config, } } if (!satisfies) - nodeps[f]->score[MATCH_LANG_INDEX] = 1000.0; + nodeps[f]->score[MATCH_LANG_INDEX] = 10000.0; } /* @@ -988,26 +816,19 @@ FcFontSetSort (FcConfig *config, if (!ret) goto bail1; - cs = 0; - - if (!FcSortWalk (nodeps, nnodes, ret, &cs, trim, (csp!=0))) + if (!FcSortWalk (nodeps, nnodes, ret, csp, trim)) goto bail2; - if (csp) - *csp = cs; - else - { - if (cs) - FcCharSetDestroy (cs); - } - free (nodes); + if (FcDebug() & FC_DBG_MATCH) + { + printf ("First font "); + FcPatternPrint (ret->fonts[0]); + } return ret; bail2: - if (cs) - FcCharSetDestroy (cs); FcFontSetDestroy (ret); bail1: free (nodes); @@ -1017,7 +838,7 @@ bail0: FcFontSet * FcFontSort (FcConfig *config, - FcPattern *p, + FcPattern *p, FcBool trim, FcCharSet **csp, FcResult *result) @@ -1025,6 +846,9 @@ FcFontSort (FcConfig *config, FcFontSet *sets[2]; int nsets; + assert (p != NULL); + assert (result != NULL); + if (!config) { config = FcConfigGetCurrent (); @@ -1038,3 +862,6 @@ FcFontSort (FcConfig *config, sets[nsets++] = config->fonts[FcSetApplication]; return FcFontSetSort (config, sets, nsets, p, trim, csp, result); } +#define __fcmatch__ +#include "fcaliastail.h" +#undef __fcmatch__