summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-07-04 13:38:18 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-07-06 15:45:40 +0200
commit4d13ba9adbe46fc84fea662b906347bfa90ce208 (patch)
tree3cb349e60b97ced79c37fed937787f4a4dc6ab4e
parent7a8be5d456254c6edbf1009a87281c1c963f951a (diff)
downloadmupdf-4d13ba9adbe46fc84fea662b906347bfa90ce208.tar.xz
Add annotations to murun.
-rw-r--r--docs/mutool/run.html20
-rw-r--r--include/mupdf/fitz/util.h8
-rw-r--r--source/fitz/util.c54
-rw-r--r--source/tools/murun.c166
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);