From c7891755cbf1fefc20fc15651373995b1e7ca06f Mon Sep 17 00:00:00 2001 From: Akira TAGOH Date: Tue, 24 Aug 2021 19:05:00 +0900 Subject: [PATCH] Reflect matching results to binding in FcPattern This change allows applications to see what property was matched perfectly and help to filter out for their needs. Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/294 --- src/fcmatch.c | 102 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 21 deletions(-) diff --git a/src/fcmatch.c b/src/fcmatch.c index fd43cbd..80d5687 100644 --- a/src/fcmatch.c +++ b/src/fcmatch.c @@ -583,6 +583,14 @@ FcCompareFamilies (FcPattern *pat, weak_value = e->weak_value; } } + if (FcDebug () & FC_DBG_MATCHV) + { + printf ("%s: %g ", FcObjectName (FC_FAMILY_OBJECT), strong_value); + FcValueListPrint (v1orig); + printf (", "); + FcValueListPrint (v2orig); + printf ("\n"); + } value[PRI_FAMILY_STRONG] = strong_value; value[PRI_FAMILY_WEAK] = weak_value; @@ -714,27 +722,29 @@ FcFontRenderPrepare (FcConfig *config, l1 != NULL || l2 != NULL; j++, l1 = l1 ? FcValueListNext (l1) : NULL, l2 = l2 ? FcValueListNext (l2) : NULL) { + FcValueListPtr (* func) (FcValueListPtr, FcValue, FcValueBinding); + FcValueBinding binding = FcValueBindingEnd; + if (j == n) { - if (l1) - ln = FcValueListPrepend (ln, - FcValueCanonicalize (&l1->value), - FcValueBindingStrong); - if (l2) - ll = FcValueListPrepend (ll, - FcValueCanonicalize (&l2->value), - FcValueBindingStrong); + binding = FcValueBindingStrong; + func = FcValueListPrepend; } else + func = FcValueListAppend; + if (l1) { - if (l1) - ln = FcValueListAppend (ln, - FcValueCanonicalize (&l1->value), - FcValueBindingStrong); - if (l2) - ll = FcValueListAppend (ll, - FcValueCanonicalize (&l2->value), - FcValueBindingStrong); + ln = func (ln, + FcValueCanonicalize (&l1->value), + l1->binding); + } + if (l2) + { + if (binding == FcValueBindingEnd) + binding = l2->binding; + ll = func (ll, + FcValueCanonicalize (&l2->value), + binding); } } FcPatternObjectListAdd (new, fe->object, ln, FcFalse); @@ -852,10 +862,11 @@ FcFontSetMatchInternal (FcFontSet **sets, double score[PRI_END], bestscore[PRI_END]; int f; FcFontSet *s; - FcPattern *best; + FcPattern *best, *pat = NULL; int i; int set; FcCompareData data; + const FcPatternElt *elt; for (i = 0; i < PRI_END; i++) bestscore[i] = 0; @@ -911,13 +922,56 @@ FcFontSetMatchInternal (FcFontSet **sets, FcCompareDataClear (&data); + /* Update the binding according to the score to indicate how exactly values matches on. */ + if (best) + { + pat = FcPatternCreate (); + elt = FcPatternElts (best); + for (i = 0; i < FcPatternObjectCount (best); i++) + { + const FcMatcher *match = FcObjectToMatcher (elt[i].object, FcFalse); + FcValueListPtr l = FcPatternEltValues (&elt[i]); + + if (!match) + FcPatternObjectListAdd(pat, elt[i].object, + FcValueListDuplicate(l), FcTrue); + else + { + FcValueBinding binding = FcValueBindingWeak; + FcValueListPtr new = NULL, ll, t = NULL; + FcValue v; + + /* If the value was matched exactly, update the binding to Strong. */ + if (bestscore[match->strong] < 1000) + binding = FcValueBindingStrong; + + for (ll = l; ll != NULL; ll = FcValueListNext (ll)) + { + if (!new) + { + t = new = FcValueListCreate (); + } + else + { + t->next = FcValueListCreate (); + t = FcValueListNext (t); + } + v = FcValueCanonicalize (&ll->value); + t->value = FcValueSave (v); + t->binding = binding; + t->next = NULL; + } + FcPatternObjectListAdd (pat, elt[i].object, new, FcTrue); + } + } + } if (FcDebug () & FC_DBG_MATCH) { printf ("Best score"); for (i = 0; i < PRI_END; i++) printf (" %g", bestscore[i]); printf ("\n"); - FcPatternPrint (best); + FcPatternPrint (pat); } if (FcDebug () & FC_DBG_MATCH2) { @@ -958,16 +1012,16 @@ FcFontSetMatchInternal (FcFontSet **sets, } free (ss); } - FcPatternPrint2 (p, best, os); + FcPatternPrint2 (p, pat, os); if (os) FcObjectSetDestroy (os); } /* assuming that 'result' is initialized with FcResultNoMatch * outside this function */ - if (best) + if (pat) *result = FcResultMatch; - return best; + return pat; } FcPattern * @@ -990,7 +1044,10 @@ FcFontSetMatch (FcConfig *config, return NULL; best = FcFontSetMatchInternal (sets, nsets, p, result); if (best) + { ret = FcFontRenderPrepare (config, p, best); + FcPatternDestroy (best); + } FcConfigDestroy (config); @@ -1022,7 +1079,10 @@ FcFontMatch (FcConfig *config, best = FcFontSetMatchInternal (sets, nsets, p, result); if (best) + { ret = FcFontRenderPrepare (config, p, best); + FcPatternDestroy (best); + } FcConfigDestroy (config);