Blame SOURCES/fontconfig-hotfix.patch

24ea22
From 93c93689f5da4ceaa675e006df63283e25b91d49 Mon Sep 17 00:00:00 2001
24ea22
From: Akira TAGOH <akira@tagoh.org>
24ea22
Date: Fri, 4 Dec 2020 18:18:03 +0900
24ea22
Subject: [PATCH 01/12] Add back fullname property at scan matching phase
24ea22
24ea22
There seems to be a lot of config files using fullname property in the world.
24ea22
To keep the backward compatibility, fullname property is back to a cache at
24ea22
the scan matching phase but will be rebuilt once it is done according to family
24ea22
and style property in the pattern no matter what changes one made in fullname
24ea22
property during that.
24ea22
24ea22
Ref. https://bugzilla.redhat.com/show_bug.cgi?id=1902881
24ea22
---
24ea22
 src/fcfreetype.c | 21 ++++++++++++++++++++-
24ea22
 src/fcopentype.c |  2 ++
24ea22
 2 files changed, 22 insertions(+), 1 deletion(-)
24ea22
24ea22
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
24ea22
index a7809cb..4b545bf 100644
24ea22
--- a/src/fcfreetype.c
24ea22
+++ b/src/fcfreetype.c
24ea22
@@ -1087,6 +1087,8 @@ static const FT_UShort nameid_order[] = {
24ea22
     TT_NAME_ID_WWS_FAMILY,
24ea22
     TT_NAME_ID_TYPOGRAPHIC_FAMILY,
24ea22
     TT_NAME_ID_FONT_FAMILY,
24ea22
+    TT_NAME_ID_MAC_FULL_NAME,
24ea22
+    TT_NAME_ID_FULL_NAME,
24ea22
     TT_NAME_ID_WWS_SUBFAMILY,
24ea22
     TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY,
24ea22
     TT_NAME_ID_FONT_SUBFAMILY,
24ea22
@@ -1222,6 +1224,8 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
24ea22
     int		    nfamily_lang = 0;
24ea22
     int		    nstyle = 0;
24ea22
     int		    nstyle_lang = 0;
24ea22
+    int		    nfullname = 0;
24ea22
+    int		    nfullname_lang = 0;
24ea22
     unsigned int    p, n;
24ea22
 
24ea22
     FcChar8	    *style = 0;
24ea22
@@ -1443,7 +1447,8 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
24ea22
 		 * and treat the instance's nameid as FONT_SUBFAMILY.
24ea22
 		 * Postscript name is automatically handled by FreeType. */
24ea22
 		if (nameid == TT_NAME_ID_WWS_SUBFAMILY ||
24ea22
-		    nameid == TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY)
24ea22
+		    nameid == TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY ||
24ea22
+		    nameid == TT_NAME_ID_FULL_NAME)
24ea22
 		    continue;
24ea22
 
24ea22
 		if (nameid == TT_NAME_ID_FONT_SUBFAMILY)
24ea22
@@ -1474,6 +1479,20 @@ FcFreeTypeQueryFaceInternal (const FT_Face  face,
24ea22
 		    np = &nfamily;
24ea22
 		    nlangp = &nfamily_lang;
24ea22
 		    break;
24ea22
+		case TT_NAME_ID_MAC_FULL_NAME:
24ea22
+		case TT_NAME_ID_FULL_NAME:
24ea22
+		    if (variable)
24ea22
+			break;
24ea22
+		    if (FcDebug () & FC_DBG_SCANV)
24ea22
+			printf ("found full   (n %2d p %d e %d l 0x%04x)",
24ea22
+				sname.name_id, sname.platform_id,
24ea22
+				sname.encoding_id, sname.language_id);
24ea22
+
24ea22
+		    obj = FC_FULLNAME_OBJECT;
24ea22
+		    objlang = FC_FULLNAMELANG_OBJECT;
24ea22
+		    np = &nfullname;
24ea22
+		    nlangp = &nfullname_lang;
24ea22
+		    break;
24ea22
 		case TT_NAME_ID_WWS_SUBFAMILY:
24ea22
 		case TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY:
24ea22
 		case TT_NAME_ID_FONT_SUBFAMILY:
24ea22
diff --git a/src/fcopentype.c b/src/fcopentype.c
24ea22
index 9382a1b..59cce45 100644
24ea22
--- a/src/fcopentype.c
24ea22
+++ b/src/fcopentype.c
24ea22
@@ -76,12 +76,14 @@ FcPatternAddFullname (FcPattern *pat)
24ea22
 	    FcStrBufChar (&sbuf, ' ');
24ea22
 	    FcStrBufString (&sbuf, style);
24ea22
 	}
24ea22
+	FcPatternObjectDel (pat, FC_FULLNAME_OBJECT);
24ea22
 	if (!FcPatternObjectAddString (pat, FC_FULLNAME_OBJECT, FcStrBufDoneStatic (&sbuf)))
