conf.d/90-synthetic.conf | 4 configure.ac | 9 + doc/fcpattern.fncs | 111 ++++++++++++++ fontconfig/fontconfig.h | 33 ++++ src/fcdbg.c | 15 -- src/fcdefault.c | 32 ++-- src/fcformat.c | 22 -- src/fcint.h | 9 + src/fcpat.c | 233 +++++++++++++++++++++++++------ test/Makefile.am | 16 +- test/run-test-conf.sh | 36 ++++ test/test-90-synthetic.json | 68 +++++++++ test/test-conf.c | 328 ++++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 829 insertions(+), 87 deletions(-) New commits: commit af964f789762df0b023c8cfd7ea622045892cb54 Author: Akira TAGOH <akira@xxxxxxxxx> Date: Fri May 11 22:15:39 2018 +0900 Add a test case for 90-synthetic.conf diff --git a/test/Makefile.am b/test/Makefile.am index 117ba01..48ec3ce 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,7 +13,12 @@ BUILT_SOURCES = $(builddir)/out.expected SH_LOG_COMPILER = sh TESTS=run-test.sh -TESTDATA=4x6.pcf 8x16.pcf fonts.conf.in +TESTDATA = \ + 4x6.pcf \ + 8x16.pcf \ + fonts.conf.in \ + test-90-synthetic.json \ + $(NULL) if FREETYPE_PCF_LONG_FAMILY_NAMES $(builddir)/out.expected: $(srcdir)/out.expected-long-family-names Makefile @@ -63,10 +68,10 @@ if ENABLE_JSONC check_PROGRAMS += test-conf test_conf_CFLAGS = $(JSONC_CFLAGS) test_conf_LDADD = $(top_builddir)/src/libfontconfig.la $(JSONC_LIBS) -TESTS += test-conf.sh +TESTS += run-test-conf.sh endif -EXTRA_DIST=run-test.sh $(TESTDATA) out.expected-long-family-names out.expected-no-long-family-names +EXTRA_DIST=run-test.sh run-test-conf.sh $(TESTDATA) out.expected-long-family-names out.expected-no-long-family-names CLEANFILES=out fonts.conf out.expected diff --git a/test/run-test-conf.sh b/test/run-test-conf.sh new file mode 100644 index 0000000..4bcc29c --- /dev/null +++ b/test/run-test-conf.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# test/run-test-conf.sh +# +# Copyright © 2000 Keith Packard +# Copyright © 2018 Akira TAGOH +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of the author(s) not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. The authors make no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +set -eu + +case "$OSTYPE" in + msys ) MyPWD=`pwd -W` ;; # On Msys/MinGW, returns a MS Windows style path. + * ) MyPWD=`pwd` ;; # On any other platforms, returns a Unix style path. +esac + +TESTDIR=${srcdir-"$MyPWD"} +BUILDTESTDIR=${builddir-"$MyPWD"} + +RUNNER=../test/test-conf$EXEEXT + +$RUNNER $TESTDIR/../conf.d/90-synthetic.conf $TESTDIR/test-90-synthetic.json diff --git a/test/test-90-synthetic.json b/test/test-90-synthetic.json new file mode 100644 index 0000000..4205402 --- /dev/null +++ b/test/test-90-synthetic.json @@ -0,0 +1,68 @@ +{ + "fonts": [ + { + "family": "Foo", + "style": "Medium", + "weight": 100 + }, + { + "family": "Bar", + "style": "Regular", + "weight": 80 + }, + { + "family": "Baz", + "style": "Bold", + "weight": 200 + } + ], + "tests": [ + { + "method": "match", + "query": { + "family": "Foo", + "weight": 200 + }, + "result": { + "family": "Foo", + "weight": 200, + "embolden": true + } + }, + { + "method": "match", + "query": { + "family": "Bar", + "weight": 102 + }, + "result": { + "family": "Bar", + "weight": 80 + } + }, + { + "method": "match", + "query": { + "family": "Bar", + "weight": 200 + }, + "result": { + "family": "Bar", + "weight": 200, + "embolden": true + } + }, + { + "method": "match", + "query": { + "family": "Baz", + "weight": 200 + }, + "result": { + "family": "Baz", + "weight": 200, + "embolden": null + } + } + ] +} commit f665852df90cd5a28c3040af8f484999ca3dfa4e Author: Akira TAGOH <akira@xxxxxxxxx> Date: Fri May 11 21:39:50 2018 +0900 Add a testrunner for conf diff --git a/configure.ac b/configure.ac index 557d151..3e37663 100644 --- a/configure.ac +++ b/configure.ac @@ -474,6 +474,15 @@ if test "$enable_libxml2" = "yes"; then fi # +# Check json-c +# +PKG_CHECK_MODULES([JSONC], [json-c], [use_jsonc=yes], [use_jsonc=no]) + +AM_CONDITIONAL(ENABLE_JSONC, test "x$use_jsonc" = "xyes") +AC_SUBST(JSONC_CFLAGS) +AC_SUBST(JSONC_LIBS) + +# # Set default hinting # diff --git a/test/Makefile.am b/test/Makefile.am index e5b8626..117ba01 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -59,6 +59,13 @@ check_PROGRAMS += test-name-parse test_name_parse_LDADD = $(top_builddir)/src/libfontconfig.la TESTS += test-name-parse +if ENABLE_JSONC +check_PROGRAMS += test-conf +test_conf_CFLAGS = $(JSONC_CFLAGS) +test_conf_LDADD = $(top_builddir)/src/libfontconfig.la $(JSONC_LIBS) +TESTS += test-conf.sh +endif + EXTRA_DIST=run-test.sh $(TESTDATA) out.expected-long-family-names out.expected-no-long-family-names CLEANFILES=out fonts.conf out.expected diff --git a/test/test-conf.c b/test/test-conf.c new file mode 100644 index 0000000..6619ea7 --- /dev/null +++ b/test/test-conf.c @@ -0,0 +1,328 @@ +/* + * fontconfig/test/test-conf.c + * + * Copyright © 2000 Keith Packard + * Copyright © 2018 Akira TAGOH + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the author(s) not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors make no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#include <stdio.h> +#include <string.h> +#include <fontconfig/fontconfig.h> +#include <json.h> + +struct _FcConfig { + FcStrSet *configDirs; /* directories to scan for fonts */ + FcStrSet *fontDirs; + FcStrSet *cacheDirs; + FcStrSet *configFiles; /* config files loaded */ + void *subst[FcMatchKindEnd]; + int maxObjects; /* maximum number of tests in all substs */ + FcStrSet *acceptGlobs; + FcStrSet *rejectGlobs; + FcFontSet *acceptPatterns; + FcFontSet *rejectPatterns; + FcFontSet *fonts[FcSetApplication + 1]; +}; + +static FcPattern * +build_pattern (json_object *obj) +{ + json_object_iter iter; + FcPattern *pat = FcPatternCreate (); + + json_object_object_foreachC (obj, iter) + { + FcValue v; + + if (json_object_get_type (iter.val) == json_type_boolean) + { + v.type = FcTypeBool; + v.u.b = json_object_get_boolean (iter.val); + } + else if (json_object_get_type (iter.val) == json_type_double) + { + v.type = FcTypeDouble; + v.u.d = json_object_get_double (iter.val); + } + else if (json_object_get_type (iter.val) == json_type_int) + { + v.type = FcTypeInteger; + v.u.i = json_object_get_int (iter.val); + } + else if (json_object_get_type (iter.val) == json_type_string) + { + v.type = FcTypeString; + v.u.s = json_object_get_string (iter.val); + } + else if (json_object_get_type (iter.val) == json_type_null) + { + v.type = FcTypeVoid; + } + else + { + 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); + } + return pat; +} + +static FcBool +build_fonts (FcConfig *config, json_object *root) +{ + json_object *fonts; + FcFontSet *fs; + int i, n; + + if (!json_object_object_get_ex (root, "fonts", &fonts) || + json_object_get_type (fonts) != json_type_array) + { + fprintf (stderr, "W: No fonts defined\n"); + return FcFalse; + } + fs = FcFontSetCreate (); + n = json_object_array_length (fonts); + for (i = 0; i < n; i++) + { + json_object *obj = json_object_array_get_idx (fonts, i); + FcPattern *pat; + + if (json_object_get_type (obj) != json_type_object) + continue; + pat = build_pattern (obj); + FcFontSetAdd (fs, pat); + } + /* FcConfigSetFonts (config, fs, FcSetSystem); */ + if (config->fonts[FcSetSystem]) + FcFontSetDestroy (config->fonts[FcSetSystem]); + config->fonts[FcSetSystem] = fs; + + return FcTrue; +} + +static FcBool +run_test (FcConfig *config, json_object *root) +{ + json_object *tests; + FcFontSet *fs; + int i, n, fail = 0; + + if (!json_object_object_get_ex (root, "tests", &tests) || + json_object_get_type (tests) != json_type_array) + { + fprintf (stderr, "W: No test cases defined\n"); + return FcFalse; + } + fs = FcFontSetCreate (); + n = json_object_array_length (tests); + for (i = 0; i < n; i++) + { + json_object *obj = json_object_array_get_idx (tests, i); + json_object_iter iter; + FcPattern *query, *result; + const char *method; + + if (json_object_get_type (obj) != json_type_object) + continue; + json_object_object_foreachC (obj, iter) + { + 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; + } + method = json_object_get_string (iter.val); + } + else if (strcmp (iter.key, "query") == 0) + { + if (json_object_get_type (iter.val) != json_type_object) + { + fprintf (stderr, "W: invalid type of query: (%s)\n", json_type_to_name (json_object_get_type (iter.val))); + continue; + } + query = build_pattern (iter.val); + } + else if (strcmp (iter.key, "result") == 0) + { + if (json_object_get_type (iter.val) != json_type_object) + { + fprintf (stderr, "W: invalid type of result: (%s)\n", json_type_to_name (json_object_get_type (iter.val))); + continue; + } + result = build_pattern (iter.val); + } + else + { + fprintf (stderr, "W: unknown object: %s\n", iter.key); + } + } + if (strcmp (method, "match") == 0) + { + FcPattern *match; + FcResult res; + + FcConfigSubstitute (config, query, FcMatchPattern); + FcDefaultSubstitute (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:; + } + else + { + fprintf (stderr, "E: no match\n"); + fail++; + } + } + else + { + fprintf (stderr, "W: unknown testing method: %s\n", method); + } + } + + return fail == 0; +} + +static FcBool +run_scenario (FcConfig *config, char *file) +{ + FcBool ret = FcTrue; + json_object *root, *scenario; + + root = json_object_from_file (file); + if (!root) + { + fprintf (stderr, "E: Unable to read the file: %s\n", file); + return FcFalse; + } + if (!build_fonts (config, root)) + { + ret = FcFalse; + goto bail1; + } + if (!run_test (config, root)) + { + ret = FcFalse; + goto bail1; + } + +bail1: + json_object_put (root); + + return ret; +} + +static FcBool +load_config (FcConfig *config, char *file) +{ + FILE *fp; + long len; + char *buf = NULL; + FcBool ret = FcTrue; + + if ((fp = fopen(file, "rb")) == NULL) + return FcFalse; + fseek (fp, 0L, SEEK_END); + len = ftell (fp); + fseek (fp, 0L, SEEK_SET); + buf = malloc (sizeof (char) * (len + 1)); + if (!buf) + { + ret = FcFalse; + goto bail1; + } + fread (buf, (size_t)len, sizeof (char), fp); + buf[len] = 0; + + ret = FcConfigParseAndLoadFromMemory (config, buf, FcTrue); +bail1: + fclose (fp); + if (buf) + free (buf); + + return ret; +} + +int +main (int argc, char **argv) +{ + FcConfig *config; + int retval = 0; + + if (argc < 3) + { + fprintf(stderr, "Usage: %s <conf file> <test scenario>\n", argv[0]); + return 1; + } + + config = FcConfigCreate (); + if (!load_config (config, argv[1])) + { + fprintf(stderr, "E: Failed to load config\n"); + retval = 1; + goto bail1; + } + if (!run_scenario (config, argv[2])) + { + retval = 1; + goto bail1; + } +bail1: + FcConfigDestroy (config); + + return retval; +} commit 307639cff143341cb10273db1a19264ba28b247e Author: Akira TAGOH <akira@xxxxxxxxx> Date: Fri May 11 20:48:30 2018 +0900 Bug 43367 - RFE: iterator to peek objects in FcPattern Add various APIs to obtain things in FcPattern through the iterator https://bugs.freedesktop.org/show_bug.cgi?id=43367 diff --git a/doc/fcpattern.fncs b/doc/fcpattern.fncs index 928f0bc..3b13c22 100644 --- a/doc/fcpattern.fncs +++ b/doc/fcpattern.fncs @@ -57,6 +57,15 @@ Decrement the pattern reference count. If all references are gone, destroys the pattern, in the process destroying all related values. @@ +@RET@ int +@FUNC@ FcPatternObjectCount +@TYPE1@ const FcPattern * @ARG1@ p +@PURPOSE@ Returns the number of the object +@DESC@ +Returns the number of the object <parameter>p</parameter> has. +@SINCE@ 2.13.1 +@@ + @RET@ FcBool @FUNC@ FcPatternEqual @TYPE1@ const FcPattern * @ARG1@ pa @@ -383,7 +392,107 @@ whether the property existed or not. Removes the value associated with the property `object' at position `id', returning whether the property existed and had a value at that position or not. @@ - + +@RET@ void +@FUNC@ FcPatternIterStart +@TYPE1@ const FcPattern * @ARG1@ p +@TYPE2@ FcPatternIter * @ARG2@ iter +@PURPOSE@ Initialize the iterator with the first iterator in the pattern +@DESC@ +Initialize <parameter>iter</parameter> with the first iterator in <parameter>p</parameter>. +If there are no objects in <parameter>p</parameter>, <parameter>iter</parameter> +will not have any valid data. +@SINCE@ 2.13.1 +@@ + +@RET@ FcBool +@FUNC@ FcPatternIterNext +@TYPE1@ const FcPattern * @ARG1@ p +@TYPE2@ FcPatternIter * @ARG2@ iter +@PURPUSE@ Set the iterator to point to the next object in the pattern +@DESC@ +Set <parameter>iter</parameter> to point to the next object in <parameter>p</parameter> +and returns FcTrue if <parameter>iter</parameter> has been changed to the next object. +returns FcFalse otherwise. +@SINCE@ 2.13.1 +@@ + +@RET@ FcBool +@FUNC@ FcPatternIterEqual +@TYPE1@ const FcPattern * @ARG1@ p1 +@TYPE2@ FcPatternIter * @ARG2@ i1 +@TYPE3@ const FcPattern * @ARG3@ p2 +@TYPE4@ FcPatternIter * @ARG4@ i2 +@PURPOSE@ Compare iterators +@DESC@ +Return FcTrue if both <parameter>i1</parameter> and <parameter>i2</parameter> +point to same object and contains same values. return FcFalse otherwise. +@SINCE@ 2.13.1 +@@ + +@RET@ FcBool +@FUNC@ FcPatternFindIter +@TYPE1@ const FcPattern * @ARG1@ p +@TYPE2@ FcPatternIter * @ARG2@ iter +@TYPE3@ const char * @ARG3@ object +@PURPOSE@ Set the iterator to point to the object in the pattern +@DESC@ +Set <parameter>iter</parameter> to point to <parameter>object</parameter> in +<parameter>p</parameter> if any and returns FcTrue. returns FcFalse otherwise. +@SINCE@ 2.13.1 +@@ + +@RET@ FcBool +@FUNC@ FcPatternIterIsValid +@TYPE1@ const FcPattern * @ARG1@ p +@TYPE2@ FcPatternIter : @ARG2@ iter +@PURPOSE@ Check whether the iterator is valid or not +@DESC@ +Returns FcTrue if <parameter>iter</parameter> point to the valid entry +in <parameter>p</parameter>. returns FcFalse otherwise. +@SINCE@ 2.13.1 +@@ + +@RET@ const char * +@FUNC@ FcPatternIterGetObject +@TYPE1@ const FcPattern * @ARG1@ p +@TYPE2@ FcPatternIter * @ARG2@ iter +@PURPOSE@ Returns an object name which the iterator point to +@DESC@ +Returns an object name in <parameter>p</parameter> which +<parameter>iter</parameter> point to. returns NULL if +<parameter>iter</parameter> isn't valid. +@SINCE@ 2.13.1 +@@ + +@RET@ int +@FUNC@ FcPatternIterValueCount +@TYPE1@ const FcPattern * @ARG1@ p +@TYPE2@ FcPatternIter * @ARG2@ iter +@PURPOSE@ Returns the number of the values which the iterator point to +@DESC@ +Returns the number of the values in the object which <parameter>iter</parameter> +point to. if <parameter>iter</parameter> isn't valid, returns 0. +@SINCE@ 2.13.1 +@@ + +@RET@ FcResult +@FUNC@ FcPatternIterGetValue +@TYPE1@ const FcPattern * @ARG1@ p +@TYPE2@ FcPatternIter * @ARG2@ iter +@TYPE3@ int @ARG3@ id +@TYPE4@ FcValue * @ARG4@ v +@TYPE5@ FcValueBinding * @ARG5@ b +@PURPOSE@ Returns a value which the iterator point to +@DESC@ +Returns in <parameter>v</parameter> the <parameter>id</parameter>'th value +which <parameter>iter</parameter> point to. also binding to <parameter>b</parameter> +if given. +The value returned is not a copy, but rather refers to the data stored +within the pattern directly. Applications must not free this value. +@SINCE@ 2.13.1 +@@ + @RET@ void @FUNC@ FcPatternPrint @TYPE1@ const FcPattern * @ARG1@ p diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h index a89b22f..5c04219 100644 --- a/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig.h @@ -248,6 +248,11 @@ typedef enum _FcValueBinding { typedef struct _FcPattern FcPattern; +typedef struct _FcPatternIter { + void *dummy1; + void *dummy2; +} FcPatternIter; + typedef struct _FcLangSet FcLangSet; typedef struct _FcRange FcRange; @@ -861,6 +866,9 @@ FcValueSave (FcValue v); FcPublic void FcPatternDestroy (FcPattern *p); +int +FcPatternObjectCount (const FcPattern *pat); + FcPublic FcBool FcPatternEqual (const FcPattern *pa, const FcPattern *pb); @@ -961,6 +969,31 @@ FcRangeCopy (const FcRange *r); FcPublic FcBool FcRangeGetDouble(const FcRange *range, double *begin, double *end); +FcPublic void +FcPatternIterStart (const FcPattern *pat, FcPatternIter *iter); + +FcPublic FcBool +FcPatternIterNext (const FcPattern *pat, FcPatternIter *iter); + +FcPublic FcBool +FcPatternIterEqual (const FcPattern *p1, FcPatternIter *i1, + const FcPattern *p2, FcPatternIter *i2); + +FcPublic FcBool +FcPatternFindIter (const FcPattern *pat, FcPatternIter *iter, const char *object); + +FcPublic FcBool +FcPatternIterIsValid (const FcPattern *pat, FcPatternIter *iter); + +FcPublic const char * +FcPatternIterGetObject (const FcPattern *pat, FcPatternIter *iter); + +FcPublic int +FcPatternIterValueCount (const FcPattern *pat, FcPatternIter *iter); + +FcPublic FcResult +FcPatternIterGetValue (const FcPattern *pat, FcPatternIter *iter, int id, FcValue *v, FcValueBinding *b); + /* fcweight.c */ FcPublic int diff --git a/src/fcdbg.c b/src/fcdbg.c index 2e16a31..e2c6b56 100644 --- a/src/fcdbg.c +++ b/src/fcdbg.c @@ -187,22 +187,21 @@ FcCharSetPrint (const FcCharSet *c) void FcPatternPrint (const FcPattern *p) { - int i; - FcPatternElt *e; + FcPatternIter iter; if (!p) { printf ("Null pattern\n"); return; } - printf ("Pattern has %d elts (size %d)\n", p->num, p->size); - for (i = 0; i < p->num; i++) + printf ("Pattern has %d elts (size %d)\n", FcPatternObjectCount (p), p->size); + FcPatternIterStart (p, &iter); + do { - e = &FcPatternElts(p)[i]; - printf ("\t%s:", FcObjectName(e->object)); - FcValueListPrint (FcPatternEltValues(e)); + printf ("\t%s:", FcPatternIterGetObject (p, &iter)); + FcValueListPrint (FcPatternIterGetValues (p, &iter)); printf ("\n"); - } + } while (FcPatternIterNext (p, &iter)); printf ("\n"); } diff --git a/src/fcdefault.c b/src/fcdefault.c index 35973d7..f3addca 100644 --- a/src/fcdefault.c +++ b/src/fcdefault.c @@ -238,21 +238,22 @@ FcDefaultFini (void) void FcDefaultSubstitute (FcPattern *pattern) { + FcPatternIter iter; FcValue v, namelang, v2; int i; double dpi, size, scale, pixelsize; - if (FcPatternObjectGet (pattern, FC_WEIGHT_OBJECT, 0, &v) == FcResultNoMatch ) + if (!FcPatternFindObjectIter (pattern, &iter, FC_WEIGHT_OBJECT)) FcPatternObjectAddInteger (pattern, FC_WEIGHT_OBJECT, FC_WEIGHT_NORMAL); - if (FcPatternObjectGet (pattern, FC_SLANT_OBJECT, 0, &v) == FcResultNoMatch) + if (!FcPatternFindObjectIter (pattern, &iter, FC_SLANT_OBJECT)) FcPatternObjectAddInteger (pattern, FC_SLANT_OBJECT, FC_SLANT_ROMAN); - if (FcPatternObjectGet (pattern, FC_WIDTH_OBJECT, 0, &v) == FcResultNoMatch) + if (!FcPatternFindObjectIter (pattern, &iter, FC_WIDTH_OBJECT)) FcPatternObjectAddInteger (pattern, FC_WIDTH_OBJECT, FC_WIDTH_NORMAL); for (i = 0; i < NUM_FC_BOOL_DEFAULTS; i++) - if (FcPatternObjectGet (pattern, FcBoolDefaults[i].field, 0, &v) == FcResultNoMatch) + if (!FcPatternFindObjectIter (pattern, &iter, FcBoolDefaults[i].field)) FcPatternObjectAddBool (pattern, FcBoolDefaults[i].field, FcBoolDefaults[i].value); if (FcPatternObjectGetDouble (pattern, FC_SIZE_OBJECT, 0, &size) != FcResultMatch) @@ -269,7 +270,7 @@ FcDefaultSubstitute (FcPattern *pattern) if (FcPatternObjectGetDouble (pattern, FC_DPI_OBJECT, 0, &dpi) != FcResultMatch) dpi = 75.0; - if (FcPatternObjectGet (pattern, FC_PIXEL_SIZE_OBJECT, 0, &v) != FcResultMatch) + if (!FcPatternFindObjectIter (pattern, &iter, FC_PIXEL_SIZE_OBJECT)) { (void) FcPatternObjectDel (pattern, FC_SCALE_OBJECT); FcPatternObjectAddDouble (pattern, FC_SCALE_OBJECT, scale); @@ -281,25 +282,22 @@ FcDefaultSubstitute (FcPattern *pattern) } else { + FcPatternIterGetValue(pattern, &iter, 0, &v, NULL); size = v.u.d; size = size / dpi * 72.0 / scale; } (void) FcPatternObjectDel (pattern, FC_SIZE_OBJECT); FcPatternObjectAddDouble (pattern, FC_SIZE_OBJECT, size); - if (FcPatternObjectGet (pattern, FC_FONTVERSION_OBJECT, 0, &v) == FcResultNoMatch) - { + if (!FcPatternFindObjectIter (pattern, &iter, FC_FONTVERSION_OBJECT)) FcPatternObjectAddInteger (pattern, FC_FONTVERSION_OBJECT, 0x7fffffff); - } - if (FcPatternObjectGet (pattern, FC_HINT_STYLE_OBJECT, 0, &v) == FcResultNoMatch) - { + if (!FcPatternFindObjectIter (pattern, &iter, FC_HINT_STYLE_OBJECT)) FcPatternObjectAddInteger (pattern, FC_HINT_STYLE_OBJECT, FC_HINT_FULL); - } - if (FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &v) == FcResultNoMatch) - { + + if (!FcPatternFindObjectIter (pattern, &iter, FC_NAMELANG_OBJECT)) FcPatternObjectAddString (pattern, FC_NAMELANG_OBJECT, FcGetDefaultLang ()); - } + /* shouldn't be failed. */ FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &namelang); /* Add a fallback to ensure the english name when the requested language @@ -315,17 +313,17 @@ FcDefaultSubstitute (FcPattern *pattern) */ v2.type = FcTypeString; v2.u.s = (FcChar8 *) "en-us"; - if (FcPatternObjectGet (pattern, FC_FAMILYLANG_OBJECT, 0, &v) == FcResultNoMatch) + if (!FcPatternFindObjectIter (pattern, &iter, FC_FAMILYLANG_OBJECT)) { FcPatternObjectAdd (pattern, FC_FAMILYLANG_OBJECT, namelang, FcTrue); FcPatternObjectAddWithBinding (pattern, FC_FAMILYLANG_OBJECT, v2, FcValueBindingWeak, FcTrue); } - if (FcPatternObjectGet (pattern, FC_STYLELANG_OBJECT, 0, &v) == FcResultNoMatch) + if (!FcPatternFindObjectIter (pattern, &iter, FC_STYLELANG_OBJECT)) { FcPatternObjectAdd (pattern, FC_STYLELANG_OBJECT, namelang, FcTrue); FcPatternObjectAddWithBinding (pattern, FC_STYLELANG_OBJECT, v2, FcValueBindingWeak, FcTrue); } - if (FcPatternObjectGet (pattern, FC_FULLNAMELANG_OBJECT, 0, &v) == FcResultNoMatch) + if (!FcPatternFindObjectIter (pattern, &iter, FC_FULLNAMELANG_OBJECT)) { FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue); FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue); diff --git a/src/fcformat.c b/src/fcformat.c index 59f8681..c76dc5e 100644 --- a/src/fcformat.c +++ b/src/fcformat.c @@ -544,7 +544,7 @@ interpret_count (FcFormatContext *c, FcStrBuf *buf) { int count; - FcPatternElt *e; + FcPatternIter iter; FcChar8 buf_static[64]; if (!expect_char (c, '#')) @@ -554,16 +554,9 @@ interpret_count (FcFormatContext *c, return FcFalse; count = 0; - e = FcPatternObjectFindElt (pat, - FcObjectFromName ((const char *) c->word)); - if (e) + if (FcPatternFindIter (pat, &iter, (const char *) c->word)) { - FcValueListPtr l; - count++; - for (l = FcPatternEltValues(e); - l->next; - l = l->next) - count++; + count = FcPatternIterValueCount (pat, &iter); } snprintf ((char *) buf_static, sizeof (buf_static), "%d", count); @@ -695,7 +688,7 @@ interpret_simple (FcFormatContext *c, FcPattern *pat, FcStrBuf *buf) { - FcPatternElt *e; + FcPatternIter iter; FcBool add_colon = FcFalse; FcBool add_elt_name = FcFalse; int idx; @@ -743,9 +736,7 @@ interpret_simple (FcFormatContext *c, c->word = orig; } - e = FcPatternObjectFindElt (pat, - FcObjectFromName ((const char *) c->word)); - if (e || else_string) + if (FcPatternFindIter (pat, &iter, (const char *) c->word) || else_string) { FcValueListPtr l = NULL; @@ -757,8 +748,7 @@ interpret_simple (FcFormatContext *c, FcStrBufChar (buf, '='); } - if (e) - l = FcPatternEltValues(e); + l = FcPatternIterGetValues (pat, &iter); if (idx != -1) { diff --git a/src/fcint.h b/src/fcint.h index d837a38..a402ca2 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -1150,6 +1150,15 @@ FcPatternAppend (FcPattern *p, FcPattern *s); FcPrivate int FcPatternPosition (const FcPattern *p, const char *object); +FcPrivate FcBool +FcPatternFindObjectIter (const FcPattern *pat, FcPatternIter *iter, FcObject object); + +FcPrivate FcObject +FcPatternIterGetObjectId (const FcPattern *pat, FcPatternIter *iter); + +FcPrivate FcValueListPtr +FcPatternIterGetValues (const FcPattern *pat, FcPatternIter *iter); + FcPrivate FcChar32 FcStringHash (const FcChar8 *s); diff --git a/src/fcpat.c b/src/fcpat.c index e624aea..eb534c3 100644 --- a/src/fcpat.c +++ b/src/fcpat.c @@ -392,13 +392,23 @@ FcPatternDestroy (FcPattern *p) return; elts = FcPatternElts (p); - for (i = 0; i < p->num; i++) + for (i = 0; i < FcPatternObjectCount (p); i++) FcValueListDestroy (FcPatternEltValues(&elts[i])); free (elts); free (p); } +int +FcPatternObjectCount (const FcPattern *pat) +{ + if (pat) + return pat->num; + + return 0; +} + + static int FcPatternObjectPosition (const FcPattern *p, FcObject object) { @@ -406,7 +416,7 @@ FcPatternObjectPosition (const FcPattern *p, FcObject object) FcPatternElt *elts = FcPatternElts(p); low = 0; - high = p->num - 1; + high = FcPatternObjectCount (p) - 1; c = 1; mid = 0; while (low <= high) @@ -452,7 +462,7 @@ FcPatternObjectInsertElt (FcPattern *p, FcObject object) i = -i - 1; /* reallocate array */ - if (p->num + 1 >= p->size) + if (FcPatternObjectCount (p) + 1 >= p->size) { int s = p->size + 16; if (p->size) @@ -463,7 +473,7 @@ FcPatternObjectInsertElt (FcPattern *p, FcObject object) { e = malloc(s * sizeof (FcPatternElt)); if (e) - memcpy(e, e0, p->num * sizeof (FcPatternElt)); + memcpy(e, e0, FcPatternObjectCount (p) * sizeof (FcPatternElt)); } } else @@ -484,7 +494,7 @@ FcPatternObjectInsertElt (FcPattern *p, FcObject object) memmove (e + i + 1, e + i, sizeof (FcPatternElt) * - (p->num - i)); + (FcPatternObjectCount (p) - i)); /* bump count */ p->num++; @@ -499,24 +509,26 @@ FcPatternObjectInsertElt (FcPattern *p, FcObject object) FcBool FcPatternEqual (const FcPattern *pa, const FcPattern *pb) { - int i; - FcPatternElt *pae, *pbe; + FcPatternIter ia, ib; if (pa == pb) return FcTrue; - if (pa->num != pb->num) + if (FcPatternObjectCount (pa) != FcPatternObjectCount (pb)) return FcFalse; - pae = FcPatternElts(pa); - pbe = FcPatternElts(pb); - for (i = 0; i < pa->num; i++) - { - if (pae[i].object != pbe[i].object) - return FcFalse; - if (!FcValueListEqual (FcPatternEltValues(&pae[i]), - FcPatternEltValues(&pbe[i]))) + FcPatternIterStart (pa, &ia); + FcPatternIterStart (pb, &ib); + do { + FcBool ra, rb; + + if (!FcPatternIterEqual (pa, &ia, pb, &ib)) return FcFalse; - } + ra = FcPatternIterNext (pa, &ia); + rb = FcPatternIterNext (pb, &ib); + if (!ra && !rb) + break; + } while (1); + return FcTrue; } @@ -527,7 +539,7 @@ FcPatternHash (const FcPattern *p) FcChar32 h = 0; FcPatternElt *pe = FcPatternElts(p); - for (i = 0; i < p->num; i++) + for (i = 0; i < FcPatternObjectCount (p); i++) { h = (((h << 1) | (h >> 31)) ^ pe[i].object ^ @@ -713,10 +725,10 @@ FcPatternObjectDel (FcPattern *p, FcObject object) /* shuffle existing ones down */ memmove (e, e+1, - (FcPatternElts(p) + p->num - (e + 1)) * + (FcPatternElts(p) + FcPatternObjectCount (p) - (e + 1)) * sizeof (FcPatternElt)); p->num--; - e = FcPatternElts(p) + p->num; + e = FcPatternElts(p) + FcPatternObjectCount (p); e->object = 0; e->values = NULL; return FcTrue; @@ -1115,8 +1127,7 @@ FcPattern * FcPatternDuplicate (const FcPattern *orig) { FcPattern *new; - FcPatternElt *e; - int i; + FcPatternIter iter; FcValueListPtr l; if (!orig) @@ -1126,20 +1137,18 @@ FcPatternDuplicate (const FcPattern *orig) if (!new) goto bail0; - e = FcPatternElts(orig); - - for (i = 0; i < orig->num; i++) + FcPatternIterStart (orig, &iter); + do { - for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l)) + for (l = FcPatternIterGetValues (orig, &iter); l; l = FcValueListNext (l)) { - if (!FcPatternObjectAddWithBinding (new, e[i].object, + if (!FcPatternObjectAddWithBinding (new, FcPatternIterGetObjectId (orig, &iter), FcValueCanonicalize(&l->value), l->binding, FcTrue)) goto bail1; - } - } + } while (FcPatternIterNext (orig, &iter)); return new; @@ -1184,21 +1193,21 @@ FcPatternBuild (FcPattern *p, ...) FcBool FcPatternAppend (FcPattern *p, FcPattern *s) { - int i; - FcPatternElt *e; - FcValueListPtr v; + FcPatternIter iter; + FcValueListPtr v; - for (i = 0; i < s->num; i++) + FcPatternIterStart (s, &iter); + do { - e = FcPatternElts(s)+i; - for (v = FcPatternEltValues(e); v; v = FcValueListNext(v)) + for (v = FcPatternIterGetValues (s, &iter); v; v = FcValueListNext (v)) { - if (!FcPatternObjectAddWithBinding (p, e->object, + if (!FcPatternObjectAddWithBinding (p, FcPatternIterGetObjectId (s, &iter), FcValueCanonicalize(&v->value), v->binding, FcTrue)) return FcFalse; } - } + } while (FcPatternIterNext (s, &iter)); + return FcTrue; } @@ -1239,6 +1248,148 @@ bail0: return NULL; } +typedef struct _FcPatternPrivateIter { + FcPatternElt *elt; + int pos; +} FcPatternPrivateIter; + +static void +FcPatternIterSet (const FcPattern *pat, FcPatternPrivateIter *iter) +{ + iter->elt = FcPatternObjectCount (pat) > 0 && iter->pos < FcPatternObjectCount (pat) ? &FcPatternElts (pat)[iter->pos] : NULL; +} + +void +FcPatternIterStart (const FcPattern *pat, FcPatternIter *iter) +{ + FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter; + + priv->pos = 0; + FcPatternIterSet (pat, priv); +} + +FcBool +FcPatternIterNext (const FcPattern *pat, FcPatternIter *iter) +{ + FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter; + + priv->pos++; + if (priv->pos >= FcPatternObjectCount (pat)) + return FcFalse; + FcPatternIterSet (pat, priv); + + return FcTrue; +} + +FcBool +FcPatternIterEqual (const FcPattern *p1, FcPatternIter *i1, + const FcPattern *p2, FcPatternIter *i2) +{ + FcBool b1 = FcPatternIterIsValid (p1, i1); + FcBool b2 = FcPatternIterIsValid (p2, i2); + + if (!i1 && !i2) + return FcTrue; + if (!b1 || !b2) + return FcFalse; + if (FcPatternIterGetObjectId (p1, i1) != FcPatternIterGetObjectId (p2, i2)) + return FcFalse; + + return FcValueListEqual (FcPatternIterGetValues (p1, i1), + FcPatternIterGetValues (p2, i2)); +} + +FcBool +FcPatternFindObjectIter (const FcPattern *pat, FcPatternIter *iter, FcObject object) +{ + FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter; + int i = FcPatternObjectPosition (pat, object); + + priv->elt = NULL; + if (i < 0) + return FcFalse; + + priv->pos = i; + FcPatternIterSet (pat, priv); + + return FcTrue; +} + +FcBool +FcPatternFindIter (const FcPattern *pat, FcPatternIter *iter, const char *object) +{ + return FcPatternFindObjectIter (pat, iter, FcObjectFromName (object)); +} + +FcBool +FcPatternIterIsValid (const FcPattern *pat, FcPatternIter *iter) +{ + FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter; + + if (priv && priv->elt) + return FcTrue; + + return FcFalse; +} + +FcObject +FcPatternIterGetObjectId (const FcPattern *pat, FcPatternIter *iter) +{ + FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter; + + if (priv && priv->elt) + return priv->elt->object; + + return 0; +} + +const char * +FcPatternIterGetObject (const FcPattern *pat, FcPatternIter *iter) +{ + return FcObjectName (FcPatternIterGetObjectId (pat, iter)); +} + +FcValueListPtr +FcPatternIterGetValues (const FcPattern *pat, FcPatternIter *iter) +{ + FcPatternPrivateIter *priv = (FcPatternPrivateIter *) iter; + + if (priv && priv->elt) + return FcPatternEltValues (priv->elt); + + return NULL; +} + +int +FcPatternIterValueCount (const FcPattern *pat, FcPatternIter *iter) +{ + int count = 0; + FcValueListPtr l; + + for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l)) + count++; + + return count; +} + +FcResult +FcPatternIterGetValue (const FcPattern *pat, FcPatternIter *iter, int id, FcValue *v, FcValueBinding *b) +{ + FcValueListPtr l; + + for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l)) + { + if (id == 0) + { + *v = FcValueCanonicalize (&l->value); + if (b) + *b = l->binding; + return FcResultMatch; + } + id--; + } + return FcResultNoId; +} FcBool FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat) @@ -1248,9 +1399,9 @@ FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat) if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern))) return FcFalse; - if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt))) + if (!FcSerializeAlloc (serialize, elts, FcPatternObjectCount (pat) * sizeof (FcPatternElt))) return FcFalse; - for (i = 0; i < pat->num; i++) + for (i = 0; i < FcPatternObjectCount (pat); i++) if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i))) return FcFalse; return FcTrue; @@ -1269,7 +1420,7 @@ FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat) if (!pat_serialized) return NULL; *pat_serialized = *pat; - pat_serialized->size = pat->num; + pat_serialized->size = FcPatternObjectCount (pat); FcRefSetConst (&pat_serialized->ref); elts_serialized = FcSerializePtr (serialize, elts); @@ -1279,7 +1430,7 @@ FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat) pat_serialized->elts_offset = FcPtrToOffset (pat_serialized, elts_serialized); - for (i = 0; i < pat->num; i++) + for (i = 0; i < FcPatternObjectCount (pat); i++) { values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i)); if (!values_serialized) commit 454923709a1a1e480554c400e053aea9a1ba951a Author: Akira TAGOH <akira@xxxxxxxxx> Date: Thu May 10 22:01:29 2018 +0900 Change the emboldening logic again enable emboldening when request was >= bold and font was <= medium https://bugs.freedesktop.org/show_bug.cgi?id=106460 diff --git a/conf.d/90-synthetic.conf b/conf.d/90-synthetic.conf index e344e4a..6b929dd 100644 --- a/conf.d/90-synthetic.conf +++ b/conf.d/90-synthetic.conf @@ -42,9 +42,9 @@ --> <match target="font"> - <!-- check to see if the font is just regular --> + <!-- check to see if the weight in the font is less than medium which possibly need emboldening --> <test name="weight" compare="less_eq"> - <const>regular</const> + <const>medium</const> </test> <!-- check to see if the pattern requests bold --> <test target="pattern" name="weight" compare="more_eq"> _______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/fontconfig