summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2013-01-30 16:49:43 +0000
committerRobin Watts <robin.watts@artifex.com>2013-01-31 11:17:32 +0000
commitaeed1e16e440cefbf5137eef7f4af608b0c70569 (patch)
tree40a55a1bff17a6ef632eaab053437f40123d1f4e /pdf
parent0203bd8921ffa9569273a077c1cb8bb92a35e520 (diff)
downloadmupdf-aeed1e16e440cefbf5137eef7f4af608b0c70569.tar.xz
Add support for annotation creation
Diffstat (limited to 'pdf')
-rw-r--r--pdf/mupdf-internal.h5
-rw-r--r--pdf/mupdf.h1
-rw-r--r--pdf/pdf_annot.c129
-rw-r--r--pdf/pdf_form.c2
-rw-r--r--pdf/pdf_object.c19
-rw-r--r--pdf/pdf_page.c2
6 files changed, 152 insertions, 6 deletions
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h
index 4f2524ad..6ac228ef 100644
--- a/pdf/mupdf-internal.h
+++ b/pdf/mupdf-internal.h
@@ -494,6 +494,7 @@ float pdf_text_stride(fz_context *ctx, pdf_font_desc *fontdesc, float fontsize,
struct pdf_annot_s
{
+ pdf_page *page;
pdf_obj *obj;
fz_rect rect;
fz_rect pagerect;
@@ -513,7 +514,7 @@ pdf_obj *pdf_load_name_tree(pdf_document *doc, char *which);
fz_link *pdf_load_link_annots(pdf_document *, pdf_obj *annots, fz_matrix page_ctm);
-pdf_annot *pdf_load_annots(pdf_document *, pdf_obj *annots, fz_matrix page_ctm);
+pdf_annot *pdf_load_annots(pdf_document *, pdf_obj *annots, pdf_page *page);
void pdf_update_annot(pdf_document *, pdf_annot *annot);
void pdf_free_annot(fz_context *ctx, pdf_annot *link);
@@ -583,6 +584,8 @@ int pdf_choice_widget_options(pdf_document *doc, fz_widget *tw, char *opts[]);
int pdf_choice_widget_is_multiselect(pdf_document *doc, fz_widget *tw);
int pdf_choice_widget_value(pdf_document *doc, fz_widget *tw, char *opts[]);
void pdf_choice_widget_set_value(pdf_document *doc, fz_widget *tw, int n, char *opts[]);
+pdf_annot *pdf_create_annot(pdf_document *doc, pdf_page *page, fz_annot_type type);
+void pdf_set_annot_appearance(pdf_document *doc, pdf_annot *annot, fz_display_list *disp_list);
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/mupdf.h b/pdf/mupdf.h
index e10a4982..27bd1644 100644
--- a/pdf/mupdf.h
+++ b/pdf/mupdf.h
@@ -78,6 +78,7 @@ void pdf_dict_put(pdf_obj *dict, pdf_obj *key, pdf_obj *val);
void pdf_dict_puts(pdf_obj *dict, const char *key, pdf_obj *val);
void pdf_dict_puts_drop(pdf_obj *dict, const char *key, pdf_obj *val);
void pdf_dict_putp(pdf_obj *dict, const char *key, pdf_obj *val);
+void pdf_dict_putp_drop(pdf_obj *dict, const char *key, pdf_obj *val);
void pdf_dict_del(pdf_obj *dict, pdf_obj *key);
void pdf_dict_dels(pdf_obj *dict, const char *key);
void pdf_sort_dict(pdf_obj *dict);
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c
index 4d0d0f84..b93fa258 100644
--- a/pdf/pdf_annot.c
+++ b/pdf/pdf_annot.c
@@ -353,7 +353,7 @@ pdf_transform_annot(pdf_annot *annot)
}
pdf_annot *
-pdf_load_annots(pdf_document *xref, pdf_obj *annots, fz_matrix page_ctm)
+pdf_load_annots(pdf_document *xref, pdf_obj *annots, pdf_page *page)
{
pdf_annot *annot, *head, *tail;
pdf_obj *obj, *ap, *as, *n, *rect;
@@ -400,9 +400,10 @@ pdf_load_annots(pdf_document *xref, pdf_obj *annots, fz_matrix page_ctm)
n = pdf_dict_get(n, as);
annot = fz_malloc_struct(ctx, pdf_annot);
+ annot->page = page;
annot->obj = pdf_keep_obj(obj);
annot->rect = pdf_to_rect(ctx, rect);
- annot->pagerect = fz_transform_rect(page_ctm, annot->rect);
+ annot->pagerect = fz_transform_rect(page->ctm, annot->rect);
annot->ap = NULL;
annot->type = pdf_field_type(xref, obj);
@@ -507,3 +508,127 @@ pdf_bound_annot(pdf_document *doc, pdf_annot *annot)
return annot->pagerect;
return fz_empty_rect;
}
+
+pdf_annot *
+pdf_create_annot(pdf_document *doc, pdf_page *page, fz_annot_type type)
+{
+ fz_context *ctx = doc->ctx;
+ pdf_annot *annot = NULL;
+ pdf_obj *annot_obj = pdf_new_dict(ctx, 0);
+
+ fz_var(annot);
+ fz_try(ctx)
+ {
+ fz_rect rect = {0.0, 0.0, 0.0, 0.0};
+ char *type_str = "";
+ pdf_obj *annot_arr = pdf_dict_gets(page->me, "Annots");
+ if (annot_arr == NULL)
+ {
+ annot_arr = pdf_new_array(ctx, 0);
+ pdf_dict_puts_drop(page->me, "Annots", annot_arr);
+ }
+
+ pdf_dict_puts_drop(annot_obj, "Type", pdf_new_name(ctx, "Annot"));
+
+ switch(type)
+ {
+ case FZ_ANNOT_STRIKEOUT:
+ type_str = "StrikeOut";
+ break;
+ }
+
+ pdf_dict_puts_drop(annot_obj, "Subtype", pdf_new_name(ctx, type_str));
+ pdf_dict_puts_drop(annot_obj, "Rect", pdf_new_rect(ctx, rect));
+
+ annot = fz_malloc_struct(ctx, pdf_annot);
+ annot->page = page;
+ annot->obj = pdf_keep_obj(annot_obj);
+ annot->rect = rect;
+ annot->pagerect = rect;
+ annot->ap = NULL;
+ annot->type = FZ_WIDGET_TYPE_NOT_WIDGET;
+
+ /*
+ Both annotation object and annotation structure are now created.
+ Insert the object in the hierarchy and the structure in the
+ page's array.
+ */
+ pdf_array_push(annot_arr, annot_obj);
+
+ /*
+ Linking must be done before any call that might throw because
+ pdf_free_annot below actually frees a list
+ */
+ annot->next = page->annots;
+ page->annots = annot;
+
+ doc->dirty = 1;
+ }
+ fz_always(ctx)
+ {
+ pdf_drop_obj(annot_obj);
+ }
+ fz_catch(ctx)
+ {
+ pdf_free_annot(ctx, annot);
+ fz_rethrow(ctx);
+ }
+
+ return annot;
+}
+
+void
+pdf_set_annot_appearance(pdf_document *doc, pdf_annot *annot, fz_display_list *disp_list)
+{
+ fz_context *ctx = doc->ctx;
+ fz_matrix ctm = fz_invert_matrix(annot->page->ctm);
+ fz_rect rect;
+ fz_matrix mat = fz_identity;
+ fz_device *dev = fz_new_bbox_device(ctx, &rect);
+
+ fz_try(ctx)
+ {
+ pdf_obj *ap_obj;
+
+ fz_run_display_list(disp_list, dev, ctm, fz_infinite_rect, NULL);
+ fz_free_device(dev);
+ dev = NULL;
+
+ pdf_dict_puts_drop(annot->obj, "Rect", pdf_new_rect(ctx, rect));
+
+ /* See if there is a current normal appearance */
+ ap_obj = pdf_dict_getp(annot->obj, "AP/N");
+ if (!pdf_is_stream(doc, pdf_to_num(annot->obj), pdf_to_gen(annot->obj)))
+ ap_obj = NULL;
+
+ if (ap_obj == NULL)
+ {
+ ap_obj = pdf_new_xobject(doc, rect, mat);
+ pdf_dict_putp_drop(annot->obj, "AP/N", ap_obj);
+ }
+ else
+ {
+ pdf_dict_puts_drop(ap_obj, "Rect", pdf_new_rect(ctx, rect));
+ pdf_dict_puts_drop(ap_obj, "Matrix", pdf_new_matrix(ctx, mat));
+ }
+
+ /* Remove annot reference to the xobject and don't recreate it
+ so that pdf_update_page counts it as dirty */
+ pdf_drop_xobject(ctx, annot->ap);
+ annot->ap = NULL;
+
+ annot->rect = rect;
+ annot->pagerect = fz_transform_rect(annot->page->ctm, rect);
+
+ dev = pdf_new_pdf_device(doc, ap_obj, pdf_dict_gets(ap_obj, "Resources"), mat);
+ fz_run_display_list(disp_list, dev, ctm, fz_infinite_rect, NULL);
+ fz_free_device(dev);
+
+ doc->dirty = 1;
+ }
+ fz_catch(ctx)
+ {
+ fz_free_device(dev);
+ fz_rethrow(ctx);
+ }
+}
diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c
index 8fbebbc8..e92ba738 100644
--- a/pdf/pdf_form.c
+++ b/pdf/pdf_form.c
@@ -3,8 +3,6 @@
#define MATRIX_COEFS (6)
-#define FZ_WIDGET_TYPE_NOT_WIDGET (-1)
-
enum
{
Ff_Multiline = 1 << (13-1),
diff --git a/pdf/pdf_object.c b/pdf/pdf_object.c
index 9ebb4aec..8a2d71fc 100644
--- a/pdf/pdf_object.c
+++ b/pdf/pdf_object.c
@@ -1056,6 +1056,25 @@ pdf_dict_putp(pdf_obj *obj, const char *keys, pdf_obj *val)
}
void
+pdf_dict_putp_drop(pdf_obj *obj, const char *keys, pdf_obj *val)
+{
+ fz_context *ctx = obj->ctx;
+
+ fz_try(ctx)
+ {
+ pdf_dict_putp(obj, keys, val);
+ }
+ fz_always(ctx)
+ {
+ pdf_drop_obj(val);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+void
pdf_dict_dels(pdf_obj *obj, const char *key)
{
RESOLVE(obj);
diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c
index 93643e7c..a071732a 100644
--- a/pdf/pdf_page.c
+++ b/pdf/pdf_page.c
@@ -408,7 +408,7 @@ pdf_load_page(pdf_document *xref, int number)
if (obj)
{
page->links = pdf_load_link_annots(xref, obj, page->ctm);
- page->annots = pdf_load_annots(xref, obj, page->ctm);
+ page->annots = pdf_load_annots(xref, obj, page);
}
page->duration = pdf_to_real(pdf_dict_gets(pageobj, "Dur"));