24ea22
 	{
24ea22
 	    FcStrBufDestroy (&sbuf);
24ea22
 	    return FcFalse;
24ea22
 	}
24ea22
 	FcStrBufDestroy (&sbuf);
24ea22
+	FcPatternObjectDel (pat, FC_FULLNAMELANG_OBJECT);
24ea22
 	if (!FcPatternObjectAddString (pat, FC_FULLNAMELANG_OBJECT, (const FcChar8 *) "en"))
24ea22
 	    return FcFalse;
24ea22
     }
24ea22
-- 
24ea22
2.29.2
24ea22
24ea22
From 3d6926380dc3c8597dc2fd9d34087da9b39dfdd9 Mon Sep 17 00:00:00 2001
24ea22
From: Ben Wagner <bungeman@chromium.org>
24ea22
Date: Fri, 4 Dec 2020 15:00:08 -0500
24ea22
Subject: [PATCH 02/12] Skip leading whitespace in style name.
24ea22
24ea22
Found by Clang-Tidy. The intent seems to have been to skip all leading
24ea22
whitespace in the 'style' string, but instead this loop was an odd
24ea22
looking no-op. Remove the 'break' from the loop so that it will
24ea22
continue until end of string or a non-space character is found.
24ea22
---
24ea22
 src/fcopentype.c | 3 +--
24ea22
 1 file changed, 1 insertion(+), 2 deletions(-)
24ea22
24ea22
diff --git a/src/fcopentype.c b/src/fcopentype.c
24ea22
index 59cce45..39c05e9 100644
24ea22
--- a/src/fcopentype.c
24ea22
+++ b/src/fcopentype.c
24ea22
@@ -66,8 +66,7 @@ FcPatternAddFullname (FcPattern *pat)
24ea22
 	if (FcPatternObjectGetString (pat, FC_STYLE_OBJECT, n, &style) != FcResultMatch)
24ea22
 	    return FcFalse;
24ea22
 	len = strlen ((const char *) style);
24ea22
-	for (i = 0; style[i] != 0 && isspace (style[i]); i++)
24ea22
-	    break;
24ea22
+	for (i = 0; style[i] != 0 && isspace (style[i]); i++);
24ea22
 	memcpy (style, &style[i], len - i);
24ea22
 	FcStrBufInit (&sbuf, NULL, 0);
24ea22
 	FcStrBufString (&sbuf, family);
24ea22
-- 
24ea22
2.29.2
24ea22
24ea22
From 97d541855429629f40a0accdd2b06b7dce7ba2db Mon Sep 17 00:00:00 2001
24ea22
From: Ben Wagner <bungeman@chromium.org>
24ea22
Date: Fri, 4 Dec 2020 15:42:28 -0500
24ea22
Subject: [PATCH 03/12] Remove abort from FcCompareSize.
24ea22
24ea22
There doesn't appear to be a good reason to abort when 'v1' has type
24ea22
FcTypeRange. If there does turn out to be a good reason for this then it
24ea22
should be better documented and the code for handling this case removed.
24ea22
At worst it seems -1 should be returned as it is for other unknown
24ea22
types. It is possible this is left over debug code from the initial
24ea22
implementation.
24ea22
---
24ea22
 src/fcmatch.c | 1 -
24ea22
 1 file changed, 1 deletion(-)
24ea22
24ea22
diff --git a/src/fcmatch.c b/src/fcmatch.c
24ea22
index df6db71..53c3b0e 100644
24ea22
--- a/src/fcmatch.c
24ea22
+++ b/src/fcmatch.c
24ea22
@@ -235,7 +235,6 @@ FcCompareSize (const FcValue *v1, const FcValue *v2, FcValue *bestValue)
24ea22
         b1 = e1 = value1.u.d;
24ea22
 	break;
24ea22
     case FcTypeRange:
24ea22
-	abort();
24ea22
 	b1 = value1.u.r->begin;
24ea22
 	e1 = value1.u.r->end;
24ea22
 	break;
24ea22
-- 
24ea22
2.29.2
24ea22
24ea22
From d55eaa6b3148691f32ec19c5c36dfc8818a6385f Mon Sep 17 00:00:00 2001
24ea22
From: Ben Wagner <bungeman@chromium.org>
24ea22
Date: Fri, 11 Dec 2020 11:54:43 -0500
24ea22
Subject: [PATCH 07/12] Fix leaks in fcxml.c, fc-match.c, and tests.
24ea22
24ea22
Fix leaks reported by AddressSanitizer when running 'make check'.
24ea22
---
24ea22
 fc-match/fc-match.c  | 8 +++++++-
24ea22
 src/fcxml.c          | 4 +++-
24ea22
 test/test-bz106632.c | 8 ++++++++
