From 50b0de6e463ebd954b1a97a2cd093731335f1671 Mon Sep 17 00:00:00 2001 From: Paul Gardiner Date: Tue, 8 May 2012 12:35:00 +0100 Subject: Forms: handle field appearance change on mouse up/down --- apps/pdfapp.c | 15 +++++++++++++ fitz/doc_document.c | 24 +++++++++++++++++++++ fitz/fitz-internal.h | 12 +++++++++++ fitz/fitz.h | 4 ++-- pdf/mupdf-internal.h | 18 +++++++++++++++- pdf/mupdf.h | 19 +++++++++++++++++ pdf/pdf_annot.c | 17 +++++++++++++-- pdf/pdf_form.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ pdf/pdf_page.c | 2 +- pdf/pdf_xref.c | 18 ++++++++++++++++ win32/libmupdf.vcproj | 4 ++++ 11 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 pdf/pdf_form.c diff --git a/apps/pdfapp.c b/apps/pdfapp.c index 52bb4c48..939d4e58 100644 --- a/apps/pdfapp.c +++ b/apps/pdfapp.c @@ -964,6 +964,21 @@ void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int sta p = fz_transform_point(ctm, p); + if (btn == 1 && (state == 1 || state == -1)) + { + fz_ui_event event; + + event.etype = FZ_EVENT_TYPE_POINTER; + event.event.pointer.pt = p; + if (state == 1) + event.event.pointer.ptype = FZ_POINTER_DOWN; + else /* state == -1 */ + event.event.pointer.ptype = FZ_POINTER_UP; + + if (fz_pass_event(app->doc, app->page, &event)) + pdfapp_showpage(app, 1, 1, 1); + } + for (link = app->page_links; link; link = link->next) { if (p.x >= link->rect.x0 && p.x <= link->rect.x1) diff --git a/fitz/doc_document.c b/fitz/doc_document.c index 22229892..18b9d557 100644 --- a/fitz/doc_document.c +++ b/fitz/doc_document.c @@ -129,3 +129,27 @@ fz_meta(fz_document *doc, int key, void *ptr, int size) return doc->meta(doc, key, ptr, size); return FZ_META_UNKNOWN_KEY; } + +int +fz_pass_event(fz_document *doc, fz_page *page, fz_ui_event *ui_event) +{ + if (doc && doc->pass_event) + return doc->pass_event(doc, page, ui_event); + return 0; +} + +fz_rect * +fz_get_screen_update(fz_document *doc) +{ + if (doc && doc->get_screen_update, doc) + return doc->get_screen_update(doc); + return NULL; +} + +fz_widget * +fz_get_focussed_widget(fz_document *doc) +{ + if (doc && doc->get_focussed_widget) + return doc->get_focussed_widget(doc); + return NULL; +} diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 97bbfa5c..92896da0 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -829,6 +829,15 @@ fz_pixmap *fz_render_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_colorsp fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_matrix, fz_stroke_state *stroke); void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate); +/* + * Forms + */ +struct fz_widget +{ + int type; + fz_bbox bbox; +}; + /* * Text buffer. * @@ -1085,6 +1094,9 @@ struct fz_document_s void (*run_page)(fz_document *doc, fz_page *page, fz_device *dev, fz_matrix transform, fz_cookie *cookie); void (*free_page)(fz_document *doc, fz_page *page); int (*meta)(fz_document *doc, int key, void *ptr, int size); + int (*pass_event)(fz_document *doc, fz_page *page, fz_ui_event *ui_event); + fz_rect *(*get_screen_update)(fz_document *doc); + fz_widget *(*get_focussed_widget)(fz_document *doc); }; #endif diff --git a/fitz/fitz.h b/fitz/fitz.h index 5ab7b7f1..b68090cb 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -2269,7 +2269,7 @@ typedef struct fz_ui_event_s struct { int ptype; - float x, y; + fz_point pt; } pointer; } event; } fz_ui_event; @@ -2282,7 +2282,7 @@ typedef struct fz_widget_s fz_widget; /* Specific types of widget */ -typedef struct fz_widget_text_s fz_widget_test; +typedef struct fz_widget_text_s fz_widget_text; /* fz_pass_event: Pass a UI event to an interactive diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h index a66871dd..f501b916 100644 --- a/pdf/mupdf-internal.h +++ b/pdf/mupdf-internal.h @@ -156,6 +156,7 @@ struct pdf_xref_entry_s typedef struct pdf_crypt_s pdf_crypt; typedef struct pdf_ocg_descriptor_s pdf_ocg_descriptor; typedef struct pdf_ocg_entry_s pdf_ocg_entry; +typedef struct pdf_hotspot_s pdf_hotspot; struct pdf_ocg_entry_s { @@ -171,6 +172,19 @@ struct pdf_ocg_descriptor_s pdf_obj *intent; }; +enum +{ + HOTSPOT_POINTER_DOWN = 0x1, + HOTSPOT_POINTER_OVER = 0x2 +}; + +struct pdf_hotspot_s +{ + int num; + int gen; + int state; +}; + struct pdf_document_s { fz_document super; @@ -184,6 +198,7 @@ struct pdf_document_s pdf_crypt *crypt; pdf_obj *trailer; pdf_ocg_descriptor *ocg; + pdf_hotspot hotspot; int len; pdf_xref_entry *table; @@ -494,6 +509,7 @@ struct pdf_annot_s { pdf_obj *obj; fz_rect rect; + fz_rect pagerect; pdf_xobject *ap; fz_matrix matrix; pdf_annot *next; @@ -507,7 +523,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); +pdf_annot *pdf_load_annots(pdf_document *, pdf_obj *annots, fz_matrix page_ctm); void pdf_free_annot(fz_context *ctx, pdf_annot *link); /* diff --git a/pdf/mupdf.h b/pdf/mupdf.h index 07bfa12d..e257dd5a 100644 --- a/pdf/mupdf.h +++ b/pdf/mupdf.h @@ -216,4 +216,23 @@ void pdf_run_page(pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix c void pdf_run_page_with_usage(pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event, fz_cookie *cookie); +/* + pdf_pass_event: pass a UI event to a page. + + The event may activate or focus a form field. +*/ +int pdf_pass_event(pdf_document *doc, pdf_page *page, fz_ui_event *ui_event); + +/* + pdf_get_screen_update: return areas needing updating because of + appearance change. +*/ +fz_rect *pdf_get_screen_update(pdf_document *doc); + +/* + pdf_get_focussed_widget: return the currently focussed form field, + if any. +*/ +fz_widget *pdf_get_focussed_widget(pdf_document *doc); + #endif diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c index 3864c62e..5b08990f 100644 --- a/pdf/pdf_annot.c +++ b/pdf/pdf_annot.c @@ -352,7 +352,7 @@ pdf_transform_annot(pdf_annot *annot) } pdf_annot * -pdf_load_annots(pdf_document *xref, pdf_obj *annots) +pdf_load_annots(pdf_document *xref, pdf_obj *annots, fz_matrix page_ctm) { pdf_annot *annot, *head, *tail; pdf_obj *obj, *ap, *as, *n, *rect; @@ -373,7 +373,19 @@ pdf_load_annots(pdf_document *xref, pdf_obj *annots) as = pdf_dict_gets(obj, "AS"); if (pdf_is_dict(ap)) { - n = pdf_dict_gets(ap, "N"); /* normal state */ + pdf_hotspot *hp = &xref->hotspot; + + n = NULL; + + if (hp->num == pdf_to_num(obj) + && hp->gen == pdf_to_gen(obj) + && (hp->state & HOTSPOT_POINTER_DOWN)) + { + n = pdf_dict_gets(ap, "D"); /* down state */ + } + + if (n == NULL) + n = pdf_dict_gets(ap, "N"); /* normal state */ /* lookup current state in sub-dictionary */ if (!pdf_is_stream(xref, pdf_to_num(n), pdf_to_gen(n))) @@ -394,6 +406,7 @@ pdf_load_annots(pdf_document *xref, pdf_obj *annots) annot = fz_malloc_struct(ctx, pdf_annot); annot->obj = pdf_keep_obj(obj); annot->rect = pdf_to_rect(ctx, rect); + annot->pagerect = fz_transform_rect(page_ctm, annot->rect); annot->ap = form; annot->next = NULL; diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c new file mode 100644 index 00000000..ff5babeb --- /dev/null +++ b/pdf/pdf_form.c @@ -0,0 +1,59 @@ +#include "fitz-internal.h" +#include "mupdf-internal.h" + +int pdf_pass_event(pdf_document *doc, pdf_page *page, fz_ui_event *ui_event) +{ + int changed = 0; + + switch (ui_event->etype) + { + case FZ_EVENT_TYPE_POINTER: + { + pdf_hotspot *hp = &doc->hotspot; + fz_point *pt = &(ui_event->event.pointer.pt); + pdf_annot *annot; + switch (ui_event->event.pointer.ptype) + { + case FZ_POINTER_DOWN: + for (annot = page->annots; annot; annot = annot->next) + { + if (pt->x >= annot->pagerect.x0 && pt->x <= annot->pagerect.x1) + if (pt->y >= annot->pagerect.y0 && pt->y <= annot->pagerect.y1) + break; + } + + if (annot) + { + hp->num = pdf_to_num(annot->obj); + hp->gen = pdf_to_gen(annot->obj); + hp->state = HOTSPOT_POINTER_DOWN; + changed = 1; + } + break; + + case FZ_POINTER_UP: + if (hp->state != 0) + changed = 1; + + hp->num = 0; + hp->gen = 0; + hp->state = 0; + break; + } + + } + break; + } + + return changed; +} + +fz_rect *pdf_get_screen_update(pdf_document *doc) +{ + return NULL; +} + +fz_widget *pdf_get_focussed_widget(pdf_document *doc) +{ + return NULL; +} diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c index 55d7ef97..3e95e9a5 100644 --- a/pdf/pdf_page.c +++ b/pdf/pdf_page.c @@ -412,7 +412,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->annots = pdf_load_annots(xref, obj, page->ctm); } page->resources = pdf_dict_gets(pageobj, "Resources"); diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c index 30f4bd69..ea068e27 100644 --- a/pdf/pdf_xref.c +++ b/pdf/pdf_xref.c @@ -1280,6 +1280,21 @@ static int pdf_meta(fz_document *doc_, int key, void *ptr, int size) } } +static int pdf_pass_event_shim(fz_document *doc, fz_page *page, fz_ui_event *ui_event) +{ + return pdf_pass_event((pdf_document*)doc, (pdf_page*)page, ui_event); +} + +static fz_rect *pdf_get_screen_update_shim(fz_document *doc) +{ + return pdf_get_screen_update((pdf_document*)doc); +} + +static fz_widget *pdf_get_focussed_widget_shim(fz_document *doc) +{ + return pdf_get_focussed_widget((pdf_document*)doc); +} + static void pdf_init_document(pdf_document *doc) { @@ -1294,4 +1309,7 @@ pdf_init_document(pdf_document *doc) doc->super.run_page = pdf_run_page_shim; doc->super.free_page = pdf_free_page_shim; doc->super.meta = pdf_meta; + doc->super.pass_event = pdf_pass_event_shim; + doc->super.get_screen_update = pdf_get_screen_update_shim; + doc->super.get_focussed_widget = pdf_get_focussed_widget_shim; } diff --git a/win32/libmupdf.vcproj b/win32/libmupdf.vcproj index b984cc8f..ddbb9ef2 100644 --- a/win32/libmupdf.vcproj +++ b/win32/libmupdf.vcproj @@ -269,6 +269,10 @@ RelativePath="..\pdf\pdf_fontfile.c" > + + -- cgit v1.2.3