summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2013-03-25 12:50:19 +0000
committerPaul Gardiner <paulg.artifex@glidos.net>2013-03-25 12:50:19 +0000
commit41f10c71dbae05fb538f51a495ef7aaa1861fd5d (patch)
tree40a9b0ce7a528f95db71f5c1e3cf165032d927a9 /pdf
parentf031719c18e610269e85aa1d1b83a619ddc7fec7 (diff)
downloadmupdf-41f10c71dbae05fb538f51a495ef7aaa1861fd5d.tar.xz
Support creation of Ink annotations in MuPDF library
Diffstat (limited to 'pdf')
-rw-r--r--pdf/mupdf-internal.h2
-rw-r--r--pdf/pdf_annot.c182
-rw-r--r--pdf/pdf_form.c3
3 files changed, 180 insertions, 7 deletions
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h
index 667f996a..164b0c81 100644
--- a/pdf/mupdf-internal.h
+++ b/pdf/mupdf-internal.h
@@ -614,6 +614,8 @@ void pdf_set_annot_appearance(pdf_document *doc, pdf_annot *annot, fz_rect *rect
void pdf_set_markup_annot_quadpoints(pdf_document *doc, pdf_annot *annot, fz_point *qp, int n);
void pdf_set_markup_obj_appearance(pdf_document *doc, pdf_obj *annot, float color[3], float alpha, float line_thickness, float line_height);
void pdf_set_markup_appearance(pdf_document *doc, pdf_annot *annot, float color[3], float alpha, float line_thickness, float line_height);
+void pdf_set_ink_annot_list(pdf_document *doc, pdf_annot *annot, fz_point *pts, int *counts, int ncount, float color[3], float thickness);
+void pdf_set_ink_obj_appearance(pdf_document *doc, pdf_obj *annot);
void pdf_set_doc_event_callback(pdf_document *doc, fz_doc_event_cb *event_cb, void *data);
void pdf_event_issue_alert(pdf_document *doc, fz_alert_event *event);
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c
index 5252ce9a..0c2128a7 100644
--- a/pdf/pdf_annot.c
+++ b/pdf/pdf_annot.c
@@ -768,6 +768,25 @@ pdf_delete_annot(pdf_document *doc, pdf_page *page, pdf_annot *annot)
doc->dirty = 1;
}
+static fz_colorspace *pdf_to_color(pdf_obj *col, float color[4])
+{
+ fz_colorspace *cs;
+ int i, ncol = pdf_array_len(col);
+
+ switch (ncol)
+ {
+ case 1: cs = fz_device_gray; break;
+ case 3: cs = fz_device_rgb; break;
+ case 4: cs = fz_device_cmyk; break;
+ default: return NULL;
+ }
+
+ for (i = 0; i < ncol; i++)
+ color[i] = pdf_to_real(pdf_array_get(col, i));
+
+ return cs;
+}
+
static fz_point *
quadpoints(pdf_document *doc, pdf_obj *annot, int *nout)
{
@@ -831,6 +850,70 @@ pdf_set_markup_annot_quadpoints(pdf_document *doc, pdf_annot *annot, fz_point *q
}
}
+static void update_rect(fz_context *ctx, pdf_annot *annot)
+{
+ pdf_to_rect(ctx, pdf_dict_gets(annot->obj, "Rect"), &annot->rect);
+ annot->pagerect = annot->rect;
+ fz_transform_rect(&annot->pagerect, &annot->page->ctm);
+}
+
+void
+pdf_set_ink_annot_list(pdf_document *doc, pdf_annot *annot, fz_point *pts, int *counts, int ncount, float color[3], float thickness)
+{
+ fz_context *ctx = doc->ctx;
+ fz_matrix ctm;
+ pdf_obj *list = pdf_new_array(ctx, ncount);
+ pdf_obj *bs, *col;
+ fz_rect rect;
+ int i, k = 0;
+
+ fz_invert_matrix(&ctm, &annot->page->ctm);
+
+ pdf_dict_puts_drop(annot->obj, "InkList", list);
+
+ for (i = 0; i < ncount; i++)
+ {
+ int j;
+ pdf_obj *arc = pdf_new_array(ctx, counts[i]);
+
+ pdf_array_push_drop(list, arc);
+
+ for (j = 0; j < counts[i]; j++)
+ {
+ fz_point pt = pts[k];
+
+ fz_transform_point(&pt, &ctm);
+
+ if (i == 0 && j == 0)
+ {
+ rect.x0 = rect.x1 = pt.x;
+ rect.y0 = rect.y1 = pt.y;
+ }
+ else
+ {
+ fz_include_point_in_rect(&rect, &pt);
+ }
+
+ pdf_array_push_drop(arc, pdf_new_real(ctx, pt.x));
+ pdf_array_push_drop(arc, pdf_new_real(ctx, pt.y));
+ k++;
+ }
+ }
+
+ fz_expand_rect(&rect, thickness);
+ pdf_dict_puts_drop(annot->obj, "Rect", pdf_new_rect(ctx, &rect));
+ update_rect(ctx, annot);
+
+ bs = pdf_new_dict(ctx, 1);
+ pdf_dict_puts_drop(annot->obj, "BS", bs);
+ pdf_dict_puts_drop(bs, "W", pdf_new_real(ctx, thickness));
+
+ col = pdf_new_array(ctx, 3);
+ pdf_dict_puts_drop(annot->obj, "C", col);
+ for (i = 0; i < 3; i++)
+ pdf_array_push_drop(col, pdf_new_real(ctx, color[i]));
+}
+
void
pdf_set_annot_obj_appearance(pdf_document *doc, pdf_obj *obj, const fz_matrix *page_ctm, fz_rect *rect, fz_display_list *disp_list)
{
@@ -889,13 +972,6 @@ pdf_set_annot_obj_appearance(pdf_document *doc, pdf_obj *obj, const fz_matrix *p
}
}
-static void update_rect(fz_context *ctx, pdf_annot *annot)
-{
- pdf_to_rect(ctx, pdf_dict_gets(annot->obj, "Rect"), &annot->rect);
- annot->pagerect = annot->rect;
- fz_transform_rect(&annot->pagerect, &annot->page->ctm);
-}
-
void
pdf_set_annot_appearance(pdf_document *doc, pdf_annot *annot, fz_rect *rect, fz_display_list *disp_list)
{
@@ -993,6 +1069,98 @@ pdf_set_markup_obj_appearance(pdf_document *doc, pdf_obj *annot, float color[3],
}
void
+pdf_set_ink_obj_appearance(pdf_document *doc, pdf_obj *annot)
+{
+ fz_context *ctx = doc->ctx;
+ fz_path *path = NULL;
+ fz_stroke_state *stroke = NULL;
+ fz_device *dev = NULL;
+ fz_display_list *strike_list = NULL;
+
+ fz_var(path);
+ fz_var(stroke);
+ fz_var(dev);
+ fz_var(strike_list);
+ fz_try(ctx)
+ {
+ fz_rect rect = fz_empty_rect;
+ fz_colorspace *cs;
+ float color[4];
+ float width;
+ pdf_obj *list;
+ int n, m, i, j;
+
+ cs = pdf_to_color(pdf_dict_gets(annot, "C"), color);
+ if (!cs)
+ {
+ cs = fz_device_rgb;
+ color[0] = 1.0f;
+ color[1] = 0.0f;
+ color[2] = 0.0f;
+ }
+
+ width = pdf_to_real(pdf_dict_gets(pdf_dict_gets(annot, "BS"), "W"));
+ if (width == 0.0f)
+ width = 1.0f;
+
+ list = pdf_dict_gets(annot, "InkList");
+
+ n = pdf_array_len(list);
+
+ strike_list = fz_new_display_list(ctx);
+ dev = fz_new_list_device(ctx, strike_list);
+ path = fz_new_path(ctx);
+ stroke = fz_new_stroke_state(ctx);
+ stroke->linewidth = width;
+
+ for (i = 0; i < n; i ++)
+ {
+ pdf_obj *arc = pdf_array_get(list, i);
+ m = pdf_array_len(arc);
+
+ for (j = 0; j < m-1; j += 2)
+ {
+ fz_point pt;
+ pt.x = pdf_to_real(pdf_array_get(arc, j));
+ pt.y = pdf_to_real(pdf_array_get(arc, j+1));
+
+ if (i == 0 && j == 0)
+ {
+ rect.x0 = rect.x1 = pt.x;
+ rect.y0 = rect.y1 = pt.y;
+ }
+ else
+ {
+ fz_include_point_in_rect(&rect, &pt);
+ }
+
+ if (j == 0)
+ fz_moveto(ctx, path, pt.x, pt.y);
+ else
+ fz_lineto(ctx, path, pt.x, pt.y);
+ }
+ }
+
+ fz_stroke_path(dev, path, stroke, &fz_identity, cs, color, 1.0f);
+
+ fz_expand_rect(&rect, width);
+
+ pdf_set_annot_obj_appearance(doc, annot, &fz_identity, &rect, strike_list);
+ }
+ fz_always(ctx)
+ {
+ fz_free_device(dev);
+ fz_drop_stroke_state(ctx, stroke);
+ fz_free_path(ctx, path);
+ fz_free_display_list(ctx, strike_list);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+void
pdf_set_markup_appearance(pdf_document *doc, pdf_annot *annot, float color[3], float alpha, float line_thickness, float line_height)
{
pdf_set_markup_obj_appearance(doc, annot->obj, color, alpha, line_thickness, line_height);
diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c
index 01f82d74..9e02f2d0 100644
--- a/pdf/pdf_form.c
+++ b/pdf/pdf_form.c
@@ -1806,6 +1806,9 @@ void pdf_update_appearance(pdf_document *doc, pdf_obj *obj)
case FZ_ANNOT_HIGHLIGHT:
update_text_markup_appearance(doc, obj, type);
break;
+ case FZ_ANNOT_INK:
+ pdf_set_ink_obj_appearance(doc, obj);
+ break;
default:
break;
}