summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2013-02-26 16:08:12 +0000
committerRobin Watts <robin.watts@artifex.com>2013-02-26 19:01:49 +0000
commit5d6087bbce6ad9177244f823f38eee802a2aa23c (patch)
tree42d9d502d7e4bdf50d6b1ec21560da0844386360 /pdf
parent4553555e8bab6f749ae007664ad6745ee816e4bf (diff)
downloadmupdf-5d6087bbce6ad9177244f823f38eee802a2aa23c.tar.xz
Implement annotation deletion, with necessary changes to partial update
Diffstat (limited to 'pdf')
-rw-r--r--pdf/mupdf-internal.h3
-rw-r--r--pdf/pdf_annot.c70
-rw-r--r--pdf/pdf_form.c31
-rw-r--r--pdf/pdf_page.c6
4 files changed, 110 insertions, 0 deletions
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h
index 0a468939..4b58f911 100644
--- a/pdf/mupdf-internal.h
+++ b/pdf/mupdf-internal.h
@@ -548,6 +548,8 @@ struct pdf_page_s
fz_link *links;
pdf_annot *annots;
pdf_annot *changed_annots;
+ pdf_annot *deleted_annots;
+ pdf_annot *tmp_annots;
pdf_obj *me;
float duration;
int transition_present;
@@ -586,6 +588,7 @@ 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_delete_annot(pdf_document *doc, pdf_page *page, pdf_annot *annot);
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);
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c
index 7201045f..aa56e056 100644
--- a/pdf/pdf_annot.c
+++ b/pdf/pdf_annot.c
@@ -671,6 +671,76 @@ pdf_create_annot(pdf_document *doc, pdf_page *page, fz_annot_type type)
}
void
+pdf_delete_annot(pdf_document *doc, pdf_page *page, pdf_annot *annot)
+{
+ fz_context *ctx = doc->ctx;
+ pdf_annot **annotptr;
+ pdf_obj *old_annot_arr;
+ pdf_obj *annot_arr;
+
+ if (annot == NULL)
+ return;
+
+ /* Remove annot from page's list */
+ for (annotptr = &page->annots; *annotptr; annotptr = &(*annotptr)->next)
+ {
+ if (*annotptr == annot)
+ break;
+ }
+
+ /* Check the passed annotation was of this page */
+ if (*annotptr == NULL)
+ return;
+
+ *annotptr = annot->next;
+
+ /* Stick it in the deleted list */
+ annot->next = page->deleted_annots;
+ page->deleted_annots = annot;
+
+ pdf_drop_xobject(ctx, annot->ap);
+ annot->ap = NULL;
+
+ /* Recreate the "Annots" array with this annot removed */
+ old_annot_arr = pdf_dict_gets(page->me, "Annots");
+
+ if (old_annot_arr)
+ {
+ int i, n = pdf_array_len(old_annot_arr);
+ annot_arr = pdf_new_array(ctx, n?(n-1):0);
+
+ fz_try(ctx)
+ {
+ for (i = 0; i < n; i++)
+ {
+ pdf_obj *obj = pdf_array_get(old_annot_arr, i);
+
+ if (obj != annot->obj)
+ pdf_array_push(annot_arr, obj);
+ }
+
+ /*
+ Overwrite "Annots" in the page dictionary, which has the
+ side-effect of releasing the last reference to old_annot_arr
+ */
+ pdf_dict_puts(page->me, "Annots", annot_arr);
+ }
+ fz_always(ctx)
+ {
+ pdf_drop_obj(annot_arr);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+ }
+
+ pdf_drop_obj(annot->obj);
+ annot->obj = NULL;
+ doc->dirty = 1;
+}
+
+void
pdf_set_annot_appearance(pdf_document *doc, pdf_annot *annot, fz_display_list *disp_list)
{
fz_context *ctx = doc->ctx;
diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c
index eddf2326..5ad5e845 100644
--- a/pdf/pdf_form.c
+++ b/pdf/pdf_form.c
@@ -2160,7 +2160,20 @@ void pdf_update_page(pdf_document *doc, pdf_page *page)
fz_context *ctx = doc->ctx;
pdf_annot *annot;
+ /* Reset changed_annots to empty */
page->changed_annots = NULL;
+
+ /*
+ Free all annots in tmp_annots, since these were
+ referenced only from changed_annots.
+ */
+ if (page->tmp_annots)
+ {
+ pdf_free_annot(ctx, page->tmp_annots);
+ page->tmp_annots = NULL;
+ }
+
+ /* Add all changed annots to the list */
for (annot = page->annots; annot; annot = annot->next)
{
pdf_xobject *ap = pdf_keep_xobject(ctx, annot->ap);
@@ -2185,6 +2198,24 @@ void pdf_update_page(pdf_document *doc, pdf_page *page)
fz_rethrow(ctx);
}
}
+
+ /*
+ Add all deleted annots to the list, since these also
+ warrant a screen update
+ */
+ for (annot = page->deleted_annots; annot; annot = annot->next)
+ {
+ annot->next_changed = page->changed_annots;
+ page->changed_annots = annot;
+ }
+
+ /*
+ Move deleted_annots to tmp_annots to keep them separate
+ from any future deleted ones. They cannot yet be freed
+ since they are linked into changed_annots
+ */
+ page->tmp_annots = page->deleted_annots;
+ page->deleted_annots = NULL;
}
pdf_annot *pdf_poll_changed_annot(pdf_document *idoc, pdf_page *page)
diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c
index a3627176..5d6d6bca 100644
--- a/pdf/pdf_page.c
+++ b/pdf/pdf_page.c
@@ -355,6 +355,8 @@ pdf_load_page(pdf_document *xref, int number)
page->transparency = 0;
page->links = NULL;
page->annots = NULL;
+ page->deleted_annots = NULL;
+ page->tmp_annots = NULL;
page->me = pdf_keep_obj(pageobj);
obj = pdf_dict_gets(pageobj, "UserUnit");
@@ -472,6 +474,10 @@ pdf_free_page(pdf_document *xref, pdf_page *page)
fz_drop_link(xref->ctx, page->links);
if (page->annots)
pdf_free_annot(xref->ctx, page->annots);
+ if (page->deleted_annots)
+ pdf_free_annot(xref->ctx, page->deleted_annots);
+ if (page->tmp_annots)
+ pdf_free_annot(xref->ctx, page->tmp_annots);
/* xref->focus, when not NULL, refers to one of
* the annotations and must be NULLed when the
* annotations are destroyed. xref->focus_obj