From 4f6bd093d6292cea66a0152b3083ce898dab0772 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 14 Mar 2012 16:24:44 +0100 Subject: Support alternate content / markup compatibility tags in XPS. --- xps/muxps-internal.h | 2 ++ xps/muxps.h | 1 + xps/xps_common.c | 26 ++++++++++++++++++++++++++ xps/xps_doc.c | 13 +++++++++++++ xps/xps_xml.c | 6 ++++++ 5 files changed, 48 insertions(+) (limited to 'xps') 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; -- cgit v1.2.3