]> git.pld-linux.org Git - packages/fontconfig.git/commitdiff
- rel 3; fixes from git
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Wed, 21 Aug 2013 13:24:50 +0000 (15:24 +0200)
committerArkadiusz Miśkiewicz <arekm@maven.pl>
Wed, 21 Aug 2013 13:24:50 +0000 (15:24 +0200)
fontconfig-git.patch [new file with mode: 0644]

diff --git a/fontconfig-git.patch b/fontconfig-git.patch
new file mode 100644 (file)
index 0000000..bb74d18
--- /dev/null
@@ -0,0 +1,1706 @@
+diff --git a/conf.d/30-metric-aliases.conf b/conf.d/30-metric-aliases.conf
+index f25052a..0fd0b8a 100644
+--- a/conf.d/30-metric-aliases.conf
++++ b/conf.d/30-metric-aliases.conf
+@@ -230,6 +230,7 @@
+       <alias binding="same">
+         <family>Helvetica</family>
+         <accept>
++        <family>TeX Gyre Heros</family>
+         <family>Nimbus Sans L</family>
+         </accept>
+       </alias>
+@@ -237,6 +238,7 @@
+       <alias binding="same">
+         <family>Times</family>
+         <accept>
++        <family>TeX Gyre Termes</family>
+         <family>Nimbus Roman No9 L</family>
+         </accept>
+       </alias>
+@@ -253,6 +255,7 @@
+       <alias binding="same">
+         <family>Arial</family>
+         <accept>
++          <family>TeX Gyre Heros</family>
+           <family>Arimo</family>
+           <family>Liberation Sans</family>
+           <family>Albany</family>
+@@ -270,6 +273,7 @@
+       <alias binding="same">
+         <family>Times New Roman</family>
+         <accept>
++          <family>TeX Gyre Termes</family>
+           <family>Tinos</family>
+           <family>Liberation Serif</family>
+           <family>Thorndale</family>
+@@ -278,6 +282,13 @@
+       </alias>
+       <alias binding="same">
++        <family>Georgia</family>
++        <accept>
++          <family>Gelasio</family>
++        </accept>
++      </alias>
++
++      <alias binding="same">
+         <family>Courier New</family>
+         <accept>
+           <family>Cousine</family>
+diff --git a/conf.d/45-latin.conf b/conf.d/45-latin.conf
+index 09fd526..aa62ed4 100644
+--- a/conf.d/45-latin.conf
++++ b/conf.d/45-latin.conf
+@@ -45,6 +45,22 @@
+               <family>Thorndale</family>
+               <default><family>serif</family></default>
+       </alias>
++      <alias>
++              <family>Georgia</family>
++              <default><family>serif</family></default>
++      </alias>
++      <alias>
++              <family>Garamond</family>
++              <default><family>serif</family></default>
++      </alias>
++      <alias>
++              <family>Palatino Linotype</family>
++              <default><family>serif</family></default>
++      </alias>
++      <alias>
++              <family>Trebuchet MS</family>
++              <default><family>serif</family></default>
++      </alias>
+ <!--
+   Sans-serif faces
+  -->
+diff --git a/configure.ac b/configure.ac
+index 0f129db..321fece 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -54,6 +54,9 @@ AC_SUBST(LIBT_VERSION_INFO)
+ LIBT_CURRENT_MINUS_AGE=`expr $LIBT_CURRENT - $LIBT_AGE`
+ AC_SUBST(LIBT_CURRENT_MINUS_AGE)
++PKGCONFIG_REQUIRES=
++PKGCONFIG_REQUIRES_PRIVATELY=
++
+ dnl ==========================================================================
+ AC_CONFIG_HEADERS(config.h)
+@@ -161,6 +164,37 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([[
+               AC_MSG_RESULT([yes])
+               AC_DEFINE([HAVE_POSIX_FADVISE], [1], [Define to 1 if you have the 'posix_fadvise' function.])
+       ],[AC_MSG_RESULT([no])])
++if test "$os_win32" = "no"; then
++      AC_MSG_CHECKING([for scandir])
++      AC_LINK_IFELSE([AC_LANG_SOURCE([[
++              #include <dirent.h>
++              int comp(const struct dirent **, const struct dirent **);
++              int comp(const struct dirent **a, const struct dirent **b) { return 0; }
++              int main(void) {
++                  struct dirent **d;
++                  return scandir(".", &d, 0, &comp) >= 0;
++              }
++              ]])],[
++                      AC_MSG_RESULT([yes])
++                      AC_DEFINE([HAVE_SCANDIR], [1], [Define to 1 if you have the 'scandir' function.])
++              ],[
++                      AC_LINK_IFELSE([AC_LANG_SOURCE([[
++                              #include <dirent.h>
++                              int comp(const void *, const void *);
++                              int comp(const void *a, const void *b) { return 0; }
++                              int main(void) {
++                                  struct dirent **d;
++                                  return scandir(".", &d, 0, &comp) >= 0;
++                              }
++                      ]])],[
++                              AC_MSG_RESULT([yes])
++                              AC_DEFINE([HAVE_SCANDIR_VOID_P], [1], [Define to 1 if you have the 'scandir' function with int (* compar)(const void *, const void *)])
++                      ],[
++                              AC_MSG_ERROR([
++*** No scandir function available.])
++                      ])
++              ])
++fi
+ CFLAGS="$fc_saved_CFLAGS"
+ #
+@@ -251,13 +285,14 @@ if test "x$enable_iconv" != "xno"; then
+               AC_TRY_LINK([#include <iconv.h>],
+                       [iconv_open ("from", "to");],
+                       [iconv_type="libiconv"
+-                       use_iconv=1],
++                       use_iconv=1
++                       ICONV_CFLAGS="$libiconv_cflags"
++                       ICONV_LIBS="$libiconv_libs"
++                       ],
+                       [use_iconv=0])
+               CFLAGS="$iconvsaved_CFLAGS"
+               LIBS="$iconvsaved_LIBS"
+-              ICONV_CFLAGS="$libiconv_cflags"
+-              ICONV_LIBS="$libiconv_libs"
+       fi
+       if test "x$use_iconv" = "x0"; then
+               AC_TRY_LINK([#include <iconv.h>],
+@@ -277,6 +312,7 @@ AC_DEFINE_UNQUOTED(USE_ICONV,$use_iconv,[Use iconv.])
+ # Checks for FreeType
+ #
+ PKG_CHECK_MODULES(FREETYPE, freetype2)
++PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES freetype2"
+ AC_SUBST(FREETYPE_LIBS)
+ AC_SUBST(FREETYPE_CFLAGS)
+@@ -336,6 +372,8 @@ if test "$enable_libxml2" != "yes"; then
+               else
+                       EXPAT_LIBS="-lexpat"
+               fi
++      else
++              PKGCONFIG_REQUIRES_PRIVATELY="$PKGCONFIG_REQUIRES_PRIVATELY expat"
+       fi
+       expatsaved_CPPFLAGS="$CPPFLAGS"
+@@ -377,6 +415,7 @@ AC_ARG_ENABLE(libxml2,
+ if test "$enable_libxml2" = "yes"; then
+     PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.6])
++    PKGCONFIG_REQUIRES_PRIVATELY="$PKGCONFIG_REQUIRES_PRIVATELY libxml-2.0"
+     AC_DEFINE_UNQUOTED(ENABLE_LIBXML2,1,[Use libxml2 instead of Expat])
+     AC_SUBST(LIBXML2_CFLAGS)
+@@ -684,6 +723,12 @@ dnl include the header file for workaround of miscalculating size on autoconf
+ dnl particularly for fat binaries
+ AH_BOTTOM([#include "config-fixups.h"])
++dnl
++dnl
++AC_SUBST(PKGCONFIG_REQUIRES)
++AC_SUBST(PKGCONFIG_REQUIRES_PRIVATELY)
++
++dnl
+ AC_CONFIG_FILES([
+ Makefile
+ fontconfig/Makefile
+diff --git a/fontconfig.pc.in b/fontconfig.pc.in
+index 9ef2c27..6e112bb 100644
+--- a/fontconfig.pc.in
++++ b/fontconfig.pc.in
+@@ -11,6 +11,8 @@ cachedir=@fc_cachedir@
+ Name: Fontconfig
+ Description: Font configuration and customization library
+ Version: @VERSION@
++Requires: @PKGCONFIG_REQUIRES@
++Requires.private: @PKGCONFIG_REQUIRES_PRIVATELY@
+ Libs: -L${libdir} -lfontconfig
+-Libs.private: @LIBXML2_LIBS@ @EXPAT_LIBS@ @FREETYPE_LIBS@ @ICONV_LIBS@
+-Cflags: -I${includedir}
++Libs.private: @EXPAT_LIBS@ @FREETYPE_LIBS@ @ICONV_LIBS@ @LIBXML2_LIBS@
++Cflags: -I${includedir} @EXPAT_CFLAGS@ @FREETYPE_CFLAGS@ @ICONV_CFLAGS@ @LIBXML2_CFLAGS@
+diff --git a/fontconfig/fcprivate.h b/fontconfig/fcprivate.h
+index 18b8c08..210c1d8 100644
+--- a/fontconfig/fcprivate.h
++++ b/fontconfig/fcprivate.h
+@@ -48,8 +48,9 @@
+       __o__ = va_arg (va, const char *);                          \
+       if (!__o__)                                                 \
+           break;                                                  \
+-      __v__.type = va_arg (va, FcType);                           \
++      __v__.type = va_arg (va, int);                              \
+       switch (__v__.type) {                                       \
++      case FcTypeUnknown:                                         \
+       case FcTypeVoid:                                            \
+           goto _FcPatternVapBuild_bail1;                          \
+       case FcTypeInteger:                                         \
+diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
+index 422187b..39d1b1b 100644
+--- a/fontconfig/fontconfig.h
++++ b/fontconfig/fontconfig.h
+@@ -185,6 +185,7 @@ typedef int                FcBool;
+ #define FC_LCD_LEGACY     3
+ typedef enum _FcType {
++    FcTypeUnknown = -1,
+     FcTypeVoid,
+     FcTypeInteger,
+     FcTypeDouble,
+diff --git a/src/fccache.c b/src/fccache.c
+index 9f1c298..e02d49e 100644
+--- a/src/fccache.c
++++ b/src/fccache.c
+@@ -830,34 +830,6 @@ bail1:
+     return NULL;
+ }
+-
+-#ifdef _WIN32
+-#include <direct.h>
+-#define mkdir(path,mode) _mkdir(path)
+-#endif
+-
+-static FcBool
+-FcMakeDirectory (const FcChar8 *dir)
+-{
+-    FcChar8 *parent;
+-    FcBool  ret;
+-
+-    if (strlen ((char *) dir) == 0)
+-      return FcFalse;
+-
+-    parent = FcStrDirname (dir);
+-    if (!parent)
+-      return FcFalse;
+-    if (access ((char *) parent, F_OK) == 0)
+-      ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
+-    else if (access ((char *) parent, F_OK) == -1)
+-      ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
+-    else
+-      ret = FcFalse;
+-    FcStrFree (parent);
+-    return ret;
+-}
+-
+ /* write serialized state to the cache file */
+ FcBool
+ FcDirCacheWrite (FcCache *cache, FcConfig *config)
+diff --git a/src/fccfg.c b/src/fccfg.c
+index fcdf73e..be738d5 100644
+--- a/src/fccfg.c
++++ b/src/fccfg.c
+@@ -214,10 +214,8 @@ FcSubstDestroy (FcSubst *s)
+     while (s)
+     {
+       n = s->next;
+-      if (s->test)
+-          FcTestDestroy (s->test);
+-      if (s->edit)
+-          FcEditDestroy (s->edit);
++      if (s->rule)
++          FcRuleDestroy (s->rule);
+       free (s);
+       s = n;
+     }
+@@ -226,20 +224,20 @@ FcSubstDestroy (FcSubst *s)
+ FcExpr *
+ FcConfigAllocExpr (FcConfig *config)
+ {
+-  if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
+-  {
+-    FcExprPage *new_page;
++    if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
++    {
++      FcExprPage *new_page;
+-    new_page = malloc (sizeof (FcExprPage));
+-    if (!new_page)
+-      return 0;
++      new_page = malloc (sizeof (FcExprPage));
++      if (!new_page)
++          return 0;
+-    new_page->next_page = config->expr_pool;
+-    new_page->next = new_page->exprs;
+-    config->expr_pool = new_page;
+-  }
++      new_page->next_page = config->expr_pool;
++      new_page->next = new_page->exprs;
++      config->expr_pool = new_page;
++    }
+-  return config->expr_pool->next++;
++    return config->expr_pool->next++;
+ }
+ FcConfig *
+@@ -644,15 +642,13 @@ FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
+     return FcConfigSetRescanInterval (config, rescanInterval);
+ }
+-
+ FcBool
+-FcConfigAddEdit (FcConfig     *config,
+-               FcTest         *test,
+-               FcEdit         *edit,
++FcConfigAddRule (FcConfig     *config,
++               FcRule         *rule,
+                FcMatchKind    kind)
+ {
+     FcSubst   *subst, **prev;
+-    FcTest    *t;
++    FcRule    *r;
+     int               num;
+     switch (kind) {
+@@ -673,15 +669,27 @@ FcConfigAddEdit (FcConfig        *config,
+       return FcFalse;
+     for (; *prev; prev = &(*prev)->next);
+     *prev = subst;
+-    subst->next = 0;
+-    subst->test = test;
+-    subst->edit = edit;
++    subst->next = NULL;
++    subst->rule = rule;
+     num = 0;
+-    for (t = test; t; t = t->next)
++    for (r = rule; r; r = r->next)
+     {
+-      if (t->kind == FcMatchDefault)
+-          t->kind = kind;
+-      num++;
++      switch (r->type)
++      {
++      case FcRuleTest:
++          if (r->u.test &&
++              r->u.test->kind == FcMatchDefault)
++              r->u.test->kind = kind;
++          if (r->u.test->object > FC_MAX_BASE_OBJECT)
++              num++;
++          break;
++      case FcRuleEdit:
++          if (r->u.edit->object > FC_MAX_BASE_OBJECT)
++              num++;
++          break;
++      default:
++          break;
++      }
+     }
+     if (config->maxObjects < num)
+       config->maxObjects = num;
+@@ -721,7 +729,7 @@ FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
+ FcBool
+ FcConfigCompareValue (const FcValue   *left_o,
+-                    FcOp              op_,
++                    unsigned int      op_,
+                     const FcValue     *right_o)
+ {
+     FcValue   left = FcValueCanonicalize(left_o);
+@@ -736,6 +744,8 @@ FcConfigCompareValue (const FcValue        *left_o,
+     if (left.type == right.type)
+     {
+       switch (left.type) {
++      case FcTypeUnknown:
++          break;      /* No way to guess how to compare for this object */
+       case FcTypeInteger:
+           break;      /* FcConfigPromote prevents this from happening */
+       case FcTypeDouble:
+@@ -1484,13 +1494,16 @@ FcConfigSubstituteWithPat (FcConfig    *config,
+ {
+     FcValue v;
+     FcSubst       *s;
+-    FcSubState            *st;
+-    int                   i;
+-    FcTest        *t;
+-    FcEdit        *e;
+-    FcValueList           *l;
++    FcRule          *r;
++    FcValueList           *l, **value = NULL;
+     FcPattern     *m;
+     FcStrSet      *strs;
++    FcObject      object = FC_INVALID_OBJECT;
++    FcPatternElt    **elt = NULL;
++    int                   i, nobjs;
++    FcBool        retval = FcTrue;
++
++#define FC_OBJ_ID(_n_)        ((_n_) > FC_MAX_BASE_OBJECT ? ((_n_) - FC_EXT_OBJ_INDEX) : (_n_))
+     if (!config)
+     {
+@@ -1535,9 +1548,19 @@ FcConfigSubstituteWithPat (FcConfig    *config,
+       return FcFalse;
+     }
+-    st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState));
+-    if (!st && config->maxObjects)
+-      return FcFalse;
++    nobjs = FC_MAX_BASE_OBJECT + config->maxObjects + 2;
++    value = (FcValueList **) malloc (SIZEOF_VOID_P * nobjs);
++    if (!value)
++    {
++      retval = FcFalse;
++      goto bail1;
++    }
++    elt = (FcPatternElt **) malloc (SIZEOF_VOID_P * nobjs);
++    if (!elt)
++    {
++      retval = FcFalse;
++      goto bail1;
++    }
+     if (FcDebug () & FC_DBG_EDIT)
+     {
+@@ -1546,200 +1569,185 @@ FcConfigSubstituteWithPat (FcConfig    *config,
+     }
+     for (; s; s = s->next)
+     {
+-      /*
+-       * Check the tests to see if
+-       * they all match the pattern
+-       */
+-      for (t = s->test, i = 0; t; t = t->next, i++)
++      r = s->rule;
++      for (i = 0; i < nobjs; i++)
+       {
+-          if (FcDebug () & FC_DBG_EDIT)
+-          {
+-              printf ("FcConfigSubstitute test ");
+-              FcTestPrint (t);
+-          }
+-          st[i].elt = 0;
+-          if (kind == FcMatchFont && t->kind == FcMatchPattern)
+-              m = p_pat;
+-          else
+-              m = p;
+-          if (m)
+-              st[i].elt = FcPatternObjectFindElt (m, t->object);
+-          else
+-              st[i].elt = 0;
+-          /*
+-           * If there's no such field in the font,
+-           * then FcQualAll matches while FcQualAny does not
+-           */
+-          if (!st[i].elt)
+-          {
+-              if (t->qual == FcQualAll)
++          elt[i] = NULL;
++          value[i] = NULL;
++      }
++      for (; r; r = r->next)
++      {
++          switch (r->type) {
++          case FcRuleUnknown:
++              /* shouldn't be reached */
++              break;
++          case FcRuleTest:
++              object = FC_OBJ_ID (r->u.test->object);
++              /*
++               * Check the tests to see if
++               * they all match the pattern
++               */
++              if (FcDebug () & FC_DBG_EDIT)
+               {
+-                  st[i].value = 0;
+-                  continue;
++                  printf ("FcConfigSubstitute test ");
++                  FcTestPrint (r->u.test);
+               }
++              if (kind == FcMatchFont && r->u.test->kind == FcMatchPattern)
++                  m = p_pat;
+               else
+-                  break;
+-          }
+-          /*
+-           * Check to see if there is a match, mark the location
+-           * to apply match-relative edits
+-           */
+-          st[i].value = FcConfigMatchValueList (m, p_pat, kind, t, st[i].elt->values);
+-          if (!st[i].value)
+-              break;
+-          if (t->qual == FcQualFirst && st[i].value != st[i].elt->values)
+-              break;
+-          if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values)
+-              break;
+-      }
+-      if (t)
+-      {
+-          if (FcDebug () & FC_DBG_EDIT)
+-              printf ("No match\n");
+-          continue;
+-      }
+-      if (FcDebug () & FC_DBG_EDIT)
+-      {
+-          printf ("Substitute ");
+-          FcSubstPrint (s);
+-      }
+-      for (e = s->edit; e; e = e->next)
+-      {
+-          /*
+-           * Evaluate the list of expressions
+-           */
+-          l = FcConfigValues (p, p_pat,kind,  e->expr, e->binding);
+-          /*
+-           * Locate any test associated with this field, skipping
+-           * tests associated with the pattern when substituting in
+-           * the font
+-           */
+-          for (t = s->test, i = 0; t; t = t->next, i++)
+-          {
+-              if ((t->kind == FcMatchFont || kind == FcMatchPattern) &&
+-                  t->object == e->object)
++                  m = p;
++              if (m)
++                  elt[object] = FcPatternObjectFindElt (m, r->u.test->object);
++              /*
++               * If there's no such field in the font,
++               * then FcQualAll matches while FcQualAny does not
++               */
++              if (!elt[object])
+               {
+-                  /*
+-                   * KLUDGE - the pattern may have been reallocated or
+-                   * things may have been inserted or deleted above
+-                   * this element by other edits.  Go back and find
+-                   * the element again
+-                   */
+-                  if (e != s->edit && st[i].elt)
+-                      st[i].elt = FcPatternObjectFindElt (p, t->object);
+-                  if (!st[i].elt)
+-                      t = 0;
+-                  break;
++                  if (r->u.test->qual == FcQualAll)
++                  {
++                      value[object] = NULL;
++                      continue;
++                  }
++                  else
++                  {
++                      if (FcDebug () & FC_DBG_EDIT)
++                          printf ("No match\n");
++                      goto bail;
++                  }
+               }
+-          }
+-          switch (FC_OP_GET_OP (e->op)) {
+-          case FcOpAssign:
+               /*
+-               * If there was a test, then replace the matched
+-               * value with the new list of values
++               * Check to see if there is a match, mark the location
++               * to apply match-relative edits
+                */
+-              if (t)
++              value[object] = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt[object]->values);
++              if (!value[object] ||
++                  (r->u.test->qual == FcQualFirst && value[object] != elt[object]->values) ||
++                  (r->u.test->qual == FcQualNotFirst && value[object] == elt[object]->values))
+               {
+-                  FcValueList *thisValue = st[i].value;
+-                  FcValueList *nextValue = thisValue;
+-              
++                  if (FcDebug () & FC_DBG_EDIT)
++                      printf ("No match\n");
++                  goto bail;
++              }
++              break;
++          case FcRuleEdit:
++              object = FC_OBJ_ID (r->u.edit->object);
++              if (FcDebug () & FC_DBG_EDIT)
++              {
++                  printf ("Substitute ");
++                  FcEditPrint (r->u.edit);
++                  printf ("\n\n");
++              }
++              /*
++               * Evaluate the list of expressions
++               */
++              l = FcConfigValues (p, p_pat,kind,  r->u.edit->expr, r->u.edit->binding);
++
++              switch (FC_OP_GET_OP (r->u.edit->op)) {
++              case FcOpAssign:
+                   /*
+-                   * Append the new list of values after the current value
++                   * If there was a test, then replace the matched
++                   * value with the new list of values
+                    */
+-                  FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l, e->object);
++                  if (value[object])
++                  {
++                      FcValueList     *thisValue = value[object];
++                      FcValueList     *nextValue = l;
++
++                      /*
++                       * Append the new list of values after the current value
++                       */
++                      FcConfigAdd (&elt[object]->values, thisValue, FcTrue, l, r->u.edit->object);
++                      /*
++                       * Delete the marked value
++                       */
++                      if (thisValue)
++                          FcConfigDel (&elt[object]->values, thisValue);
++                      /*
++                       * Adjust a pointer into the value list to ensure
++                       * future edits occur at the same place
++                       */
++                      value[object] = nextValue;
++                      break;
++                  }
++                  /* fall through ... */
++              case FcOpAssignReplace:
+                   /*
+-                   * Delete the marked value
++                   * Delete all of the values and insert
++                   * the new set
+                    */
+-                    if (thisValue)
+-                      FcConfigDel (&st[i].elt->values, thisValue);
++                  FcConfigPatternDel (p, r->u.edit->object);
++                  FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
+                   /*
+-                   * Adjust any pointers into the value list to ensure
+-                   * future edits occur at the same place
++                   * Adjust a pointer into the value list as they no
++                   * longer point to anything valid
+                    */
+-                  for (t = s->test, i = 0; t; t = t->next, i++)
++                  value[object] = NULL;
++                  break;
++              case FcOpPrepend:
++                  if (value[object])
+                   {
+-                      if (st[i].value == thisValue)
+-                          st[i].value = nextValue;
++                      FcConfigAdd (&elt[object]->values, value[object], FcFalse, l, r->u.edit->object);
++                      break;
+                   }
++                  /* fall through ... */
++              case FcOpPrependFirst:
++                  FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse);
+                   break;
+-              }
+-              /* fall through ... */
+-          case FcOpAssignReplace:
+-              /*
+-               * Delete all of the values and insert
+-               * the new set
+-               */
+-              FcConfigPatternDel (p, e->object);
+-              FcConfigPatternAdd (p, e->object, l, FcTrue);
+-              /*
+-               * Adjust any pointers into the value list as they no
+-               * longer point to anything valid
+-               */
+-              if (t)
+-              {
+-                  FcPatternElt    *thisElt = st[i].elt;
+-                  for (t = s->test, i = 0; t; t = t->next, i++)
++              case FcOpAppend:
++                  if (value[object])
+                   {
+-                      if (st[i].elt == thisElt)
+-                          st[i].value = 0;
++                      FcConfigAdd (&elt[object]->values, value[object], FcTrue, l, r->u.edit->object);
++                      break;
+                   }
+-              }
+-              break;
+-          case FcOpPrepend:
+-              if (t)
+-              {
+-                  FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l, e->object);
++                  /* fall through ... */
++              case FcOpAppendLast:
++                  FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
+                   break;
+-              }
+-              /* fall through ... */
+-          case FcOpPrependFirst:
+-              FcConfigPatternAdd (p, e->object, l, FcFalse);
+-              break;
+-          case FcOpAppend:
+-              if (t)
+-              {
+-                  FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l, e->object);
++              case FcOpDelete:
++                  if (value[object])
++                  {
++                      FcConfigDel (&elt[object]->values, value[object]);
++                      break;
++                  }
++                  /* fall through ... */
++              case FcOpDeleteAll:
++                  FcConfigPatternDel (p, r->u.edit->object);
++                  break;
++              default:
++                  FcValueListDestroy (l);
+                   break;
+               }
+-              /* fall through ... */
+-          case FcOpAppendLast:
+-              FcConfigPatternAdd (p, e->object, l, FcTrue);
+-              break;
+-          case FcOpDelete:
+-              if (t)
++              /*
++               * Now go through the pattern and eliminate
++               * any properties without data
++               */
++              FcConfigPatternCanon (p, r->u.edit->object);
++
++              if (FcDebug () & FC_DBG_EDIT)
+               {
+-                  FcConfigDel (&st[i].elt->values, st[i].value);
+-                  break;
++                  printf ("FcConfigSubstitute edit");
++                  FcPatternPrint (p);
+               }
+-              /* fall through ... */
+-          case FcOpDeleteAll:
+-              FcConfigPatternDel (p, e->object);
+-              break;
+-          default:
+-                FcValueListDestroy (l);
+               break;
+           }
+       }
+-      /*
+-       * Now go through the pattern and eliminate
+-       * any properties without data
+-       */
+-      for (e = s->edit; e; e = e->next)
+-          FcConfigPatternCanon (p, e->object);
+-
+-      if (FcDebug () & FC_DBG_EDIT)
+-      {
+-          printf ("FcConfigSubstitute edit");
+-          FcPatternPrint (p);
+-      }
++    bail:;
+     }
+-    free (st);
+     if (FcDebug () & FC_DBG_EDIT)
+     {
+       printf ("FcConfigSubstitute done");
+       FcPatternPrint (p);
+     }
+-    return FcTrue;
++bail1:
++    if (elt)
++      free (elt);
++    if (value)
++      free (value);
++
++#undef FC_OBJ_ID
++
++    return retval;
+ }
+ FcBool
+diff --git a/src/fccompat.c b/src/fccompat.c
+index a217160..d4f88c8 100644
+--- a/src/fccompat.c
++++ b/src/fccompat.c
+@@ -219,3 +219,30 @@ FcRandom(void)
+     return result;
+ }
++
++#ifdef _WIN32
++#include <direct.h>
++#define mkdir(path,mode) _mkdir(path)
++#endif
++
++FcBool
++FcMakeDirectory (const FcChar8 *dir)
++{
++    FcChar8 *parent;
++    FcBool  ret;
++
++    if (strlen ((char *) dir) == 0)
++      return FcFalse;
++
++    parent = FcStrDirname (dir);
++    if (!parent)
++      return FcFalse;
++    if (access ((char *) parent, F_OK) == 0)
++      ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
++    else if (access ((char *) parent, F_OK) == -1)
++      ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
++    else
++      ret = FcFalse;
++    FcStrFree (parent);
++    return ret;
++}
+diff --git a/src/fcdbg.c b/src/fcdbg.c
+index 9d02f5a..d74bc27 100644
+--- a/src/fcdbg.c
++++ b/src/fcdbg.c
+@@ -30,6 +30,9 @@ static void
+ _FcValuePrintFile (FILE *f, const FcValue v)
+ {
+     switch (v.type) {
++    case FcTypeUnknown:
++      fprintf (f, "<unknown>");
++      break;
+     case FcTypeVoid:
+       fprintf (f, "<void>");
+       break;
+@@ -98,6 +101,10 @@ FcValueBindingPrint (const FcValueListPtr l)
+     case FcValueBindingSame:
+       printf ("(=)");
+       break;
++    default:
++      /* shouldn't be reached */
++      printf ("(?)");
++      break;
+     }
+ }
+@@ -420,21 +427,38 @@ FcEditPrint (const FcEdit *edit)
+ void
+ FcSubstPrint (const FcSubst *subst)
+ {
+-    FcEdit    *e;
+-    FcTest    *t;
++    FcRule *r;
++    FcRuleType last_type = FcRuleUnknown;
+     printf ("match\n");
+-    for (t = subst->test; t; t = t->next)
+-    {
+-      printf ("\t");
+-      FcTestPrint (t);
+-    }
+-    printf ("edit\n");
+-    for (e = subst->edit; e; e = e->next)
++    for (r = subst->rule; r; r = r->next)
+     {
++      if (last_type != r->type)
++      {
++          switch (r->type) {
++          case FcRuleTest:
++              printf ("[test]\n");
++              break;
++          case FcRuleEdit:
++              printf ("[edit]\n");
++              break;
++          default:
++              break;
++          }
++          last_type = r->type;
++      }
+       printf ("\t");
+-      FcEditPrint (e);
+-      printf (";\n");
++      switch (r->type) {
++      case FcRuleTest:
++          FcTestPrint (r->u.test);
++          break;
++      case FcRuleEdit:
++          FcEditPrint (r->u.edit);
++          printf (";\n");
++          break;
++      default:
++          break;
++      }
+     }
+     printf ("\n");
+ }
+diff --git a/src/fcdir.c b/src/fcdir.c
+index dc580bb..b040a28 100644
+--- a/src/fcdir.c
++++ b/src/fcdir.c
+@@ -49,6 +49,16 @@ FcFileIsLink (const FcChar8 *file)
+ #endif
+ }
++FcBool
++FcFileIsFile (const FcChar8 *file)
++{
++    struct stat statb;
++
++    if (FcStat (file, &statb) != 0)
++      return FcFalse;
++    return S_ISREG (statb.st_mode);
++}
++
+ static FcBool
+ FcFileScanFontConfig (FcFontSet               *set,
+                     FcBlanks          *blanks,
+diff --git a/src/fchash.c b/src/fchash.c
+index 92585a6..7216bee 100644
+--- a/src/fchash.c
++++ b/src/fchash.c
+@@ -190,14 +190,14 @@ FcHashGetSHA256Digest (const FcChar8 *input_strings,
+     }
+     /* set input size at the end */
+     len *= 8;
+-    block[63 - 0] =  len        & 0xff;
+-    block[63 - 1] = (len >>  8) & 0xff;
+-    block[63 - 2] = (len >> 16) & 0xff;
+-    block[63 - 3] = (len >> 24) & 0xff;
+-    block[63 - 4] = (len >> 32) & 0xff;
+-    block[63 - 5] = (len >> 40) & 0xff;
+-    block[63 - 6] = (len >> 48) & 0xff;
+-    block[63 - 7] = (len >> 56) & 0xff;
++    block[63 - 0] =  (uint64_t)len        & 0xff;
++    block[63 - 1] = ((uint64_t)len >>  8) & 0xff;
++    block[63 - 2] = ((uint64_t)len >> 16) & 0xff;
++    block[63 - 3] = ((uint64_t)len >> 24) & 0xff;
++    block[63 - 4] = ((uint64_t)len >> 32) & 0xff;
++    block[63 - 5] = ((uint64_t)len >> 40) & 0xff;
++    block[63 - 6] = ((uint64_t)len >> 48) & 0xff;
++    block[63 - 7] = ((uint64_t)len >> 56) & 0xff;
+     FcHashComputeSHA256Digest (ret, block);
+     return FcHashSHA256ToString (ret);
+@@ -226,7 +226,7 @@ FcHashGetSHA256DigestFromFile (const FcChar8 *filename)
+     {
+       if ((len = fread (ibuf, sizeof (char), 64, fp)) < 64)
+       {
+-          long v;
++          uint64_t v;
+           /* add a padding */
+           memset (&ibuf[len], 0, 64 - len);
+@@ -281,7 +281,7 @@ FcHashGetSHA256DigestFromMemory (const char *fontdata,
+     {
+       if ((length - i) < 64)
+       {
+-          long v;
++          uint64_t v;
+           size_t n;
+           /* add a padding */
+diff --git a/src/fcint.h b/src/fcint.h
+index 65bf333..ec0c674 100644
+--- a/src/fcint.h
++++ b/src/fcint.h
+@@ -37,6 +37,7 @@
+ #include <ctype.h>
+ #include <assert.h>
+ #include <errno.h>
++#include <limits.h>
+ #include <unistd.h>
+ #include <stddef.h>
+ #include <sys/types.h>
+@@ -85,7 +86,7 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
+ #define FC_DBG_CONFIG 1024
+ #define FC_DBG_LANGSET        2048
+-#define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
++#define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] FC_UNUSED
+ #define _FC_ASSERT_STATIC0(_line, _cond) _FC_ASSERT_STATIC1 (_line, (_cond))
+ #define FC_ASSERT_STATIC(_cond) _FC_ASSERT_STATIC0 (__LINE__, (_cond))
+@@ -107,7 +108,9 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
+ FC_ASSERT_STATIC (sizeof (FcRef) == sizeof (int));
+ typedef enum _FcValueBinding {
+-    FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame
++    FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame,
++    /* to make sure sizeof (FcValueBinding) == 4 even with -fshort-enums */
++    FcValueBindingEnd = INT_MAX
+ } FcValueBinding;
+ #define FcStrdup(s) ((FcChar8 *) strdup ((const char *) (s)))
+@@ -171,6 +174,11 @@ typedef struct _FcValueList {
+                       
+ typedef int FcObject;
++/* The 1000 is to leave some room for future added internal objects, such
++ * that caches from newer fontconfig can still be used with older fontconfig
++ * without getting confused. */
++#define FC_EXT_OBJ_INDEX      1000
++
+ typedef struct _FcPatternElt *FcPatternEltPtr;
+ /*
+@@ -271,7 +279,6 @@ typedef enum _FcQual {
+ #define FcMatchDefault        ((FcMatchKind) -1)
+ typedef struct _FcTest {
+-    struct _FcTest    *next;
+     FcMatchKind               kind;
+     FcQual            qual;
+     FcObject          object;
+@@ -280,17 +287,28 @@ typedef struct _FcTest {
+ } FcTest;
+ typedef struct _FcEdit {
+-    struct _FcEdit *next;
+     FcObject      object;
+     FcOp          op;
+     FcExpr        *expr;
+     FcValueBinding  binding;
+ } FcEdit;
++typedef enum _FcRuleType {
++    FcRuleUnknown, FcRuleTest, FcRuleEdit
++} FcRuleType;
++
++typedef struct _FcRule {
++    struct _FcRule *next;
++    FcRuleType      type;
++    union {
++      FcTest *test;
++      FcEdit *edit;
++    } u;
++} FcRule;
++
+ typedef struct _FcSubst {
+     struct _FcSubst   *next;
+-    FcTest            *test;
+-    FcEdit            *edit;
++    FcRule            *rule;
+ } FcSubst;
+ typedef struct _FcCharLeaf {
+@@ -610,10 +628,9 @@ FcPrivate FcBool
+ FcConfigAddBlank (FcConfig    *config,
+                 FcChar32      blank);
+-FcPrivate FcBool
+-FcConfigAddEdit (FcConfig     *config,
+-               FcTest         *test,
+-               FcEdit         *edit,
++FcBool
++FcConfigAddRule (FcConfig     *config,
++               FcRule         *rule,
+                FcMatchKind    kind);
+ FcPrivate void
+@@ -623,7 +640,7 @@ FcConfigSetFonts (FcConfig *config,
+ FcPrivate FcBool
+ FcConfigCompareValue (const FcValue *m,
+-                    FcOp          op,
++                    unsigned int   op_,
+                     const FcValue *v);
+ FcPrivate FcBool
+@@ -730,6 +747,9 @@ FcMakeTempfile (char *template);
+ FcPrivate int32_t
+ FcRandom (void);
++FcPrivate FcBool
++FcMakeDirectory (const FcChar8 *dir);
++
+ /* fcdbg.c */
+ FcPrivate void
+@@ -788,6 +808,9 @@ FcPrivate FcBool
+ FcFileIsLink (const FcChar8 *file);
+ FcPrivate FcBool
++FcFileIsFile (const FcChar8 *file);
++
++FcPrivate FcBool
+ FcFileScanConfig (FcFontSet   *set,
+                 FcStrSet      *dirs,
+                 FcBlanks      *blanks,
+@@ -840,6 +863,9 @@ FcTestDestroy (FcTest *test);
+ FcPrivate void
+ FcEditDestroy (FcEdit *e);
++void
++FcRuleDestroy (FcRule *rule);
++
+ /* fclang.c */
+ FcPrivate FcLangSet *
+ FcFreeTypeLangSet (const FcCharSet  *charset,
+diff --git a/src/fclist.c b/src/fclist.c
+index b7ae899..c56e24c 100644
+--- a/src/fclist.c
++++ b/src/fclist.c
+@@ -252,6 +252,7 @@ FcListValueHash (FcValue    *value)
+ {
+     FcValue v = FcValueCanonicalize(value);
+     switch (v.type) {
++    case FcTypeUnknown:
+     case FcTypeVoid:
+       return 0;
+     case FcTypeInteger:
+diff --git a/src/fcmatch.c b/src/fcmatch.c
+index 10976d6..dec92b9 100644
+--- a/src/fcmatch.c
++++ b/src/fcmatch.c
+@@ -245,6 +245,8 @@ typedef enum _FcMatcherPriorityDummy {
+ typedef enum _FcMatcherPriority {
+     PRI1(HASH),
+     PRI1(FILE),
++    PRI1(FONTFORMAT),
++    PRI1(SCALABLE),
+     PRI1(FOUNDRY),
+     PRI1(CHARSET),
+     PRI_FAMILY_STRONG,
+diff --git a/src/fcname.c b/src/fcname.c
+index 6dd4d49..712b2fa 100644
+--- a/src/fcname.c
++++ b/src/fcname.c
+@@ -76,6 +76,8 @@ FcObjectValidType (FcObject object, FcType type)
+     if (t) {
+       switch ((int) t->type) {
++      case FcTypeUnknown:
++          return FcTrue;
+       case FcTypeDouble:
+       case FcTypeInteger:
+           if (type == FcTypeDouble || type == FcTypeInteger)
+@@ -86,7 +88,7 @@ FcObjectValidType (FcObject object, FcType type)
+               return FcTrue;
+           break;
+       default:
+-          if (t->type == (unsigned int) -1 || type == t->type)
++          if (type == t->type)
+               return FcTrue;
+           break;
+       }
+@@ -318,6 +320,12 @@ FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *l
+     while ((c = *cur))
+     {
++      if (!isspace (c))
++          break;
++      ++cur;
++    }
++    while ((c = *cur))
++    {
+       if (c == '\\')
+       {
+           ++cur;
+@@ -468,6 +476,7 @@ FcNameUnparseValue (FcStrBuf       *buf,
+     FcValue v = FcValueCanonicalize(v0);
+     switch (v.type) {
++    case FcTypeUnknown:
+     case FcTypeVoid:
+       return FcTrue;
+     case FcTypeInteger:
+diff --git a/src/fcobjs.c b/src/fcobjs.c
+index 146ca70..bad9824 100644
+--- a/src/fcobjs.c
++++ b/src/fcobjs.c
+@@ -37,7 +37,7 @@ FcObjectTypeLookup (register const char *str, register unsigned int len);
+ /* The 1000 is to leave some room for future added internal objects, such
+  * that caches from newer fontconfig can still be used with older fontconfig
+  * without getting confused. */
+-static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + 1000;
++static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + FC_EXT_OBJ_INDEX;
+ struct FcObjectOtherTypeInfo {
+     struct FcObjectOtherTypeInfo *next;
+     FcObjectType object;
+@@ -63,7 +63,7 @@ retry:
+           return NULL;
+       ot->object.object = (const char *) FcStrdup (str);
+-      ot->object.type = -1;
++      ot->object.type = FcTypeUnknown;
+       ot->id = fc_atomic_int_add (next_id, +1);
+       ot->next = ots;
+diff --git a/src/fcobjs.h b/src/fcobjs.h
+index 682fe6a..87c7319 100644
+--- a/src/fcobjs.h
++++ b/src/fcobjs.h
+@@ -23,7 +23,7 @@ FC_OBJECT (FILE,             FcTypeString,   FcCompareFilename)
+ FC_OBJECT (INDEX,             FcTypeInteger,  NULL)
+ FC_OBJECT (RASTERIZER,                FcTypeString,   FcCompareString)
+ FC_OBJECT (OUTLINE,           FcTypeBool,     FcCompareBool)
+-FC_OBJECT (SCALABLE,          FcTypeBool,     NULL)
++FC_OBJECT (SCALABLE,          FcTypeBool,     FcCompareBool)
+ FC_OBJECT (DPI,                       FcTypeDouble,   NULL)
+ FC_OBJECT (RGBA,              FcTypeInteger,  NULL)
+ FC_OBJECT (SCALE,             FcTypeDouble,   NULL)
+@@ -35,7 +35,7 @@ FC_OBJECT (CHARSET,          FcTypeCharSet,  FcCompareCharSet)
+ FC_OBJECT (LANG,              FcTypeLangSet,  FcCompareLang)
+ FC_OBJECT (FONTVERSION,               FcTypeInteger,  FcCompareNumber)
+ FC_OBJECT (CAPABILITY,                FcTypeString,   NULL)
+-FC_OBJECT (FONTFORMAT,                FcTypeString,   NULL)
++FC_OBJECT (FONTFORMAT,                FcTypeString,   FcCompareString)
+ FC_OBJECT (EMBOLDEN,          FcTypeBool,     NULL)
+ FC_OBJECT (EMBEDDED_BITMAP,   FcTypeBool,     NULL)
+ FC_OBJECT (DECORATIVE,                FcTypeBool,     FcCompareBool)
+diff --git a/src/fcpat.c b/src/fcpat.c
+index 25bff64..0614ac2 100644
+--- a/src/fcpat.c
++++ b/src/fcpat.c
+@@ -246,6 +246,8 @@ FcValueEqual (FcValue va, FcValue vb)
+           return FcFalse;
+     }
+     switch (va.type) {
++    case FcTypeUnknown:
++      return FcFalse; /* don't know how to compare this object */
+     case FcTypeVoid:
+       return FcTrue;
+     case FcTypeInteger:
+@@ -294,6 +296,7 @@ static FcChar32
+ FcValueHash (const FcValue *v)
+ {
+     switch (v->type) {
++    case FcTypeUnknown:
+     case FcTypeVoid:
+       return 0;
+     case FcTypeInteger:
+@@ -317,7 +320,7 @@ FcValueHash (const FcValue *v)
+     case FcTypeLangSet:
+       return FcLangSetHash (FcValueLangSet(v));
+     }
+-    return FcFalse;
++    return 0;
+ }
+ static FcBool
+diff --git a/src/fcstat.c b/src/fcstat.c
+index 390f45c..ab56aca 100644
+--- a/src/fcstat.c
++++ b/src/fcstat.c
+@@ -164,11 +164,21 @@ FcDirChecksumScandirFilter(const struct dirent *entry)
+ }
+ #endif
++#ifdef HAVE_SCANDIR
+ static int
+ FcDirChecksumScandirSorter(const struct dirent **lhs, const struct dirent **rhs)
+ {
+     return strcmp((*lhs)->d_name, (*rhs)->d_name);
+ }
++#elif HAVE_SCANDIR_VOID_P
++static int
++FcDirChecksumScandirSorter(const void *a, const void *b)
++{
++    const struct dirent *lhs = a, *rhs = b;
++
++    return strcmp(lhs->d_name, rhs->d_name);
++}
++#endif
+ static int
+ FcDirChecksum (const FcChar8 *dir, time_t *checksum)
+diff --git a/src/fcxml.c b/src/fcxml.c
+index 470e44f..2cdf0ad 100644
+--- a/src/fcxml.c
++++ b/src/fcxml.c
+@@ -62,12 +62,30 @@ FcExprDestroy (FcExpr *e);
+ void
+ FcTestDestroy (FcTest *test)
+ {
+-    if (test->next)
+-      FcTestDestroy (test->next);
+     FcExprDestroy (test->expr);
+     free (test);
+ }
++void
++FcRuleDestroy (FcRule *rule)
++{
++    FcRule *n = rule->next;
++
++    switch (rule->type) {
++    case FcRuleTest:
++      FcTestDestroy (rule->u.test);
++      break;
++    case FcRuleEdit:
++      FcEditDestroy (rule->u.edit);
++      break;
++    default:
++      break;
++    }
++    free (rule);
++    if (n)
++      FcRuleDestroy (n);
++}
++
+ static FcExpr *
+ FcExprCreateInteger (FcConfig *config, int i)
+ {
+@@ -300,8 +318,6 @@ FcExprDestroy (FcExpr *e)
+ void
+ FcEditDestroy (FcEdit *e)
+ {
+-    if (e->next)
+-      FcEditDestroy (e->next);
+     if (e->expr)
+       FcExprDestroy (e->expr);
+     free (e);
+@@ -705,7 +721,7 @@ FcTestCreate (FcConfigParse *parse,
+             FcMatchKind   kind,
+             FcQual        qual,
+             const FcChar8 *field,
+-            FcOp          compare,
++            unsigned int  compare,
+             FcExpr        *expr)
+ {
+     FcTest    *test = (FcTest *) malloc (sizeof (FcTest));
+@@ -714,7 +730,6 @@ FcTestCreate (FcConfigParse *parse,
+     {
+       const FcObjectType      *o;
+       
+-      test->next = 0;
+       test->kind = kind;
+       test->qual = qual;
+       test->object = FcObjectFromName ((const char *) field);
+@@ -740,7 +755,6 @@ FcEditCreate (FcConfigParse        *parse,
+     {
+       const FcObjectType      *o;
+-      e->next = 0;
+       e->object = object;
+       e->op = op;
+       e->expr = expr;
+@@ -752,6 +766,34 @@ FcEditCreate (FcConfigParse       *parse,
+     return e;
+ }
++static FcRule *
++FcRuleCreate (FcRuleType type,
++            void       *p)
++{
++    FcRule *r = (FcRule *) malloc (sizeof (FcRule));
++
++    if (!r)
++      return NULL;
++
++    r->next = NULL;
++    r->type = type;
++    switch (type)
++    {
++    case FcRuleTest:
++      r->u.test = (FcTest *) p;
++      break;
++    case FcRuleEdit:
++      r->u.edit = (FcEdit *) p;
++      break;
++    default:
++      free (r);
++      r = NULL;
++      break;
++    }
++
++    return r;
++}
++
+ static FcVStack *
+ FcVStackCreateAndPush (FcConfigParse *parse)
+ {
+@@ -1657,9 +1699,9 @@ static void
+ FcParseAlias (FcConfigParse *parse)
+ {
+     FcExpr    *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
+-    FcEdit    *edit = 0, *next;
++    FcEdit    *edit = 0;
+     FcVStack  *vstack;
+-    FcTest    *test = NULL;
++    FcRule    *rule = NULL, *r;
+     FcValueBinding  binding;
+     if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
+@@ -1704,8 +1746,14 @@ FcParseAlias (FcConfigParse *parse)
+           vstack->tag = FcVStackNone;
+           break;
+       case FcVStackTest:
+-          vstack->u.test->next = test;
+-          test = vstack->u.test;
++          if (rule)
++          {
++              r = FcRuleCreate (FcRuleTest, vstack->u.test);
++              r->next = rule;
++              rule = r;
++          }
++          else
++              rule = FcRuleCreate (FcRuleTest, vstack->u.test);
+           vstack->tag = FcVStackNone;
+           break;
+       default:
+@@ -1723,8 +1771,35 @@ FcParseAlias (FcConfigParse *parse)
+           FcExprDestroy (accept);
+       if (def)
+           FcExprDestroy (def);
++      if (rule)
++          FcRuleDestroy (rule);
+       return;
+     }
++    if (!prefer &&
++      !accept &&
++      !def)
++    {
++      FcExprDestroy (family);
++      return;
++    }
++    else
++    {
++      FcTest *t = FcTestCreate (parse, FcMatchPattern,
++                                FcQualAny,
++                                (FcChar8 *) FC_FAMILY,
++                                FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
++                                family);
++      if (rule)
++      {
++          for (r = rule; r->next; r = r->next);
++          r->next = FcRuleCreate (FcRuleTest, t);
++          r = r->next;
++      }
++      else
++      {
++          r = rule = FcRuleCreate (FcRuleTest, t);
++      }
++    }
+     if (prefer)
+     {
+       edit = FcEditCreate (parse,
+@@ -1732,60 +1807,46 @@ FcParseAlias (FcConfigParse *parse)
+                            FcOpPrepend,
+                            prefer,
+                            binding);
+-      if (edit)
+-          edit->next = 0;
+-      else
++      if (!edit)
+           FcExprDestroy (prefer);
++      else
++      {
++          r->next = FcRuleCreate (FcRuleEdit, edit);
++          r = r->next;
++      }
+     }
+     if (accept)
+     {
+-      next = edit;
+       edit = FcEditCreate (parse,
+                            FC_FAMILY_OBJECT,
+                            FcOpAppend,
+                            accept,
+                            binding);
+-      if (edit)
+-          edit->next = next;
+-      else
++      if (!edit)
+           FcExprDestroy (accept);
++      else
++      {
++          r->next = FcRuleCreate (FcRuleEdit, edit);
++          r = r->next;
++      }
+     }
+     if (def)
+     {
+-      next = edit;
+       edit = FcEditCreate (parse,
+                            FC_FAMILY_OBJECT,
+                            FcOpAppendLast,
+                            def,
+                            binding);
+-      if (edit)
+-          edit->next = next;
+-      else
++      if (!edit)
+           FcExprDestroy (def);
+-    }
+-    if (edit)
+-    {
+-      FcTest *t = FcTestCreate (parse, FcMatchPattern,
+-                                FcQualAny,
+-                                (FcChar8 *) FC_FAMILY,
+-                                FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
+-                                family);
+-      if (test)
++      else
+       {
+-          FcTest *p = test;
+-
+-          while (p->next)
+-              p = p->next;
+-          p->next = t;
++          r->next = FcRuleCreate (FcRuleEdit, edit);
++          r = r->next;
+       }
+-      else
+-          test = t;
+-      if (test)
+-          if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern))
+-              FcTestDestroy (test);
+     }
+-    else
+-      FcExprDestroy (family);
++    if (!FcConfigAddRule (parse->config, rule, FcMatchPattern))
++      FcRuleDestroy (rule);
+ }
+ static FcExpr *
+@@ -2121,6 +2182,8 @@ FcParseInclude (FcConfigParse *parse)
+     FcBool        ignore_missing = FcFalse;
+     FcBool        deprecated = FcFalse;
+     FcChar8       *prefix = NULL, *p;
++    static FcChar8  *userdir = NULL;
++    static FcChar8  *userconf = NULL;
+     s = FcStrBufDoneStatic (&parse->pstack->str);
+     if (!s)
+@@ -2153,23 +2216,78 @@ FcParseInclude (FcConfigParse *parse)
+       memcpy (&prefix[plen + 1], s, dlen);
+       prefix[plen + 1 + dlen] = 0;
+       s = prefix;
++      if (FcFileIsDir (s))
++      {
++      userdir:
++          if (!userdir)
++              userdir = FcStrdup (s);
++      }
++      else if (FcFileIsFile (s))
++      {
++      userconf:
++          if (!userconf)
++              userconf = FcStrdup (s);
++      }
++      else
++      {
++          /* No config dir nor file on the XDG directory spec compliant place
++           * so need to guess what it is supposed to be.
++           */
++          FcChar8 *parent = FcStrDirname (s);
++
++          if (!FcFileIsDir (parent))
++              FcMakeDirectory (parent);
++          FcStrFree (parent);
++          if (FcStrStr (s, (const FcChar8 *)"conf.d") != NULL)
++              goto userdir;
++          else
++              goto userconf;
++      }
+     }
+     if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
+       parse->error = FcTrue;
++#ifndef _WIN32
+     else
+     {
+         FcChar8 *filename;
++      static FcBool warn_conf = FcFalse, warn_confd = FcFalse;
+         filename = FcConfigFilename(s);
+       if (deprecated == FcTrue &&
+           filename != NULL &&
+           !FcFileIsLink (filename))
+       {
+-            FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated.", s);
++          if (FcFileIsDir (filename))
++          {
++              if (FcFileIsDir (userdir) ||
++                  rename ((const char *)filename, (const char *)userdir) != 0 ||
++                  symlink ((const char *)userdir, (const char *)filename) != 0)
++              {
++                  if (!warn_confd)
++                  {
++                      FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userdir);
++                      warn_confd = FcTrue;
++                  }
++              }
++          }
++          else
++          {
++              if (FcFileIsFile (userconf) ||
++                  rename ((const char *)filename, (const char *)userconf) != 0 ||
++                  symlink ((const char *)userconf, (const char *)filename) != 0)
++              {
++                  if (!warn_conf)
++                  {
++                      FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userconf);
++                      warn_conf = FcTrue;
++                  }
++              }
++          }
+         }
+         if(filename)
+             FcStrFree(filename);
+     }
++#endif
+     FcStrBufDestroy (&parse->pstack->str);
+   bail:
+@@ -2386,22 +2504,14 @@ FcParseEdit (FcConfigParse *parse)
+       FcEditDestroy (edit);
+ }
+-typedef struct FcSubstStack {
+-    FcTest *test;
+-    FcEdit *edit;
+-} FcSubstStack;
+-
+ static void
+ FcParseMatch (FcConfigParse *parse)
+ {
+     const FcChar8   *kind_name;
+     FcMatchKind           kind;
+-    FcTest        *test = 0;
+     FcEdit        *edit = 0;
+     FcVStack      *vstack;
+-    FcBool           tested = FcFalse;
+-    FcSubstStack    *sstack = NULL;
+-    int              len, pos = 0;
++    FcRule        *rule = NULL, *r;
+     kind_name = FcConfigGetAttribute (parse, "target");
+     if (!kind_name)
+@@ -2420,48 +2530,29 @@ FcParseMatch (FcConfigParse *parse)
+           return;
+       }
+     }
+-    len = FcVStackElements(parse);
+-    if (len > 0)
+-    {
+-      sstack = malloc (sizeof (FcSubstStack) * (len + 1));
+-      if (!sstack)
+-      {
+-          FcConfigMessage (parse, FcSevereError, "out of memory");
+-          return;
+-      }
+-    }
+     while ((vstack = FcVStackPeek (parse)))
+     {
+       switch ((int) vstack->tag) {
+       case FcVStackTest:
+-          vstack->u.test->next = test;
+-          test = vstack->u.test;
++          r = FcRuleCreate (FcRuleTest, vstack->u.test);
++          if (rule)
++              r->next = rule;
++          rule = r;
+           vstack->tag = FcVStackNone;
+-          tested = FcTrue;
+           break;
+       case FcVStackEdit:
+-          /* due to the reverse traversal, <edit> node appears faster than
+-           * <test> node if any. so we have to deal with it here rather than
+-           * the above in FcVStackTest, and put recipes in reverse order.
+-           */
+-          if (tested)
+-          {
+-              sstack[pos].test = test;
+-              sstack[pos].edit = edit;
+-              pos++;
+-              test = NULL;
+-              edit = NULL;
+-              tested = FcFalse;
+-          }
+-          vstack->u.edit->next = edit;
+-          edit = vstack->u.edit;
+-          vstack->tag = FcVStackNone;
+-          if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT)
++          if (kind == FcMatchScan && vstack->u.edit->object > FC_MAX_BASE_OBJECT)
+           {
+               FcConfigMessage (parse, FcSevereError,
+                                "<match target=\"scan\"> cannot edit user-defined object \"%s\"",
+                                FcObjectName(edit->object));
++              break;
+           }
++          r = FcRuleCreate (FcRuleEdit, vstack->u.edit);
++          if (rule)
++              r->next = rule;
++          rule = r;
++          vstack->tag = FcVStackNone;
+           break;
+       default:
+           FcConfigMessage (parse, FcSevereWarning, "invalid match element");
+@@ -2469,22 +2560,8 @@ FcParseMatch (FcConfigParse *parse)
+       }
+       FcVStackPopAndDestroy (parse);
+     }
+-    if (!FcConfigAddEdit (parse->config, test, edit, kind))
++    if (!FcConfigAddRule (parse->config, rule, kind))
+       FcConfigMessage (parse, FcSevereError, "out of memory");
+-    if (sstack)
+-    {
+-      int i;
+-
+-      for (i = 0; i < pos; i++)
+-      {
+-          if (!FcConfigAddEdit (parse->config, sstack[pos - i - 1].test, sstack[pos - i - 1].edit, kind))
+-          {
+-              FcConfigMessage (parse, FcSevereError, "out of memory");
+-              return;
+-          }
+-      }
+-      free (sstack);
+-    }
+ }
+ static void
This page took 0.148175 seconds and 4 git commands to generate.