summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2017-04-15 00:07:34 +0800
committerSebastian Rasmussen <sebras@gmail.com>2017-04-20 19:47:03 +0800
commiteeaf906a504d48d8d140c2040519a59d80d5ea0f (patch)
tree7580c5bcf82fafabb0bad1bda421e8a650108376 /source
parent96b76d2b9748551df1ef50db0688b39d4670e23a (diff)
downloadmupdf-eeaf906a504d48d8d140c2040519a59d80d5ea0f.tar.xz
Improve PDF annotation error handling.
Diffstat (limited to 'source')
-rw-r--r--source/pdf/pdf-annot-edit.c218
1 files changed, 152 insertions, 66 deletions
diff --git a/source/pdf/pdf-annot-edit.c b/source/pdf/pdf-annot-edit.c
index a3a0137d..401f11a1 100644
--- a/source/pdf/pdf-annot-edit.c
+++ b/source/pdf/pdf-annot-edit.c
@@ -65,6 +65,18 @@ int pdf_annot_type_from_string(fz_context *ctx, const char *subtype)
return PDF_ANNOT_UNKNOWN;
}
+static void check_allowed_subtypes(fz_context *ctx, pdf_annot *annot, pdf_obj *property, pdf_obj **allowed)
+{
+ pdf_obj *subtype = pdf_dict_get(ctx, annot->obj, PDF_NAME_Subtype);
+ while (allowed) {
+ if (pdf_name_eq(ctx, subtype, *allowed))
+ return;
+ allowed++;
+ }
+
+ fz_throw(ctx, FZ_ERROR_GENERIC, "%s annotations have no %s property", pdf_to_name(ctx, subtype), pdf_to_name(ctx, property));
+}
+
pdf_annot *
pdf_create_annot(fz_context *ctx, pdf_page *page, fz_annot_type type)
{
@@ -280,107 +292,161 @@ pdf_set_annot_border(fz_context *ctx, pdf_annot *annot, float w)
}
static void
-pdf_annot_color_imp(fz_context *ctx, pdf_annot *annot, pdf_obj *key, int *n, float color[4])
+pdf_annot_color_imp(fz_context *ctx, pdf_annot *annot, pdf_obj *key, int *n, float color[4], pdf_obj **allowed)
{
- pdf_obj *obj = pdf_dict_get(ctx, annot->obj, key);
- *n = 0;
- if (pdf_is_array(ctx, obj))
+ pdf_obj *arr;
+ int len;
+
+ if (allowed)
+ check_allowed_subtypes(ctx, annot, key, allowed);
+
+ arr = pdf_dict_get(ctx, annot->obj, key);
+ len = pdf_array_len(ctx, arr);
+
+ switch (len)
{
- switch (pdf_array_len(ctx, obj))
- {
- case 1:
+ case 0:
+ if (n)
+ *n = 0;
+ break;
+ case 1:
+ case 2:
+ if (n)
*n = 1;
- color[0] = pdf_to_real(ctx, pdf_array_get(ctx, obj, 0));
- break;
- case 3:
+ if (color)
+ color[0] = pdf_to_real(ctx, pdf_array_get(ctx, arr, 0));
+ break;
+ case 3:
+ if (n)
*n = 3;
- color[0] = pdf_to_real(ctx, pdf_array_get(ctx, obj, 0));
- color[1] = pdf_to_real(ctx, pdf_array_get(ctx, obj, 1));
- color[2] = pdf_to_real(ctx, pdf_array_get(ctx, obj, 2));
- break;
- case 4:
+ if (color)
+ {
+ color[0] = pdf_to_real(ctx, pdf_array_get(ctx, arr, 0));
+ color[1] = pdf_to_real(ctx, pdf_array_get(ctx, arr, 1));
+ color[2] = pdf_to_real(ctx, pdf_array_get(ctx, arr, 2));
+ }
+ break;
+ case 4:
+ default:
+ if (n)
*n = 4;
- color[0] = pdf_to_real(ctx, pdf_array_get(ctx, obj, 0));
- color[1] = pdf_to_real(ctx, pdf_array_get(ctx, obj, 1));
- color[2] = pdf_to_real(ctx, pdf_array_get(ctx, obj, 2));
- color[3] = pdf_to_real(ctx, pdf_array_get(ctx, obj, 3));
- break;
+ if (color)
+ {
+ color[0] = pdf_to_real(ctx, pdf_array_get(ctx, arr, 0));
+ color[1] = pdf_to_real(ctx, pdf_array_get(ctx, arr, 1));
+ color[2] = pdf_to_real(ctx, pdf_array_get(ctx, arr, 2));
+ color[3] = pdf_to_real(ctx, pdf_array_get(ctx, arr, 3));
}
+ break;
}
}
static void
-pdf_set_annot_color_imp(fz_context *ctx, pdf_annot *annot, pdf_obj *key, int n, const float color[4])
+pdf_set_annot_color_imp(fz_context *ctx, pdf_annot *annot, pdf_obj *key, int n, const float color[4], pdf_obj **allowed)
{
pdf_document *doc = annot->page->doc;
- pdf_obj *obj;
+ pdf_obj *arr;
+
+ if (allowed)
+ check_allowed_subtypes(ctx, annot, key, allowed);
if (n != 0 && n != 1 && n != 3 && n != 4)
fz_throw(ctx, FZ_ERROR_GENERIC, "color must be 0, 1, 3 or 4 components");
+ if (!color)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "no color given");
- obj = pdf_new_array(ctx, doc, n);
- switch (n)
+ arr = pdf_new_array(ctx, doc, n);
+ fz_try(ctx)
{
- default:
- case 0:
- break;
- case 1:
- pdf_array_push_drop(ctx, obj, pdf_new_real(ctx, doc, color[0]));
- break;
- case 3:
- pdf_array_push_drop(ctx, obj, pdf_new_real(ctx, doc, color[0]));
- pdf_array_push_drop(ctx, obj, pdf_new_real(ctx, doc, color[1]));
- pdf_array_push_drop(ctx, obj, pdf_new_real(ctx, doc, color[2]));
- break;
- case 4:
- pdf_array_push_drop(ctx, obj, pdf_new_real(ctx, doc, color[0]));
- pdf_array_push_drop(ctx, obj, pdf_new_real(ctx, doc, color[1]));
- pdf_array_push_drop(ctx, obj, pdf_new_real(ctx, doc, color[2]));
- pdf_array_push_drop(ctx, obj, pdf_new_real(ctx, doc, color[3]));
- break;
+ switch (n)
+ {
+ case 1:
+ pdf_array_insert_drop(ctx, arr, pdf_new_real(ctx, doc, color[0]), 0);
+ break;
+ case 3:
+ pdf_array_insert_drop(ctx, arr, pdf_new_real(ctx, doc, color[0]), 0);
+ pdf_array_insert_drop(ctx, arr, pdf_new_real(ctx, doc, color[1]), 1);
+ pdf_array_insert_drop(ctx, arr, pdf_new_real(ctx, doc, color[2]), 2);
+ break;
+ case 4:
+ pdf_array_insert_drop(ctx, arr, pdf_new_real(ctx, doc, color[0]), 0);
+ pdf_array_insert_drop(ctx, arr, pdf_new_real(ctx, doc, color[1]), 1);
+ pdf_array_insert_drop(ctx, arr, pdf_new_real(ctx, doc, color[2]), 2);
+ pdf_array_insert_drop(ctx, arr, pdf_new_real(ctx, doc, color[3]), 3);
+ break;
+ }
+ }
+ fz_catch(ctx)
+ {
+ pdf_drop_obj(ctx, arr);
+ fz_rethrow(ctx);
}
- pdf_dict_put_drop(ctx, annot->obj, key, obj);
+
+ pdf_dict_put_drop(ctx, annot->obj, key, arr);
annot->changed = 1;
}
void
pdf_annot_color(fz_context *ctx, pdf_annot *annot, int *n, float color[4])
{
- pdf_annot_color_imp(ctx, annot, PDF_NAME_C, n, color);
+ pdf_annot_color_imp(ctx, annot, PDF_NAME_C, n, color, NULL);
}
void
pdf_set_annot_color(fz_context *ctx, pdf_annot *annot, int n, const float color[4])
{
- pdf_set_annot_color_imp(ctx, annot, PDF_NAME_C, n, color);
+ pdf_set_annot_color_imp(ctx, annot, PDF_NAME_C, n, color, NULL);
}
+static pdf_obj *interior_color_subtypes[] = {
+ PDF_NAME_Circle,
+ PDF_NAME_Line,
+ PDF_NAME_PolyLine,
+ PDF_NAME_Polygon,
+ PDF_NAME_Square,
+ NULL,
+};
+
void
pdf_annot_interior_color(fz_context *ctx, pdf_annot *annot, int *n, float color[4])
{
- // TODO: check annot type
- pdf_annot_color_imp(ctx, annot, PDF_NAME_IC, n, color);
+ pdf_annot_color_imp(ctx, annot, PDF_NAME_IC, n, color, interior_color_subtypes);
}
void
pdf_set_annot_interior_color(fz_context *ctx, pdf_annot *annot, int n, const float color[4])
{
- // TODO: check annot type
- pdf_set_annot_color_imp(ctx, annot, PDF_NAME_IC, n, color);
+ pdf_set_annot_color_imp(ctx, annot, PDF_NAME_IC, n, color, interior_color_subtypes);
}
+static pdf_obj *quad_point_subtypes[] = {
+ PDF_NAME_Highlight,
+ PDF_NAME_Link,
+ PDF_NAME_Squiggly,
+ PDF_NAME_StrikeOut,
+ PDF_NAME_Underline,
+ NULL,
+};
+
int pdf_annot_quad_point_count(fz_context *ctx, pdf_annot *annot)
{
- pdf_obj *quad_points = pdf_dict_get(ctx, annot->obj, PDF_NAME_QuadPoints);
+ pdf_obj *quad_points;
+ check_allowed_subtypes(ctx, annot, PDF_NAME_QuadPoints, quad_point_subtypes);
+ quad_points = pdf_dict_get(ctx, annot->obj, PDF_NAME_QuadPoints);
return pdf_array_len(ctx, quad_points);
}
void pdf_annot_quad_point(fz_context *ctx, pdf_annot *annot, int idx, float v[8])
{
- pdf_obj *quad_points = pdf_dict_get(ctx, annot->obj, PDF_NAME_QuadPoints);
- pdf_obj *quad_point = pdf_array_get(ctx, quad_points, idx);
+ pdf_obj *quad_points;
+ pdf_obj *quad_point;
fz_matrix page_ctm;
int i;
+ check_allowed_subtypes(ctx, annot, PDF_NAME_QuadPoints, quad_point_subtypes);
+
+ quad_points = pdf_dict_get(ctx, annot->obj, PDF_NAME_QuadPoints);
+ quad_point = pdf_array_get(ctx, quad_points, idx);
+
pdf_page_transform(ctx, annot->page, NULL, &page_ctm);
for (i = 0; i < 8; i += 2)
@@ -403,7 +469,9 @@ pdf_set_annot_quad_points(fz_context *ctx, pdf_annot *annot, int n, const float
fz_point point;
int i, k;
- // TODO: check annot type
+ check_allowed_subtypes(ctx, annot, PDF_NAME_QuadPoints, quad_point_subtypes);
+ if (n <= 0 || !v)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "invalid number of quadrilaterals");
pdf_page_transform(ctx, annot->page, NULL, &page_ctm);
fz_invert_matrix(&inv_page_ctm, &page_ctm);
@@ -424,33 +492,52 @@ pdf_set_annot_quad_points(fz_context *ctx, pdf_annot *annot, int n, const float
annot->changed = 1;
}
+static pdf_obj *ink_list_subtypes[] = {
+ PDF_NAME_Ink,
+ NULL,
+};
+
int pdf_annot_ink_list_count(fz_context *ctx, pdf_annot *annot)
{
- pdf_obj *ink_list = pdf_dict_get(ctx, annot->obj, PDF_NAME_InkList);
+ pdf_obj *ink_list;
+ check_allowed_subtypes(ctx, annot, PDF_NAME_InkList, ink_list_subtypes);
+ ink_list = pdf_dict_get(ctx, annot->obj, PDF_NAME_InkList);
return pdf_array_len(ctx, ink_list);
}
int pdf_annot_ink_list_stroke_count(fz_context *ctx, pdf_annot *annot, int i)
{
- pdf_obj *ink_list = pdf_dict_get(ctx, annot->obj, PDF_NAME_InkList);
- pdf_obj *stroke = pdf_array_get(ctx, ink_list, i);
+ pdf_obj *ink_list;
+ pdf_obj *stroke;
+ check_allowed_subtypes(ctx, annot, PDF_NAME_InkList, ink_list_subtypes);
+ ink_list = pdf_dict_get(ctx, annot->obj, PDF_NAME_InkList);
+ stroke = pdf_array_get(ctx, ink_list, i);
return pdf_array_len(ctx, stroke);
}
void pdf_annot_ink_list_stroke_vertex(fz_context *ctx, pdf_annot *annot, int i, int k, float v[2])
{
- pdf_obj *ink_list = pdf_dict_get(ctx, annot->obj, PDF_NAME_InkList);
- pdf_obj *stroke = pdf_array_get(ctx, ink_list, i);
+ pdf_obj *ink_list;
+ pdf_obj *stroke;
fz_matrix page_ctm;
- fz_point point;
+ fz_point point = { 0, 0 };
- pdf_page_transform(ctx, annot->page, NULL, &page_ctm);
+ check_allowed_subtypes(ctx, annot, PDF_NAME_InkList, ink_list_subtypes);
+
+ ink_list = pdf_dict_get(ctx, annot->obj, PDF_NAME_InkList);
+ stroke = pdf_array_get(ctx, ink_list, i);
+
+ if (v)
+ {
+ pdf_page_transform(ctx, annot->page, NULL, &page_ctm);
+
+ point.x = pdf_to_real(ctx, pdf_array_get(ctx, stroke, k * 2 + 0));
+ point.y = pdf_to_real(ctx, pdf_array_get(ctx, stroke, k * 2 + 1));
+ fz_transform_point(&point, &page_ctm);
- point.x = pdf_to_real(ctx, pdf_array_get(ctx, stroke, k * 2 + 0));
- point.y = pdf_to_real(ctx, pdf_array_get(ctx, stroke, k * 2 + 1));
- fz_transform_point(&point, &page_ctm);
- v[0] = point.x;
- v[1] = point.y;
+ v[0] = point.x;
+ v[1] = point.y;
+ }
}
void
@@ -462,8 +549,7 @@ pdf_set_annot_ink_list(fz_context *ctx, pdf_annot *annot, int n, const int *coun
fz_point point;
int i, k;
- if (pdf_annot_type(ctx, annot) != PDF_ANNOT_INK)
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot set InkList on non-ink annotations");
+ check_allowed_subtypes(ctx, annot, PDF_NAME_InkList, ink_list_subtypes);
pdf_page_transform(ctx, annot->page, NULL, &page_ctm);
fz_invert_matrix(&inv_page_ctm, &page_ctm);