summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2012-03-14 14:59:46 +0100
committerTor Andersson <tor.andersson@artifex.com>2012-03-14 15:29:56 +0100
commitbcb88cede5edb232ac87235d957c023a0397bd5e (patch)
tree2522fb8d1a31cf9421b245ecc05747dde9e72010
parent621e33bdb921bdc3ccd9068101acd3858c9c14c8 (diff)
downloadmupdf-bcb88cede5edb232ac87235d957c023a0397bd5e.tar.xz
Miscellaneous fixes for XPS from SumatraPDf.
-rw-r--r--xps/xps_doc.c15
-rw-r--r--xps/xps_gradient.c10
-rw-r--r--xps/xps_outline.c8
-rw-r--r--xps/xps_path.c23
-rw-r--r--xps/xps_resource.c5
-rw-r--r--xps/xps_tile.c29
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);
}