[Fontconfig] fontconfig: Branch 'master'

Akira TAGOH tagoh at kemper.freedesktop.org
Thu Jul 4 03:52:02 PDT 2013


 src/fccfg.c |  349 +++++++++++++++++++++++++++---------------------------------
 src/fcdbg.c |   39 ++++--
 src/fcint.h |   29 +++-
 src/fcxml.c |  245 +++++++++++++++++++-----------------------
 4 files changed, 321 insertions(+), 341 deletions(-)

New commits:
commit d420e1df983871ab18b0f07976596fdf0ce78847
Author: Akira TAGOH <akira at tagoh.org>
Date:   Thu Jul 4 19:51:03 2013 +0900

    Rework to apply the intermixed test and edit elements in one-pass

diff --git a/src/fccfg.c b/src/fccfg.c
index 3cf31e8..7ea94b8 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,8 +224,6 @@ FcSubstDestroy (FcSubst *s)
 FcExpr *
 FcConfigAllocExpr (FcConfig *config)
 {
-    FcExpr *e;
-
     if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
     {
 	FcExprPage *new_page;
@@ -241,10 +237,7 @@ FcConfigAllocExpr (FcConfig *config)
 	config->expr_pool = new_page;
     }
 
-    e = config->expr_pool->next++;
-    FcRefInit (&e->ref, 1);
-
-    return e;
+    return config->expr_pool->next++;
 }
 
 FcConfig *
@@ -649,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) {
@@ -678,15 +669,18 @@ 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++;
+	if (r->type == FcRuleTest)
+	{
+	    if (r->u.test &&
+		r->u.test->kind == FcMatchDefault)
+		r->u.test->kind = kind;
+	    num++;
+	}
     }
     if (config->maxObjects < num)
 	config->maxObjects = num;
