diff options
author | Akira TAGOH <akira@tagoh.org> | 2013-01-25 20:01:24 +0900 |
---|---|---|
committer | Akira TAGOH <akira@tagoh.org> | 2013-01-31 19:55:21 +0900 |
commit | d26fb23c41abd87422778bb38eea39f25ba3dc4a (patch) | |
tree | 5af43c964fa83df2391083f401fd94e53ec9afe5 | |
parent | fb3b410998aba8835999e2ca7003a180431cfaf4 (diff) | |
download | fontconfig-d26fb23c41abd87422778bb38eea39f25ba3dc4a.tar.gz |
Bug 59385 - Do the right thing for intermixed edit and test elements
This changes allows to have multiple mathcing rules in one <match> block
in the same order.
After this changes, the following thing will works as two matching rules:
<match>
<!-- rule 1 -->
<test name="family" compare="eq">
<string>foo</string>
</test>
<edit name="foo" mode="append">
<string>foo</string>
</edit>
<!-- rule 2 -->
<test name="foo" compare="eq">
<string>foo</string>
</test>
<edit name="foo" mode="append">
<string>bar</string>
</edit>
</match>
-rw-r--r-- | fonts.dtd | 2 | ||||
-rw-r--r-- | src/fcxml.c | 46 |
2 files changed, 47 insertions, 1 deletions
@@ -140,7 +140,7 @@ if 'target' is 'font', execute the match on the result of a font selection. --> -<!ELEMENT match (test*, edit*)> +<!ELEMENT match (test*, edit*)+> <!ATTLIST match target (pattern|font|scan) "pattern"> diff --git a/src/fcxml.c b/src/fcxml.c index 2a0d088..5981ea9 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -2375,6 +2375,11 @@ FcParseEdit (FcConfigParse *parse) FcEditDestroy (edit); } +typedef struct FcSubstStack { + FcTest *test; + FcEdit *edit; +} FcSubstStack; + static void FcParseMatch (FcConfigParse *parse) { @@ -2383,6 +2388,9 @@ FcParseMatch (FcConfigParse *parse) FcTest *test = 0; FcEdit *edit = 0; FcVStack *vstack; + FcBool tested = FcFalse; + FcSubstStack *sstack = NULL; + int len, pos = 0; kind_name = FcConfigGetAttribute (parse, "target"); if (!kind_name) @@ -2401,6 +2409,16 @@ 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) { @@ -2408,8 +2426,22 @@ FcParseMatch (FcConfigParse *parse) vstack->u.test->next = test; test = vstack->u.test; 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; @@ -2428,6 +2460,20 @@ FcParseMatch (FcConfigParse *parse) } if (!FcConfigAddEdit (parse->config, test, edit, 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 |