24ea22
 test/test-issue180.c | 4 +++-
24ea22
 4 files changed, 21 insertions(+), 3 deletions(-)
24ea22
24ea22
diff --git a/fc-match/fc-match.c b/fc-match/fc-match.c
24ea22
index 4362ec1..f31047e 100644
24ea22
--- a/fc-match/fc-match.c
24ea22
+++ b/fc-match/fc-match.c
24ea22
@@ -117,6 +117,7 @@ main (int argc, char **argv)
24ea22
     int			brief = 0;
24ea22
     int			sort = 0, all = 0;
24ea22
     const FcChar8	*format = NULL;
24ea22
+    const FcChar8	*format_optarg = NULL;
24ea22
     int			i;
24ea22
     FcObjectSet		*os = 0;
24ea22
     FcFontSet		*fs;
24ea22
@@ -146,7 +147,7 @@ main (int argc, char **argv)
24ea22
 	    brief = 1;
24ea22
 	    break;
24ea22
 	case 'f':
24ea22
-	    format = (FcChar8 *) strdup (optarg);
24ea22
+	    format = format_optarg = (FcChar8 *) strdup (optarg);
24ea22
 	    break;
24ea22
 	case 'V':
24ea22
 	    fprintf (stderr, "fontconfig version %d.%d.%d\n", 
24ea22
@@ -269,5 +270,10 @@ main (int argc, char **argv)
24ea22
 
24ea22
     FcFini ();
24ea22
 
24ea22
+    if (format_optarg) {
24ea22
+	free ((void*)format_optarg);
24ea22
+	format_optarg = NULL;
24ea22
+    }
24ea22
+
24ea22
     return 0;
24ea22
 }
24ea22
diff --git a/src/fcxml.c b/src/fcxml.c
24ea22
index 3f22581..9efe157 100644
24ea22
--- a/src/fcxml.c
24ea22
+++ b/src/fcxml.c
24ea22
@@ -2307,7 +2307,9 @@ FcParseCacheDir (FcConfigParse *parse)
24ea22
     if (data[0] == 0)
24ea22
     {
24ea22
 	FcConfigMessage (parse, FcSevereWarning, "empty cache directory name ignored");
24ea22
-	return;
24ea22
+	FcStrFree (data);
24ea22
+	data = prefix;
24ea22
+	goto bail;
24ea22
     }
24ea22
     if (prefix)
24ea22
     {
24ea22
diff --git a/test/test-bz106632.c b/test/test-bz106632.c
24ea22
index 0f37b9c..c610d73 100644
24ea22
--- a/test/test-bz106632.c
24ea22
+++ b/test/test-bz106632.c
24ea22
@@ -221,6 +221,7 @@ main (void)
24ea22
 	ret = 1;
24ea22
 	goto bail;
24ea22
     }
24ea22
+    FcFontSetDestroy (fs);
24ea22
     fprintf (stderr, "D: Removing %s\n", fontdir);
24ea22
     snprintf (cmd, 512, "sleep 1; rm -f %s%s*; sleep 1", fontdir, FC_DIR_SEPARATOR_S);
24ea22
     (void) system (cmd);
24ea22
@@ -243,6 +244,8 @@ main (void)
24ea22
 	ret = 3;
24ea22
 	goto bail;
24ea22
     }
24ea22
+    FcConfigDestroy (config);
24ea22
+
24ea22
     config = FcConfigCreate ();
24ea22
     if (!FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) conf, FcTrue))
24ea22
     {
24ea22
@@ -266,6 +269,7 @@ main (void)
24ea22
 	ret = 1;
24ea22
 	goto bail;
24ea22
     }
24ea22
+    FcFontSetDestroy (fs);
24ea22
     fprintf (stderr, "D: Copying %s to %s\n", FONTFILE, fontdir);
24ea22
     snprintf (cmd, 512, "sleep 1; cp -a %s %s; sleep 1", FONTFILE, fontdir);
24ea22
     (void) system (cmd);
24ea22
@@ -288,6 +292,8 @@ main (void)
24ea22
 	ret = 3;
24ea22
 	goto bail;
24ea22
     }
24ea22
+    FcConfigDestroy (config);
24ea22
+
24ea22
     config = FcConfigCreate ();
24ea22
     if (!FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) conf, FcTrue))
24ea22
     {
24ea22
@@ -311,6 +317,8 @@ main (void)
24ea22
 	ret = 1;
24ea22
 	goto bail;
24ea22
     }
24ea22
+    FcFontSetDestroy (fs);
24ea22
+    FcConfigDestroy (config);
24ea22
 
24ea22
 bail:
24ea22
     fprintf (stderr, "Cleaning up\n");
