summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkira TAGOH <akira@tagoh.org>2013-01-25 20:01:24 +0900
committerAkira TAGOH <akira@tagoh.org>2013-01-31 19:55:21 +0900
commitd26fb23c41abd87422778bb38eea39f25ba3dc4a (patch)
tree5af43c964fa83df2391083f401fd94e53ec9afe5
parentfb3b410998aba8835999e2ca7003a180431cfaf4 (diff)
downloadfontconfig-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.dtd2
-rw-r--r--src/fcxml.c46
2 files changed, 47 insertions, 1 deletions
diff --git a/fonts.dtd b/fonts.dtd
index def8c21..664467d 100644
--- a/fonts.dtd
+++ b/fonts.dtd
@@ -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