diff options
author | Paul Gardiner <paulg.artifex@glidos.net> | 2013-01-30 16:49:43 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-01-31 11:17:32 +0000 |
commit | aeed1e16e440cefbf5137eef7f4af608b0c70569 (patch) | |
tree | 40a55a1bff17a6ef632eaab053437f40123d1f4e | |
parent | 0203bd8921ffa9569273a077c1cb8bb92a35e520 (diff) | |
download | mupdf-aeed1e16e440cefbf5137eef7f4af608b0c70569.tar.xz |
Add support for annotation creation
-rw-r--r-- | fitz/doc_interactive.c | 10 | ||||
-rw-r--r-- | fitz/fitz-internal.h | 18 | ||||
-rw-r--r-- | fitz/fitz.h | 1 | ||||
-rw-r--r-- | pdf/mupdf-internal.h | 5 | ||||
-rw-r--r-- | pdf/mupdf.h | 1 | ||||
-rw-r--r-- | pdf/pdf_annot.c | 129 | ||||
-rw-r--r-- | pdf/pdf_form.c | 2 | ||||
-rw-r--r-- | pdf/pdf_object.c | 19 | ||||
-rw-r--r-- | pdf/pdf_page.c | 2 |
9 files changed, 181 insertions, 6 deletions
diff --git a/fitz/doc_interactive.c b/fitz/doc_interactive.c index f2fb059d..ea08577d 100644 --- a/fitz/doc_interactive.c +++ b/fitz/doc_interactive.c @@ -81,6 +81,16 @@ void fz_choice_widget_set_value(fz_interactive *idoc, fz_widget *tw, int n, char pdf_choice_widget_set_value((pdf_document *)idoc, tw, n, opts); } +fz_annot *fz_create_annot(fz_interactive *idoc, fz_page *page, fz_annot_type type) +{ + return (fz_annot *)pdf_create_annot((pdf_document *)idoc, (pdf_page *)page, type); +} + +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); +} + void fz_set_doc_event_callback(fz_interactive *idoc, fz_doc_event_cb *event_cb, void *data) { pdf_set_doc_event_callback((pdf_document *)idoc, event_cb, data); diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 13fd94de..4839af7d 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -1194,6 +1194,24 @@ fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate, int nestedDepth); void fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid, int nestedDepth); +typedef enum +{ + FZ_ANNOT_STRIKEOUT +} fz_annot_type; + +/* + fz_create_annot: create a new annotation of the specified type on the + specified page. The returned pdf_annot structure is owned by the page + and does not need to be freed. +*/ +fz_annot *fz_create_annot(fz_interactive *idoc, fz_page *page, fz_annot_type type); + +/* + fz_set_annot_appearance: update the appearance of an annotation based + on a display list. +*/ +void fz_set_annot_appearance(fz_interactive *idoc, fz_annot *annot, fz_display_list *disp_list); + /* * Text buffer. * diff --git a/fitz/fitz.h b/fitz/fitz.h index 8f39d3f4..43634dd9 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -2511,6 +2511,7 @@ fz_transition *fz_page_presentation(fz_document *doc, fz_page *page, float *dura /* Types of widget */ enum { + FZ_WIDGET_TYPE_NOT_WIDGET = -1, FZ_WIDGET_TYPE_PUSHBUTTON, FZ_WIDGET_TYPE_CHECKBOX, FZ_WIDGET_TYPE_RADIOBUTTON, 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")); |