24ea22
diff --git a/test/test-issue180.c b/test/test-issue180.c
24ea22
index 2832d3b..9d0795e 100644
24ea22
--- a/test/test-issue180.c
24ea22
+++ b/test/test-issue180.c
24ea22
@@ -53,7 +53,9 @@ main (void)
24ea22
 	fprintf (stderr, "There was one or more cachedirs\n");
24ea22
 	return 1;
24ea22
     }
24ea22
+    FcStrListDone (l);
24ea22
     FcConfigDestroy (cfg);
24ea22
+
24ea22
     cfg = FcConfigCreate ();
24ea22
     if (!FcConfigParseAndLoadFromMemory (cfg, doc2, FcTrue))
24ea22
     {
24ea22
@@ -66,7 +68,7 @@ main (void)
24ea22
 	fprintf (stderr, "There was one or more cachedirs (with prefix)\n");
24ea22
 	return 1;
24ea22
     }
24ea22
-
24ea22
+    FcStrListDone (l);
24ea22
     FcConfigDestroy (cfg);
24ea22
 
24ea22
     return 0;
24ea22
-- 
24ea22
2.29.2
24ea22
24ea22
From 5cd11d19dfb2d901e1f6b690ae504d3bf5f5ff69 Mon Sep 17 00:00:00 2001
24ea22
From: Ben Wagner <bungeman@chromium.org>
24ea22
Date: Thu, 10 Dec 2020 14:12:05 -0500
24ea22
Subject: [PATCH 08/12] Fix wild frees and leak of fs in test-conf.
24ea22
24ea22
Reported by AddressSanitizer when running test-conf. The `query`,
24ea22
`result`, and `result_fs` were not initialized to NULL so could result
24ea22
in a wild free when first initialized.
24ea22
24ea22
The `method` was also not initialized to NULL so comparisons could be
24ea22
made against random data if it had not yet been assigned.
24ea22
24ea22
The outer `fs` was never destroyed, but is also not used, so remove.
24ea22
---
24ea22
 test/test-conf.c | 9 ++++-----
24ea22
 1 file changed, 4 insertions(+), 5 deletions(-)
24ea22
24ea22
diff --git a/test/test-conf.c b/test/test-conf.c
24ea22
index d4de21a..6097983 100644
24ea22
--- a/test/test-conf.c
24ea22
+++ b/test/test-conf.c
24ea22
@@ -158,7 +158,6 @@ static FcBool
24ea22
 run_test (FcConfig *config, json_object *root)
