From da1c9f7a6ce7cb90a132ed6f251f879d3e3624a1 Mon Sep 17 00:00:00 2001 From: Akira TAGOH Date: Thu, 24 Jun 2021 14:44:39 +0900 Subject: [PATCH] Fix score evaluation for multiple values in properties Sometimes fonts has multiple values in family and sub-family in order to unify other variants into one. they basically make difference in sub-family though, they also still have standalone family and sub-family. in that case, sub-family is likely to be Regular. fontconfig couldn't recognize the difference between :family=Foo:style=Regular and :family=Foo Caption:style=Regular for example because fontconfig didn't give different score on matching result for the position of multiple values in a cache. Thus, when querying a font like :family=Foo:style=Regular may results :family=Foo Caption:style=Regular. (see the test case for more details) To fix this situation, giving different score according to the position of multiple values in a cache as well as the position of multiple values in a query. Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/283 --- src/fcmatch.c | 2 +- test/Makefile.am | 1 + test/run-test-conf.sh | 6 ++++++ test/test-conf.c | 18 +++++++++++++++++- test/test-style-match.json | 31 +++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 test/test-style-match.json diff --git a/src/fcmatch.c b/src/fcmatch.c index 53c3b0e..c88e3aa 100644 --- a/src/fcmatch.c +++ b/src/fcmatch.c @@ -433,7 +433,7 @@ FcCompareValueList (FcObject object, *result = FcResultTypeMismatch; return FcFalse; } - v = v * 1000 + j; + v = v * 1000 + j * 100 + k; if (v < best) { if (bestValue) diff --git a/test/Makefile.am b/test/Makefile.am index 2117ef0..aea8724 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -47,6 +47,7 @@ TESTDATA = \ test-45-generic.json \ test-60-generic.json \ test-90-synthetic.json \ + test-style-match.json \ $(NULL) if FREETYPE_PCF_LONG_FAMILY_NAMES diff --git a/test/run-test-conf.sh b/test/run-test-conf.sh index 6fad983..0c2bd52 100644 --- a/test/run-test-conf.sh +++ b/test/run-test-conf.sh @@ -48,3 +48,9 @@ for i in \ echo $RUNNER $TESTDIR/../conf.d/$i $TESTDIR/$test_json $RUNNER $TESTDIR/../conf.d/$i $TESTDIR/$test_json done +for i in \ + test-style-match.json \ + ; do + echo $RUNNER $TESTDIR/$i ... + $RUNNER $TESTDIR/../conf.d/10-autohint.conf $TESTDIR/$i +done diff --git a/test/test-conf.c b/test/test-conf.c index 4959f76..e4e9da4 100644 --- a/test/test-conf.c +++ b/test/test-conf.c @@ -166,6 +166,21 @@ build_pattern (json_object *obj) continue; } } + } else if (fc_o && fc_o->type == FcTypeString) { + for (i = 0; i < n; i++) + { + o = json_object_array_get_idx (iter.val, i); + type = json_object_get_type (o); + if (type != json_type_string) { + fprintf (stderr, "E: unable to convert to string\n"); + continue; + } + v.type = FcTypeString; + v.u.s = (const FcChar8 *) json_object_get_string (o); + FcPatternAdd (pat, iter.key, v, FcTrue); + v.type = FcTypeVoid; + } + continue; } else { FcLangSet* ls = FcLangSetCreate (); if (!ls) { @@ -232,7 +247,8 @@ build_pattern (json_object *obj) fprintf (stderr, "W: unexpected object to build a pattern: (%s %s)", iter.key, json_type_to_name (json_object_get_type (iter.val))); continue; } - FcPatternAdd (pat, iter.key, v, FcTrue); + if (v.type != FcTypeVoid) + FcPatternAdd (pat, iter.key, v, FcTrue); if (destroy_v) FcValueDestroy (v); } diff --git a/test/test-style-match.json b/test/test-style-match.json new file mode 100644 index 0000000..bb60d16 --- /dev/null +++ b/test/test-style-match.json @@ -0,0 +1,31 @@ +{ + "fonts": [ + { + "family": [ "Foo", "Foo Caption" ], + "style": [ "Caption", "Regular" ], + "file": "/path/to/Foo-Capt.ttf", + "fontversion": 133365 + }, + { + "family": "Foo", + "style": "Regular", + "file": "/path/to/Foo-Regular.ttf", + "fontversion": 133365 + } + ], + "tests": [ + { + "method": "match", + "query": { + "family": "Foo", + "style": "Regular" + }, + "result": { + "family": "Foo", + "style": "Regular", + "file": "/path/to/Foo-Regular.ttf", + "fontversion": 133365 + } + } + ] +}