diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2012-03-14 14:59:46 +0100 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2012-03-14 15:29:56 +0100 |
commit | bcb88cede5edb232ac87235d957c023a0397bd5e (patch) | |
tree | 2522fb8d1a31cf9421b245ecc05747dde9e72010 | |
parent | 621e33bdb921bdc3ccd9068101acd3858c9c14c8 (diff) | |
download | mupdf-bcb88cede5edb232ac87235d957c023a0397bd5e.tar.xz |
Miscellaneous fixes for XPS from SumatraPDf.
-rw-r--r-- | xps/xps_doc.c | 15 | ||||
-rw-r--r-- | xps/xps_gradient.c | 10 | ||||
-rw-r--r-- | xps/xps_outline.c | 8 | ||||
-rw-r--r-- | xps/xps_path.c | 23 | ||||
-rw-r--r-- | xps/xps_resource.c | 5 | ||||
-rw-r--r-- | xps/xps_tile.c | 29 |
6 files changed, 72 insertions, 18 deletions
diff --git a/xps/xps_doc.c b/xps/xps_doc.c index a2665f95..a840e7ba 100644 --- a/xps/xps_doc.c +++ b/xps/xps_doc.c @@ -278,6 +278,8 @@ xps_parse_metadata_imp(xps_document *doc, xml_element *item, xps_fixdoc *fixdoc) doc->start_part = fz_strdup(doc->ctx, tgtbuf); if (!strcmp(type, REL_DOC_STRUCTURE) && fixdoc) fixdoc->outline = fz_strdup(doc->ctx, tgtbuf); + if (!xml_att(item, "Id")) + fz_warn(doc->ctx, "missing relationship id for %s", target); } } @@ -408,17 +410,28 @@ xps_load_fixed_page(xps_document *doc, xps_page *page) part = xps_read_part(doc, page->name); root = xml_parse_document(doc->ctx, part->data, part->size); xps_free_part(doc, part); + if (!root) + fz_throw(doc->ctx, "FixedPage missing root element"); if (strcmp(xml_tag(root), "FixedPage")) - fz_throw(doc->ctx, "expected FixedPage element (found %s)", xml_tag(root)); + { + xml_free_element(doc->ctx, root); + fz_throw(doc->ctx, "expected FixedPage element"); + } width_att = xml_att(root, "Width"); if (!width_att) + { + xml_free_element(doc->ctx, root); fz_throw(doc->ctx, "FixedPage missing required attribute: Width"); + } height_att = xml_att(root, "Height"); if (!height_att) + { + xml_free_element(doc->ctx, root); fz_throw(doc->ctx, "FixedPage missing required attribute: Height"); + } page->width = atoi(width_att); page->height = atoi(height_att); diff --git a/xps/xps_gradient.c b/xps/xps_gradient.c index fe88b295..0e50f3c8 100644 --- a/xps/xps_gradient.c +++ b/xps/xps_gradient.c @@ -146,10 +146,10 @@ xps_parse_gradient_stops(xps_document *doc, char *base_uri, xml_element *node, { float d = (1 - stops[count-2].offset) / (stops[count-1].offset - stops[count-2].offset); stops[count-1].offset = 1; - stops[0].r = lerp(stops[count-2].r, stops[count-1].r, d); - stops[0].g = lerp(stops[count-2].g, stops[count-1].g, d); - stops[0].b = lerp(stops[count-2].b, stops[count-1].b, d); - stops[0].a = lerp(stops[count-2].a, stops[count-1].a, d); + stops[count-1].r = lerp(stops[count-2].r, stops[count-1].r, d); + stops[count-1].g = lerp(stops[count-2].g, stops[count-1].g, d); + stops[count-1].b = lerp(stops[count-2].b, stops[count-1].b, d); + stops[count-1].a = lerp(stops[count-2].a, stops[count-1].a, d); } /* First stop > 0 -- insert a duplicate at 0 */ @@ -275,7 +275,7 @@ xps_draw_one_linear_gradient(xps_document *doc, fz_matrix ctm, shade->mesh[4] = y1; shade->mesh[5] = 0; - fz_fill_shade(doc->dev, shade, ctm, 1); + fz_fill_shade(doc->dev, shade, ctm, doc->opacity[doc->opacity_top]); fz_drop_shade(doc->ctx, shade); } diff --git a/xps/xps_outline.c b/xps/xps_outline.c index 6bf7fd14..0feb7b24 100644 --- a/xps/xps_outline.c +++ b/xps/xps_outline.c @@ -94,6 +94,8 @@ xps_load_document_structure(xps_document *doc, xps_fixdoc *fixdoc) fz_rethrow(doc->ctx); } xps_free_part(doc, part); + if (!root) + return NULL; fz_try(doc->ctx) { @@ -118,10 +120,16 @@ xps_load_outline(xps_document *doc) for (fixdoc = doc->first_fixdoc; fixdoc; fixdoc = fixdoc->next) { if (fixdoc->outline) { outline = xps_load_document_structure(doc, fixdoc); + if (!outline) + continue; if (!head) head = outline; else + { + while (tail->next) + tail = tail->next; tail->next = outline; + } tail = outline; } } diff --git a/xps/xps_path.c b/xps/xps_path.c index 337f144d..04f298b8 100644 --- a/xps/xps_path.c +++ b/xps/xps_path.c @@ -292,8 +292,7 @@ xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) } } - pargs[0] = s; - pargs[1] = 0; + *pargs = s; n = pargs - args; i = 0; @@ -323,53 +322,63 @@ xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) switch (cmd) { case 'F': + if (i >= n) break; *fill_rule = atoi(args[i]); i ++; break; case 'M': + if (i + 1 >= n) break; fz_moveto(doc->ctx, path, fz_atof(args[i]), fz_atof(args[i+1])); i += 2; break; case 'm': + if (i + 1 >= n) break; pt = fz_currentpoint(path); fz_moveto(doc->ctx, path, pt.x + fz_atof(args[i]), pt.y + fz_atof(args[i+1])); i += 2; break; case 'L': + if (i + 1 >= n) break; fz_lineto(doc->ctx, path, fz_atof(args[i]), fz_atof(args[i+1])); i += 2; break; case 'l': + if (i + 1 >= n) break; pt = fz_currentpoint(path); fz_lineto(doc->ctx, path, pt.x + fz_atof(args[i]), pt.y + fz_atof(args[i+1])); i += 2; break; case 'H': + if (i >= n) break; pt = fz_currentpoint(path); fz_lineto(doc->ctx, path, fz_atof(args[i]), pt.y); i += 1; break; case 'h': + if (i >= n) break; pt = fz_currentpoint(path); fz_lineto(doc->ctx, path, pt.x + fz_atof(args[i]), pt.y); i += 1; break; case 'V': + if (i >= n) break; pt = fz_currentpoint(path); fz_lineto(doc->ctx, path, pt.x, fz_atof(args[i])); i += 1; break; case 'v': + if (i >= n) break; pt = fz_currentpoint(path); fz_lineto(doc->ctx, path, pt.x, pt.y + fz_atof(args[i])); i += 1; break; case 'C': + if (i + 5 >= n) break; x1 = fz_atof(args[i+0]); y1 = fz_atof(args[i+1]); x2 = fz_atof(args[i+2]); @@ -384,6 +393,7 @@ xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) break; case 'c': + if (i + 5 >= n) break; pt = fz_currentpoint(path); x1 = fz_atof(args[i+0]) + pt.x; y1 = fz_atof(args[i+1]) + pt.y; @@ -399,6 +409,7 @@ xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) break; case 'S': + if (i + 3 >= n) break; pt = fz_currentpoint(path); x1 = fz_atof(args[i+0]); y1 = fz_atof(args[i+1]); @@ -412,6 +423,7 @@ xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) break; case 's': + if (i + 3 >= n) break; pt = fz_currentpoint(path); x1 = fz_atof(args[i+0]) + pt.x; y1 = fz_atof(args[i+1]) + pt.y; @@ -425,6 +437,7 @@ xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) break; case 'Q': + if (i + 3 >= n) break; pt = fz_currentpoint(path); x1 = fz_atof(args[i+0]); y1 = fz_atof(args[i+1]); @@ -437,6 +450,7 @@ xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) i += 4; break; case 'q': + if (i + 3 >= n) break; pt = fz_currentpoint(path); x1 = fz_atof(args[i+0]) + pt.x; y1 = fz_atof(args[i+1]) + pt.y; @@ -450,6 +464,7 @@ xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) break; case 'A': + if (i + 6 >= n) break; xps_draw_arc(doc->ctx, path, fz_atof(args[i+0]), fz_atof(args[i+1]), fz_atof(args[i+2]), atoi(args[i+3]), atoi(args[i+4]), @@ -457,6 +472,7 @@ xps_parse_abbreviated_geometry(xps_document *doc, char *geom, int *fill_rule) i += 7; break; case 'a': + if (i + 6 >= n) break; pt = fz_currentpoint(path); xps_draw_arc(doc->ctx, path, fz_atof(args[i+0]), fz_atof(args[i+1]), fz_atof(args[i+2]), @@ -515,6 +531,9 @@ xps_parse_arc_segment(fz_context *doc, fz_path *path, xml_element *root, int str if (!is_stroked) *skipped_stroke = 1; + point_x = point_y = 0; + size_x = size_y = 0; + xps_parse_point(point_att, &point_x, &point_y); xps_parse_point(size_att, &size_x, &size_y); rotation_angle = fz_atof(rotation_angle_att); diff --git a/xps/xps_resource.c b/xps/xps_resource.c index aa3cdc75..845bea6c 100644 --- a/xps/xps_resource.c +++ b/xps/xps_resource.c @@ -67,6 +67,9 @@ xps_parse_remote_resource_dictionary(xps_document *doc, char *base_uri, char *so xml = xml_parse_document(doc->ctx, part->data, part->size); xps_free_part(doc, part); + if (!xml) + return NULL; + if (strcmp(xml_tag(xml), "ResourceDictionary")) { xml_free_element(doc->ctx, xml); @@ -118,8 +121,6 @@ xps_parse_resource_dictionary(xps_document *doc, char *base_uri, xml_element *ro if (head) head->base_uri = fz_strdup(doc->ctx, base_uri); - else - fz_warn(doc->ctx, "empty resource dictionary"); return head; } diff --git a/xps/xps_tile.c b/xps/xps_tile.c index 5ec0463f..fcac57d8 100644 --- a/xps/xps_tile.c +++ b/xps/xps_tile.c @@ -126,6 +126,11 @@ xps_parse_tiling_brush(xps_document *doc, fz_matrix ctm, fz_rect area, if (viewport_att) xps_parse_rectangle(doc, viewport_att, &viewport); + if (fabsf(viewport.x1 - viewport.x0) < 0.01f || fabsf(viewport.y1 - viewport.y0) < 0.01f) + fz_warn(doc->ctx, "not drawing tile for viewport size %.4f x %.4f", viewport.x1 - viewport.x0, viewport.y1 - viewport.y0); + else if (fabsf(viewbox.x1 - viewbox.x0) < 0.01f || fabsf(viewbox.y1 - viewbox.y0) < 0.01f) + fz_warn(doc->ctx, "not drawing tile for viewbox size %.4f x %.4f", viewbox.x1 - viewbox.x0, viewbox.y1 - viewbox.y0); + /* some sanity checks on the viewport/viewbox size */ if (fabsf(viewport.x1 - viewport.x0) < 0.01f) return; if (fabsf(viewport.y1 - viewport.y0) < 0.01f) return; @@ -270,15 +275,20 @@ xps_parse_canvas(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri, for (node = xml_down(root); node; node = xml_next(node)) { - /* FIXME: Sumatra warns of memory leak here where we have multiple - * Canvas.Resources. */ if (!strcmp(xml_tag(node), "Canvas.Resources") && xml_down(node)) { - new_dict = xps_parse_resource_dictionary(doc, base_uri, xml_down(node)); if (new_dict) { - new_dict->parent = dict; - dict = new_dict; + fz_warn(doc->ctx, "ignoring follow-up resource dictionaries"); + } + else + { + new_dict = xps_parse_resource_dictionary(doc, base_uri, xml_down(node)); + if (new_dict) + { + new_dict->parent = dict; + dict = new_dict; + } } } @@ -350,10 +360,13 @@ xps_parse_fixed_page(xps_document *doc, fz_matrix ctm, xps_page *page) for (node = xml_down(page->root); node; node = xml_next(node)) { - /* FIXME: Sumatra warns of memory leak here where we have multiple - * FixedPage.Resources. */ if (!strcmp(xml_tag(node), "FixedPage.Resources") && xml_down(node)) - dict = xps_parse_resource_dictionary(doc, base_uri, xml_down(node)); + { + if (dict) + fz_warn(doc->ctx, "ignoring follow-up resource dictionaries"); + else + dict = xps_parse_resource_dictionary(doc, base_uri, xml_down(node)); + } xps_parse_element(doc, ctm, area, base_uri, dict, node); } |