1 diff --git a/conf.d/30-metric-aliases.conf b/conf.d/30-metric-aliases.conf
2 index f25052a..0fd0b8a 100644
3 --- a/conf.d/30-metric-aliases.conf
4 +++ b/conf.d/30-metric-aliases.conf
7 <family>Helvetica</family>
9 + <family>TeX Gyre Heros</family>
10 <family>Nimbus Sans L</family>
14 <alias binding="same">
15 <family>Times</family>
17 + <family>TeX Gyre Termes</family>
18 <family>Nimbus Roman No9 L</family>
22 <alias binding="same">
23 <family>Arial</family>
25 + <family>TeX Gyre Heros</family>
26 <family>Arimo</family>
27 <family>Liberation Sans</family>
28 <family>Albany</family>
30 <alias binding="same">
31 <family>Times New Roman</family>
33 + <family>TeX Gyre Termes</family>
34 <family>Tinos</family>
35 <family>Liberation Serif</family>
36 <family>Thorndale</family>
40 <alias binding="same">
41 + <family>Georgia</family>
43 + <family>Gelasio</family>
47 + <alias binding="same">
48 <family>Courier New</family>
50 <family>Cousine</family>
51 diff --git a/conf.d/45-latin.conf b/conf.d/45-latin.conf
52 index 09fd526..aa62ed4 100644
53 --- a/conf.d/45-latin.conf
54 +++ b/conf.d/45-latin.conf
56 <family>Thorndale</family>
57 <default><family>serif</family></default>
60 + <family>Georgia</family>
61 + <default><family>serif</family></default>
64 + <family>Garamond</family>
65 + <default><family>serif</family></default>
68 + <family>Palatino Linotype</family>
69 + <default><family>serif</family></default>
72 + <family>Trebuchet MS</family>
73 + <default><family>serif</family></default>
78 diff --git a/configure.ac b/configure.ac
79 index 0f129db..321fece 100644
82 @@ -54,6 +54,9 @@ AC_SUBST(LIBT_VERSION_INFO)
83 LIBT_CURRENT_MINUS_AGE=`expr $LIBT_CURRENT - $LIBT_AGE`
84 AC_SUBST(LIBT_CURRENT_MINUS_AGE)
87 +PKGCONFIG_REQUIRES_PRIVATELY=
89 dnl ==========================================================================
91 AC_CONFIG_HEADERS(config.h)
92 @@ -161,6 +164,37 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([[
94 AC_DEFINE([HAVE_POSIX_FADVISE], [1], [Define to 1 if you have the 'posix_fadvise' function.])
95 ],[AC_MSG_RESULT([no])])
96 +if test "$os_win32" = "no"; then
97 + AC_MSG_CHECKING([for scandir])
98 + AC_LINK_IFELSE([AC_LANG_SOURCE([[
100 + int comp(const struct dirent **, const struct dirent **);
101 + int comp(const struct dirent **a, const struct dirent **b) { return 0; }
104 + return scandir(".", &d, 0, &comp) >= 0;
107 + AC_MSG_RESULT([yes])
108 + AC_DEFINE([HAVE_SCANDIR], [1], [Define to 1 if you have the 'scandir' function.])
110 + AC_LINK_IFELSE([AC_LANG_SOURCE([[
111 + #include <dirent.h>
112 + int comp(const void *, const void *);
113 + int comp(const void *a, const void *b) { return 0; }
116 + return scandir(".", &d, 0, &comp) >= 0;
119 + AC_MSG_RESULT([yes])
120 + AC_DEFINE([HAVE_SCANDIR_VOID_P], [1], [Define to 1 if you have the 'scandir' function with int (* compar)(const void *, const void *)])
123 +*** No scandir function available.])
127 CFLAGS="$fc_saved_CFLAGS"
130 @@ -251,13 +285,14 @@ if test "x$enable_iconv" != "xno"; then
131 AC_TRY_LINK([#include <iconv.h>],
132 [iconv_open ("from", "to");],
133 [iconv_type="libiconv"
136 + ICONV_CFLAGS="$libiconv_cflags"
137 + ICONV_LIBS="$libiconv_libs"
141 CFLAGS="$iconvsaved_CFLAGS"
142 LIBS="$iconvsaved_LIBS"
143 - ICONV_CFLAGS="$libiconv_cflags"
144 - ICONV_LIBS="$libiconv_libs"
146 if test "x$use_iconv" = "x0"; then
147 AC_TRY_LINK([#include <iconv.h>],
148 @@ -277,6 +312,7 @@ AC_DEFINE_UNQUOTED(USE_ICONV,$use_iconv,[Use iconv.])
149 # Checks for FreeType
151 PKG_CHECK_MODULES(FREETYPE, freetype2)
152 +PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES freetype2"
154 AC_SUBST(FREETYPE_LIBS)
155 AC_SUBST(FREETYPE_CFLAGS)
156 @@ -336,6 +372,8 @@ if test "$enable_libxml2" != "yes"; then
161 + PKGCONFIG_REQUIRES_PRIVATELY="$PKGCONFIG_REQUIRES_PRIVATELY expat"
164 expatsaved_CPPFLAGS="$CPPFLAGS"
165 @@ -377,6 +415,7 @@ AC_ARG_ENABLE(libxml2,
167 if test "$enable_libxml2" = "yes"; then
168 PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.6])
169 + PKGCONFIG_REQUIRES_PRIVATELY="$PKGCONFIG_REQUIRES_PRIVATELY libxml-2.0"
170 AC_DEFINE_UNQUOTED(ENABLE_LIBXML2,1,[Use libxml2 instead of Expat])
172 AC_SUBST(LIBXML2_CFLAGS)
173 @@ -684,6 +723,12 @@ dnl include the header file for workaround of miscalculating size on autoconf
174 dnl particularly for fat binaries
175 AH_BOTTOM([#include "config-fixups.h"])
179 +AC_SUBST(PKGCONFIG_REQUIRES)
180 +AC_SUBST(PKGCONFIG_REQUIRES_PRIVATELY)
186 diff --git a/fontconfig.pc.in b/fontconfig.pc.in
187 index 9ef2c27..6e112bb 100644
188 --- a/fontconfig.pc.in
189 +++ b/fontconfig.pc.in
190 @@ -11,6 +11,8 @@ cachedir=@fc_cachedir@
192 Description: Font configuration and customization library
194 +Requires: @PKGCONFIG_REQUIRES@
195 +Requires.private: @PKGCONFIG_REQUIRES_PRIVATELY@
196 Libs: -L${libdir} -lfontconfig
197 -Libs.private: @LIBXML2_LIBS@ @EXPAT_LIBS@ @FREETYPE_LIBS@ @ICONV_LIBS@
198 -Cflags: -I${includedir}
199 +Libs.private: @EXPAT_LIBS@ @FREETYPE_LIBS@ @ICONV_LIBS@ @LIBXML2_LIBS@
200 +Cflags: -I${includedir} @EXPAT_CFLAGS@ @FREETYPE_CFLAGS@ @ICONV_CFLAGS@ @LIBXML2_CFLAGS@
201 diff --git a/fontconfig/fcprivate.h b/fontconfig/fcprivate.h
202 index 18b8c08..210c1d8 100644
203 --- a/fontconfig/fcprivate.h
204 +++ b/fontconfig/fcprivate.h
206 __o__ = va_arg (va, const char *); \
209 - __v__.type = va_arg (va, FcType); \
210 + __v__.type = va_arg (va, int); \
211 switch (__v__.type) { \
212 + case FcTypeUnknown: \
214 goto _FcPatternVapBuild_bail1; \
215 case FcTypeInteger: \
216 diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
217 index 422187b..39d1b1b 100644
218 --- a/fontconfig/fontconfig.h
219 +++ b/fontconfig/fontconfig.h
220 @@ -185,6 +185,7 @@ typedef int FcBool;
221 #define FC_LCD_LEGACY 3
223 typedef enum _FcType {
224 + FcTypeUnknown = -1,
228 diff --git a/src/fccache.c b/src/fccache.c
229 index 9f1c298..e02d49e 100644
232 @@ -830,34 +830,6 @@ bail1:
239 -#define mkdir(path,mode) _mkdir(path)
243 -FcMakeDirectory (const FcChar8 *dir)
248 - if (strlen ((char *) dir) == 0)
251 - parent = FcStrDirname (dir);
254 - if (access ((char *) parent, F_OK) == 0)
255 - ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
256 - else if (access ((char *) parent, F_OK) == -1)
257 - ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
260 - FcStrFree (parent);
264 /* write serialized state to the cache file */
266 FcDirCacheWrite (FcCache *cache, FcConfig *config)
267 diff --git a/src/fccfg.c b/src/fccfg.c
268 index fcdf73e..be738d5 100644
271 @@ -214,10 +214,8 @@ FcSubstDestroy (FcSubst *s)
276 - FcTestDestroy (s->test);
278 - FcEditDestroy (s->edit);
280 + FcRuleDestroy (s->rule);
284 @@ -226,20 +224,20 @@ FcSubstDestroy (FcSubst *s)
286 FcConfigAllocExpr (FcConfig *config)
288 - if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
290 - FcExprPage *new_page;
291 + if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
293 + FcExprPage *new_page;
295 - new_page = malloc (sizeof (FcExprPage));
298 + new_page = malloc (sizeof (FcExprPage));
302 - new_page->next_page = config->expr_pool;
303 - new_page->next = new_page->exprs;
304 - config->expr_pool = new_page;
306 + new_page->next_page = config->expr_pool;
307 + new_page->next = new_page->exprs;
308 + config->expr_pool = new_page;
311 - return config->expr_pool->next++;
312 + return config->expr_pool->next++;
316 @@ -644,15 +642,13 @@ FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
317 return FcConfigSetRescanInterval (config, rescanInterval);
322 -FcConfigAddEdit (FcConfig *config,
325 +FcConfigAddRule (FcConfig *config,
329 FcSubst *subst, **prev;
335 @@ -673,15 +669,27 @@ FcConfigAddEdit (FcConfig *config,
337 for (; *prev; prev = &(*prev)->next);
340 - subst->test = test;
341 - subst->edit = edit;
342 + subst->next = NULL;
343 + subst->rule = rule;
345 - for (t = test; t; t = t->next)
346 + for (r = rule; r; r = r->next)
348 - if (t->kind == FcMatchDefault)
355 + r->u.test->kind == FcMatchDefault)
356 + r->u.test->kind = kind;
357 + if (r->u.test->object > FC_MAX_BASE_OBJECT)
361 + if (r->u.edit->object > FC_MAX_BASE_OBJECT)
368 if (config->maxObjects < num)
369 config->maxObjects = num;
370 @@ -721,7 +729,7 @@ FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
373 FcConfigCompareValue (const FcValue *left_o,
376 const FcValue *right_o)
378 FcValue left = FcValueCanonicalize(left_o);
379 @@ -736,6 +744,8 @@ FcConfigCompareValue (const FcValue *left_o,
380 if (left.type == right.type)
383 + case FcTypeUnknown:
384 + break; /* No way to guess how to compare for this object */
386 break; /* FcConfigPromote prevents this from happening */
388 @@ -1484,13 +1494,16 @@ FcConfigSubstituteWithPat (FcConfig *config,
398 + FcValueList *l, **value = NULL;
401 + FcObject object = FC_INVALID_OBJECT;
402 + FcPatternElt **elt = NULL;
404 + FcBool retval = FcTrue;
406 +#define FC_OBJ_ID(_n_) ((_n_) > FC_MAX_BASE_OBJECT ? ((_n_) - FC_EXT_OBJ_INDEX) : (_n_))
410 @@ -1535,9 +1548,19 @@ FcConfigSubstituteWithPat (FcConfig *config,
414 - st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState));
415 - if (!st && config->maxObjects)
417 + nobjs = FC_MAX_BASE_OBJECT + config->maxObjects + 2;
418 + value = (FcValueList **) malloc (SIZEOF_VOID_P * nobjs);
424 + elt = (FcPatternElt **) malloc (SIZEOF_VOID_P * nobjs);
431 if (FcDebug () & FC_DBG_EDIT)
433 @@ -1546,200 +1569,185 @@ FcConfigSubstituteWithPat (FcConfig *config,
435 for (; s; s = s->next)
438 - * Check the tests to see if
439 - * they all match the pattern
441 - for (t = s->test, i = 0; t; t = t->next, i++)
443 + for (i = 0; i < nobjs; i++)
445 - if (FcDebug () & FC_DBG_EDIT)
447 - printf ("FcConfigSubstitute test ");
451 - if (kind == FcMatchFont && t->kind == FcMatchPattern)
456 - st[i].elt = FcPatternObjectFindElt (m, t->object);
460 - * If there's no such field in the font,
461 - * then FcQualAll matches while FcQualAny does not
465 - if (t->qual == FcQualAll)
469 + for (; r; r = r->next)
472 + case FcRuleUnknown:
473 + /* shouldn't be reached */
476 + object = FC_OBJ_ID (r->u.test->object);
478 + * Check the tests to see if
479 + * they all match the pattern
481 + if (FcDebug () & FC_DBG_EDIT)
485 + printf ("FcConfigSubstitute test ");
486 + FcTestPrint (r->u.test);
488 + if (kind == FcMatchFont && r->u.test->kind == FcMatchPattern)
494 - * Check to see if there is a match, mark the location
495 - * to apply match-relative edits
497 - st[i].value = FcConfigMatchValueList (m, p_pat, kind, t, st[i].elt->values);
500 - if (t->qual == FcQualFirst && st[i].value != st[i].elt->values)
502 - if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values)
507 - if (FcDebug () & FC_DBG_EDIT)
508 - printf ("No match\n");
511 - if (FcDebug () & FC_DBG_EDIT)
513 - printf ("Substitute ");
516 - for (e = s->edit; e; e = e->next)
519 - * Evaluate the list of expressions
521 - l = FcConfigValues (p, p_pat,kind, e->expr, e->binding);
523 - * Locate any test associated with this field, skipping
524 - * tests associated with the pattern when substituting in
527 - for (t = s->test, i = 0; t; t = t->next, i++)
529 - if ((t->kind == FcMatchFont || kind == FcMatchPattern) &&
530 - t->object == e->object)
533 + elt[object] = FcPatternObjectFindElt (m, r->u.test->object);
535 + * If there's no such field in the font,
536 + * then FcQualAll matches while FcQualAny does not
541 - * KLUDGE - the pattern may have been reallocated or
542 - * things may have been inserted or deleted above
543 - * this element by other edits. Go back and find
544 - * the element again
546 - if (e != s->edit && st[i].elt)
547 - st[i].elt = FcPatternObjectFindElt (p, t->object);
551 + if (r->u.test->qual == FcQualAll)
553 + value[object] = NULL;
558 + if (FcDebug () & FC_DBG_EDIT)
559 + printf ("No match\n");
564 - switch (FC_OP_GET_OP (e->op)) {
567 - * If there was a test, then replace the matched
568 - * value with the new list of values
569 + * Check to see if there is a match, mark the location
570 + * to apply match-relative edits
573 + value[object] = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt[object]->values);
574 + if (!value[object] ||
575 + (r->u.test->qual == FcQualFirst && value[object] != elt[object]->values) ||
576 + (r->u.test->qual == FcQualNotFirst && value[object] == elt[object]->values))
578 - FcValueList *thisValue = st[i].value;
579 - FcValueList *nextValue = thisValue;
581 + if (FcDebug () & FC_DBG_EDIT)
582 + printf ("No match\n");
587 + object = FC_OBJ_ID (r->u.edit->object);
588 + if (FcDebug () & FC_DBG_EDIT)
590 + printf ("Substitute ");
591 + FcEditPrint (r->u.edit);
595 + * Evaluate the list of expressions
597 + l = FcConfigValues (p, p_pat,kind, r->u.edit->expr, r->u.edit->binding);
599 + switch (FC_OP_GET_OP (r->u.edit->op)) {
602 - * Append the new list of values after the current value
603 + * If there was a test, then replace the matched
604 + * value with the new list of values
606 - FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l, e->object);
609 + FcValueList *thisValue = value[object];
610 + FcValueList *nextValue = l;
613 + * Append the new list of values after the current value
615 + FcConfigAdd (&elt[object]->values, thisValue, FcTrue, l, r->u.edit->object);
617 + * Delete the marked value
620 + FcConfigDel (&elt[object]->values, thisValue);
622 + * Adjust a pointer into the value list to ensure
623 + * future edits occur at the same place
625 + value[object] = nextValue;
628 + /* fall through ... */
629 + case FcOpAssignReplace:
631 - * Delete the marked value
632 + * Delete all of the values and insert
636 - FcConfigDel (&st[i].elt->values, thisValue);
637 + FcConfigPatternDel (p, r->u.edit->object);
638 + FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
640 - * Adjust any pointers into the value list to ensure
641 - * future edits occur at the same place
642 + * Adjust a pointer into the value list as they no
643 + * longer point to anything valid
645 - for (t = s->test, i = 0; t; t = t->next, i++)
646 + value[object] = NULL;
651 - if (st[i].value == thisValue)
652 - st[i].value = nextValue;
653 + FcConfigAdd (&elt[object]->values, value[object], FcFalse, l, r->u.edit->object);
656 + /* fall through ... */
657 + case FcOpPrependFirst:
658 + FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse);
661 - /* fall through ... */
662 - case FcOpAssignReplace:
664 - * Delete all of the values and insert
667 - FcConfigPatternDel (p, e->object);
668 - FcConfigPatternAdd (p, e->object, l, FcTrue);
670 - * Adjust any pointers into the value list as they no
671 - * longer point to anything valid
675 - FcPatternElt *thisElt = st[i].elt;
676 - for (t = s->test, i = 0; t; t = t->next, i++)
680 - if (st[i].elt == thisElt)
682 + FcConfigAdd (&elt[object]->values, value[object], FcTrue, l, r->u.edit->object);
690 - FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l, e->object);
691 + /* fall through ... */
692 + case FcOpAppendLast:
693 + FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
696 - /* fall through ... */
697 - case FcOpPrependFirst:
698 - FcConfigPatternAdd (p, e->object, l, FcFalse);
703 - FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l, e->object);
707 + FcConfigDel (&elt[object]->values, value[object]);
710 + /* fall through ... */
711 + case FcOpDeleteAll:
712 + FcConfigPatternDel (p, r->u.edit->object);
715 + FcValueListDestroy (l);
718 - /* fall through ... */
719 - case FcOpAppendLast:
720 - FcConfigPatternAdd (p, e->object, l, FcTrue);
725 + * Now go through the pattern and eliminate
726 + * any properties without data
728 + FcConfigPatternCanon (p, r->u.edit->object);
730 + if (FcDebug () & FC_DBG_EDIT)
732 - FcConfigDel (&st[i].elt->values, st[i].value);
734 + printf ("FcConfigSubstitute edit");
735 + FcPatternPrint (p);
737 - /* fall through ... */
738 - case FcOpDeleteAll:
739 - FcConfigPatternDel (p, e->object);
742 - FcValueListDestroy (l);
747 - * Now go through the pattern and eliminate
748 - * any properties without data
750 - for (e = s->edit; e; e = e->next)
751 - FcConfigPatternCanon (p, e->object);
753 - if (FcDebug () & FC_DBG_EDIT)
755 - printf ("FcConfigSubstitute edit");
756 - FcPatternPrint (p);
761 if (FcDebug () & FC_DBG_EDIT)
763 printf ("FcConfigSubstitute done");
779 diff --git a/src/fccompat.c b/src/fccompat.c
780 index a217160..d4f88c8 100644
783 @@ -219,3 +219,30 @@ FcRandom(void)
790 +#define mkdir(path,mode) _mkdir(path)
794 +FcMakeDirectory (const FcChar8 *dir)
799 + if (strlen ((char *) dir) == 0)
802 + parent = FcStrDirname (dir);
805 + if (access ((char *) parent, F_OK) == 0)
806 + ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
807 + else if (access ((char *) parent, F_OK) == -1)
808 + ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
811 + FcStrFree (parent);
814 diff --git a/src/fcdbg.c b/src/fcdbg.c
815 index 9d02f5a..d74bc27 100644
818 @@ -30,6 +30,9 @@ static void
819 _FcValuePrintFile (FILE *f, const FcValue v)
822 + case FcTypeUnknown:
823 + fprintf (f, "<unknown>");
826 fprintf (f, "<void>");
828 @@ -98,6 +101,10 @@ FcValueBindingPrint (const FcValueListPtr l)
829 case FcValueBindingSame:
833 + /* shouldn't be reached */
839 @@ -420,21 +427,38 @@ FcEditPrint (const FcEdit *edit)
841 FcSubstPrint (const FcSubst *subst)
846 + FcRuleType last_type = FcRuleUnknown;
849 - for (t = subst->test; t; t = t->next)
855 - for (e = subst->edit; e; e = e->next)
856 + for (r = subst->rule; r; r = r->next)
858 + if (last_type != r->type)
862 + printf ("[test]\n");
865 + printf ("[edit]\n");
870 + last_type = r->type;
877 + FcTestPrint (r->u.test);
880 + FcEditPrint (r->u.edit);
889 diff --git a/src/fcdir.c b/src/fcdir.c
890 index dc580bb..b040a28 100644
893 @@ -49,6 +49,16 @@ FcFileIsLink (const FcChar8 *file)
898 +FcFileIsFile (const FcChar8 *file)
902 + if (FcStat (file, &statb) != 0)
904 + return S_ISREG (statb.st_mode);
908 FcFileScanFontConfig (FcFontSet *set,
910 diff --git a/src/fchash.c b/src/fchash.c
911 index 92585a6..7216bee 100644
914 @@ -190,14 +190,14 @@ FcHashGetSHA256Digest (const FcChar8 *input_strings,
916 /* set input size at the end */
918 - block[63 - 0] = len & 0xff;
919 - block[63 - 1] = (len >> 8) & 0xff;
920 - block[63 - 2] = (len >> 16) & 0xff;
921 - block[63 - 3] = (len >> 24) & 0xff;
922 - block[63 - 4] = (len >> 32) & 0xff;
923 - block[63 - 5] = (len >> 40) & 0xff;
924 - block[63 - 6] = (len >> 48) & 0xff;
925 - block[63 - 7] = (len >> 56) & 0xff;
926 + block[63 - 0] = (uint64_t)len & 0xff;
927 + block[63 - 1] = ((uint64_t)len >> 8) & 0xff;
928 + block[63 - 2] = ((uint64_t)len >> 16) & 0xff;
929 + block[63 - 3] = ((uint64_t)len >> 24) & 0xff;
930 + block[63 - 4] = ((uint64_t)len >> 32) & 0xff;
931 + block[63 - 5] = ((uint64_t)len >> 40) & 0xff;
932 + block[63 - 6] = ((uint64_t)len >> 48) & 0xff;
933 + block[63 - 7] = ((uint64_t)len >> 56) & 0xff;
934 FcHashComputeSHA256Digest (ret, block);
936 return FcHashSHA256ToString (ret);
937 @@ -226,7 +226,7 @@ FcHashGetSHA256DigestFromFile (const FcChar8 *filename)
939 if ((len = fread (ibuf, sizeof (char), 64, fp)) < 64)
945 memset (&ibuf[len], 0, 64 - len);
946 @@ -281,7 +281,7 @@ FcHashGetSHA256DigestFromMemory (const char *fontdata,
948 if ((length - i) < 64)
955 diff --git a/src/fcint.h b/src/fcint.h
956 index 65bf333..ec0c674 100644
966 #include <sys/types.h>
967 @@ -85,7 +86,7 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
968 #define FC_DBG_CONFIG 1024
969 #define FC_DBG_LANGSET 2048
971 -#define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
972 +#define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] FC_UNUSED
973 #define _FC_ASSERT_STATIC0(_line, _cond) _FC_ASSERT_STATIC1 (_line, (_cond))
974 #define FC_ASSERT_STATIC(_cond) _FC_ASSERT_STATIC0 (__LINE__, (_cond))
976 @@ -107,7 +108,9 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
977 FC_ASSERT_STATIC (sizeof (FcRef) == sizeof (int));
979 typedef enum _FcValueBinding {
980 - FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame
981 + FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame,
982 + /* to make sure sizeof (FcValueBinding) == 4 even with -fshort-enums */
983 + FcValueBindingEnd = INT_MAX
986 #define FcStrdup(s) ((FcChar8 *) strdup ((const char *) (s)))
987 @@ -171,6 +174,11 @@ typedef struct _FcValueList {
989 typedef int FcObject;
991 +/* The 1000 is to leave some room for future added internal objects, such
992 + * that caches from newer fontconfig can still be used with older fontconfig
993 + * without getting confused. */
994 +#define FC_EXT_OBJ_INDEX 1000
996 typedef struct _FcPatternElt *FcPatternEltPtr;
999 @@ -271,7 +279,6 @@ typedef enum _FcQual {
1000 #define FcMatchDefault ((FcMatchKind) -1)
1002 typedef struct _FcTest {
1003 - struct _FcTest *next;
1007 @@ -280,17 +287,28 @@ typedef struct _FcTest {
1010 typedef struct _FcEdit {
1011 - struct _FcEdit *next;
1015 FcValueBinding binding;
1018 +typedef enum _FcRuleType {
1019 + FcRuleUnknown, FcRuleTest, FcRuleEdit
1022 +typedef struct _FcRule {
1023 + struct _FcRule *next;
1031 typedef struct _FcSubst {
1032 struct _FcSubst *next;
1038 typedef struct _FcCharLeaf {
1039 @@ -610,10 +628,9 @@ FcPrivate FcBool
1040 FcConfigAddBlank (FcConfig *config,
1044 -FcConfigAddEdit (FcConfig *config,
1048 +FcConfigAddRule (FcConfig *config,
1053 @@ -623,7 +640,7 @@ FcConfigSetFonts (FcConfig *config,
1056 FcConfigCompareValue (const FcValue *m,
1062 @@ -730,6 +747,9 @@ FcMakeTempfile (char *template);
1067 +FcMakeDirectory (const FcChar8 *dir);
1072 @@ -788,6 +808,9 @@ FcPrivate FcBool
1073 FcFileIsLink (const FcChar8 *file);
1076 +FcFileIsFile (const FcChar8 *file);
1079 FcFileScanConfig (FcFontSet *set,
1082 @@ -840,6 +863,9 @@ FcTestDestroy (FcTest *test);
1084 FcEditDestroy (FcEdit *e);
1087 +FcRuleDestroy (FcRule *rule);
1090 FcPrivate FcLangSet *
1091 FcFreeTypeLangSet (const FcCharSet *charset,
1092 diff --git a/src/fclist.c b/src/fclist.c
1093 index b7ae899..c56e24c 100644
1096 @@ -252,6 +252,7 @@ FcListValueHash (FcValue *value)
1098 FcValue v = FcValueCanonicalize(value);
1100 + case FcTypeUnknown:
1104 diff --git a/src/fcmatch.c b/src/fcmatch.c
1105 index 10976d6..dec92b9 100644
1108 @@ -245,6 +245,8 @@ typedef enum _FcMatcherPriorityDummy {
1109 typedef enum _FcMatcherPriority {
1117 diff --git a/src/fcname.c b/src/fcname.c
1118 index 6dd4d49..712b2fa 100644
1121 @@ -76,6 +76,8 @@ FcObjectValidType (FcObject object, FcType type)
1124 switch ((int) t->type) {
1125 + case FcTypeUnknown:
1129 if (type == FcTypeDouble || type == FcTypeInteger)
1130 @@ -86,7 +88,7 @@ FcObjectValidType (FcObject object, FcType type)
1134 - if (t->type == (unsigned int) -1 || type == t->type)
1135 + if (type == t->type)
1139 @@ -318,6 +320,12 @@ FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *l
1147 + while ((c = *cur))
1152 @@ -468,6 +476,7 @@ FcNameUnparseValue (FcStrBuf *buf,
1153 FcValue v = FcValueCanonicalize(v0);
1156 + case FcTypeUnknown:
1160 diff --git a/src/fcobjs.c b/src/fcobjs.c
1161 index 146ca70..bad9824 100644
1164 @@ -37,7 +37,7 @@ FcObjectTypeLookup (register const char *str, register unsigned int len);
1165 /* The 1000 is to leave some room for future added internal objects, such
1166 * that caches from newer fontconfig can still be used with older fontconfig
1167 * without getting confused. */
1168 -static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + 1000;
1169 +static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + FC_EXT_OBJ_INDEX;
1170 struct FcObjectOtherTypeInfo {
1171 struct FcObjectOtherTypeInfo *next;
1172 FcObjectType object;
1173 @@ -63,7 +63,7 @@ retry:
1176 ot->object.object = (const char *) FcStrdup (str);
1177 - ot->object.type = -1;
1178 + ot->object.type = FcTypeUnknown;
1179 ot->id = fc_atomic_int_add (next_id, +1);
1182 diff --git a/src/fcobjs.h b/src/fcobjs.h
1183 index 682fe6a..87c7319 100644
1186 @@ -23,7 +23,7 @@ FC_OBJECT (FILE, FcTypeString, FcCompareFilename)
1187 FC_OBJECT (INDEX, FcTypeInteger, NULL)
1188 FC_OBJECT (RASTERIZER, FcTypeString, FcCompareString)
1189 FC_OBJECT (OUTLINE, FcTypeBool, FcCompareBool)
1190 -FC_OBJECT (SCALABLE, FcTypeBool, NULL)
1191 +FC_OBJECT (SCALABLE, FcTypeBool, FcCompareBool)
1192 FC_OBJECT (DPI, FcTypeDouble, NULL)
1193 FC_OBJECT (RGBA, FcTypeInteger, NULL)
1194 FC_OBJECT (SCALE, FcTypeDouble, NULL)
1195 @@ -35,7 +35,7 @@ FC_OBJECT (CHARSET, FcTypeCharSet, FcCompareCharSet)
1196 FC_OBJECT (LANG, FcTypeLangSet, FcCompareLang)
1197 FC_OBJECT (FONTVERSION, FcTypeInteger, FcCompareNumber)
1198 FC_OBJECT (CAPABILITY, FcTypeString, NULL)
1199 -FC_OBJECT (FONTFORMAT, FcTypeString, NULL)
1200 +FC_OBJECT (FONTFORMAT, FcTypeString, FcCompareString)
1201 FC_OBJECT (EMBOLDEN, FcTypeBool, NULL)
1202 FC_OBJECT (EMBEDDED_BITMAP, FcTypeBool, NULL)
1203 FC_OBJECT (DECORATIVE, FcTypeBool, FcCompareBool)
1204 diff --git a/src/fcpat.c b/src/fcpat.c
1205 index 25bff64..0614ac2 100644
1208 @@ -246,6 +246,8 @@ FcValueEqual (FcValue va, FcValue vb)
1212 + case FcTypeUnknown:
1213 + return FcFalse; /* don't know how to compare this object */
1217 @@ -294,6 +296,7 @@ static FcChar32
1218 FcValueHash (const FcValue *v)
1221 + case FcTypeUnknown:
1225 @@ -317,7 +320,7 @@ FcValueHash (const FcValue *v)
1227 return FcLangSetHash (FcValueLangSet(v));
1234 diff --git a/src/fcstat.c b/src/fcstat.c
1235 index 390f45c..ab56aca 100644
1238 @@ -164,11 +164,21 @@ FcDirChecksumScandirFilter(const struct dirent *entry)
1242 +#ifdef HAVE_SCANDIR
1244 FcDirChecksumScandirSorter(const struct dirent **lhs, const struct dirent **rhs)
1246 return strcmp((*lhs)->d_name, (*rhs)->d_name);
1248 +#elif HAVE_SCANDIR_VOID_P
1250 +FcDirChecksumScandirSorter(const void *a, const void *b)
1252 + const struct dirent *lhs = a, *rhs = b;
1254 + return strcmp(lhs->d_name, rhs->d_name);
1259 FcDirChecksum (const FcChar8 *dir, time_t *checksum)
1260 diff --git a/src/fcxml.c b/src/fcxml.c
1261 index 470e44f..2cdf0ad 100644
1264 @@ -62,12 +62,30 @@ FcExprDestroy (FcExpr *e);
1266 FcTestDestroy (FcTest *test)
1269 - FcTestDestroy (test->next);
1270 FcExprDestroy (test->expr);
1275 +FcRuleDestroy (FcRule *rule)
1277 + FcRule *n = rule->next;
1279 + switch (rule->type) {
1281 + FcTestDestroy (rule->u.test);
1284 + FcEditDestroy (rule->u.edit);
1291 + FcRuleDestroy (n);
1295 FcExprCreateInteger (FcConfig *config, int i)
1297 @@ -300,8 +318,6 @@ FcExprDestroy (FcExpr *e)
1299 FcEditDestroy (FcEdit *e)
1302 - FcEditDestroy (e->next);
1304 FcExprDestroy (e->expr);
1306 @@ -705,7 +721,7 @@ FcTestCreate (FcConfigParse *parse,
1309 const FcChar8 *field,
1311 + unsigned int compare,
1314 FcTest *test = (FcTest *) malloc (sizeof (FcTest));
1315 @@ -714,7 +730,6 @@ FcTestCreate (FcConfigParse *parse,
1317 const FcObjectType *o;
1322 test->object = FcObjectFromName ((const char *) field);
1323 @@ -740,7 +755,6 @@ FcEditCreate (FcConfigParse *parse,
1325 const FcObjectType *o;
1331 @@ -752,6 +766,34 @@ FcEditCreate (FcConfigParse *parse,
1336 +FcRuleCreate (FcRuleType type,
1339 + FcRule *r = (FcRule *) malloc (sizeof (FcRule));
1349 + r->u.test = (FcTest *) p;
1352 + r->u.edit = (FcEdit *) p;
1364 FcVStackCreateAndPush (FcConfigParse *parse)
1366 @@ -1657,9 +1699,9 @@ static void
1367 FcParseAlias (FcConfigParse *parse)
1369 FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
1370 - FcEdit *edit = 0, *next;
1373 - FcTest *test = NULL;
1374 + FcRule *rule = NULL, *r;
1375 FcValueBinding binding;
1377 if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
1378 @@ -1704,8 +1746,14 @@ FcParseAlias (FcConfigParse *parse)
1379 vstack->tag = FcVStackNone;
1382 - vstack->u.test->next = test;
1383 - test = vstack->u.test;
1386 + r = FcRuleCreate (FcRuleTest, vstack->u.test);
1391 + rule = FcRuleCreate (FcRuleTest, vstack->u.test);
1392 vstack->tag = FcVStackNone;
1395 @@ -1723,8 +1771,35 @@ FcParseAlias (FcConfigParse *parse)
1396 FcExprDestroy (accept);
1398 FcExprDestroy (def);
1400 + FcRuleDestroy (rule);
1407 + FcExprDestroy (family);
1412 + FcTest *t = FcTestCreate (parse, FcMatchPattern,
1414 + (FcChar8 *) FC_FAMILY,
1415 + FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
1419 + for (r = rule; r->next; r = r->next);
1420 + r->next = FcRuleCreate (FcRuleTest, t);
1425 + r = rule = FcRuleCreate (FcRuleTest, t);
1430 edit = FcEditCreate (parse,
1431 @@ -1732,60 +1807,46 @@ FcParseAlias (FcConfigParse *parse)
1439 FcExprDestroy (prefer);
1442 + r->next = FcRuleCreate (FcRuleEdit, edit);
1449 edit = FcEditCreate (parse,
1455 - edit->next = next;
1458 FcExprDestroy (accept);
1461 + r->next = FcRuleCreate (FcRuleEdit, edit);
1468 edit = FcEditCreate (parse,
1474 - edit->next = next;
1477 FcExprDestroy (def);
1481 - FcTest *t = FcTestCreate (parse, FcMatchPattern,
1483 - (FcChar8 *) FC_FAMILY,
1484 - FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
1494 + r->next = FcRuleCreate (FcRuleEdit, edit);
1500 - if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern))
1501 - FcTestDestroy (test);
1504 - FcExprDestroy (family);
1505 + if (!FcConfigAddRule (parse->config, rule, FcMatchPattern))
1506 + FcRuleDestroy (rule);
1510 @@ -2121,6 +2182,8 @@ FcParseInclude (FcConfigParse *parse)
1511 FcBool ignore_missing = FcFalse;
1512 FcBool deprecated = FcFalse;
1513 FcChar8 *prefix = NULL, *p;
1514 + static FcChar8 *userdir = NULL;
1515 + static FcChar8 *userconf = NULL;
1517 s = FcStrBufDoneStatic (&parse->pstack->str);
1519 @@ -2153,23 +2216,78 @@ FcParseInclude (FcConfigParse *parse)
1520 memcpy (&prefix[plen + 1], s, dlen);
1521 prefix[plen + 1 + dlen] = 0;
1523 + if (FcFileIsDir (s))
1527 + userdir = FcStrdup (s);
1529 + else if (FcFileIsFile (s))
1533 + userconf = FcStrdup (s);
1537 + /* No config dir nor file on the XDG directory spec compliant place
1538 + * so need to guess what it is supposed to be.
1540 + FcChar8 *parent = FcStrDirname (s);
1542 + if (!FcFileIsDir (parent))
1543 + FcMakeDirectory (parent);
1544 + FcStrFree (parent);
1545 + if (FcStrStr (s, (const FcChar8 *)"conf.d") != NULL)
1551 if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
1552 parse->error = FcTrue;
1557 + static FcBool warn_conf = FcFalse, warn_confd = FcFalse;
1559 filename = FcConfigFilename(s);
1560 if (deprecated == FcTrue &&
1562 !FcFileIsLink (filename))
1564 - FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated.", s);
1565 + if (FcFileIsDir (filename))
1567 + if (FcFileIsDir (userdir) ||
1568 + rename ((const char *)filename, (const char *)userdir) != 0 ||
1569 + symlink ((const char *)userdir, (const char *)filename) != 0)
1573 + FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userdir);
1574 + warn_confd = FcTrue;
1580 + if (FcFileIsFile (userconf) ||
1581 + rename ((const char *)filename, (const char *)userconf) != 0 ||
1582 + symlink ((const char *)userconf, (const char *)filename) != 0)
1586 + FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userconf);
1587 + warn_conf = FcTrue;
1593 FcStrFree(filename);
1596 FcStrBufDestroy (&parse->pstack->str);
1599 @@ -2386,22 +2504,14 @@ FcParseEdit (FcConfigParse *parse)
1600 FcEditDestroy (edit);
1603 -typedef struct FcSubstStack {
1609 FcParseMatch (FcConfigParse *parse)
1611 const FcChar8 *kind_name;
1616 - FcBool tested = FcFalse;
1617 - FcSubstStack *sstack = NULL;
1619 + FcRule *rule = NULL, *r;
1621 kind_name = FcConfigGetAttribute (parse, "target");
1623 @@ -2420,48 +2530,29 @@ FcParseMatch (FcConfigParse *parse)
1627 - len = FcVStackElements(parse);
1630 - sstack = malloc (sizeof (FcSubstStack) * (len + 1));
1633 - FcConfigMessage (parse, FcSevereError, "out of memory");
1637 while ((vstack = FcVStackPeek (parse)))
1639 switch ((int) vstack->tag) {
1641 - vstack->u.test->next = test;
1642 - test = vstack->u.test;
1643 + r = FcRuleCreate (FcRuleTest, vstack->u.test);
1647 vstack->tag = FcVStackNone;
1651 - /* due to the reverse traversal, <edit> node appears faster than
1652 - * <test> node if any. so we have to deal with it here rather than
1653 - * the above in FcVStackTest, and put recipes in reverse order.
1657 - sstack[pos].test = test;
1658 - sstack[pos].edit = edit;
1664 - vstack->u.edit->next = edit;
1665 - edit = vstack->u.edit;
1666 - vstack->tag = FcVStackNone;
1667 - if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT)
1668 + if (kind == FcMatchScan && vstack->u.edit->object > FC_MAX_BASE_OBJECT)
1670 FcConfigMessage (parse, FcSevereError,
1671 "<match target=\"scan\"> cannot edit user-defined object \"%s\"",
1672 FcObjectName(edit->object));
1675 + r = FcRuleCreate (FcRuleEdit, vstack->u.edit);
1679 + vstack->tag = FcVStackNone;
1682 FcConfigMessage (parse, FcSevereWarning, "invalid match element");
1683 @@ -2469,22 +2560,8 @@ FcParseMatch (FcConfigParse *parse)
1685 FcVStackPopAndDestroy (parse);
1687 - if (!FcConfigAddEdit (parse->config, test, edit, kind))
1688 + if (!FcConfigAddRule (parse->config, rule, kind))
1689 FcConfigMessage (parse, FcSevereError, "out of memory");
1694 - for (i = 0; i < pos; i++)
1696 - if (!FcConfigAddEdit (parse->config, sstack[pos - i - 1].test, sstack[pos - i - 1].edit, kind))
1698 - FcConfigMessage (parse, FcSevereError, "out of memory");