@@ -1491,13 +1485,12 @@ 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;
+    FcPatternElt    *elt = NULL;
+    FcObject	    object = FC_INVALID_OBJECT;
 
     if (!config)
     {
@@ -1542,10 +1535,6 @@ FcConfigSubstituteWithPat (FcConfig    *config,
 	return FcFalse;
     }
 
-    st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState));
-    if (!st && config->maxObjects)
-	return FcFalse;
-
     if (FcDebug () & FC_DBG_EDIT)
     {
 	printf ("FcConfigSubstitute ");
@@ -1553,194 +1542,174 @@ 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 (; r; r = r->next)
 	{
-	    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)
+	    switch (r->type) {
+	    case FcRuleUnknown:
+		/* shouldn't be reached */
+		break;
+	    case FcRuleTest:
+		/*
+		 * 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 = FcPatternObjectFindElt (m, r->u.test->object);
+		else
+		    elt = NULL;
+		/*
+		 * If there's no such field in the font,
+		 * then FcQualAll matches while FcQualAny does not
+		 */
+		if (!elt)
 		{
-		    /*
-		     * 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 = 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 = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt->values);
+		if (!value ||
+		    (r->u.test->qual == FcQualFirst && value != elt->values) ||
+		    (r->u.test->qual == FcQualNotFirst && value == elt->values))
 		{
-		    FcValueList	*thisValue = st[i].value;
-		    FcValueList	*nextValue = thisValue;
-		
+		    if (FcDebug () & FC_DBG_EDIT)
+			printf ("No match\n");
+		    goto bail;
+		}
+		object = r->u.test->object;
+		break;
+	    case FcRuleEdit:
+		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);
+		/*
+		 * Locate any test associated with this field, skipping
+		 * tests associated with the pattern when substituting in
+		 * the font
+		 */
+		if (object != r->u.edit->object)
+		    value = NULL;
+
+		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)
+		    {
+			FcValueList	*thisValue = value;
+			FcValueList	*nextValue = thisValue;
+
+			/*
+			 * Append the new list of values after the current value
+			 */
+			FcConfigAdd (&elt->values, thisValue, FcTrue, l, r->u.edit->object);
+			/*
+			 * Delete the marked value
+			 */
+			if (thisValue)
+			    FcConfigDel (&elt->values, thisValue);
+			/*
+			 * Adjust a pointer into the value list to ensure
+			 * future edits occur at the same place
+			 */
+			value = 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 = NULL;
+		    break;
+		case FcOpPrepend:
+		    if (value)
 		    {
-			if (st[i].value == thisValue)
-			    st[i].value = nextValue;
+			FcConfigAdd (&elt->values, value, 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)
 		    {
-			if (st[i].elt == thisElt)
-			    st[i].value = 0;
+			FcConfigAdd (&elt->values, value, 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)
+		    {
+			FcConfigDel (&elt->values, value);
+			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");
diff --git a/src/fcdbg.c b/src/fcdbg.c
index ce64214..d74bc27 100644
--- a/src/fcdbg.c
+++ b/src/fcdbg.c
@@ -427,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/fcint.h b/src/fcint.h
index 9dff033..fe523fb 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -241,7 +241,6 @@ typedef struct _FcExprName {
 
 typedef struct _FcExpr {
     FcOp   op;
-    FcRef  ref;
     union {
 	int	    ival;
 	double	    dval;
@@ -275,7 +274,6 @@ typedef enum _FcQual {
 #define FcMatchDefault	((FcMatchKind) -1)
 
 typedef struct _FcTest {
-    struct _FcTest	*next;
     FcMatchKind		kind;
     FcQual		qual;
     FcObject		object;
@@ -284,17 +282,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 {
@@ -614,10 +623,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
@@ -844,6 +852,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/fcxml.c b/src/fcxml.c
index 4b8049f..61dc630 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -62,12 +62,28 @@ FcExprDestroy (FcExpr *e);
 void
 FcTestDestroy (FcTest *test)
 {
-    if (test->next)
-	FcTestDestroy (test->next);
     FcExprDestroy (test->expr);
     free (test);
 }
 
+void
+FcRuleDestroy (FcRule *rule)
+{
+    if (rule->next)
+	FcRuleDestroy (rule->next);
+    switch (rule->type) {
+    case FcRuleTest:
+	FcTestDestroy (rule->u.test);
+	break;
+    case FcRuleEdit:
+	FcEditDestroy (rule->u.edit);
+	break;
+    default:
+	break;
+    }
+    free (rule);
+}
+
 static FcExpr *
 FcExprCreateInteger (FcConfig *config, int i)
 {
@@ -223,24 +239,11 @@ FcExprCreateOp (FcConfig *config, FcExpr *left, FcOp op, FcExpr *right)
     return e;
 }
 
-static FcExpr *
-FcExprReference (FcExpr *e)
-{
-    if (e)
-    {
-	FcRefInc (&e->ref);
-    }
-
-    return e;
-}
-
 static void
 FcExprDestroy (FcExpr *e)
 {
     if (!e)
 	return;
-    if (FcRefDec (&e->ref) != 1)
-	return;
     switch (FC_OP_GET_OP (e->op)) {
     case FcOpInteger:
 	break;
@@ -313,8 +316,6 @@ FcExprDestroy (FcExpr *e)
 void
 FcEditDestroy (FcEdit *e)
 {
-    if (e->next)
-	FcEditDestroy (e->next);
     if (e->expr)
 	FcExprDestroy (e->expr);
     free (e);
@@ -727,7 +728,6 @@ FcTestCreate (FcConfigParse *parse,
     {
 	const FcObjectType	*o;
 	
-	test->next = 0;
 	test->kind = kind;
 	test->qual = qual;
 	test->object = FcObjectFromName ((const char *) field);
@@ -740,21 +740,6 @@ FcTestCreate (FcConfigParse *parse,
     return test;
 }
 
-static FcTest *
-FcTestDuplicate (FcTest *test)
-{
-    FcTest *retval = (FcTest *) malloc (sizeof (FcTest));
-
-    if (retval)
-    {
-	memcpy (retval, test, sizeof (FcTest));
-	retval->next = NULL;
-	retval->expr = FcExprReference (test->expr);
-    }
-
-    return retval;
-}
-
 static FcEdit *
 FcEditCreate (FcConfigParse	*parse,
 	      FcObject		object,
@@ -768,7 +753,6 @@ FcEditCreate (FcConfigParse	*parse,
     {
 	const FcObjectType	*o;
 
-	e->next = 0;
 	e->object = object;
 	e->op = op;
 	e->expr = expr;
@@ -780,6 +764,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)
 {
@@ -1685,9 +1697,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))
@@ -1732,8 +1744,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:
@@ -1751,8 +1769,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,
@@ -1760,60 +1805,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 *
@@ -2414,22 +2445,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, i;
+    FcRule	    *rule = NULL, *r;
 
     kind_name = FcConfigGetAttribute (parse, "target");
     if (!kind_name)
@@ -2448,55 +2471,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;
-	    for (i = 0; i < pos; i++)
-	    {
-		FcTest *t = FcTestDuplicate(test);
-
-		t->next = sstack[i].test;
-		sstack[i].test = t;
-	    }
 	    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");
@@ -2504,22 +2501,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


More information about the Fontconfig mailing list