summaryrefslogtreecommitdiff
path: root/xps
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2012-03-14 16:24:44 +0100
committerTor Andersson <tor.andersson@artifex.com>2012-03-14 16:24:44 +0100
commit4f6bd093d6292cea66a0152b3083ce898dab0772 (patch)
tree27af20cf5110469fbf33408ac37935250b5ee415 /xps
parentfac8b8f9f0df6d617b333ee8cad87e295926922a (diff)
downloadmupdf-4f6bd093d6292cea66a0152b3083ce898dab0772.tar.xz
Support alternate content / markup compatibility tags in XPS.
Diffstat (limited to 'xps')
-rw-r--r--xps/muxps-internal.h2
-rw-r--r--xps/muxps.h1
-rw-r--r--xps/xps_common.c26
-rw-r--r--xps/xps_doc.c13
-rw-r--r--xps/xps_xml.c6
5 files changed, 48 insertions, 0 deletions
diff --git a/xps/muxps-internal.h b/xps/muxps-internal.h
index 37dd6f96..5a354555 100644
--- a/xps/muxps-internal.h
+++ b/xps/muxps-internal.h
@@ -165,6 +165,8 @@ void xps_parse_element(xps_document *doc, fz_matrix ctm, fz_rect area, char *bas
void xps_clip(xps_document *doc, fz_matrix ctm, xps_resource *dict, char *clip_att, xml_element *clip_tag);
+xml_element *xps_lookup_alternate_content(xml_element *node);
+
/*
* The interpreter context.
*/
diff --git a/xps/muxps.h b/xps/muxps.h
index a485adca..128ed35f 100644
--- a/xps/muxps.h
+++ b/xps/muxps.h
@@ -19,6 +19,7 @@ char *xml_tag(xml_element *item);
char *xml_att(xml_element *item, const char *att);
void xml_free_element(fz_context *doc, xml_element *item);
void xml_print_element(xml_element *item, int level);
+void xml_detach(xml_element *node);
/*
xps_open_document: Open a document.
diff --git a/xps/xps_common.c b/xps/xps_common.c
index 4829ef9c..eddef1b0 100644
--- a/xps/xps_common.c
+++ b/xps/xps_common.c
@@ -8,6 +8,26 @@ static inline int unhex(int a)
return 0;
}
+xml_element *
+xps_lookup_alternate_content(xml_element *node)
+{
+ for (node = xml_down(node); node; node = xml_next(node))
+ {
+ if (!strcmp(xml_tag(node), "mc:Choice") && xml_att(node, "Requires"))
+ {
+ char list[64];
+ char *next = list, *item;
+ fz_strlcpy(list, xml_att(node, "Requires"), sizeof(list));
+ while ((item = fz_strsep(&next, " \t\r\n")) && (!*item || !strcmp(item, "xps")));
+ if (!item)
+ return xml_down(node);
+ }
+ else if (!strcmp(xml_tag(node), "mc:Fallback"))
+ return xml_down(node);
+ }
+ return NULL;
+}
+
void
xps_parse_brush(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node)
{
@@ -37,6 +57,12 @@ xps_parse_element(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri
xps_parse_glyphs(doc, ctm, base_uri, dict, node);
if (!strcmp(xml_tag(node), "Canvas"))
xps_parse_canvas(doc, ctm, area, base_uri, dict, node);
+ if (!strcmp(xml_tag(node), "mc:AlternateContent"))
+ {
+ node = xps_lookup_alternate_content(node);
+ if (node)
+ xps_parse_element(doc, ctm, area, base_uri, dict, node);
+ }
/* skip unknown tags (like Foo.Resources and similar) */
}
diff --git a/xps/xps_doc.c b/xps/xps_doc.c
index 69609eb2..54e90186 100644
--- a/xps/xps_doc.c
+++ b/xps/xps_doc.c
@@ -422,6 +422,19 @@ xps_load_fixed_page(xps_document *doc, xps_page *page)
if (!root)
fz_throw(doc->ctx, "FixedPage missing root element");
+ if (!strcmp(xml_tag(root), "mc:AlternateContent"))
+ {
+ xml_element *node = xps_lookup_alternate_content(root);
+ if (!node)
+ {
+ xml_free_element(doc->ctx, root);
+ fz_throw(doc->ctx, "FixedPage missing alternate root element");
+ }
+ xml_detach(node);
+ xml_free_element(doc->ctx, root);
+ root = node;
+ }
+
if (strcmp(xml_tag(root), "FixedPage"))
{
xml_free_element(doc->ctx, root);
diff --git a/xps/xps_xml.c b/xps/xps_xml.c
index e2e958c8..8daee00b 100644
--- a/xps/xps_xml.c
+++ b/xps/xps_xml.c
@@ -94,6 +94,12 @@ void xml_free_element(fz_context *ctx, struct element *item)
}
}
+void xml_detach(xml_element *node)
+{
+ if (node->up)
+ node->up->down = NULL;
+}
+
static int xml_parse_entity(int *c, char *a)
{
char *b;