diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2011-04-03 03:44:12 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2011-04-03 03:44:12 +0200 |
commit | e603c180e7d70f64cf50302ecf6d8937172ed121 (patch) | |
tree | 19771c1b19aecac290ba755ca0bfd5c36c794c30 /xps | |
parent | 9e43fd5ace67a6c8493c222c8a71ba7bcca87325 (diff) | |
download | mupdf-e603c180e7d70f64cf50302ecf6d8937172ed121.tar.xz |
xps: Remove dependency on expat.
Diffstat (limited to 'xps')
-rw-r--r-- | xps/muxps.h | 80 | ||||
-rw-r--r-- | xps/xpsanalyze.c | 112 | ||||
-rw-r--r-- | xps/xpscommon.c | 26 | ||||
-rw-r--r-- | xps/xpsdoc.c | 120 | ||||
-rw-r--r-- | xps/xpsglyphs.c | 68 | ||||
-rw-r--r-- | xps/xpsgradient.c | 68 | ||||
-rw-r--r-- | xps/xpsimage.c | 8 | ||||
-rw-r--r-- | xps/xpsopacity.c | 12 | ||||
-rw-r--r-- | xps/xpspage.c | 63 | ||||
-rw-r--r-- | xps/xpspath.c | 166 | ||||
-rw-r--r-- | xps/xpsresource.c | 32 | ||||
-rw-r--r-- | xps/xpstile.c | 36 | ||||
-rw-r--r-- | xps/xpsvisual.c | 18 | ||||
-rw-r--r-- | xps/xpsxml.c | 588 | ||||
-rw-r--r-- | xps/xpszip.c | 8 |
15 files changed, 713 insertions, 692 deletions
diff --git a/xps/muxps.h b/xps/muxps.h index d0478e7b..0455ee68 100644 --- a/xps/muxps.h +++ b/xps/muxps.h @@ -49,6 +49,20 @@ void xps_hash_free(xps_context *ctx, xps_hash_table *table, void xps_hash_debug(xps_hash_table *table); /* + * XML document model + */ + +typedef struct element xml_element; + +xml_element *xml_parse_document(byte *buf, int len); +xml_element *xml_next(xml_element *item); +xml_element *xml_down(xml_element *item); +char *xml_tag(xml_element *item); +char *xml_att(xml_element *item, const char *att); +void xml_free_element(xml_element *item); +void xml_print_element(xml_element *item, int level); + +/* * Container parts. */ @@ -84,7 +98,7 @@ struct xps_page_s char *name; int width; int height; - struct xps_item_s *root; + struct element *root; xps_page *next; }; @@ -144,20 +158,6 @@ void xps_parse_color(xps_context *ctx, char *base_uri, char *hexstring, fz_color void xps_set_color(xps_context *ctx, fz_colorspace *colorspace, float *samples); /* - * XML document model - */ - -typedef struct xps_item_s xps_item; - -xps_item * xps_parse_xml(xps_context *ctx, byte *buf, int len); -xps_item * xps_next(xps_item *item); -xps_item * xps_down(xps_item *item); -char * xps_tag(xps_item *item); -char * xps_att(xps_item *item, const char *att); -void xps_free_item(xps_context *ctx, xps_item *item); -void xps_debug_item(xps_item *item, int level); - -/* * Resource dictionaries. */ @@ -167,15 +167,15 @@ struct xps_resource_s { char *name; char *base_uri; /* only used in the head nodes */ - xps_item *base_xml; /* only used in the head nodes, to free the xml document */ - xps_item *data; + xml_element *base_xml; /* only used in the head nodes, to free the xml document */ + xml_element *data; xps_resource *next; xps_resource *parent; /* up to the previous dict in the stack */ }; -int xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xps_item *root); +int xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xml_element *root); void xps_free_resource_dictionary(xps_context *ctx, xps_resource *dict); -void xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict, char **attp, xps_item **tagp, char **urip); +void xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict, char **attp, xml_element **tagp, char **urip); void xps_debug_resource_dictionary(xps_resource *dict); @@ -185,34 +185,34 @@ void xps_debug_resource_dictionary(xps_resource *dict); int xps_load_fixed_page(xps_context *ctx, xps_page *page); void xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page); -void xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_solid_color_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_linear_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_radial_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node); - -void xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *root, void(*func)(xps_context*, fz_matrix, char*, xps_resource*, xps_item*, void*), void *user); - -void xps_parse_matrix_transform(xps_context *ctx, xps_item *root, fz_matrix *matrix); +void xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_solid_color_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_linear_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_radial_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); + +void xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root, void(*func)(xps_context*, fz_matrix, char*, xps_resource*, xml_element*, void*), void *user); + +void xps_parse_matrix_transform(xps_context *ctx, xml_element *root, fz_matrix *matrix); void xps_parse_render_transform(xps_context *ctx, char *text, fz_matrix *matrix); void xps_parse_rectangle(xps_context *ctx, char *text, fz_rect *rect); fz_path *xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule); -fz_path *xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, int stroking, int *fill_rule); +fz_path *xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xml_element *root, int stroking, int *fill_rule); -void xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, char *opacity_att, xps_item *opacity_mask_tag); -void xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, char *opacity_att, xps_item *opacity_mask_tag); +void xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag); +void xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag); -void xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_element(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); +void xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); +void xps_parse_element(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); -void xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xps_item *clip_tag); +void xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xml_element *clip_tag); -int xps_element_has_transparency(xps_context *ctx, char *base_uri, xps_item *node); -int xps_resource_dictionary_has_transparency(xps_context *ctx, char *base_uri, xps_item *node); -int xps_image_brush_has_transparency(xps_context *ctx, char *base_uri, xps_item *root); +int xps_element_has_transparency(xps_context *ctx, char *base_uri, xml_element *node); +int xps_resource_dictionary_has_transparency(xps_context *ctx, char *base_uri, xml_element *node); +int xps_image_brush_has_transparency(xps_context *ctx, char *base_uri, xml_element *root); /* * The interpreter context. diff --git a/xps/xpsanalyze.c b/xps/xpsanalyze.c index 9cd29840..86dd4626 100644 --- a/xps/xpsanalyze.c +++ b/xps/xpsanalyze.c @@ -14,16 +14,16 @@ xps_remote_resource_dictionary_has_transparency(xps_context *ctx, char *base_uri } int -xps_resource_dictionary_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) +xps_resource_dictionary_has_transparency(xps_context *ctx, char *base_uri, xml_element *root) { char *source; - xps_item *node; + xml_element *node; - source = xps_att(root, "Source"); + source = xml_att(root, "Source"); if (source) return xps_remote_resource_dictionary_has_transparency(ctx, base_uri, source); - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { // TODO: ... all kinds of stuff can be here, brushes, elements, whatnot } @@ -32,18 +32,18 @@ xps_resource_dictionary_has_transparency(xps_context *ctx, char *base_uri, xps_i } static int -xps_gradient_stops_have_transparency(xps_context *ctx, char *base_uri, xps_item *root) +xps_gradient_stops_have_transparency(xps_context *ctx, char *base_uri, xml_element *root) { - xps_item *node; + xml_element *node; fz_colorspace *colorspace; char *color_att; float samples[32]; - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "GradientStop")) + if (!strcmp(xml_tag(node), "GradientStop")) { - color_att = xps_att(node, "Color"); + color_att = xml_att(node, "Color"); if (color_att) { xps_parse_color(ctx, base_uri, color_att, &colorspace, samples); @@ -60,12 +60,12 @@ xps_gradient_stops_have_transparency(xps_context *ctx, char *base_uri, xps_item } static int -xps_gradient_brush_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) +xps_gradient_brush_has_transparency(xps_context *ctx, char *base_uri, xml_element *root) { - xps_item *node; + xml_element *node; char *opacity_att; - opacity_att = xps_att(root, "Opacity"); + opacity_att = xml_att(root, "Opacity"); if (opacity_att) { if (atof(opacity_att) < 1.0) @@ -75,14 +75,14 @@ xps_gradient_brush_has_transparency(xps_context *ctx, char *base_uri, xps_item * } } - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "RadialGradientBrush.GradientStops")) + if (!strcmp(xml_tag(node), "RadialGradientBrush.GradientStops")) { if (xps_gradient_stops_have_transparency(ctx, base_uri, node)) return 1; } - if (!strcmp(xps_tag(node), "LinearGradientBrush.GradientStops")) + if (!strcmp(xml_tag(node), "LinearGradientBrush.GradientStops")) { if (xps_gradient_stops_have_transparency(ctx, base_uri, node)) return 1; @@ -93,18 +93,18 @@ xps_gradient_brush_has_transparency(xps_context *ctx, char *base_uri, xps_item * } static int -xps_brush_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) +xps_brush_has_transparency(xps_context *ctx, char *base_uri, xml_element *root) { char *opacity_att; char *color_att; - xps_item *node; + xml_element *node; fz_colorspace *colorspace; float samples[32]; - if (!strcmp(xps_tag(root), "SolidColorBrush")) + if (!strcmp(xml_tag(root), "SolidColorBrush")) { - opacity_att = xps_att(root, "Opacity"); + opacity_att = xml_att(root, "Opacity"); if (opacity_att) { if (atof(opacity_att) < 1.0) @@ -114,7 +114,7 @@ xps_brush_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) } } - color_att = xps_att(root, "Color"); + color_att = xml_att(root, "Color"); if (color_att) { xps_parse_color(ctx, base_uri, color_att, &colorspace, samples); @@ -126,9 +126,9 @@ xps_brush_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) } } - if (!strcmp(xps_tag(root), "VisualBrush")) + if (!strcmp(xml_tag(root), "VisualBrush")) { - char *opacity_att = xps_att(root, "Opacity"); + char *opacity_att = xml_att(root, "Opacity"); if (opacity_att) { if (atof(opacity_att) < 1.0) @@ -138,29 +138,29 @@ xps_brush_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) } } - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "VisualBrush.Visual")) + if (!strcmp(xml_tag(node), "VisualBrush.Visual")) { - if (xps_element_has_transparency(ctx, base_uri, xps_down(node))) + if (xps_element_has_transparency(ctx, base_uri, xml_down(node))) return 1; } } } - if (!strcmp(xps_tag(root), "ImageBrush")) + if (!strcmp(xml_tag(root), "ImageBrush")) { if (xps_image_brush_has_transparency(ctx, base_uri, root)) return 1; } - if (!strcmp(xps_tag(root), "LinearGradientBrush")) + if (!strcmp(xml_tag(root), "LinearGradientBrush")) { if (xps_gradient_brush_has_transparency(ctx, base_uri, root)) return 1; } - if (!strcmp(xps_tag(root), "RadialGradientBrush")) + if (!strcmp(xml_tag(root), "RadialGradientBrush")) { if (xps_gradient_brush_has_transparency(ctx, base_uri, root)) return 1; @@ -170,27 +170,27 @@ xps_brush_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) } static int -xps_path_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) +xps_path_has_transparency(xps_context *ctx, char *base_uri, xml_element *root) { - xps_item *node; + xml_element *node; - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "Path.OpacityMask")) + if (!strcmp(xml_tag(node), "Path.OpacityMask")) { //dputs("page has transparency: Path.OpacityMask\n"); return 1; } - if (!strcmp(xps_tag(node), "Path.Stroke")) + if (!strcmp(xml_tag(node), "Path.Stroke")) { - if (xps_brush_has_transparency(ctx, base_uri, xps_down(node))) + if (xps_brush_has_transparency(ctx, base_uri, xml_down(node))) return 1; } - if (!strcmp(xps_tag(node), "Path.Fill")) + if (!strcmp(xml_tag(node), "Path.Fill")) { - if (xps_brush_has_transparency(ctx, base_uri, xps_down(node))) + if (xps_brush_has_transparency(ctx, base_uri, xml_down(node))) return 1; } } @@ -199,21 +199,21 @@ xps_path_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) } static int -xps_glyphs_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) +xps_glyphs_has_transparency(xps_context *ctx, char *base_uri, xml_element *root) { - xps_item *node; + xml_element *node; - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "Glyphs.OpacityMask")) + if (!strcmp(xml_tag(node), "Glyphs.OpacityMask")) { //dputs("page has transparency: Glyphs.OpacityMask\n"); return 1; } - if (!strcmp(xps_tag(node), "Glyphs.Fill")) + if (!strcmp(xml_tag(node), "Glyphs.Fill")) { - if (xps_brush_has_transparency(ctx, base_uri, xps_down(node))) + if (xps_brush_has_transparency(ctx, base_uri, xml_down(node))) return 1; } } @@ -222,19 +222,19 @@ xps_glyphs_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) } static int -xps_canvas_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) +xps_canvas_has_transparency(xps_context *ctx, char *base_uri, xml_element *root) { - xps_item *node; + xml_element *node; - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "Canvas.Resources")) + if (!strcmp(xml_tag(node), "Canvas.Resources")) { - if (xps_resource_dictionary_has_transparency(ctx, base_uri, xps_down(node))) + if (xps_resource_dictionary_has_transparency(ctx, base_uri, xml_down(node))) return 1; } - if (!strcmp(xps_tag(node), "Canvas.OpacityMask")) + if (!strcmp(xml_tag(node), "Canvas.OpacityMask")) { //dputs("page has transparency: Canvas.OpacityMask\n"); return 1; @@ -248,7 +248,7 @@ xps_canvas_has_transparency(xps_context *ctx, char *base_uri, xps_item *root) } int -xps_element_has_transparency(xps_context *ctx, char *base_uri, xps_item *node) +xps_element_has_transparency(xps_context *ctx, char *base_uri, xml_element *node) { char *opacity_att; char *stroke_att; @@ -257,7 +257,7 @@ xps_element_has_transparency(xps_context *ctx, char *base_uri, xps_item *node) fz_colorspace *colorspace; float samples[32]; - stroke_att = xps_att(node, "Stroke"); + stroke_att = xml_att(node, "Stroke"); if (stroke_att) { xps_parse_color(ctx, base_uri, stroke_att, &colorspace, samples); @@ -268,7 +268,7 @@ xps_element_has_transparency(xps_context *ctx, char *base_uri, xps_item *node) } } - fill_att = xps_att(node, "Fill"); + fill_att = xml_att(node, "Fill"); if (fill_att) { xps_parse_color(ctx, base_uri, fill_att, &colorspace, samples); @@ -279,7 +279,7 @@ xps_element_has_transparency(xps_context *ctx, char *base_uri, xps_item *node) } } - opacity_att = xps_att(node, "Opacity"); + opacity_att = xml_att(node, "Opacity"); if (opacity_att) { if (atof(opacity_att) < 1.0) @@ -289,19 +289,19 @@ xps_element_has_transparency(xps_context *ctx, char *base_uri, xps_item *node) } } - if (xps_att(node, "OpacityMask")) + if (xml_att(node, "OpacityMask")) { //dputs("page has transparency: OpacityMask\n"); return 1; } - if (!strcmp(xps_tag(node), "Path")) + if (!strcmp(xml_tag(node), "Path")) if (xps_path_has_transparency(ctx, base_uri, node)) return 1; - if (!strcmp(xps_tag(node), "Glyphs")) + if (!strcmp(xml_tag(node), "Glyphs")) if (xps_glyphs_has_transparency(ctx, base_uri, node)) return 1; - if (!strcmp(xps_tag(node), "Canvas")) + if (!strcmp(xml_tag(node), "Canvas")) if (xps_canvas_has_transparency(ctx, base_uri, node)) return 1; diff --git a/xps/xpscommon.c b/xps/xpscommon.c index 063435c5..77aec58c 100644 --- a/xps/xpscommon.c +++ b/xps/xpscommon.c @@ -2,29 +2,29 @@ #include "muxps.h" void -xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node) +xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node) { /* SolidColorBrushes are handled in a special case and will never show up here */ - if (!strcmp(xps_tag(node), "ImageBrush")) + if (!strcmp(xml_tag(node), "ImageBrush")) xps_parse_image_brush(ctx, ctm, area, base_uri, dict, node); - else if (!strcmp(xps_tag(node), "VisualBrush")) + else if (!strcmp(xml_tag(node), "VisualBrush")) xps_parse_visual_brush(ctx, ctm, area, base_uri, dict, node); - else if (!strcmp(xps_tag(node), "LinearGradientBrush")) + else if (!strcmp(xml_tag(node), "LinearGradientBrush")) xps_parse_linear_gradient_brush(ctx, ctm, area, base_uri, dict, node); - else if (!strcmp(xps_tag(node), "RadialGradientBrush")) + else if (!strcmp(xml_tag(node), "RadialGradientBrush")) xps_parse_radial_gradient_brush(ctx, ctm, area, base_uri, dict, node); else - fz_warn("unknown brush tag: %s", xps_tag(node)); + fz_warn("unknown brush tag: %s", xml_tag(node)); } void -xps_parse_element(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node) +xps_parse_element(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node) { - if (!strcmp(xps_tag(node), "Path")) + if (!strcmp(xml_tag(node), "Path")) xps_parse_path(ctx, ctm, base_uri, dict, node); - if (!strcmp(xps_tag(node), "Glyphs")) + if (!strcmp(xml_tag(node), "Glyphs")) xps_parse_glyphs(ctx, ctm, base_uri, dict, node); - if (!strcmp(xps_tag(node), "Canvas")) + if (!strcmp(xml_tag(node), "Canvas")) xps_parse_canvas(ctx, ctm, base_uri, dict, node); /* skip unknown tags (like Foo.Resources and similar) */ } @@ -55,15 +55,15 @@ xps_parse_render_transform(xps_context *ctx, char *transform, fz_matrix *matrix) } void -xps_parse_matrix_transform(xps_context *ctx, xps_item *root, fz_matrix *matrix) +xps_parse_matrix_transform(xps_context *ctx, xml_element *root, fz_matrix *matrix) { char *transform; *matrix = fz_identity; - if (!strcmp(xps_tag(root), "MatrixTransform")) + if (!strcmp(xml_tag(root), "MatrixTransform")) { - transform = xps_att(root, "Matrix"); + transform = xml_att(root, "Matrix"); if (transform) xps_parse_render_transform(ctx, transform, matrix); } diff --git a/xps/xpsdoc.c b/xps/xpsdoc.c index a37ed0e9..94fb32d7 100644 --- a/xps/xpsdoc.c +++ b/xps/xpsdoc.c @@ -1,8 +1,6 @@ #include "fitz.h" #include "muxps.h" -#include <expat.h> - xps_part * xps_new_part(xps_context *ctx, char *name, int size) { @@ -11,7 +9,8 @@ xps_new_part(xps_context *ctx, char *name, int size) part = fz_malloc(sizeof(xps_part)); part->name = fz_strdup(name); part->size = size; - part->data = fz_malloc(size); + part->data = fz_malloc(size + 1); + part->data[size] = 0; /* null-terminate for xml parser */ return part; } @@ -137,87 +136,63 @@ xps_free_fixed_pages(xps_context *ctx) } /* - * Parse the fixed document sequence structure and _rels/.rels to find the - * start part. We hook up unique expat handlers for this, since we don't need - * the full document model. + * Parse the fixed document sequence structure and _rels/.rels to find the start part. */ static void -xps_parse_metadata_imp(void *zp, char *name, char **atts) +xps_parse_metadata_imp(xps_context *ctx, xml_element *item) { - xps_context *ctx = zp; - int i; - - if (!strcmp(name, "Relationship")) - { - char tgtbuf[1024]; - char *target = NULL; - char *type = NULL; - - for (i = 0; atts[i]; i += 2) - { - if (!strcmp(atts[i], "Target")) - target = atts[i + 1]; - if (!strcmp(atts[i], "Type")) - type = atts[i + 1]; - } - - if (target && type) - { - xps_absolute_path(tgtbuf, ctx->base_uri, target, sizeof tgtbuf); - if (!strcmp(type, REL_START_PART)) - ctx->start_part = fz_strdup(tgtbuf); - } - } - - if (!strcmp(name, "DocumentReference")) + while (item) { - char *source = NULL; - char srcbuf[1024]; + xps_parse_metadata_imp(ctx, xml_down(item)); - for (i = 0; atts[i]; i += 2) + if (!strcmp(xml_tag(item), "Relationship")) { - if (!strcmp(atts[i], "Source")) - source = atts[i + 1]; + char *target = xml_att(item, "Target"); + char *type = xml_att(item, "Type"); + if (target && type) + { + char tgtbuf[1024]; + xps_absolute_path(tgtbuf, ctx->base_uri, target, sizeof tgtbuf); + if (!strcmp(type, REL_START_PART)) + ctx->start_part = fz_strdup(tgtbuf); + } } - if (source) + if (!strcmp(xml_tag(item), "DocumentReference")) { - xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); - xps_add_fixed_document(ctx, srcbuf); + char *source = xml_att(item, "Source"); + if (source) + { + char srcbuf[1024]; + xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); + xps_add_fixed_document(ctx, srcbuf); + } } - } - - if (!strcmp(name, "PageContent")) - { - char *source = NULL; - char srcbuf[1024]; - int width = 0; - int height = 0; - for (i = 0; atts[i]; i += 2) + if (!strcmp(xml_tag(item), "PageContent")) { - if (!strcmp(atts[i], "Source")) - source = atts[i + 1]; - if (!strcmp(atts[i], "Width")) - width = atoi(atts[i + 1]); - if (!strcmp(atts[i], "Height")) - height = atoi(atts[i + 1]); + char *source = xml_att(item, "Source"); + char *width_att = xml_att(item, "Width"); + char *height_att = xml_att(item, "Height"); + int width = width_att ? atoi(width_att) : 0; + int height = height_att ? atoi(height_att) : 0; + if (source) + { + char srcbuf[1024]; + xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); + xps_add_fixed_page(ctx, srcbuf, width, height); + } } - if (source) - { - xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); - xps_add_fixed_page(ctx, srcbuf, width, height); - } + item = xml_next(item); } } int xps_parse_metadata(xps_context *ctx, xps_part *part) { - XML_Parser xp; - int code; + xml_element *root; char buf[1024]; char *s; @@ -238,23 +213,16 @@ xps_parse_metadata(xps_context *ctx, xps_part *part) ctx->base_uri = buf; ctx->part_uri = part->name; - xp = XML_ParserCreate(NULL); - if (!xp) - return fz_throw("cannot create XML parser"); + root = xml_parse_document(part->data, part->size); + if (!root) + return fz_rethrow(-1, "cannot parse metadata part '%s'", part->name); - XML_SetUserData(xp, ctx); - XML_SetParamEntityParsing(xp, XML_PARAM_ENTITY_PARSING_NEVER); - XML_SetStartElementHandler(xp, (XML_StartElementHandler)xps_parse_metadata_imp); + xps_parse_metadata_imp(ctx, root); - code = XML_Parse(xp, (char*)part->data, part->size, 1); - - XML_ParserFree(xp); + xml_free_element(root); ctx->base_uri = NULL; ctx->part_uri = NULL; - if (code == 0) - return fz_throw("cannot parse XML in part: %s", part->name); - - return 0; + return fz_okay; } diff --git a/xps/xpsglyphs.c b/xps/xpsglyphs.c index f62cc928..1936534b 100644 --- a/xps/xpsglyphs.c +++ b/xps/xpsglyphs.c @@ -286,9 +286,9 @@ xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, fz_font *font, float size, void xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, - char *base_uri, xps_resource *dict, xps_item *root) + char *base_uri, xps_resource *dict, xml_element *root) { - xps_item *node; + xml_element *node; int code; char *fill_uri; @@ -310,10 +310,10 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, char *opacity_att; char *opacity_mask_att; - xps_item *transform_tag = NULL; - xps_item *clip_tag = NULL; - xps_item *fill_tag = NULL; - xps_item *opacity_mask_tag = NULL; + xml_element *transform_tag = NULL; + xml_element *clip_tag = NULL; + xml_element *fill_tag = NULL; + xml_element *opacity_mask_tag = NULL; char *fill_opacity_att = NULL; @@ -335,32 +335,32 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, * Extract attributes and extended attributes. */ - bidi_level_att = xps_att(root, "BidiLevel"); - caret_stops_att = xps_att(root, "CaretStops"); - fill_att = xps_att(root, "Fill"); - font_size_att = xps_att(root, "FontRenderingEmSize"); - font_uri_att = xps_att(root, "FontUri"); - origin_x_att = xps_att(root, "OriginX"); - origin_y_att = xps_att(root, "OriginY"); - is_sideways_att = xps_att(root, "IsSideways"); - indices_att = xps_att(root, "Indices"); - unicode_att = xps_att(root, "UnicodeString"); - style_att = xps_att(root, "StyleSimulations"); - transform_att = xps_att(root, "RenderTransform"); - clip_att = xps_att(root, "Clip"); - opacity_att = xps_att(root, "Opacity"); - opacity_mask_att = xps_att(root, "OpacityMask"); - - for (node = xps_down(root); node; node = xps_next(node)) + bidi_level_att = xml_att(root, "BidiLevel"); + caret_stops_att = xml_att(root, "CaretStops"); + fill_att = xml_att(root, "Fill"); + font_size_att = xml_att(root, "FontRenderingEmSize"); + font_uri_att = xml_att(root, "FontUri"); + origin_x_att = xml_att(root, "OriginX"); + origin_y_att = xml_att(root, "OriginY"); + is_sideways_att = xml_att(root, "IsSideways"); + indices_att = xml_att(root, "Indices"); + unicode_att = xml_att(root, "UnicodeString"); + style_att = xml_att(root, "StyleSimulations"); + transform_att = xml_att(root, "RenderTransform"); + clip_att = xml_att(root, "Clip"); + opacity_att = xml_att(root, "Opacity"); + opacity_mask_att = xml_att(root, "OpacityMask"); + + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "Glyphs.RenderTransform")) - transform_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Glyphs.OpacityMask")) - opacity_mask_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Glyphs.Clip")) - clip_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Glyphs.Fill")) - fill_tag = xps_down(node); + if (!strcmp(xml_tag(node), "Glyphs.RenderTransform")) + transform_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Glyphs.OpacityMask")) + opacity_mask_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Glyphs.Clip")) + clip_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Glyphs.Fill")) + fill_tag = xml_down(node); } fill_uri = base_uri; @@ -462,10 +462,10 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, * If it's a solid color brush fill/stroke do a simple fill */ - if (fill_tag && !strcmp(xps_tag(fill_tag), "SolidColorBrush")) + if (fill_tag && !strcmp(xml_tag(fill_tag), "SolidColorBrush")) { - fill_opacity_att = xps_att(fill_tag, "Opacity"); - fill_att = xps_att(fill_tag, "Color"); + fill_opacity_att = xml_att(fill_tag, "Opacity"); + fill_att = xml_att(fill_tag, "Color"); fill_tag = NULL; } diff --git a/xps/xpsgradient.c b/xps/xpsgradient.c index 180224f8..8c877a0b 100644 --- a/xps/xpsgradient.c +++ b/xps/xpsgradient.c @@ -35,7 +35,7 @@ static inline float lerp(float a, float b, float x) } static int -xps_parse_gradient_stops(xps_context *ctx, char *base_uri, xps_item *node, +xps_parse_gradient_stops(xps_context *ctx, char *base_uri, xml_element *node, struct stop *stops, int maxcount) { fz_colorspace *colorspace; @@ -51,10 +51,10 @@ xps_parse_gradient_stops(xps_context *ctx, char *base_uri, xps_item *node, count = 0; while (node && count < maxcount) { - if (!strcmp(xps_tag(node), "GradientStop")) + if (!strcmp(xml_tag(node), "GradientStop")) { - char *offset = xps_att(node, "Offset"); - char *color = xps_att(node, "Color"); + char *offset = xml_att(node, "Offset"); + char *color = xml_att(node, "Color"); if (offset && color) { stops[count].offset = atof(offset); @@ -71,7 +71,7 @@ xps_parse_gradient_stops(xps_context *ctx, char *base_uri, xps_item *node, count ++; } } - node = xps_next(node); + node = xml_next(node); } if (count == 0) @@ -299,7 +299,7 @@ static inline float point_inside_circle(float px, float py, float x, float y, fl static void xps_draw_radial_gradient(xps_context *ctx, fz_matrix ctm, struct stop *stops, int count, - xps_item *root, int spread) + xml_element *root, int spread) { float x0, y0, r0; float x1, y1, r1; @@ -307,10 +307,10 @@ xps_draw_radial_gradient(xps_context *ctx, fz_matrix ctm, float yrad = 1; float invscale; - char *center_att = xps_att(root, "Center"); - char *origin_att = xps_att(root, "GradientOrigin"); - char *radius_x_att = xps_att(root, "RadiusX"); - char *radius_y_att = xps_att(root, "RadiusY"); + char *center_att = xml_att(root, "Center"); + char *origin_att = xml_att(root, "GradientOrigin"); + char *radius_x_att = xml_att(root, "RadiusX"); + char *radius_y_att = xml_att(root, "RadiusY"); if (origin_att) sscanf(origin_att, "%g,%g", &x0, &y0); @@ -342,12 +342,12 @@ xps_draw_radial_gradient(xps_context *ctx, fz_matrix ctm, static void xps_draw_linear_gradient(xps_context *ctx, fz_matrix ctm, struct stop *stops, int count, - xps_item *root, int spread) + xml_element *root, int spread) { float x0, y0, x1, y1; - char *start_point_att = xps_att(root, "StartPoint"); - char *end_point_att = xps_att(root, "EndPoint"); + char *start_point_att = xml_att(root, "StartPoint"); + char *end_point_att = xml_att(root, "EndPoint"); x0 = y0 = 0; x1 = y1 = 1; @@ -367,10 +367,10 @@ xps_draw_linear_gradient(xps_context *ctx, fz_matrix ctm, static void xps_parse_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xps_item *root, - void (*draw)(xps_context *, fz_matrix, struct stop *, int, xps_item *, int)) + char *base_uri, xps_resource *dict, xml_element *root, + void (*draw)(xps_context *, fz_matrix, struct stop *, int, xml_element *, int)) { - xps_item *node; + xml_element *node; char *opacity_att; char *interpolation_att; @@ -378,30 +378,30 @@ xps_parse_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *mapping_att; char *transform_att; - xps_item *transform_tag = NULL; - xps_item *stop_tag = NULL; + xml_element *transform_tag = NULL; + xml_element *stop_tag = NULL; struct stop stop_list[MAX_STOPS]; int stop_count; fz_matrix transform; int spread_method; - opacity_att = xps_att(root, "Opacity"); - interpolation_att = xps_att(root, "ColorInterpolationMode"); - spread_att = xps_att(root, "SpreadMethod"); - mapping_att = xps_att(root, "MappingMode"); - transform_att = xps_att(root, "Transform"); + opacity_att = xml_att(root, "Opacity"); + interpolation_att = xml_att(root, "ColorInterpolationMode"); + spread_att = xml_att(root, "SpreadMethod"); + mapping_att = xml_att(root, "MappingMode"); + transform_att = xml_att(root, "Transform"); - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "LinearGradientBrush.Transform")) - transform_tag = xps_down(node); - if (!strcmp(xps_tag(node), "RadialGradientBrush.Transform")) - transform_tag = xps_down(node); - if (!strcmp(xps_tag(node), "LinearGradientBrush.GradientStops")) - stop_tag = xps_down(node); - if (!strcmp(xps_tag(node), "RadialGradientBrush.GradientStops")) - stop_tag = xps_down(node); + if (!strcmp(xml_tag(node), "LinearGradientBrush.Transform")) + transform_tag = xml_down(node); + if (!strcmp(xml_tag(node), "RadialGradientBrush.Transform")) + transform_tag = xml_down(node); + if (!strcmp(xml_tag(node), "LinearGradientBrush.GradientStops")) + stop_tag = xml_down(node); + if (!strcmp(xml_tag(node), "RadialGradientBrush.GradientStops")) + stop_tag = xml_down(node); } xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); @@ -447,14 +447,14 @@ xps_parse_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, void xps_parse_linear_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xps_item *root) + char *base_uri, xps_resource *dict, xml_element *root) { xps_parse_gradient_brush(ctx, ctm, area, base_uri, dict, root, xps_draw_linear_gradient); } void xps_parse_radial_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xps_item *root) + char *base_uri, xps_resource *dict, xml_element *root) { xps_parse_gradient_brush(ctx, ctm, area, base_uri, dict, root, xps_draw_radial_gradient); } diff --git a/xps/xpsimage.c b/xps/xpsimage.c index 102051cb..c9bf64fd 100644 --- a/xps/xpsimage.c +++ b/xps/xpsimage.c @@ -42,7 +42,7 @@ xps_decode_image(xps_image **imagep, xps_context *ctx, xps_part *part) } static void -xps_paint_image_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *root, void *vimage) +xps_paint_image_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *root, void *vimage) { xps_image *image = vimage; fz_pixmap *pixmap = image->pixmap; @@ -55,7 +55,7 @@ xps_paint_image_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resou } static xps_part * -xps_find_image_brush_source_part(xps_context *ctx, char *base_uri, xps_item *root) +xps_find_image_brush_source_part(xps_context *ctx, char *base_uri, xml_element *root) { char *image_source_att; char buf[1024]; @@ -64,7 +64,7 @@ xps_find_image_brush_source_part(xps_context *ctx, char *base_uri, xps_item *roo char *profile_name; char *p; - image_source_att = xps_att(root, "ImageSource"); + image_source_att = xml_att(root, "ImageSource"); if (!image_source_att) return NULL; @@ -106,7 +106,7 @@ xps_find_image_brush_source_part(xps_context *ctx, char *base_uri, xps_item *roo void xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xps_item *root) + char *base_uri, xps_resource *dict, xml_element *root) { xps_part *part; xps_image *image; diff --git a/xps/xpsopacity.c b/xps/xpsopacity.c index e5b0f787..75064452 100644 --- a/xps/xpsopacity.c +++ b/xps/xpsopacity.c @@ -4,7 +4,7 @@ void xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, - char *opacity_att, xps_item *opacity_mask_tag) + char *opacity_att, xml_element *opacity_mask_tag) { float opacity; @@ -15,10 +15,10 @@ xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, if (opacity_att) opacity = atof(opacity_att); - if (opacity_mask_tag && !strcmp(xps_tag(opacity_mask_tag), "SolidColorBrush")) + if (opacity_mask_tag && !strcmp(xml_tag(opacity_mask_tag), "SolidColorBrush")) { - char *scb_opacity_att = xps_att(opacity_mask_tag, "Opacity"); - char *scb_color_att = xps_att(opacity_mask_tag, "Color"); + char *scb_opacity_att = xml_att(opacity_mask_tag, "Opacity"); + char *scb_color_att = xml_att(opacity_mask_tag, "Color"); if (scb_opacity_att) opacity = opacity * atof(scb_opacity_att); if (scb_color_att) @@ -47,7 +47,7 @@ xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, void xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, - char *opacity_att, xps_item *opacity_mask_tag) + char *opacity_att, xml_element *opacity_mask_tag) { if (!opacity_att && !opacity_mask_tag) return; @@ -57,7 +57,7 @@ xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, if (opacity_mask_tag) { - if (strcmp(xps_tag(opacity_mask_tag), "SolidColorBrush")) + if (strcmp(xml_tag(opacity_mask_tag), "SolidColorBrush")) ctx->dev->popclip(ctx->dev->user); } } diff --git a/xps/xpspage.c b/xps/xpspage.c index 1854b1fc..7659a1a7 100644 --- a/xps/xpspage.c +++ b/xps/xpspage.c @@ -2,10 +2,10 @@ #include "muxps.h" void -xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *root) +xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *root) { xps_resource *new_dict = NULL; - xps_item *node; + xml_element *node; char *opacity_mask_uri; int code; @@ -14,22 +14,22 @@ xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource * char *opacity_att; char *opacity_mask_att; - xps_item *transform_tag = NULL; - xps_item *clip_tag = NULL; - xps_item *opacity_mask_tag = NULL; + xml_element *transform_tag = NULL; + xml_element *clip_tag = NULL; + xml_element *opacity_mask_tag = NULL; fz_matrix transform; - transform_att = xps_att(root, "RenderTransform"); - clip_att = xps_att(root, "Clip"); - opacity_att = xps_att(root, "Opacity"); - opacity_mask_att = xps_att(root, "OpacityMask"); + transform_att = xml_att(root, "RenderTransform"); + clip_att = xml_att(root, "Clip"); + opacity_att = xml_att(root, "Opacity"); + opacity_mask_att = xml_att(root, "OpacityMask"); - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "Canvas.Resources") && xps_down(node)) + if (!strcmp(xml_tag(node), "Canvas.Resources") && xml_down(node)) { - code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xps_down(node)); + code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xml_down(node)); if (code) fz_catch(code, "cannot load Canvas.Resources"); else @@ -39,12 +39,12 @@ xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource * } } - if (!strcmp(xps_tag(node), "Canvas.RenderTransform")) - transform_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Canvas.Clip")) - clip_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Canvas.OpacityMask")) - opacity_mask_tag = xps_down(node); + if (!strcmp(xml_tag(node), "Canvas.RenderTransform")) + transform_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Canvas.Clip")) + clip_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Canvas.OpacityMask")) + opacity_mask_tag = xml_down(node); } opacity_mask_uri = base_uri; @@ -64,7 +64,7 @@ xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource * xps_begin_opacity(ctx, ctm, fz_infiniterect, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { xps_parse_element(ctx, ctm, base_uri, dict, node); } @@ -81,7 +81,7 @@ xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource * void xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page) { - xps_item *node; + xml_element *node; xps_resource *dict; char base_uri[1024]; char *s; @@ -97,11 +97,14 @@ xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page) ctx->opacity_top = 0; ctx->opacity[0] = 1; - for (node = xps_down(page->root); node; node = xps_next(node)) + if (!page->root) + return; + + for (node = xml_down(page->root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "FixedPage.Resources") && xps_down(node)) + if (!strcmp(xml_tag(node), "FixedPage.Resources") && xml_down(node)) { - code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xps_down(node)); + code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xml_down(node)); if (code) fz_catch(code, "cannot load FixedPage.Resources"); } @@ -118,7 +121,7 @@ int xps_load_fixed_page(xps_context *ctx, xps_page *page) { xps_part *part; - xps_item *root; + xml_element *root; char *width_att; char *height_att; @@ -126,20 +129,20 @@ xps_load_fixed_page(xps_context *ctx, xps_page *page) if (!part) return fz_rethrow(-1, "cannot read zip part '%s'", page->name); - root = xps_parse_xml(ctx, part->data, part->size); + root = xml_parse_document(part->data, part->size); if (!root) - return fz_rethrow(-1, "cannot parse xml"); + return fz_rethrow(-1, "cannot parse xml part '%s'", page->name); xps_free_part(ctx, part); - if (strcmp(xps_tag(root), "FixedPage")) - return fz_throw("expected FixedPage element (found %s)", xps_tag(root)); + if (strcmp(xml_tag(root), "FixedPage")) + return fz_throw("expected FixedPage element (found %s)", xml_tag(root)); - width_att = xps_att(root, "Width"); + width_att = xml_att(root, "Width"); if (!width_att) return fz_throw("FixedPage missing required attribute: Width"); - height_att = xps_att(root, "Height"); + height_att = xml_att(root, "Height"); if (!height_att) return fz_throw("FixedPage missing required attribute: Height"); diff --git a/xps/xpspath.c b/xps/xpspath.c index ded566ca..00e57bee 100644 --- a/xps/xpspath.c +++ b/xps/xpspath.c @@ -36,7 +36,7 @@ fz_currentpoint(fz_path *path) } void -xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xps_item *clip_tag) +xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xml_element *clip_tag) { fz_path *path; int fill_rule = 0; @@ -462,7 +462,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) } static void -xps_parse_arc_segment(fz_path *path, xps_item *root, int stroking, int *skipped_stroke) +xps_parse_arc_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) { /* ArcSegment pretty much follows the SVG algorithm for converting an * arc in endpoint representation to an arc in centerpoint @@ -475,12 +475,12 @@ xps_parse_arc_segment(fz_path *path, xps_item *root, int stroking, int *skipped_ float size_x, size_y; int is_stroked; - char *point_att = xps_att(root, "Point"); - char *size_att = xps_att(root, "Size"); - char *rotation_angle_att = xps_att(root, "RotationAngle"); - char *is_large_arc_att = xps_att(root, "IsLargeArc"); - char *sweep_direction_att = xps_att(root, "SweepDirection"); - char *is_stroked_att = xps_att(root, "IsStroked"); + char *point_att = xml_att(root, "Point"); + char *size_att = xml_att(root, "Size"); + char *rotation_angle_att = xml_att(root, "RotationAngle"); + char *is_large_arc_att = xml_att(root, "IsLargeArc"); + char *sweep_direction_att = xml_att(root, "SweepDirection"); + char *is_stroked_att = xml_att(root, "IsStroked"); if (!point_att || !size_att || !rotation_angle_att || !is_large_arc_att || !sweep_direction_att) { @@ -510,10 +510,10 @@ xps_parse_arc_segment(fz_path *path, xps_item *root, int stroking, int *skipped_ } static void -xps_parse_poly_quadratic_bezier_segment(fz_path *path, xps_item *root, int stroking, int *skipped_stroke) +xps_parse_poly_quadratic_bezier_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) { - char *points_att = xps_att(root, "Points"); - char *is_stroked_att = xps_att(root, "IsStroked"); + char *points_att = xml_att(root, "Points"); + char *is_stroked_att = xml_att(root, "IsStroked"); float x[2], y[2]; int is_stroked; fz_point pt; @@ -560,10 +560,10 @@ xps_parse_poly_quadratic_bezier_segment(fz_path *path, xps_item *root, int strok } static void -xps_parse_poly_bezier_segment(fz_path *path, xps_item *root, int stroking, int *skipped_stroke) +xps_parse_poly_bezier_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) { - char *points_att = xps_att(root, "Points"); - char *is_stroked_att = xps_att(root, "IsStroked"); + char *points_att = xml_att(root, "Points"); + char *is_stroked_att = xml_att(root, "IsStroked"); float x[3], y[3]; int is_stroked; char *s; @@ -601,10 +601,10 @@ xps_parse_poly_bezier_segment(fz_path *path, xps_item *root, int stroking, int * } static void -xps_parse_poly_line_segment(fz_path *path, xps_item *root, int stroking, int *skipped_stroke) +xps_parse_poly_line_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) { - char *points_att = xps_att(root, "Points"); - char *is_stroked_att = xps_att(root, "IsStroked"); + char *points_att = xml_att(root, "Points"); + char *is_stroked_att = xml_att(root, "IsStroked"); int is_stroked; float x, y; char *s; @@ -635,9 +635,9 @@ xps_parse_poly_line_segment(fz_path *path, xps_item *root, int stroking, int *sk } static void -xps_parse_path_figure(fz_path *path, xps_item *root, int stroking) +xps_parse_path_figure(fz_path *path, xml_element *root, int stroking) { - xps_item *node; + xml_element *node; char *is_closed_att; char *start_point_att; @@ -650,9 +650,9 @@ xps_parse_path_figure(fz_path *path, xps_item *root, int stroking) int skipped_stroke = 0; - is_closed_att = xps_att(root, "IsClosed"); - start_point_att = xps_att(root, "StartPoint"); - is_filled_att = xps_att(root, "IsFilled"); + is_closed_att = xml_att(root, "IsClosed"); + start_point_att = xml_att(root, "StartPoint"); + is_filled_att = xml_att(root, "IsFilled"); if (is_closed_att) is_closed = !strcmp(is_closed_att, "true"); @@ -666,15 +666,15 @@ xps_parse_path_figure(fz_path *path, xps_item *root, int stroking) fz_moveto(path, start_x, start_y); - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "ArcSegment")) + if (!strcmp(xml_tag(node), "ArcSegment")) xps_parse_arc_segment(path, node, stroking, &skipped_stroke); - if (!strcmp(xps_tag(node), "PolyBezierSegment")) + if (!strcmp(xml_tag(node), "PolyBezierSegment")) xps_parse_poly_bezier_segment(path, node, stroking, &skipped_stroke); - if (!strcmp(xps_tag(node), "PolyLineSegment")) + if (!strcmp(xml_tag(node), "PolyLineSegment")) xps_parse_poly_line_segment(path, node, stroking, &skipped_stroke); - if (!strcmp(xps_tag(node), "PolyQuadraticBezierSegment")) + if (!strcmp(xml_tag(node), "PolyQuadraticBezierSegment")) xps_parse_poly_quadratic_bezier_segment(path, node, stroking, &skipped_stroke); } @@ -688,28 +688,28 @@ xps_parse_path_figure(fz_path *path, xps_item *root, int stroking) } fz_path * -xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, int stroking, int *fill_rule) +xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xml_element *root, int stroking, int *fill_rule) { - xps_item *node; + xml_element *node; char *figures_att; char *fill_rule_att; char *transform_att; - xps_item *transform_tag = NULL; - xps_item *figures_tag = NULL; /* only used by resource */ + xml_element *transform_tag = NULL; + xml_element *figures_tag = NULL; /* only used by resource */ fz_matrix transform; fz_path *path; - figures_att = xps_att(root, "Figures"); - fill_rule_att = xps_att(root, "FillRule"); - transform_att = xps_att(root, "Transform"); + figures_att = xml_att(root, "Figures"); + fill_rule_att = xml_att(root, "FillRule"); + transform_att = xml_att(root, "Transform"); - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "PathGeometry.Transform")) - transform_tag = xps_down(node); + if (!strcmp(xml_tag(node), "PathGeometry.Transform")) + transform_tag = xml_down(node); } xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); @@ -737,9 +737,9 @@ xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, in if (figures_tag) xps_parse_path_figure(path, figures_tag, stroking); - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "PathFigure")) + if (!strcmp(xml_tag(node), "PathFigure")) xps_parse_path_figure(path, node, stroking); } @@ -768,9 +768,9 @@ xps_parse_line_cap(char *attr) */ void -xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *root) +xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *root) { - xps_item *node; + xml_element *node; char *fill_uri; char *stroke_uri; @@ -784,12 +784,12 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di char *opacity_att; char *opacity_mask_att; - xps_item *transform_tag = NULL; - xps_item *clip_tag = NULL; - xps_item *data_tag = NULL; - xps_item *fill_tag = NULL; - xps_item *stroke_tag = NULL; - xps_item *opacity_mask_tag = NULL; + xml_element *transform_tag = NULL; + xml_element *clip_tag = NULL; + xml_element *data_tag = NULL; + xml_element *fill_tag = NULL; + xml_element *stroke_tag = NULL; + xml_element *opacity_mask_tag = NULL; char *fill_opacity_att = NULL; char *stroke_opacity_att = NULL; @@ -815,37 +815,37 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di * Extract attributes and extended attributes. */ - transform_att = xps_att(root, "RenderTransform"); - clip_att = xps_att(root, "Clip"); - data_att = xps_att(root, "Data"); - fill_att = xps_att(root, "Fill"); - stroke_att = xps_att(root, "Stroke"); - opacity_att = xps_att(root, "Opacity"); - opacity_mask_att = xps_att(root, "OpacityMask"); - - stroke_dash_array_att = xps_att(root, "StrokeDashArray"); - stroke_dash_cap_att = xps_att(root, "StrokeDashCap"); - stroke_dash_offset_att = xps_att(root, "StrokeDashOffset"); - stroke_end_line_cap_att = xps_att(root, "StrokeEndLineCap"); - stroke_start_line_cap_att = xps_att(root, "StrokeStartLineCap"); - stroke_line_join_att = xps_att(root, "StrokeLineJoin"); - stroke_miter_limit_att = xps_att(root, "StrokeMiterLimit"); - stroke_thickness_att = xps_att(root, "StrokeThickness"); - - for (node = xps_down(root); node; node = xps_next(node)) + transform_att = xml_att(root, "RenderTransform"); + clip_att = xml_att(root, "Clip"); + data_att = xml_att(root, "Data"); + fill_att = xml_att(root, "Fill"); + stroke_att = xml_att(root, "Stroke"); + opacity_att = xml_att(root, "Opacity"); + opacity_mask_att = xml_att(root, "OpacityMask"); + + stroke_dash_array_att = xml_att(root, "StrokeDashArray"); + stroke_dash_cap_att = xml_att(root, "StrokeDashCap"); + stroke_dash_offset_att = xml_att(root, "StrokeDashOffset"); + stroke_end_line_cap_att = xml_att(root, "StrokeEndLineCap"); + stroke_start_line_cap_att = xml_att(root, "StrokeStartLineCap"); + stroke_line_join_att = xml_att(root, "StrokeLineJoin"); + stroke_miter_limit_att = xml_att(root, "StrokeMiterLimit"); + stroke_thickness_att = xml_att(root, "StrokeThickness"); + + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "Path.RenderTransform")) - transform_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Path.OpacityMask")) - opacity_mask_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Path.Clip")) - clip_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Path.Fill")) - fill_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Path.Stroke")) - stroke_tag = xps_down(node); - if (!strcmp(xps_tag(node), "Path.Data")) - data_tag = xps_down(node); + if (!strcmp(xml_tag(node), "Path.RenderTransform")) + transform_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Path.OpacityMask")) + opacity_mask_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Path.Clip")) + clip_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Path.Fill")) + fill_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Path.Stroke")) + stroke_tag = xml_down(node); + if (!strcmp(xml_tag(node), "Path.Data")) + data_tag = xml_down(node); } fill_uri = base_uri; @@ -866,17 +866,17 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di if (!data_att && !data_tag) return; - if (fill_tag && !strcmp(xps_tag(fill_tag), "SolidColorBrush")) + if (fill_tag && !strcmp(xml_tag(fill_tag), "SolidColorBrush")) { - fill_opacity_att = xps_att(fill_tag, "Opacity"); - fill_att = xps_att(fill_tag, "Color"); + fill_opacity_att = xml_att(fill_tag, "Opacity"); + fill_att = xml_att(fill_tag, "Color"); fill_tag = NULL; } - if (stroke_tag && !strcmp(xps_tag(stroke_tag), "SolidColorBrush")) + if (stroke_tag && !strcmp(xml_tag(stroke_tag), "SolidColorBrush")) { - stroke_opacity_att = xps_att(stroke_tag, "Opacity"); - stroke_att = xps_att(stroke_tag, "Color"); + stroke_opacity_att = xml_att(stroke_tag, "Opacity"); + stroke_att = xml_att(stroke_tag, "Color"); stroke_tag = NULL; } diff --git a/xps/xpsresource.c b/xps/xpsresource.c index 28c172bf..59dc3f9d 100644 --- a/xps/xpsresource.c +++ b/xps/xpsresource.c @@ -1,7 +1,7 @@ #include "fitz.h" #include "muxps.h" -static xps_item * +static xml_element * xps_find_resource(xps_context *ctx, xps_resource *dict, char *name, char **urip) { xps_resource *head, *node; @@ -20,7 +20,7 @@ xps_find_resource(xps_context *ctx, xps_resource *dict, char *name, char **urip) return NULL; } -static xps_item * +static xml_element * xps_parse_resource_reference(xps_context *ctx, xps_resource *dict, char *att, char **urip) { char name[1024]; @@ -39,11 +39,11 @@ xps_parse_resource_reference(xps_context *ctx, xps_resource *dict, char *att, ch void xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict, - char **attp, xps_item **tagp, char **urip) + char **attp, xml_element **tagp, char **urip) { if (*attp) { - xps_item *rsrc = xps_parse_resource_reference(ctx, dict, *attp, urip); + xml_element *rsrc = xps_parse_resource_reference(ctx, dict, *attp, urip); if (rsrc) { *attp = NULL; @@ -59,7 +59,7 @@ xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, cha char part_uri[1024]; xps_resource *dict; xps_part *part; - xps_item *xml; + xml_element *xml; char *s; int code; @@ -71,18 +71,18 @@ xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, cha return fz_throw("cannot find remote resource part '%s'", part_name); } - xml = xps_parse_xml(ctx, part->data, part->size); + xml = xml_parse_document(part->data, part->size); if (!xml) { xps_free_part(ctx, part); return fz_rethrow(-1, "cannot parse xml"); } - if (strcmp(xps_tag(xml), "ResourceDictionary")) + if (strcmp(xml_tag(xml), "ResourceDictionary")) { - xps_free_item(ctx, xml); + xml_free_element(xml); xps_free_part(ctx, part); - return fz_throw("expected ResourceDictionary element (found %s)", xps_tag(xml)); + return fz_throw("expected ResourceDictionary element (found %s)", xml_tag(xml)); } fz_strlcpy(part_uri, part_name, sizeof part_uri); @@ -93,7 +93,7 @@ xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, cha code = xps_parse_resource_dictionary(ctx, &dict, part_uri, xml); if (code) { - xps_free_item(ctx, xml); + xml_free_element(xml); xps_free_part(ctx, part); return fz_rethrow(code, "cannot parse remote resource dictionary: %s", part_uri); } @@ -107,16 +107,16 @@ xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, cha } int -xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xps_item *root) +xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xml_element *root) { xps_resource *head; xps_resource *entry; - xps_item *node; + xml_element *node; char *source; char *key; int code; - source = xps_att(root, "Source"); + source = xml_att(root, "Source"); if (source) { code = xps_parse_remote_resource_dictionary(ctx, dictp, base_uri, source); @@ -127,10 +127,10 @@ xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base head = NULL; - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { /* Usually "x:Key"; we have already processed and stripped namespace */ - key = xps_att(node, "Key"); + key = xml_att(node, "Key"); if (key) { entry = fz_malloc(sizeof(xps_resource)); @@ -161,7 +161,7 @@ xps_free_resource_dictionary(xps_context *ctx, xps_resource *dict) { next = dict->next; if (dict->base_xml) - xps_free_item(ctx, dict->base_xml); + xml_free_element(dict->base_xml); if (dict->base_uri) fz_free(dict->base_uri); fz_free(dict); diff --git a/xps/xpstile.c b/xps/xpstile.c index 1b96a7d3..ecc0af3f 100644 --- a/xps/xpstile.c +++ b/xps/xpstile.c @@ -12,9 +12,9 @@ struct closure { char *base_uri; xps_resource *dict; - xps_item *root; + xml_element *root; void *user; - void (*func)(xps_context*, fz_matrix, char*, xps_resource*, xps_item*, void*); + void (*func)(xps_context*, fz_matrix, char*, xps_resource*, xml_element*, void*); }; static void @@ -65,10 +65,10 @@ xps_paint_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, int til void xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xps_item *root, - void (*func)(xps_context*, fz_matrix, char*, xps_resource*, xps_item*, void*), void *user) + char *base_uri, xps_resource *dict, xml_element *root, + void (*func)(xps_context*, fz_matrix, char*, xps_resource*, xml_element*, void*), void *user) { - xps_item *node; + xml_element *node; struct closure c; char *opacity_att; @@ -79,7 +79,7 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *viewbox_units_att; char *viewport_units_att; - xps_item *transform_tag = NULL; + xml_element *transform_tag = NULL; fz_matrix transform; fz_rect viewbox; @@ -88,13 +88,13 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, float xscale, yscale; int tile_mode; - opacity_att = xps_att(root, "Opacity"); - transform_att = xps_att(root, "Transform"); - viewbox_att = xps_att(root, "Viewbox"); - viewport_att = xps_att(root, "Viewport"); - tile_mode_att = xps_att(root, "TileMode"); - viewbox_units_att = xps_att(root, "ViewboxUnits"); - viewport_units_att = xps_att(root, "ViewportUnits"); + opacity_att = xml_att(root, "Opacity"); + transform_att = xml_att(root, "Transform"); + viewbox_att = xml_att(root, "Viewbox"); + viewport_att = xml_att(root, "Viewport"); + tile_mode_att = xml_att(root, "TileMode"); + viewbox_units_att = xml_att(root, "ViewboxUnits"); + viewport_units_att = xml_att(root, "ViewportUnits"); c.base_uri = base_uri; c.dict = dict; @@ -102,12 +102,12 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, c.user = user; c.func = func; - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "ImageBrush.Transform")) - transform_tag = xps_down(node); - if (!strcmp(xps_tag(node), "VisualBrush.Transform")) - transform_tag = xps_down(node); + if (!strcmp(xml_tag(node), "ImageBrush.Transform")) + transform_tag = xml_down(node); + if (!strcmp(xml_tag(node), "VisualBrush.Transform")) + transform_tag = xml_down(node); } xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); diff --git a/xps/xpsvisual.c b/xps/xpsvisual.c index ad633708..ac7de23c 100644 --- a/xps/xpsvisual.c +++ b/xps/xpsvisual.c @@ -5,27 +5,27 @@ enum { TILE_NONE, TILE_TILE, TILE_FLIP_X, TILE_FLIP_Y, TILE_FLIP_X_Y }; static void xps_paint_visual_brush(xps_context *ctx, fz_matrix ctm, - char *base_uri, xps_resource *dict, xps_item *root, void *visual_tag) + char *base_uri, xps_resource *dict, xml_element *root, void *visual_tag) { - xps_parse_element(ctx, ctm, base_uri, dict, (xps_item *)visual_tag); + xps_parse_element(ctx, ctm, base_uri, dict, (xml_element *)visual_tag); } void xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xps_item *root) + char *base_uri, xps_resource *dict, xml_element *root) { - xps_item *node; + xml_element *node; char *visual_uri; char *visual_att; - xps_item *visual_tag = NULL; + xml_element *visual_tag = NULL; - visual_att = xps_att(root, "Visual"); + visual_att = xml_att(root, "Visual"); - for (node = xps_down(root); node; node = xps_next(node)) + for (node = xml_down(root); node; node = xml_next(node)) { - if (!strcmp(xps_tag(node), "VisualBrush.Visual")) - visual_tag = xps_down(node); + if (!strcmp(xml_tag(node), "VisualBrush.Visual")) + visual_tag = xml_down(node); } visual_uri = base_uri; diff --git a/xps/xpsxml.c b/xps/xpsxml.c index c6f41123..397b68ec 100644 --- a/xps/xpsxml.c +++ b/xps/xpsxml.c @@ -1,339 +1,387 @@ -/* Simple XML document object model on top of Expat. */ - #include "fitz.h" #include "muxps.h" -#include <expat.h> - -#define XMLBUFLEN 4096 - -#define NS_XPS "http://schemas.microsoft.com/xps/2005/06" -#define NS_MC "http://schemas.openxmlformats.org/markup-compatibility/2006" - -typedef struct xps_parser_s xps_parser; +struct attribute +{ + char name[32]; + char *value; + struct attribute *next; +}; -struct xps_parser_s +struct element { - xps_context *ctx; - xps_item *root; - xps_item *head; - char *error; - int compat; - char *base; /* base of relative URIs */ + char name[32]; + struct attribute *atts; + struct element *up, *down, *next; }; -struct xps_item_s +struct parser { - char *name; - char **atts; - xps_item *up; - xps_item *down; - xps_item *next; + struct element *head; }; -static char * -skip_namespace(char *s) +static inline void indent(int n) { - char *p = strchr(s, ' '); - if (p) - return p + 1; - return s; + while (n--) putchar(' '); } -static void -on_open_tag(void *zp, char *ns_name, char **atts) +void xml_print_element(struct element *item, int level) { - xps_parser *parser = zp; - xps_item *item; - xps_item *tail; - int namelen; - int attslen; - int textlen; - char *name, *p; - int i; - - if (parser->error) - return; - - /* check namespace */ - - name = NULL; - - p = strstr(ns_name, NS_XPS); - if (p == ns_name) - { - name = strchr(ns_name, ' ') + 1; + while (item) { + struct attribute *att; + indent(level); + printf("<%s", item->name); + for (att = item->atts; att; att = att->next) + printf(" %s=\"%s\"", att->name, att->value); + if (item->down) { + printf(">\n"); + xml_print_element(item->down, level + 1); + indent(level); + printf("</%s>\n", item->name); + } + else { + printf("/>\n"); + } + item = item->next; } +} - p = strstr(ns_name, NS_MC); - if (p == ns_name) - { - name = strchr(ns_name, ' ') + 1; - parser->compat = 1; - } +struct element *xml_next(struct element *item) +{ + return item->next; +} - if (!name) - { - fz_warn("unknown namespace: %s", ns_name); - name = ns_name; - } +struct element *xml_down(struct element *item) +{ + return item->down; +} - /* count size to alloc */ +char *xml_tag(struct element *item) +{ + return item->name; +} - namelen = strlen(name) + 1; /* zero terminated */ - attslen = sizeof(char*); /* with space for sentinel */ - textlen = 0; - for (i = 0; atts[i]; i++) - { - attslen += sizeof(char*); - if ((i & 1) == 0) - textlen += strlen(skip_namespace(atts[i])) + 1; - else - textlen += strlen(atts[i]) + 1; - } +char *xml_att(struct element *item, const char *name) +{ + struct attribute *att; + for (att = item->atts; att; att = att->next) + if (!strcmp(att->name, name)) + return att->value; + return NULL; +} - item = fz_malloc(sizeof(xps_item) + attslen + namelen + textlen); - if (!item) - { - parser->error = "out of memory"; +static void xml_free_attribute(struct attribute *att) +{ + while (att) { + struct attribute *next = att->next; + if (att->value) + fz_free(att->value); + fz_free(att); + att = next; } +} - /* copy strings to new memory */ - - item->atts = (char**) (((char*)item) + sizeof(xps_item)); - item->name = ((char*)item) + sizeof(xps_item) + attslen; - p = ((char*)item) + sizeof(xps_item) + attslen + namelen; +void xml_free_element(struct element *item) +{ + while (item) { + struct element *next = item->next; + if (item->atts) + xml_free_attribute(item->atts); + if (item->down) + xml_free_element(item->down); + fz_free(item); + item = next; + } +} - strcpy(item->name, name); - for (i = 0; atts[i]; i++) - { - item->atts[i] = p; - if ((i & 1) == 0) - strcpy(item->atts[i], skip_namespace(atts[i])); +static int xml_parse_entity(int *c, char *a) +{ + char *b; + if (a[1] == '#') { + if (a[2] == 'x') + *c = strtol(a + 3, &b, 16); else - strcpy(item->atts[i], atts[i]); - p += strlen(p) + 1; + *c = strtol(a + 2, &b, 10); + if (*b == ';') + return b - a; } - - item->atts[i] = 0; - - /* link item into tree */ - - item->up = parser->head; - item->down = NULL; - item->next = NULL; - - if (!parser->head) - { - parser->root = item; - parser->head = item; - return; + else if (a[1] == 'l' && a[2] == 't' && a[3] == ';') { + *c = '<'; + return 4; } - - if (!parser->head->down) - { - parser->head->down = item; - parser->head = item; - return; + else if (a[1] == 'g' && a[2] == 't' && a[3] == ';') { + *c = '>'; + return 4; } - - tail = parser->head->down; - while (tail->next) - tail = tail->next; - tail->next = item; - parser->head = item; + else if (a[1] == 'a' && a[2] == 'm' && a[3] == 'p' && a[4] == ';') { + *c = '&'; + return 5; + } + else if (a[1] == 'a' && a[2] == 'p' && a[3] == 'o' && a[4] == 's' && a[5] == ';') { + *c = '\''; + return 6; + } + else if (a[1] == 'q' && a[2] == 'u' && a[3] == 'o' && a[4] == 't' && a[5] == ';') { + *c = '"'; + return 6; + } + *c = *a++; + return 1; } -static void -on_close_tag(void *zp, char *name) +static void xml_emit_open_tag(struct parser *parser, char *a, char *b) { - xps_parser *parser = zp; + struct element *head, *tail; - if (parser->error) - return; + head = fz_malloc(sizeof(struct element)); + if (b - a > sizeof(head->name)) + b = a + sizeof(head->name); + memcpy(head->name, a, b - a); + head->name[b - a] = 0; - if (parser->head) - parser->head = parser->head->up; -} + head->atts = NULL; + head->up = parser->head; + head->down = NULL; + head->next = NULL; -static inline int -is_xml_space(int c) -{ - return c == ' ' || c == '\t' || c == '\r' || c == '\n'; -} - -static void -on_text(void *zp, char *buf, int len) -{ - xps_parser *parser = zp; - char *atts[3]; - int i; - - if (parser->error) - return; - - for (i = 0; i < len; i++) - { - if (!is_xml_space(buf[i])) - { - char *tmp = fz_malloc(len + 1); - if (!tmp) - { - parser->error = "out of memory"; - return; - } - - atts[0] = ""; - atts[1] = tmp; - atts[2] = NULL; - - memcpy(tmp, buf, len); - tmp[len] = 0; - on_open_tag(zp, "", atts); - on_close_tag(zp, ""); - fz_free(tmp); - return; - } + if (!parser->head->down) { + parser->head->down = head; + } + else { + tail = parser->head->down; + while (tail->next) + tail = tail->next; + tail->next = head; } + + parser->head = head; } -static xps_item * -xps_process_compatibility(xps_context *ctx, xps_item *root) +static void xml_emit_att_name(struct parser *parser, char *a, char *b) { - fz_warn("XPS document uses markup compatibility tags"); - return root; + struct element *head = parser->head; + struct attribute *att; + + att = fz_malloc(sizeof(struct attribute)); + if (b - a > sizeof(att->name)) + b = a + sizeof(att->name); + memcpy(att->name, a, b - a); + att->name[b - a] = 0; + att->value = NULL; + att->next = head->atts; + head->atts = att; } -xps_item * -xps_parse_xml(xps_context *ctx, byte *buf, int len) +static void xml_emit_att_value(struct parser *parser, char *a, char *b) { - xps_parser parser; - XML_Parser xp; - int code; - - parser.ctx = ctx; - parser.root = NULL; - parser.head = NULL; - parser.error = NULL; - parser.compat = 0; - - xp = XML_ParserCreateNS(NULL, ' '); - if (!xp) - { - fz_throw("xml error: cannot create expat parser"); - return NULL; - } - - XML_SetUserData(xp, &parser); - XML_SetParamEntityParsing(xp, XML_PARAM_ENTITY_PARSING_NEVER); - XML_SetStartElementHandler(xp, (XML_StartElementHandler)on_open_tag); - XML_SetEndElementHandler(xp, (XML_EndElementHandler)on_close_tag); - XML_SetCharacterDataHandler(xp, (XML_CharacterDataHandler)on_text); - - code = XML_Parse(xp, (char*)buf, len, 1); - if (code == 0) - { - if (parser.root) - xps_free_item(ctx, parser.root); - XML_ParserFree(xp); - fz_throw("xml error: %s", XML_ErrorString(XML_GetErrorCode(xp))); - return NULL; + struct element *head = parser->head; + struct attribute *att = head->atts; + char *s; + int c; + + /* entities are all longer than UTFmax so runetochar is safe */ + s = att->value = fz_malloc(b - a + 1); + while (a < b) { + if (*a == '&') { + a += xml_parse_entity(&c, a); + s += runetochar(s, &c); + } + else { + *s++ = *a++; + } } - - XML_ParserFree(xp); - - if (parser.compat) - xps_process_compatibility(ctx, parser.root); - - return parser.root; + *s = 0; } -xps_item * -xps_next(xps_item *item) +static void xml_emit_close_tag(struct parser *parser) { - return item->next; + if (parser->head->up) + parser->head = parser->head->up; } -xps_item * -xps_down(xps_item *item) +static inline int isname(int c) { - return item->down; + return c == '.' || c == '-' || c == '_' || c == ':' || + (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z'); } -char * -xps_tag(xps_item *item) +static inline int iswhite(int c) { - return item->name; + return c == ' ' || c == '\r' || c == '\n' || c == '\t'; } -char * -xps_att(xps_item *item, const char *att) +static char *xml_parse_document_imp(struct parser *x, char *p) { - int i; - for (i = 0; item->atts[i]; i += 2) - if (!strcmp(item->atts[i], att)) - return item->atts[i + 1]; + char *mark; + int quote; + +parse_text: + mark = p; + while (*p && *p != '<') ++p; + if (*p == '<') { ++p; goto parse_element; } return NULL; -} -void -xps_free_item(xps_context *ctx, xps_item *item) -{ - xps_item *next; - while (item) - { - next = item->next; - if (item->down) - xps_free_item(ctx, item->down); - fz_free(item); - item = next; +parse_element: + if (*p == '/') { ++p; goto parse_closing_element; } + if (*p == '!') { ++p; goto parse_comment; } + if (*p == '?') { ++p; goto parse_processing_instruction; } + while (iswhite(*p)) ++p; + if (isname(*p)) + goto parse_element_name; + return "syntax error in element"; + +parse_comment: + if (*p == '[') goto parse_cdata; + if (*p++ != '-') return "syntax error in comment (<! not followed by --)"; + if (*p++ != '-') return "syntax error in comment (<!- not followed by -)"; + mark = p; + while (*p) { + if (p[0] == '-' && p[1] == '-' && p[2] == '>') { + p += 3; + goto parse_text; + } + ++p; + } + return "end of data in comment"; + +parse_cdata: + if (p[1] != 'C' || p[2] != 'D' || p[3] != 'A' || p[4] != 'T' || p[5] != 'A' || p[6] != '[') + return "syntax error in CDATA section"; + p += 7; + mark = p; + while (*p) { + if (p[0] == ']' && p[1] == ']' && p[2] == '>') { + p += 3; + goto parse_text; + } + ++p; + } + return "end of data in CDATA section"; + +parse_processing_instruction: + while (*p) { + if (p[0] == '?' && p[1] == '>') { + p += 2; + goto parse_text; + } + ++p; + } + return "end of data in processing instruction"; + +parse_closing_element: + while (iswhite(*p)) ++p; + mark = p; + while (isname(*p)) ++p; + while (iswhite(*p)) ++p; + if (*p != '>') + return "syntax error in closing element"; + xml_emit_close_tag(x); + ++p; + goto parse_text; + +parse_element_name: + mark = p; + while (isname(*p)) ++p; + xml_emit_open_tag(x, mark, p); + if (*p == '>') { ++p; goto parse_text; } + if (p[0] == '/' && p[1] == '>') { + xml_emit_close_tag(x); + p += 2; + goto parse_text; + } + if (iswhite(*p)) + goto parse_attributes; + return "syntax error after element name"; + +parse_attributes: + while (iswhite(*p)) ++p; + if (isname(*p)) + goto parse_attribute_name; + if (*p == '>') { ++p; goto parse_text; } + if (p[0] == '/' && p[1] == '>') { + xml_emit_close_tag(x); + p += 2; + goto parse_text; } + return "syntax error in attributes"; + +parse_attribute_name: + mark = p; + while (isname(*p)) ++p; + xml_emit_att_name(x, mark, p); + while (iswhite(*p)) ++p; + if (*p == '=') { ++p; goto parse_attribute_value; } + return "syntax error after attribute name"; + +parse_attribute_value: + while (iswhite(*p)) ++p; + quote = *p++; + if (quote != '"' && quote != '\'') + return "missing quote character"; + mark = p; + while (*p && *p != quote) ++p; + if (*p == quote) { + xml_emit_att_value(x, mark, p++); + goto parse_attributes; + } + return "end of data in attribute value"; } -static void indent(int n) +static char *convert_to_utf8(unsigned char *s, int n) { - while (n--) - printf(" "); + unsigned char *e = s + n; + char *dst, *d; + int c; + + if (s[0] == 0xFE && s[1] == 0xFF) { + dst = d = fz_malloc(n * 2); + while (s + 1 < e) { + c = s[0] << 8 | s[1]; + d += runetochar(d, &c); + s += 2; + } + *d = 0; + return dst; + } + + if (s[0] == 0xFF && s[1] == 0xFE) { + dst = d = fz_malloc(n * 2); + while (s + 1 < e) { + c = s[0] | s[1] << 8; + d += runetochar(d, &c); + s += 2; + } + *d = 0; + return dst; + } + + return (char*)s; } -static void -xps_debug_item_imp(xps_item *item, int level, int loop) +struct element * +xml_parse_document(unsigned char *s, int n) { - int i; + struct parser parser; + struct element root; + char *p, *error; - while (item) - { - indent(level); + /* s is already null-terminated (see xps_new_part) */ - if (strlen(item->name) == 0) - printf("%s\n", item->atts[1]); - else - { - printf("<%s", item->name); - - for (i = 0; item->atts[i]; i += 2) - printf(" %s=\"%s\"", item->atts[i], item->atts[i+1]); - - if (item->down) - { - printf(">\n"); - xps_debug_item_imp(item->down, level + 1, 1); - indent(level); - printf("</%s>\n", item->name); - } - else - printf(" />\n"); - } + memset(&root, 0, sizeof(root)); + parser.head = &root; - item = item->next; + p = convert_to_utf8(s, n); - if (!loop) - return; + error = xml_parse_document_imp(&parser, p); + if (error) { + fz_throw(error); + return NULL; } -} -void -xps_debug_item(xps_item *item, int level) -{ - xps_debug_item_imp(item, level, 0); + if (p != (char*)s) + fz_free(p); + + return root.down; } diff --git a/xps/xpszip.c b/xps/xpszip.c index 4905ea37..ad708bcb 100644 --- a/xps/xpszip.c +++ b/xps/xpszip.c @@ -474,8 +474,10 @@ xps_load_page(xps_context *ctx, int number) if (!page->root) { code = xps_load_fixed_page(ctx, page); - if (code) - fz_catch(code, "ignoring errors on page"); + if (code) { + fz_rethrow(code, "cannot load page %d", number + 1); + return NULL; + } } return page; } @@ -488,7 +490,7 @@ void xps_free_page(xps_context *ctx, xps_page *page) { if (page->root) - xps_free_item(ctx, page->root); + xml_free_element(page->root); page->root = NULL; } |