24ea22
 {
24ea22
     json_object *tests;
24ea22
-    FcFontSet *fs;
24ea22
     int i, n, fail = 0;
24ea22
 
24ea22
     if (!json_object_object_get_ex (root, "tests", &tests) ||
24ea22
@@ -167,15 +166,15 @@ run_test (FcConfig *config, json_object *root)
24ea22
 	fprintf (stderr, "W: No test cases defined\n");
24ea22
 	return FcFalse;
24ea22
     }
24ea22
-    fs = FcFontSetCreate ();
24ea22
     n = json_object_array_length (tests);
24ea22
     for (i = 0; i < n; i++)
24ea22
     {
24ea22
 	json_object *obj = json_object_array_get_idx (tests, i);
24ea22
 	json_object_iter iter;
24ea22
-	FcPattern *query, *result;
24ea22
-	FcFontSet *result_fs;
24ea22
-	const char *method;
24ea22
+	FcPattern *query = NULL;
24ea22
+	FcPattern *result = NULL;
24ea22
+	FcFontSet *result_fs = NULL;
24ea22
+	const char *method = NULL;
24ea22
 
24ea22
 	if (json_object_get_type (obj) != json_type_object)
24ea22
 	    continue;
24ea22
-- 
24ea22
2.29.2
24ea22
24ea22
From b35c72dbc7da5b61a84766cfa431c95c1d1b35bd Mon Sep 17 00:00:00 2001
24ea22
From: Ben Wagner <bungeman@chromium.org>
24ea22
Date: Tue, 15 Dec 2020 17:39:05 -0500
24ea22
Subject: [PATCH 09/12] Always run-test-conf, but skip if not built.
24ea22
24ea22
The test-conf test requires libjson-c to be available in order to be
24ea22
built. However, there has been no user indication that additional tests
24ea22
could be built if the json-c development files were available.
24ea22
24ea22
Continue to not build test-conf if json-c is not available, but do run
24ea22
the test harness. The test harness is updated to SKIP the test if the
24ea22
test-conf binary is unavailable.
24ea22
---
24ea22
 test/Makefile.am      | 2 +-
24ea22
 test/run-test-conf.sh | 6 ++++++
24ea22
 2 files changed, 7 insertions(+), 1 deletion(-)
24ea22
24ea22
diff --git a/test/Makefile.am b/test/Makefile.am
24ea22
index 5a998b3..1a9b293 100644
24ea22
--- a/test/Makefile.am
24ea22
+++ b/test/Makefile.am
24ea22
@@ -101,8 +101,8 @@ if ENABLE_JSONC
24ea22
 check_PROGRAMS += test-conf
24ea22
 test_conf_CFLAGS = $(JSONC_CFLAGS)
24ea22
 test_conf_LDADD = $(top_builddir)/src/libfontconfig.la $(JSONC_LIBS)
24ea22
-TESTS += run-test-conf.sh
24ea22
 endif
24ea22
+TESTS += run-test-conf.sh
24ea22
 
24ea22
 check_PROGRAMS += test-bz106618
24ea22
 test_bz106618_LDADD = $(top_builddir)/src/libfontconfig.la
24ea22
diff --git a/test/run-test-conf.sh b/test/run-test-conf.sh
24ea22
index 437bafa..e085e82 100644
24ea22
--- a/test/run-test-conf.sh
24ea22
+++ b/test/run-test-conf.sh
24ea22
@@ -33,6 +33,12 @@ BUILDTESTDIR=${builddir-"$MyPWD"}
24ea22
 
24ea22
 RUNNER=../test/test-conf$EXEEXT
24ea22
 
24ea22
+if [ ! -f ${RUNNER} ]; then
24ea22
+    echo "${RUNNER} not found!\n"
24ea22
+    echo "Building this test requires libjson-c development files to be available."
24ea22
+    exit 77 # SKIP
24ea22
+fi
24ea22
+
24ea22
 for i in \
24ea22
 	60-generic.conf \
24ea22
 	90-synthetic.conf \
24ea22
-- 
24ea22
2.29.2
24ea22
24ea22
From 921ede9f460fb661146182809557a1da2dd7afd7 Mon Sep 17 00:00:00 2001
24ea22
From: Ben Wagner <bungeman@chromium.org>
24ea22
Date: Tue, 15 Dec 2020 16:30:14 -0500
24ea22
Subject: [PATCH 10/12] Fix test-conf string to integer conversion.
24ea22
24ea22
The test-conf build_pattern attempted to convert known constant strings
24ea22
into integer values. However, it did so by always converting the string
24ea22
value to an integer if possible and then complaining if the key wasn't
24ea22
of the expected type. This lead to error messages on "style": "Regular"
24ea22
since "Regular" was recognized as "weight".
24ea22
24ea22
Instead, only attempt conversion from string to integer if the key is
24ea22
the name of an object which can take an integer type. This eliminates
24ea22
the spurious non-fatal errors reported when parsing
24ea22
test-90-synthetic.json.
24ea22
24ea22
This also fixes an issue where the created value was given the type of
24ea22
the object found, but the integer field was assigned. Instead, check
24ea22
that the object type can take an integer and always set the value type
24ea22
to integer.
24ea22
---
24ea22
 test/test-conf.c | 25 ++++++++++++++-----------
24ea22
 1 file changed, 14 insertions(+), 11 deletions(-)
24ea22
24ea22
diff --git a/test/test-conf.c b/test/test-conf.c
24ea22
index 6097983..288bb5b 100644
24ea22
--- a/test/test-conf.c
24ea22
+++ b/test/test-conf.c
24ea22
@@ -69,22 +69,25 @@ build_pattern (json_object *obj)
24ea22
 	}
24ea22
 	else if (json_object_get_type (iter.val) == json_type_string)
24ea22
 	{
24ea22
-		const FcConstant *c = FcNameGetConstant ((const FcChar8 *) json_object_get_string (iter.val));
24ea22
-	    FcBool b;
24ea22
-
24ea22
-	    if (c)
24ea22
+	    const FcObjectType *o = FcNameGetObjectType (iter.key);
24ea22
+	    if (o && (o->type == FcTypeRange || o->type == FcTypeDouble || o->type == FcTypeInteger))
24ea22
 	    {
24ea22
-		const FcObjectType *o;
24ea22
-
24ea22
+		const FcConstant *c = FcNameGetConstant ((const FcChar8 *) json_object_get_string (iter.val));
24ea22
+		if (!c) {
24ea22
+		    fprintf (stderr, "E: value is not a known constant\n");
24ea22
+		    fprintf (stderr, "   key: %s\n", iter.key);
24ea22
+		    fprintf (stderr, "   val: %s\n", json_object_get_string (iter.val));
24ea22
+		    continue;
24ea22
+		}
24ea22
 		if (strcmp (c->object, iter.key) != 0)
24ea22
 		{
24ea22
-		    fprintf (stderr, "E: invalid object type for const\n");
24ea22
-		    fprintf (stderr, "   actual result: %s\n", iter.key);
24ea22
-		    fprintf (stderr, "   expected result: %s\n", c->object);
24ea22
+		    fprintf (stderr, "E: value is a constant of different object\n");
24ea22
+		    fprintf (stderr, "   key: %s\n", iter.key);
24ea22
+		    fprintf (stderr, "   val: %s\n", json_object_get_string (iter.val));
24ea22
+		    fprintf (stderr, "   key implied by value: %s\n", c->object);
24ea22
 		    continue;
24ea22
 		}
24ea22
-		o = FcNameGetObjectType (c->object);
24ea22
-		v.type = o->type;
24ea22
+		v.type = FcTypeInteger;
24ea22
 		v.u.i = c->value;
24ea22
 	    }
24ea22
 	    else if (strcmp (json_object_get_string (iter.val), "DontCare") == 0)
24ea22
-- 
24ea22
2.29.2
24ea22
24ea22
From df29933e1a06b7aa7af229bd7cd03c62d957f15f Mon Sep 17 00:00:00 2001
24ea22
From: Szunti <Szunti@users.noreply.github.com>
24ea22
Date: Sun, 6 Dec 2020 12:52:44 +0100
24ea22
Subject: [PATCH 11/12] Check qual and compare for family tests
24ea22
24ea22
Fixes #267. Hash table lookups assumed qual="any" compare="eq".
24ea22
Add a test too.
24ea22
---
24ea22
 src/fccfg.c                 |  16 ++-
24ea22
 test/Makefile.am            |   4 +
24ea22
 test/meson.build            |   1 +
24ea22
 test/test-family-matching.c | 228 ++++++++++++++++++++++++++++++++++++
24ea22
 4 files changed, 248 insertions(+), 1 deletion(-)
24ea22
 create mode 100644 test/test-family-matching.c
24ea22
24ea22
diff --git a/src/fccfg.c b/src/fccfg.c
24ea22
index 7b857bf..00a94e5 100644
24ea22
--- a/src/fccfg.c
24ea22
+++ b/src/fccfg.c
24ea22
@@ -1714,6 +1714,7 @@ FcConfigMatchValueList (FcPattern	*p,
24ea22
     FcExpr	    *e = t->expr;
24ea22
     FcValue	    value;
24ea22
     FcValueList	    *v;
24ea22
+    FcOp            op;
24ea22
 
24ea22
     while (e)
24ea22
     {
24ea22
@@ -1731,10 +1732,23 @@ FcConfigMatchValueList (FcPattern	*p,
24ea22
 
24ea22
         if (t->object == FC_FAMILY_OBJECT && table)
24ea22
         {
24ea22
-            if (!FamilyTableLookup (table, t->op, FcValueString (&value)))
24ea22
+            op = FC_OP_GET_OP (t->op);
24ea22
+            if (op == FcOpEqual || op == FcOpListing)
24ea22
             {
24ea22
+                if (!FamilyTableLookup (table, t->op, FcValueString (&value)))
24ea22
+                {
24ea22
                     ret = 0;
24ea22
                     goto done;
24ea22
+                }
24ea22
+            }
24ea22
+            if (op == FcOpNotEqual && t->qual == FcQualAll)
24ea22
+            {
24ea22
+                ret = 0;
24ea22
+                if (!FamilyTableLookup (table, t->op, FcValueString (&value)))
24ea22
+                {
24ea22
+                    ret = values;
24ea22
+                }
24ea22
+                goto done;
24ea22
             }
24ea22
         }
24ea22
 	for (v = values; v; v = FcValueListNext(v))
24ea22
diff --git a/test/Makefile.am b/test/Makefile.am
24ea22
index 1a9b293..30d8c2a 100644
24ea22
--- a/test/Makefile.am
24ea22
+++ b/test/Makefile.am
24ea22
@@ -167,6 +167,10 @@ check_PROGRAMS += test-issue180
24ea22
 test_issue180_LDADD = $(top_builddir)/src/libfontconfig.la
24ea22
 TESTS += test-issue180
24ea22
 
24ea22
+check_PROGRAMS += test-family-matching
24ea22
+test_family_matching_LDADD = $(top_builddir)/src/libfontconfig.la
24ea22
+TESTS += test-family-matching
24ea22
+
24ea22
 EXTRA_DIST=run-test.sh run-test-conf.sh $(LOG_COMPILER) $(TESTDATA) out.expected-long-family-names out.expected-no-long-family-names
24ea22
 
24ea22
 CLEANFILES =		\
24ea22
diff --git a/test/meson.build b/test/meson.build
24ea22
index 96b30a9..59de427 100644
24ea22
--- a/test/meson.build
24ea22
+++ b/test/meson.build
24ea22
@@ -6,6 +6,7 @@ tests = [
24ea22
   ['test-bz106618.c'],
24ea22
   ['test-bz1744377.c'],
24ea22
   ['test-issue180.c'],
24ea22
+  ['test-family-matching.c'],
24ea22
 ]
24ea22
 
24ea22
 if host_machine.system() != 'windows'
24ea22
diff --git a/test/test-family-matching.c b/test/test-family-matching.c
24ea22
new file mode 100644
24ea22
index 0000000..9fab36c
24ea22
--- /dev/null
24ea22
+++ b/test/test-family-matching.c
24ea22
@@ -0,0 +1,228 @@
24ea22
+/*
24ea22
+ * fontconfig/test/test-family-matching.c
24ea22
+ *
24ea22
+ * Copyright © 2020 Zoltan Vandrus
24ea22
+ *
24ea22
+ * Permission to use, copy, modify, distribute, and sell this software and its
24ea22
+ * documentation for any purpose is hereby granted without fee, provided that
24ea22
+ * the above copyright notice appear in all copies and that both that
24ea22
+ * copyright notice and this permission notice appear in supporting
24ea22
+ * documentation, and that the name of the author(s) not be used in
24ea22
+ * advertising or publicity pertaining to distribution of the software without
24ea22
+ * specific, written prior permission.  The authors make no
24ea22
+ * representations about the suitability of this software for any purpose.  It
24ea22
+ * is provided "as is" without express or implied warranty.
24ea22
+ *
24ea22
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24ea22
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
24ea22
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24ea22
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
24ea22
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
24ea22
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24ea22
+ * PERFORMANCE OF THIS SOFTWARE.
24ea22
+ */
24ea22
+#include <stdio.h>
24ea22
+#include <stdlib.h>
24ea22
+#include <fontconfig/fontconfig.h>
24ea22
+
24ea22
+#define FC_TEST_RESULT "testresult"
24ea22
+
24ea22
+typedef enum _TestMatchResult {
24ea22
+    TestMatch,
24ea22
+    TestNoMatch,
24ea22
+    TestMatchError
24ea22
+} TestMatchResult;
24ea22
+
24ea22
+typedef enum _TestResult {
24ea22
+    TestPassed,
24ea22
+    TestFailed,
24ea22
+    TestError
24ea22
+} TestResult;
24ea22
+
24ea22
+static TestMatchResult
24ea22
+TestMatchPattern (const char *test, FcPattern *p)
24ea22
+{
24ea22
+    const FcChar8 *xml_pre = (const FcChar8 *) ""
24ea22
+        "<fontconfig>\n"
24ea22
+        "  <match>\n"
24ea22
+        "";
24ea22
+
24ea22
+    const FcChar8 *xml_post = (const FcChar8 *) ""
24ea22
+        "    <edit name=\""FC_TEST_RESULT"\">\n"
24ea22
+        "      <bool>true</bool>\n"
24ea22
+        "    </edit>\n"
24ea22
+        "  </match>\n"
24ea22
+        "</fontconfig>\n"
24ea22
+        "";
24ea22
+
24ea22
+    FcChar8 *xml, *concat;
24ea22
+    FcConfig *cfg;
24ea22
+    FcResult result;
24ea22
+    FcBool dummy;
24ea22
+    TestResult ret = TestMatchError;
24ea22
+
24ea22
+    FcPattern *pat = FcPatternDuplicate (p);
24ea22
+    if (!pat)
24ea22
+    {
24ea22
+        fprintf (stderr, "Unable to duplicate pattern.\n");
24ea22
+        goto bail0;
24ea22
+    }
24ea22
+
24ea22
+    concat = FcStrPlus (xml_pre, (const FcChar8 *) test);
24ea22
+    if (!concat)
24ea22
+    {
24ea22
+        fprintf (stderr, "Concatenation failed.\n");
24ea22
+        goto bail0;
24ea22
+    }
24ea22
+
24ea22
+    xml = FcStrPlus (concat, xml_post);
24ea22
+    FcStrFree (concat);
24ea22
+    if (!xml)
24ea22
+    {
24ea22
+        fprintf (stderr, "Concatenation failed.\n");
24ea22
+        goto bail0;
24ea22
+    }
24ea22
+
24ea22
+    cfg = FcConfigCreate ();
24ea22
+    if (!cfg)
24ea22
+    {
24ea22
+        fprintf (stderr, "Unable to create a new empty config.\n");
24ea22
+        return TestMatchError;
24ea22
+    }
24ea22
+
24ea22
+    if (!FcConfigParseAndLoadFromMemory (cfg, xml, FcTrue))
24ea22
+    {
24ea22
+        fprintf (stderr, "Unable to load a config from memory.\n");
24ea22
+        goto bail1;
24ea22
+    }
24ea22
+
24ea22
+    if (!FcConfigSubstitute (cfg, pat, FcMatchPattern))
24ea22
+    {
24ea22
+        fprintf (stderr, "Unable to substitute config.\n");
24ea22
+        goto bail1;
24ea22
+    }
24ea22
+
24ea22
+    result = FcPatternGetBool (pat, FC_TEST_RESULT, 0, &dummy);
24ea22
+    switch (result) {
24ea22
+    case FcResultMatch:
24ea22
+        ret = TestMatch;
24ea22
+        break;
24ea22
+    case FcResultNoMatch:
24ea22
+        ret = TestNoMatch;
24ea22
+        break;
24ea22
+    default:
24ea22
+        fprintf (stderr, "Unable to check pattern.\n");
24ea22
+        break;
24ea22
+    }
24ea22
+
24ea22
+bail1:
24ea22
+    FcConfigDestroy (cfg);
24ea22
+bail0:
24ea22
+    FcPatternDestroy (pat);
24ea22
+    return ret;
24ea22
+}
24ea22
+
24ea22
+static TestResult
24ea22
+TestShouldMatchPattern(const char* test, FcPattern *pat, int negate)
24ea22
+{
24ea22
+    switch (TestMatchPattern (test, pat)) {
24ea22
+    case TestMatch:
24ea22
+        if (!negate) {
24ea22
+            return TestPassed;
24ea22
+        }
24ea22
+        else
24ea22
+        {
24ea22
+            printf ("Following test unexpectedly matched:\n%s", test);
24ea22
+            printf ("on\n");
24ea22
+            FcPatternPrint (pat);
24ea22
+            return TestFailed;
24ea22
+        }
24ea22
+        break;
24ea22
+    case TestNoMatch:
24ea22
+        if (!negate) {
24ea22
+            printf ("Following test should have matched:\n%s", test);
24ea22
+            printf ("on\n");
24ea22
+            FcPatternPrint (pat);
24ea22
+            return TestFailed;
24ea22
+        }
24ea22
+        else
24ea22
+        {
24ea22
+            return TestPassed;
24ea22
+        }
24ea22
+        break;
24ea22
+    case TestMatchError:
24ea22
+        return TestError;
24ea22
+        break;
24ea22
+    default:
24ea22
+        fprintf (stderr, "This shouldn't have been reached.\n");
24ea22
+        return TestError;
24ea22
+    }
24ea22
+}
24ea22
+
24ea22
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
24ea22
+
24ea22
+static TestResult
24ea22
+UpdateResult (TestResult* res, TestResult resNew)
24ea22
+{
24ea22
+    *res = MAX(*res, resNew);
24ea22
+    return *res;
24ea22
+}
24ea22
+
24ea22
+static TestResult
24ea22
+TestFamily (void)
24ea22
+{
24ea22
+    const char *test;
24ea22
+    TestResult res = TestPassed;
24ea22
+
24ea22
+    FcPattern *pat = FcPatternBuild (NULL,
24ea22
+        FC_FAMILY, FcTypeString, "family1",
24ea22
+        FC_FAMILY, FcTypeString, "family2",
24ea22
+        FC_FAMILY, FcTypeString, "family3",
24ea22
+        NULL);
24ea22
+
24ea22
+    if (!pat)
24ea22
+    {
24ea22
+        fprintf (stderr, "Unable to build pattern.\n");
24ea22
+        return TestError;
24ea22
+    }
24ea22
+
24ea22
+    #define SHOULD_MATCH(p,t) \
24ea22
+        UpdateResult (&res, TestShouldMatchPattern (t, p, 0))
24ea22
+    #define SHOULD_NOT_MATCH(p,t) \
24ea22
+        UpdateResult (&res, TestShouldMatchPattern (t, p, 1))
24ea22
+
24ea22
+    test = "<test qual=\"all\" name=\"family\" compare=\"not_eq\">\n"
24ea22
+           "    <string>foo</string>\n"
24ea22
+           "</test>\n"
24ea22
+           "";
24ea22
+    SHOULD_MATCH(pat, test);
24ea22
+
24ea22
+    test = ""
24ea22
+           "<test qual=\"all\" name=\"family\" compare=\"not_eq\">\n"
24ea22
+           "    <string>family2</string>\n"
24ea22
+           "</test>\n"
24ea22
+           "";
24ea22
+    SHOULD_NOT_MATCH(pat, test);
24ea22
+
24ea22
+    test = ""
24ea22
+           "<test qual=\"any\" name=\"family\" compare=\"eq\">\n"
24ea22
+           "    <string>family3</string>\n"
24ea22
+           "</test>\n"
24ea22
+           "";
24ea22
+    SHOULD_MATCH(pat, test);
24ea22
+
24ea22
+    test = ""
24ea22
+           "<test qual=\"any\" name=\"family\" compare=\"eq\">\n"
24ea22
+           "    <string>foo</string>\n"
24ea22
+           "</test>\n"
24ea22
+           "";
24ea22
+    SHOULD_NOT_MATCH(pat, test);
24ea22
+
24ea22
+    return res;
24ea22
+}
24ea22
+
24ea22
+int
24ea22
+main (void)
24ea22
+{
24ea22
+    return (TestFamily ());
24ea22
+}
24ea22
-- 
24ea22
2.29.2
24ea22