fontconfig: Branch 'main' - 5 commits
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon May 26 10:28:00 UTC 2025
conf.d/48-guessfamily.conf | 44 ++++
conf.d/Makefile.am | 1
conf.d/meson.build | 1
test/run-test-conf.sh | 1
test/test-48-guessfamily.json | 32 +++
test/test-conf.c | 383 ++++++++++++++++++++++++++----------------
test/test-crbug1004254.c | 8
7 files changed, 329 insertions(+), 141 deletions(-)
New commits:
commit 3d7105d635de9ffcb1ab1265a2bce0dc44ae06ce
Merge: 61e603f 605e3a2
Author: Akira TAGOH <akira at tagoh.org>
Date: Mon May 26 10:27:57 2025 +0000
Merge branch 'guess-family-conf' into 'main'
conf.d: Add a conf to guess a generic-family for substitution
Closes #457
See merge request fontconfig/fontconfig!411
commit 605e3a2ea15064759ac6fd72ee9ce92c139cb80e
Author: Akira TAGOH <akira at tagoh.org>
Date: Mon May 26 17:47:12 2025 +0900
test-crbug1004254: hold FcConfig during running a test in a thread
diff --git a/test/test-crbug1004254.c b/test/test-crbug1004254.c
index e14c2a4..be332b1 100644
--- a/test/test-crbug1004254.c
+++ b/test/test-crbug1004254.c
@@ -38,18 +38,20 @@ run_query (void)
{
FcPattern *pat = FcPatternCreate(), *match;
FcResult result;
+ FcConfig *config = FcConfigReference (FcConfigGetCurrent());
FcPatternAddString (pat, FC_FAMILY, (const FcChar8 *)"sans-serif");
FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
- FcConfigSubstitute (NULL, pat, FcMatchPattern);
- FcConfigSetDefaultSubstitute (NULL, pat);
- match = FcFontMatch (NULL, pat, &result);
+ FcConfigSubstitute (config, pat, FcMatchPattern);
+ FcConfigSetDefaultSubstitute (config, pat);
+ match = FcFontMatch (config, pat, &result);
if (result != FcResultMatch || !match) {
fprintf (stderr, "ERROR: No matches found\n");
}
if (match)
FcPatternDestroy (match);
FcPatternDestroy (pat);
+ FcConfigDestroy (config);
}
static void
commit c5a9c84eb1832e891913c049bac7760e7a561e63
Author: Akira TAGOH <akira at tagoh.org>
Date: Mon May 26 17:16:39 2025 +0900
test: add a test scenario for 48-guessfamily.conf
diff --git a/test/run-test-conf.sh b/test/run-test-conf.sh
index e87bcc5..6cbdacc 100644
--- a/test/run-test-conf.sh
+++ b/test/run-test-conf.sh
@@ -41,6 +41,7 @@ fi
for i in \
45-generic.conf \
+ 48-guessfamily.conf \
60-generic.conf \
70-no-bitmaps-and-emoji.conf \
70-no-bitmaps-except-emoji.conf \
diff --git a/test/test-48-guessfamily.json b/test/test-48-guessfamily.json
new file mode 100644
index 0000000..63b92d7
--- /dev/null
+++ b/test/test-48-guessfamily.json
@@ -0,0 +1,32 @@
+{
+ "fonts": [],
+ "tests": [
+ {
+ "method": "pattern",
+ "query": {
+ "family": "Adwaita Mono"
+ },
+ "result": {
+ "family": ["Adwaita Mono", "monospace"]
+ }
+ },
+ {
+ "method": "pattern",
+ "query": {
+ "family": "Adwaita Sans"
+ },
+ "result": {
+ "family": ["Adwaita Sans", "sans-serif"]
+ }
+ },
+ {
+ "method": "pattern",
+ "query": {
+ "family": "Foo Serif"
+ },
+ "result": {
+ "family": ["Foo Serif", "serif"]
+ }
+ }
+ ]
+}
commit 467aebd5be5f810fc6dcd8cb8867f738cc6b52c3
Author: Akira TAGOH <akira at tagoh.org>
Date: Mon May 26 17:13:36 2025 +0900
test: add a pattern test
diff --git a/test/test-conf.c b/test/test-conf.c
index 725cd7f..1b5aa22 100644
--- a/test/test-conf.c
+++ b/test/test-conf.c
@@ -373,11 +373,248 @@ build_fonts (FcConfig *config, json_object *root)
return FcTrue;
}
+static int
+process_match (FcConfig *config,
+ FcPattern *query,
+ FcPattern *result)
+{
+ int fail = 0;
+ FcPattern *match = NULL;
+ FcResult res;
+
+ if (!query) {
+ fprintf (stderr, "E: no query defined.\n");
+ fail++;
+ goto bail;
+ }
+ if (!result) {
+ fprintf (stderr, "E: no result defined.\n");
+ fail++;
+ goto bail;
+ }
+ FcConfigSubstitute (config, query, FcMatchPattern);
+ FcConfigSetDefaultSubstitute (config, query);
+ match = FcFontMatch (config, query, &res);
+ if (match) {
+ FcPatternIter iter;
+ int x, vc;
+
+ FcPatternIterStart (result, &iter);
+ do {
+ vc = FcPatternIterValueCount (result, &iter);
+ for (x = 0; x < vc; x++) {
+ FcValue vr, vm;
+
+ if (FcPatternIterGetValue (result, &iter, x, &vr, NULL) != FcResultMatch) {
+ fprintf (stderr, "E: unable to obtain a value from the expected result\n");
+ fail++;
+ goto bail;
+ }
+ if (FcPatternGet (match, FcPatternIterGetObject (result, &iter), x, &vm) != FcResultMatch) {
+ vm.type = FcTypeVoid;
+ }
+ if (!FcValueEqual (vm, vr)) {
+ printf ("E: failed to compare %s:\n", FcPatternIterGetObject (result, &iter));
+ printf (" actual result:");
+ FcValuePrint (vm);
+ printf ("\n expected result:");
+ FcValuePrint (vr);
+ printf ("\n");
+ fail++;
+ goto bail;
+ }
+ }
+ } while (FcPatternIterNext (result, &iter));
+ bail:
+ if (match)
+ FcPatternDestroy (match);
+ } else {
+ FcPatternIter iter;
+ int vc;
+
+ FcPatternIterStart (result, &iter);
+ vc = FcPatternIterValueCount (result, &iter);
+ if (vc > 0) {
+ fprintf (stderr, "E: no match\n");
+ fail++;
+ }
+ }
+
+ return fail;
+}
+
+static int
+process_fs (FcConfig *config,
+ FcFontSet *fs,
+ FcFontSet *result_fs)
+{
+ int fail = 0;
+ int j;
+
+ if (fs->nfont != result_fs->nfont) {
+ printf ("E: The number of results is different:\n");
+ printf (" actual result: %d\n", fs->nfont);
+ printf (" expected result: %d\n", result_fs->nfont);
+ fail++;
+ goto bail;
+ }
+ for (j = 0; j < fs->nfont; j++) {
+ FcPatternIter iter;
+ int x, vc;
+
+ FcPatternIterStart (result_fs->fonts[j], &iter);
+ do {
+ vc = FcPatternIterValueCount (result_fs->fonts[j], &iter);
+ for (x = 0; x < vc; x++) {
+ FcValue vr, vm;
+
+ if (FcPatternIterGetValue (result_fs->fonts[j], &iter, x, &vr, NULL) != FcResultMatch) {
+ fprintf (stderr, "E: unable to obtain a value from the expected result\n");
+ fail++;
+ goto bail;
+ }
+ if (FcPatternGet (fs->fonts[j], FcPatternIterGetObject (result_fs->fonts[j], &iter), x, &vm) != FcResultMatch) {
+ vm.type = FcTypeVoid;
+ }
+ if (!FcValueEqual (vm, vr)) {
+ printf ("E: failed to compare %s:\n", FcPatternIterGetObject (result_fs->fonts[j], &iter));
+ printf (" actual result:");
+ FcValuePrint (vm);
+ printf ("\n expected result:");
+ FcValuePrint (vr);
+ printf ("\n");
+ fail++;
+ goto bail;
+ }
+ }
+ } while (FcPatternIterNext (result_fs->fonts[j], &iter));
+ }
+ bail:
+
+ return fail;
+}
+
+static int
+process_list (FcConfig *config,
+ FcPattern *query,
+ FcFontSet *result_fs)
+{
+ FcFontSet *fs = NULL;
+ int fail = 0;
+
+ if (!query) {
+ fprintf (stderr, "E: no query defined.\n");
+ fail++;
+ goto bail;
+ }
+ if (!result_fs) {
+ fprintf (stderr, "E: no result_fs defined.\n");
+ fail++;
+ goto bail;
+ }
+ fs = FcFontList (config, query, NULL);
+ if (!fs) {
+ fprintf (stderr, "E: failed on FcFontList\n");
+ fail++;
+ } else {
+ fail += process_fs (config, fs, result_fs);
+ }
+ bail:
+ if (fs)
+ FcFontSetDestroy (fs);
+
+ return fail;
+}
+
+static int
+process_sort (FcConfig *config,
+ FcPattern *query,
+ FcFontSet *result_fs,
+ const char *method)
+{
+ int fail = 0;
+ FcFontSet *fs = NULL;
+ FcResult res;
+
+ if (!query) {
+ fprintf (stderr, "E: no query defined.\n");
+ fail++;
+ goto bail;
+ }
+ if (!result_fs) {
+ fprintf (stderr, "E: no result_fs defined.\n");
+ fail++;
+ goto bail;
+ }
+ fs = FcFontSort (config, query, method[4] == 0 ? FcTrue : FcFalse, NULL, &res);
+ if (!fs) {
+ fprintf (stderr, "E: failed on FcFontSort\n");
+ fail++;
+ } else {
+ fail += process_fs (config, fs, result_fs);
+ }
+ bail:
+ if (fs)
+ FcFontSetDestroy (fs);
+
+ return fail;
+}
+
+static int
+process_pattern (FcConfig *config,
+ FcPattern *query,
+ FcPattern *result)
+{
+ FcPatternIter iter;
+ int x, vc, fail = 0;
+
+ if (!query) {
+ fprintf (stderr, "E: no query defined.\n");
+ fail++;
+ goto bail;
+ }
+ if (!result) {
+ fprintf (stderr, "E: no result defined.\n");
+ fail++;
+ goto bail;
+ }
+ FcConfigSubstitute (config, query, FcMatchPattern);
+
+ FcPatternIterStart (result, &iter);
+ do {
+ vc = FcPatternIterValueCount (result, &iter);
+ for (x = 0; x < vc; x++) {
+ FcValue vr, vp;
+
+ if (FcPatternIterGetValue (result, &iter, x, &vr, NULL) != FcResultMatch) {
+ fprintf (stderr, "E: unable to obtain a value from the expected result\n");
+ fail++;
+ goto bail;
+ }
+ if (FcPatternGet (query, FcPatternIterGetObject (result, &iter), x, &vp) != FcResultMatch) {
+ vp.type = FcTypeVoid;
+ }
+ if (!FcValueEqual (vp, vr)) {
+ printf ("E: failed to compare %s:\n", FcPatternIterGetObject (result, &iter));
+ printf (" actual result:");
+ FcValuePrint (vp);
+ printf ("\n expected result:");
+ FcValuePrint (vr);
+ printf ("\n");
+ fail++;
+ goto bail;
+ }
+ }
+ } while (FcPatternIterNext (result, &iter));
+ bail:
+ return fail;
+}
+
static FcBool
run_test (FcConfig *config, json_object *root)
{
json_object *tests;
- int i, j, n, fail = 0;
+ int i, n, fail = 0;
if (!json_object_object_get_ex (root, "tests", &tests) ||
json_object_get_type (tests) != json_type_array) {
@@ -392,8 +629,6 @@ run_test (FcConfig *config, json_object *root)
FcPattern *result = NULL;
FcFontSet *result_fs = NULL;
const char *method = NULL;
- FcFontSet *fs = NULL;
- FcResult res;
if (json_object_get_type (obj) != json_type_object)
continue;
@@ -442,145 +677,17 @@ run_test (FcConfig *config, json_object *root)
}
}
if (method != NULL && strcmp (method, "match") == 0) {
- FcPattern *match = NULL;
-
- if (!query) {
- fprintf (stderr, "E: no query defined.\n");
- fail++;
- goto bail;
- }
- if (!result) {
- fprintf (stderr, "E: no result defined.\n");
- fail++;
- goto bail;
- }
- FcConfigSubstitute (config, query, FcMatchPattern);
- FcConfigSetDefaultSubstitute (config, query);
- match = FcFontMatch (config, query, &res);
- if (match) {
- FcPatternIter iter;
- int x, vc;
-
- FcPatternIterStart (result, &iter);
- do {
- vc = FcPatternIterValueCount (result, &iter);
- for (x = 0; x < vc; x++) {
- FcValue vr, vm;
-
- if (FcPatternIterGetValue (result, &iter, x, &vr, NULL) != FcResultMatch) {
- fprintf (stderr, "E: unable to obtain a value from the expected result\n");
- fail++;
- goto bail;
- }
- if (FcPatternGet (match, FcPatternIterGetObject (result, &iter), x, &vm) != FcResultMatch) {
- vm.type = FcTypeVoid;
- }
- if (!FcValueEqual (vm, vr)) {
- printf ("E: failed to compare %s:\n", FcPatternIterGetObject (result, &iter));
- printf (" actual result:");
- FcValuePrint (vm);
- printf ("\n expected result:");
- FcValuePrint (vr);
- printf ("\n");
- fail++;
- goto bail;
- }
- }
- } while (FcPatternIterNext (result, &iter));
- bail:
- if (match)
- FcPatternDestroy (match);
- } else {
- FcPatternIter iter;
- int vc;
-
- FcPatternIterStart (result, &iter);
- vc = FcPatternIterValueCount (result, &iter);
- if (vc > 0) {
- fprintf (stderr, "E: no match\n");
- fail++;
- }
- }
+ fail += process_match (config, query, result);
} else if (method != NULL && strcmp (method, "list") == 0) {
- if (!query) {
- fprintf (stderr, "E: no query defined.\n");
- fail++;
- goto bail2;
- }
- if (!result_fs) {
- fprintf (stderr, "E: no result_fs defined.\n");
- fail++;
- goto bail2;
- }
- fs = FcFontList (config, query, NULL);
- if (!fs) {
- fprintf (stderr, "E: failed on FcFontList\n");
- fail++;
- } else {
- process_fs:
- if (fs->nfont != result_fs->nfont) {
- printf ("E: The number of results is different:\n");
- printf (" actual result: %d\n", fs->nfont);
- printf (" expected result: %d\n", result_fs->nfont);
- fail++;
- goto bail2;
- }
- for (j = 0; j < fs->nfont; j++) {
- FcPatternIter iter;
- int x, vc;
-
- FcPatternIterStart (result_fs->fonts[j], &iter);
- do {
- vc = FcPatternIterValueCount (result_fs->fonts[j], &iter);
- for (x = 0; x < vc; x++) {
- FcValue vr, vm;
-
- if (FcPatternIterGetValue (result_fs->fonts[j], &iter, x, &vr, NULL) != FcResultMatch) {
- fprintf (stderr, "E: unable to obtain a value from the expected result\n");
- fail++;
- goto bail2;
- }
- if (FcPatternGet (fs->fonts[j], FcPatternIterGetObject (result_fs->fonts[j], &iter), x, &vm) != FcResultMatch) {
- vm.type = FcTypeVoid;
- }
- if (!FcValueEqual (vm, vr)) {
- printf ("E: failed to compare %s:\n", FcPatternIterGetObject (result_fs->fonts[j], &iter));
- printf (" actual result:");
- FcValuePrint (vm);
- printf ("\n expected result:");
- FcValuePrint (vr);
- printf ("\n");
- fail++;
- goto bail2;
- }
- }
- } while (FcPatternIterNext (result_fs->fonts[j], &iter));
- }
- bail2:
- if (fs)
- FcFontSetDestroy (fs);
- }
+ fail += process_list (config, query, result_fs);
} else if (method != NULL &&
(strcmp (method, "sort") == 0 ||
strcmp (method, "sort_all") == 0)) {
- if (!query) {
- fprintf (stderr, "E: no query defined.\n");
- fail++;
- goto bail2;
- }
- if (!result_fs) {
- fprintf (stderr, "E: no result_fs defined.\n");
- fail++;
- goto bail2;
- }
- fs = FcFontSort (config, query, method[4] == 0 ? FcTrue : FcFalse, NULL, &res);
- if (!fs) {
- fprintf (stderr, "E: failed on FcFontSort\n");
- fail++;
- } else {
- goto process_fs;
- }
- } else {
+ fail += process_sort (config, query, result_fs, method);
+ } else if (method != NULL &&
+ strcmp (method, "pattern") == 0) {
+ fail += process_pattern (config, query, result);
+ } else {
fprintf (stderr, "W: unknown testing method: %s\n", method);
}
if (method)
commit 7661a9b4d49df61d66359b532eebb34c0be73367
Author: Akira TAGOH <akira at tagoh.org>
Date: Mon May 26 16:13:19 2025 +0900
conf.d: Add a conf to guess a generic-family for substitution
This config file aims to add proper generic-family name for substitution
when no fallback for requested family name and also to avoid unexpected
substitution by 49-sanserif.conf such as "Blah Mono" to sans-serif.
Without this:
$ fc-pattern -c "Adwaita Mono"
Pattern has 9 elts (size 16)
family: "Adwaita Mono"(s) "Noto Sans"(w) ...
With this:
$ fc-pattern -c "Adwaita Mono"
Pattern has 9 elts (size 16)
family: "Adwaita Mono"(s) "Noto Sans Mono"(w) ...
Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/457
Changelog: fixed
diff --git a/conf.d/48-guessfamily.conf b/conf.d/48-guessfamily.conf
new file mode 100644
index 0000000..aaf8527
--- /dev/null
+++ b/conf.d/48-guessfamily.conf
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
+<fontconfig>
+ <description>Guess a generic-family for substitution</description>
+ <!-- sans-serif -->
+ <match target="pattern">
+ <test qual="all" name="family" compare="not_eq">
+ <string>sans-serif</string>
+ </test>
+ <test name="family" compare="contains">
+ <string>sans</string>
+ </test>
+ <edit name="family" mode="append_last">
+ <string>sans-serif</string>
+ </edit>
+ </match>
+ <!-- serif -->
+ <match target="pattern">
+ <test qual="all" name="family" compare="not_eq">
+ <string>sans-serif</string>
+ </test>
+ <test qual="all" name="family" compare="not_eq">
+ <string>serif</string>
+ </test>
+ <test name="family" compare="contains">
+ <string>serif</string>
+ </test>
+ <edit name="family" mode="append_last">
+ <string>serif</string>
+ </edit>
+ </match>
+ <!-- monospace -->
+ <match target="pattern">
+ <test qual="all" name="family" compare="not_eq">
+ <string>monospace</string>
+ </test>
+ <test name="family" compare="contains">
+ <string>mono</string>
+ </test>
+ <edit name="family" mode="append_last">
+ <string>monospace</string>
+ </edit>
+ </match>
+</fontconfig>
diff --git a/conf.d/Makefile.am b/conf.d/Makefile.am
index 737b4fb..e9b3ddc 100644
--- a/conf.d/Makefile.am
+++ b/conf.d/Makefile.am
@@ -87,6 +87,7 @@ template_DATA = \
40-nonlatin.conf \
45-generic.conf \
45-latin.conf \
+ 48-guessfamily.conf \
48-spacing.conf \
49-sansserif.conf \
50-user.conf \
diff --git a/conf.d/meson.build b/conf.d/meson.build
index ef9b0cc..66699fd 100644
--- a/conf.d/meson.build
+++ b/conf.d/meson.build
@@ -25,6 +25,7 @@ conf_files = [
'40-nonlatin.conf',
'45-generic.conf',
'45-latin.conf',
+ '48-guessfamily.conf',
'48-spacing.conf',
'49-sansserif.conf',
'50-user.conf',
More information about the Fontconfig
mailing list