diff options
-rw-r--r-- | fitz/doc_interactive.c | 5 | ||||
-rw-r--r-- | fitz/fitz-internal.h | 5 | ||||
-rw-r--r-- | pdf/mupdf-internal.h | 3 | ||||
-rw-r--r-- | pdf/pdf_annot.c | 70 | ||||
-rw-r--r-- | pdf/pdf_form.c | 31 | ||||
-rw-r--r-- | pdf/pdf_page.c | 6 |
6 files changed, 120 insertions, 0 deletions
diff --git a/fitz/doc_interactive.c b/fitz/doc_interactive.c index db9fce87..bf08690a 100644 --- a/fitz/doc_interactive.c +++ b/fitz/doc_interactive.c @@ -91,6 +91,11 @@ fz_annot *fz_create_annot(fz_interactive *idoc, fz_page *page, fz_annot_type typ return (fz_annot *)pdf_create_annot((pdf_document *)idoc, (pdf_page *)page, type); } +void fz_delete_annot(fz_interactive *idoc, fz_page *page, fz_annot *annot) +{ + pdf_delete_annot((pdf_document *)idoc, (pdf_page *)page, (pdf_annot *)annot); +} + void fz_set_annot_appearance(fz_interactive *idoc, fz_annot *annot, fz_display_list *disp_list) { pdf_set_annot_appearance((pdf_document *)idoc, (pdf_annot *)annot, disp_list); diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 0c801ed2..7f9beace 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -1201,6 +1201,11 @@ void fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid, int nestedDept fz_annot *fz_create_annot(fz_interactive *idoc, fz_page *page, fz_annot_type type); /* + fz_delete_annot: delete an annotation +*/ +void fz_delete_annot(fz_interactive *idoc, fz_page *page, fz_annot *annot); + +/* fz_set_annot_appearance: update the appearance of an annotation based on a display list. */ 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 |