diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-07-04 13:38:18 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-07-06 15:45:40 +0200 |
commit | 4d13ba9adbe46fc84fea662b906347bfa90ce208 (patch) | |
tree | 3cb349e60b97ced79c37fed937787f4a4dc6ab4e | |
parent | 7a8be5d456254c6edbf1009a87281c1c963f951a (diff) | |
download | mupdf-4d13ba9adbe46fc84fea662b906347bfa90ce208.tar.xz |
Add annotations to murun.
-rw-r--r-- | docs/mutool/run.html | 20 | ||||
-rw-r--r-- | include/mupdf/fitz/util.h | 8 | ||||
-rw-r--r-- | source/fitz/util.c | 54 | ||||
-rw-r--r-- | source/tools/murun.c | 166 |
4 files changed, 224 insertions, 24 deletions
diff --git a/docs/mutool/run.html b/docs/mutool/run.html index ed1a9707..19433681 100644 --- a/docs/mutool/run.html +++ b/docs/mutool/run.html @@ -183,17 +183,31 @@ MuPDF can open many document types (PDF, XPS, CBZ, EPUB, FB2 and a handful of im <dl> <dt>Page#bound() <dd>Returns a rectangle containing the page dimensions. -<dt>Page#run(device, transform) +<dt>Page#run(device, transform, skipAnnotations) <dd>Calls device functions for all the contents on the page, using the specified transform matrix. The device can be one of the built-in devices or a JavaScript object with methods for the device calls. The transform maps from user space points to device space pixels. -<dt>Page#toPixmap(transform, colorspace, alpha) +If skipAnnotations is true, ignore annotations. +<dt>Page#toPixmap(transform, colorspace, alpha, skipAnnotations) <dd>Render the page into a Pixmap, using the transform and colorspace. If alpha is true, the page will be drawn on a transparent background, otherwise white. -<dt>Page#toDisplayList() +<dt>Page#toDisplayList(skipAnnotations) <dd>Record the contents on the page into a DisplayList. <dt>Page#search(needle) <dd>Search for 'needle' text on the page, and return an array with rectangles of all matches found. +<dt>Page#getAnnotations() +<dd>Return array of all annotations on the page. +</dl> + +<dl> +<dt>Annotation#bound() +<dd>Returns a rectangle containing the location and dimension of the annotation. +<dt>Annotation#run(device, transform) +<dd>Calls device functions to draw the annotation. +<dt>Annotation#toPixmap(transform, colorspace, alpha) +<dd>Render the annotation into a Pixmap, using the transform and colorspace. +<dt>Annotation#toDisplayList() +<dd>Record the contents of the annotation into a DisplayList. </dl> <h2> diff --git a/include/mupdf/fitz/util.h b/include/mupdf/fitz/util.h index a4413665..9f982699 100644 --- a/include/mupdf/fitz/util.h +++ b/include/mupdf/fitz/util.h @@ -14,13 +14,15 @@ */ fz_display_list *fz_new_display_list_from_page(fz_context *ctx, fz_page *page); fz_display_list *fz_new_display_list_from_page_number(fz_context *ctx, fz_document *doc, int number); +fz_display_list *fz_new_display_list_from_page_contents(fz_context *ctx, fz_page *page); +fz_display_list *fz_new_display_list_from_annot(fz_context *ctx, fz_annot *annot); /* fz_new_pixmap_from_page: Render the page to a pixmap using the transform and colorspace. */ +fz_pixmap *fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int alpha); fz_pixmap *fz_new_pixmap_from_page(fz_context *ctx, fz_page *page, const fz_matrix *ctm, fz_colorspace *cs, int alpha); fz_pixmap *fz_new_pixmap_from_page_number(fz_context *ctx, fz_document *doc, int number, const fz_matrix *ctm, fz_colorspace *cs, int alpha); -fz_pixmap *fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int alpha); /* fz_new_pixmap_from_page_contents: Render the page contents without annotations. @@ -28,8 +30,8 @@ fz_pixmap *fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *lis fz_pixmap *fz_new_pixmap_from_page_contents(fz_context *ctx, fz_page *page, const fz_matrix *ctm, fz_colorspace *cs, int alpha); /* - fz_new_pixmap_from_annot: Render an annotation. - suitable for blending on top of the opaque pixmap returned by fz_new_pixmap_from_page_contents. + fz_new_pixmap_from_annot: Render an annotation suitable for blending on top of the opaque + pixmap returned by fz_new_pixmap_from_page_contents. */ fz_pixmap *fz_new_pixmap_from_annot(fz_context *ctx, fz_annot *annot, const fz_matrix *ctm, fz_colorspace *cs, int alpha); diff --git a/source/fitz/util.c b/source/fitz/util.c index e1e17c25..f76e496a 100644 --- a/source/fitz/util.c +++ b/source/fitz/util.c @@ -43,6 +43,60 @@ fz_new_display_list_from_page_number(fz_context *ctx, fz_document *doc, int numb return list; } +fz_display_list * +fz_new_display_list_from_page_contents(fz_context *ctx, fz_page *page) +{ + fz_display_list *list; + fz_rect bounds; + fz_device *dev; + + list = fz_new_display_list(ctx, fz_bound_page(ctx, page, &bounds)); + + fz_try(ctx) + { + dev = fz_new_list_device(ctx, list); + fz_run_page_contents(ctx, page, dev, &fz_identity, NULL); + } + fz_always(ctx) + { + fz_drop_device(ctx, dev); + } + fz_catch(ctx) + { + fz_drop_display_list(ctx, list); + fz_rethrow(ctx); + } + + return list; +} + +fz_display_list * +fz_new_display_list_from_annot(fz_context *ctx, fz_annot *annot) +{ + fz_display_list *list; + fz_rect bounds; + fz_device *dev; + + list = fz_new_display_list(ctx, fz_bound_annot(ctx, annot, &bounds)); + + fz_try(ctx) + { + dev = fz_new_list_device(ctx, list); + fz_run_annot(ctx, annot, dev, &fz_identity, NULL); + } + fz_always(ctx) + { + fz_drop_device(ctx, dev); + } + fz_catch(ctx) + { + fz_drop_display_list(ctx, list); + fz_rethrow(ctx); + } + + return list; +} + fz_pixmap * fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int alpha) { diff --git a/source/tools/murun.c b/source/tools/murun.c index c3b01cda..8a892372 100644 --- a/source/tools/murun.c +++ b/source/tools/murun.c @@ -193,6 +193,12 @@ static void ffi_gc_fz_page(js_State *J, void *page) fz_drop_page(ctx, page); } +static void ffi_gc_fz_annot(js_State *J, void *annot) +{ + fz_context *ctx = js_getcontext(J); + fz_drop_annot(ctx, annot); +} + static void ffi_gc_fz_colorspace(js_State *J, void *colorspace) { fz_context *ctx = js_getcontext(J); @@ -1451,32 +1457,64 @@ static void ffi_Document_toPDF(js_State *J) #endif } -static void ffi_Page_toPixmap(js_State *J) +static void ffi_Page_bound(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = js_touserdata(J, 0, "fz_page"); - fz_matrix ctm = ffi_tomatrix(J, 1); - fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace"); - int alpha = js_toboolean(J, 3); - fz_pixmap *pixmap; + fz_rect bounds; fz_try(ctx) - pixmap = fz_new_pixmap_from_page(ctx, page, &ctm, colorspace, alpha); + fz_bound_page(ctx, page, &bounds); fz_catch(ctx) rethrow(J); - js_getregistry(J, "fz_pixmap"); - js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap); + ffi_pushrect(J, bounds); +} + +static void ffi_Page_run(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_device *device = NULL; + fz_matrix ctm = ffi_tomatrix(J, 2); + int no_annots = js_toboolean(J, 3); + + if (js_isuserdata(J, 1, "fz_device")) { + device = js_touserdata(J, 1, "fz_device"); + fz_try(ctx) + if (no_annots) + fz_run_page_contents(ctx, page, device, &ctm, NULL); + else + fz_run_page(ctx, page, device, &ctm, NULL); + fz_catch(ctx) + rethrow(J); + } else { + device = new_js_device(ctx, J); + js_copy(J, 1); /* put the js device on the top so the callbacks know where to get it */ + fz_try(ctx) + if (no_annots) + fz_run_page_contents(ctx, page, device, &ctm, NULL); + else + fz_run_page(ctx, page, device, &ctm, NULL); + fz_always(ctx) + fz_drop_device(ctx, device); + fz_catch(ctx) + rethrow(J); + } } static void ffi_Page_toDisplayList(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = js_touserdata(J, 0, "fz_page"); + int no_annots = js_toboolean(J, 1); fz_display_list *list; fz_try(ctx) - list = fz_new_display_list_from_page(ctx, page); + if (no_annots) + list = fz_new_display_list_from_page_contents(ctx, page); + else + list = fz_new_display_list_from_page(ctx, page); fz_catch(ctx) rethrow(J); @@ -1484,6 +1522,28 @@ static void ffi_Page_toDisplayList(js_State *J) js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list); } +static void ffi_Page_toPixmap(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_matrix ctm = ffi_tomatrix(J, 1); + fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace"); + int alpha = js_toboolean(J, 3); + int no_annots = js_toboolean(J, 4); + fz_pixmap *pixmap; + + fz_try(ctx) + if (no_annots) + pixmap = fz_new_pixmap_from_page_contents(ctx, page, &ctm, colorspace, alpha); + else + pixmap = fz_new_pixmap_from_page(ctx, page, &ctm, colorspace, alpha); + fz_catch(ctx) + rethrow(J); + + js_getregistry(J, "fz_pixmap"); + js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap); +} + static void ffi_Page_search(js_State *J) { fz_context *ctx = js_getcontext(J); @@ -1504,38 +1564,65 @@ static void ffi_Page_search(js_State *J) } } -static void ffi_Page_bound(js_State *J) +static void ffi_Page_getAnnotations(js_State *J) { fz_context *ctx = js_getcontext(J); fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_annot *annot; + int i = 0; + + js_newarray(J); + + fz_try(ctx) + annot = fz_first_annot(ctx, page); + fz_catch(ctx) + rethrow(J); + + while (annot) + { + js_getregistry(J, "fz_annot"); + js_newuserdata(J, "fz_annot", fz_keep_annot(ctx, annot), ffi_gc_fz_annot); + js_setindex(J, -2, i++); + + fz_try(ctx) + annot = fz_next_annot(ctx, annot); + fz_catch(ctx) + rethrow(J); + } +} + +static void ffi_Annotation_bound(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + fz_annot *annot = js_touserdata(J, 0, "fz_annot"); fz_rect bounds; fz_try(ctx) - fz_bound_page(ctx, page, &bounds); + fz_bound_annot(ctx, annot, &bounds); fz_catch(ctx) rethrow(J); ffi_pushrect(J, bounds); } -static void ffi_Page_run(js_State *J) +static void ffi_Annotation_run(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_annot *annot = js_touserdata(J, 0, "fz_annot"); fz_device *device = NULL; fz_matrix ctm = ffi_tomatrix(J, 2); if (js_isuserdata(J, 1, "fz_device")) { device = js_touserdata(J, 1, "fz_device"); fz_try(ctx) - fz_run_page(ctx, page, device, &ctm, NULL); + fz_run_annot(ctx, annot, device, &ctm, NULL); fz_catch(ctx) rethrow(J); } else { device = new_js_device(ctx, J); js_copy(J, 1); /* put the js device on the top so the callbacks know where to get it */ fz_try(ctx) - fz_run_page(ctx, page, device, &ctm, NULL); + fz_run_annot(ctx, annot, device, &ctm, NULL); fz_always(ctx) fz_drop_device(ctx, device); fz_catch(ctx) @@ -1543,6 +1630,39 @@ static void ffi_Page_run(js_State *J) } } +static void ffi_Annotation_toDisplayList(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + fz_annot *annot = js_touserdata(J, 0, "fz_annot"); + fz_display_list *list; + + fz_try(ctx) + list = fz_new_display_list_from_annot(ctx, annot); + fz_catch(ctx) + rethrow(J); + + js_getregistry(J, "fz_display_list"); + js_newuserdata(J, "fz_display_list", list, ffi_gc_fz_display_list); +} + +static void ffi_Annotation_toPixmap(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + fz_annot *annot = js_touserdata(J, 0, "fz_annot"); + fz_matrix ctm = ffi_tomatrix(J, 1); + fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace"); + int alpha = js_toboolean(J, 3); + fz_pixmap *pixmap; + + fz_try(ctx) + pixmap = fz_new_pixmap_from_annot(ctx, annot, &ctm, colorspace, alpha); + fz_catch(ctx) + rethrow(J); + + js_getregistry(J, "fz_pixmap"); + js_newuserdata(J, "fz_pixmap", pixmap, ffi_gc_fz_pixmap); +} + static void ffi_ColorSpace_getNumberOfComponents(js_State *J) { fz_colorspace *colorspace = js_touserdata(J, 0, "fz_colorspace"); @@ -3100,15 +3220,25 @@ int murun_main(int argc, char **argv) js_newobject(J); { jsB_propfun(J, "Page.bound", ffi_Page_bound, 0); - jsB_propfun(J, "Page.run", ffi_Page_run, 2); - jsB_propfun(J, "Page.toPixmap", ffi_Page_toPixmap, 3); - jsB_propfun(J, "Page.toDisplayList", ffi_Page_toDisplayList, 0); + jsB_propfun(J, "Page.run", ffi_Page_run, 3); + jsB_propfun(J, "Page.toPixmap", ffi_Page_toPixmap, 4); + jsB_propfun(J, "Page.toDisplayList", ffi_Page_toDisplayList, 1); jsB_propfun(J, "Page.search", ffi_Page_search, 0); + jsB_propfun(J, "Page.getAnnotations", ffi_Page_getAnnotations, 0); } js_setregistry(J, "fz_page"); js_newobject(J); { + jsB_propfun(J, "Annotation.bound", ffi_Annotation_bound, 0); + jsB_propfun(J, "Annotation.run", ffi_Annotation_run, 2); + jsB_propfun(J, "Annotation.toPixmap", ffi_Annotation_toPixmap, 3); + jsB_propfun(J, "Annotation.toDisplayList", ffi_Annotation_toDisplayList, 0); + } + js_setregistry(J, "fz_annot"); + + js_newobject(J); + { jsB_propfun(J, "Device.close", ffi_Device_close, 0); jsB_propfun(J, "Device.fillPath", ffi_Device_fillPath, 6); |