fontconfig: Branch 'main' - 3 commits
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Apr 25 06:56:50 UTC 2025
doc/fcconfig.fncs | 10 +++++
fontconfig/fontconfig.h | 3 +
src/fccfg.c | 12 ++++++
src/fcint.h | 3 +
src/fcmatch.c | 22 ++++++++----
src/fcxml.c | 2 +
test/run-test-conf.sh | 1
test/test-appfont.json | 75 +++++++++++++++++++++++++++++++++++++++++
test/test-conf.c | 86 ++++++++++++++++++++++++++++++++++++++----------
9 files changed, 190 insertions(+), 24 deletions(-)
New commits:
commit 2e4e6655c716b495374b6b1f3dd7552e860c82c4
Merge: dd5c5fd 9268bb6
Author: Akira TAGOH <akira at tagoh.org>
Date: Fri Apr 25 06:56:45 2025 +0000
Merge branch 'issues/455' into 'main'
Add API to allow changing the order of application fonts
Closes #455
See merge request fontconfig/fontconfig!379
commit 9268bb64bebd1e46a0433d780ebdeea49fc53d95
Author: Akira TAGOH <akira at tagoh.org>
Date: Fri Apr 25 14:30:21 2025 +0900
Add FcConfigPerferAppFont() to allow changing the order of application fonts
This basically takes effect for FcFont(Set)Sort only.
FcFont(Set)Match works without this change and
FcFont(Set)List doesn't need it.
Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/455
Changelog: added
diff --git a/doc/fcconfig.fncs b/doc/fcconfig.fncs
index 0a072af..7517577 100644
--- a/doc/fcconfig.fncs
+++ b/doc/fcconfig.fncs
@@ -544,3 +544,13 @@ in configuration file. This function tries to match 'pat' with them and
return FcFalse if 'pat' is rejected, otherwise FcTrue.
@SINCE@ 2.15.1
@@
+
+ at RET@ void
+ at FUNC@ FcConfigPreferAppFont
+ at TYPE1@ FcConfig * @ARG1@ config
+ at TYPE2@ FcBool% @ARG2@ flag
+ at DESC@
+Set 'flag' to change the priority of Application fonts. default behavior is turned off
+for backward compatibility.
+ at SINCE@ 2.17.0
+@@
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index bd04884..6326636 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -485,6 +485,9 @@ FcConfigAppFontAddDir (FcConfig *config,
FcPublic void
FcConfigAppFontClear (FcConfig *config);
+FcPublic void
+FcConfigPreferAppFont (FcConfig *config, FcBool flag);
+
FcPublic FcBool
FcConfigSubstituteWithPat (FcConfig *config,
FcPattern *p,
diff --git a/src/fccfg.c b/src/fccfg.c
index 8b82b42..cfa0920 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -2776,6 +2776,18 @@ FcConfigAppFontClear (FcConfig *config)
FcConfigDestroy (config);
}
+void
+FcConfigPreferAppFont (FcConfig *config, FcBool flag)
+{
+ config = FcConfigReference (config);
+ if (!config)
+ return;
+
+ config->prefer_app_fonts = flag;
+
+ FcConfigDestroy (config);
+}
+
/*
* Manage filename-based font source selectors
*/
diff --git a/src/fcint.h b/src/fcint.h
index 334cde0..e422c72 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -613,6 +613,9 @@ struct _FcConfig {
FcFilterFontSetFunc filter_func; /* A predicate function to filter out config->fonts */
FcDestroyFunc destroy_data_func; /* A callback function to destroy config->filter_data */
void *filter_data; /* An user data to be used for filter_func */
+
+ FcBool prefer_app_fonts; /* Whether FcSetApplication has a priority than
+ FcSetSystem for lookup */
};
typedef struct _FcFileTime {
diff --git a/src/fcmatch.c b/src/fcmatch.c
index 444709c..d8523a1 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -564,7 +564,7 @@ FcCompareFamilies (FcPattern *pat,
}
}
if (FcDebug() & FC_DBG_MATCHV) {
- printf ("%s: %g ", FcObjectName (FC_FAMILY_OBJECT), strong_value);
+ printf ("%s: %g (%g) ", FcObjectName (FC_FAMILY_OBJECT), strong_value, weak_value);
FcValueListPrint (v1orig);
printf (", ");
FcValueListPrint (v2orig);
@@ -1107,7 +1107,7 @@ FcFontSetSortDestroy (FcFontSet *fs)
}
FcFontSet *
-FcFontSetSort (FcConfig *config FC_UNUSED,
+FcFontSetSort (FcConfig *config,
FcFontSet **sets,
int nsets,
FcPattern *p,
@@ -1186,6 +1186,13 @@ FcFontSetSort (FcConfig *config FC_UNUSED,
newp->pattern = s->fonts[f];
if (!FcCompare (p, newp->pattern, newp->score, result, &data))
goto bail1;
+ /* TODO: Should we check a FcPattern in FcFontSet?
+ * This way may not work if someone has own list of application fonts
+ * That said, just to reduce the cost for lookup so far.
+ */
+ if (config->prefer_app_fonts && s != config->fonts[FcSetApplication]) {
+ newp->score[PRI_ORDER] += 1000;
+ }
if (FcDebug() & FC_DBG_MATCHV) {
printf ("Score");
for (i = 0; i < PRI_END; i++) {
@@ -1260,12 +1267,13 @@ FcFontSetSort (FcConfig *config FC_UNUSED,
free (nodes);
- if (FcDebug() & FC_DBG_MATCH) {
- printf ("First font ");
- FcPatternPrint (ret->fonts[0]);
- }
- if (ret->nfont > 0)
+ if (ret->nfont > 0) {
*result = FcResultMatch;
+ if (FcDebug() & FC_DBG_MATCH) {
+ printf ("First font ");
+ FcPatternPrint (ret->fonts[0]);
+ }
+ }
return ret;
diff --git a/test/run-test-conf.sh b/test/run-test-conf.sh
index 88407cd..e87bcc5 100644
--- a/test/run-test-conf.sh
+++ b/test/run-test-conf.sh
@@ -54,6 +54,7 @@ for i in \
test-issue-286.json \
test-style-match.json \
test-filter.json \
+ test-appfont.json \
; do
echo $RUNNER $TESTDIR/$i ...
$RUNNER $TESTDIR/../conf.d/10-autohint.conf $TESTDIR/$i
diff --git a/test/test-appfont.json b/test/test-appfont.json
new file mode 100644
index 0000000..4ecc15d
--- /dev/null
+++ b/test/test-appfont.json
@@ -0,0 +1,75 @@
+{
+ "fonts": [
+ {
+ "family": [
+ "Foo"
+ ],
+ "style": [
+ "Regular"
+ ],
+ "lang": "en",
+ "charset": [
+ "a",
+ "b"
+ ],
+ "file": "/system/path/to/Foo.ttf",
+ "fontversion": 1,
+ }
+ ],
+ "appfonts": [
+ {
+ "family": [
+ "Foo"
+ ],
+ "style": [
+ "Regular"
+ ],
+ "lang": "en",
+ "charset": [
+ "a",
+ "b"
+ ],
+ "file": "/app/path/to/Foo.ttf",
+ "fontversion": 2,
+ }
+ ],
+ "tests": [
+ {
+ "config": {
+ "prefer_app_font": false
+ },
+ "method": "sort",
+ "query": {
+ "family": "Foo",
+ "style": "Regular"
+ },
+ "result_fs": [
+ {
+ "family": "Foo",
+ "style": "Regular",
+ "file": "/system/path/to/Foo.ttf",
+ "fontversion": 1
+ }
+ ]
+ },
+ {
+ "config": {
+ "prefer_app_font": true
+ },
+ "method": "sort",
+ "query": {
+ "family": "Foo",
+ "style": "Regular"
+ },
+ "result_fs": [
+ {
+ "family": "Foo",
+ "style": "Regular",
+ "file": "/app/path/to/Foo.ttf",
+ "fontversion": 2
+ }
+ ]
+ }
+
+ ]
+}
diff --git a/test/test-conf.c b/test/test-conf.c
index f73c983..54e5d70 100644
--- a/test/test-conf.c
+++ b/test/test-conf.c
@@ -42,6 +42,25 @@ struct _FcConfig {
FcFontSet *fonts[FcSetApplication + 1];
};
+static void
+apply_config (FcConfig *config, json_object *obj)
+{
+ json_object_iter iter;
+
+ json_object_object_foreachC (obj, iter)
+ {
+ if (strcmp (iter.key, "prefer_app_font") == 0) {
+ if (json_object_get_type (iter.val) != json_type_boolean) {
+ fprintf (stderr, "W: invalid type of prefer_app_font: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
+ continue;
+ }
+ FcConfigPreferAppFont (config, json_object_get_boolean (iter.val));
+ } else {
+ fprintf (stderr, "W: unknown object in config: %s\n", iter.key);
+ }
+ }
+}
+
static FcPattern *
build_pattern (json_object *obj)
{
@@ -137,7 +156,7 @@ build_pattern (json_object *obj)
continue;
}
if (nchar != 1) {
- fprintf (stderr, "E: charset entry not not one codepoint\n");
+ fprintf (stderr, "E: charset entry not a codepoint\n");
FcValueDestroy (v);
continue;
}
@@ -318,7 +337,7 @@ bail:
static FcBool
build_fonts (FcConfig *config, json_object *root)
{
- json_object *fonts, *filter;
+ json_object *fonts, *filter, *appfonts;
FcFontSet *fs;
FcPattern *filterpat;
@@ -340,6 +359,16 @@ build_fonts (FcConfig *config, json_object *root)
if (config->fonts[FcSetSystem])
FcFontSetDestroy (config->fonts[FcSetSystem]);
config->fonts[FcSetSystem] = fs;
+ if (json_object_object_get_ex (root, "appfonts", &appfonts)) {
+ if (json_object_get_type (appfonts) != json_type_array) {
+ fprintf (stderr, "W: Invalid appfonts defined\n");
+ return FcFalse;
+ }
+ fs = build_fs (config, appfonts, FcTrue);
+ if (config->fonts[FcSetApplication])
+ FcFontSetDestroy (config->fonts[FcSetApplication]);
+ config->fonts[FcSetApplication] = fs;
+ }
return FcTrue;
}
@@ -348,7 +377,7 @@ static FcBool
run_test (FcConfig *config, json_object *root)
{
json_object *tests;
- int i, n, fail = 0;
+ int i, j, n, fail = 0;
if (!json_object_object_get_ex (root, "tests", &tests) ||
json_object_get_type (tests) != json_type_array) {
@@ -361,15 +390,22 @@ run_test (FcConfig *config, json_object *root)
json_object_iter iter;
FcPattern *query = NULL;
FcPattern *result = NULL;
- FcPattern *filterpat = NULL;
FcFontSet *result_fs = NULL;
const char *method = NULL;
+ FcFontSet *fs = NULL;
+ FcResult res;
if (json_object_get_type (obj) != json_type_object)
continue;
json_object_object_foreachC (obj, iter)
{
- if (strcmp (iter.key, "method") == 0) {
+ if (strcmp (iter.key, "config") == 0) {
+ if (json_object_get_type (iter.val) != json_type_object) {
+ fprintf (stderr, "W: invalid type of config: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
+ continue;
+ }
+ apply_config (config, iter.val);
+ } else if (strcmp (iter.key, "method") == 0) {
if (json_object_get_type (iter.val) != json_type_string) {
fprintf (stderr, "W: invalid type of method: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
continue;
@@ -407,7 +443,6 @@ run_test (FcConfig *config, json_object *root)
}
if (method != NULL && strcmp (method, "match") == 0) {
FcPattern *match = NULL;
- FcResult res;
if (!query) {
fprintf (stderr, "E: no query defined.\n");
@@ -467,8 +502,6 @@ run_test (FcConfig *config, json_object *root)
}
}
} else if (method != NULL && strcmp (method, "list") == 0) {
- FcFontSet *fs = NULL;
-
if (!query) {
fprintf (stderr, "E: no query defined.\n");
fail++;
@@ -484,8 +517,7 @@ run_test (FcConfig *config, json_object *root)
fprintf (stderr, "E: failed on FcFontList\n");
fail++;
} else {
- int i;
-
+ process_fs:
if (fs->nfont != result_fs->nfont) {
printf ("E: The number of results is different:\n");
printf (" actual result: %d\n", fs->nfont);
@@ -493,26 +525,26 @@ run_test (FcConfig *config, json_object *root)
fail++;
goto bail2;
}
- for (i = 0; i < fs->nfont; i++) {
+ for (j = 0; j < fs->nfont; j++) {
FcPatternIter iter;
int x, vc;
- FcPatternIterStart (result_fs->fonts[i], &iter);
+ FcPatternIterStart (result_fs->fonts[j], &iter);
do {
- vc = FcPatternIterValueCount (result_fs->fonts[i], &iter);
+ vc = FcPatternIterValueCount (result_fs->fonts[j], &iter);
for (x = 0; x < vc; x++) {
FcValue vr, vm;
- if (FcPatternIterGetValue (result_fs->fonts[i], &iter, x, &vr, NULL) != FcResultMatch) {
+ 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[i], FcPatternIterGetObject (result_fs->fonts[i], &iter), x, &vm) != FcResultMatch) {
+ 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[i], &iter));
+ printf ("E: failed to compare %s:\n", FcPatternIterGetObject (result_fs->fonts[j], &iter));
printf (" actual result:");
FcValuePrint (vm);
printf ("\n expected result:");
@@ -522,12 +554,32 @@ run_test (FcConfig *config, json_object *root)
goto bail2;
}
}
- } while (FcPatternIterNext (result_fs->fonts[i], &iter));
+ } while (FcPatternIterNext (result_fs->fonts[j], &iter));
}
bail2:
if (fs)
FcFontSetDestroy (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 {
fprintf (stderr, "W: unknown testing method: %s\n", method);
}
commit d89c253ab4ea29a2976a0b8eb6e524ddb9975762
Author: Akira TAGOH <akira at tagoh.org>
Date: Thu Apr 24 18:41:19 2025 +0900
Make sure that the debugging facilities are initialized at loading config phase
Changelog: fixed
diff --git a/src/fcxml.c b/src/fcxml.c
index d2e25fc..328e109 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -3246,6 +3246,8 @@ FcConfigParseAndLoadFromMemoryInternal (FcConfig *config,
size_t buflen;
#endif
+ FcInitDebug();
+
if (!buffer)
return FcFalse;
len = strlen ((const char *)buffer);
More information about the Fontconfig
mailing list