diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-09-22 15:48:36 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-10-07 17:22:58 +0200 |
commit | 170f35a5802ec7093b00fb2e39bbde3756516f15 (patch) | |
tree | 62b18cfc1c5fca5b28cc7e65ea488aac7ae190a3 | |
parent | 7dc527887927cb0f3b2e41ccc2913ff57d3d820d (diff) | |
download | mupdf-170f35a5802ec7093b00fb2e39bbde3756516f15.tar.xz |
js: Make PDFDocument, PDFPage, and PDFAnnotation subclasses.
Add isPDF methods to query availability of PDF specific methods.
-rw-r--r-- | docs/mutool/run.html | 14 | ||||
-rw-r--r-- | source/tools/murun.c | 227 |
2 files changed, 175 insertions, 66 deletions
diff --git a/docs/mutool/run.html b/docs/mutool/run.html index 2eb4be0a..a0401595 100644 --- a/docs/mutool/run.html +++ b/docs/mutool/run.html @@ -170,8 +170,6 @@ MuPDF can open many document types (PDF, XPS, CBZ, EPUB, FB2 and a handful of im <dd>Returns true if the password matches. <dt>Document#getMetaData(key) <dd>Return various meta data information. The common keys are: "format", "encryption", "info:Author", and "info:Title". -<dt>Document#toPDF() -<dd>Returns a PDFDocument (see below) or null if the document is not a PDF. <dt>Document#layout(pageWidth, pageHeight, fontSize) <dd>Layout a reflowable document (EPUB, FB2, or XHTML) to fit the specified page and font size. <dt>Document#countPages() @@ -182,6 +180,8 @@ MuPDF can open many document types (PDF, XPS, CBZ, EPUB, FB2 and a handful of im <dd>Returns an array with the outline (table of contents). In the array is an object for each heading with the property 'title', and a property 'page' containing the page number. If the object has a 'down' property, it contains an array with all the sub-headings for that entry. +<dt>Document#isPDF() +<dd>Returns true if the document is a PDF document. </dl> <dl> @@ -207,8 +207,8 @@ If alpha is true, the page will be drawn on a transparent background, otherwise <dd>Return an array of all the links on the page. Each link is an object with a 'bounds' property, and either a 'page' or 'uri' property, depending on whether it's an internal or external link. -<dt>Page#toPDF() -<dd>Returns the PDFObject/PDFPage for the page, if the document is a PDF file. +<dt>Page#isPDF() +<dd>Returns true if the page is from a PDF document. </dl> <dl> @@ -590,16 +590,14 @@ PDFDocument and PDFObject <p> With MuPDF it is also possible to create, edit and manipulate PDF documents using low level access to the objects and streams contained in a PDF file. +A PDFDocument object is also a Document object. You can test a Document object +to see if it is safe to use as a PDFDocument by calling document.isPDF(). <dl> <dt>new PDFDocument() <dd>Create a new empty PDF document. <dt>new PDFDocument(fileName) <dd>Load a PDF document from file. -<dt>Document#toPDF() -<dd>Get access to the raw PDFDocument from a Document; returns null if the document is not a PDF. -<dt>PDFDocument#toDocument() -<dd>Cast the PDF document to a Document. <dt>PDFDocument#save(fileName, options) <dd>Write the PDF document to file. The write options are a string of comma separated options (see the document writer <a href="#pdf-write-options">options</a>). diff --git a/source/tools/murun.c b/source/tools/murun.c index 3bb290fc..d5659304 100644 --- a/source/tools/murun.c +++ b/source/tools/murun.c @@ -290,6 +290,123 @@ static void ffi_gc_pdf_graft_map(js_State *J, void *map) pdf_drop_graft_map(ctx, map); } +static fz_document *ffi_todocument(js_State *J, int idx) +{ + if (js_isuserdata(J, idx, "pdf_document")) + return js_touserdata(J, idx, "pdf_document"); + return js_touserdata(J, idx, "fz_document"); +} + +static void ffi_pushdocument(js_State *J, fz_document *document) +{ + fz_context *ctx = js_getcontext(J); + pdf_document *pdocument = pdf_document_from_fz_document(ctx, document); + if (pdocument) { + js_getregistry(J, "pdf_document"); + js_newuserdata(J, "pdf_document", document, ffi_gc_fz_document); + } else { + js_getregistry(J, "fz_document"); + js_newuserdata(J, "fz_document", document, ffi_gc_fz_document); + } +} + +static fz_page *ffi_topage(js_State *J, int idx) +{ + if (js_isuserdata(J, idx, "pdf_page")) + return js_touserdata(J, idx, "pdf_page"); + return js_touserdata(J, idx, "fz_page"); +} + +static void ffi_pushpage(js_State *J, fz_page *page) +{ + fz_context *ctx = js_getcontext(J); + pdf_page *ppage = pdf_page_from_fz_page(ctx, page); + if (ppage) { + js_getregistry(J, "pdf_page"); + js_newuserdata(J, "pdf_page", page, ffi_gc_fz_page); + } else { + js_getregistry(J, "fz_page"); + js_newuserdata(J, "fz_page", page, ffi_gc_fz_page); + } +} + +static fz_annot *ffi_toannot(js_State *J, int idx) +{ + if (js_isuserdata(J, idx, "pdf_annot")) + return js_touserdata(J, idx, "pdf_annot"); + return js_touserdata(J, idx, "fz_annot"); +} + +static void ffi_pushannot(js_State *J, fz_annot *annot) +{ + fz_context *ctx = js_getcontext(J); + pdf_annot *pannot = pdf_annot_from_fz_annot(ctx, annot); + if (pannot) { + int subtype; + fz_try(ctx) + subtype = pdf_annot_type(ctx, pannot); + fz_catch(ctx) + rethrow(J); + switch (subtype) { + default: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_TEXT: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_LINK: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_FREE_TEXT: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_LINE: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_SQUARE: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_CIRCLE: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_POLYGON: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_POLY_LINE: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_HIGHLIGHT: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_UNDERLINE: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_SQUIGGLY: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_STRIKE_OUT: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_STAMP: js_getregistry(J, "pdf_annot"); break; + case PDF_ANNOT_INK: js_getregistry(J, "pdf_annot"); break; + } + js_newuserdata(J, "pdf_annot", fz_keep_annot(ctx, annot), ffi_gc_fz_annot); + } else { + js_getregistry(J, "fz_annot"); + js_newuserdata(J, "fz_annot", fz_keep_annot(ctx, annot), ffi_gc_fz_annot); + } +} + +#else + +static fz_document *ffi_todocument(js_State *J, int idx) +{ + return js_touserdata(J, idx, "fz_document"); +} + +static void ffi_pushdocument(js_State *J, fz_document *document) +{ + js_getregistry(J, "fz_document"); + js_newuserdata(J, "fz_document", doc, ffi_gc_fz_document); +} + +static fz_page *ffi_topage(js_State *J, int idx) +{ + return js_touserdata(J, idx, "fz_page"); +} + +static void ffi_pushpage(js_State *J, fz_page *page) +{ + js_getregistry(J, "fz_page"); + js_newuserdata(J, "fz_page", page, ffi_gc_fz_page); +} + +static fz_annot *ffi_toannot(js_State *J, int idx) +{ + return js_touserdata(J, idx, "fz_annot"); +} + +static void ffi_pushannot(js_State *J, fz_annot *annot) +{ + fz_context *ctx = js_getcontext(J); + js_getregistry(J, "fz_annot"); + js_newuserdata(J, "fz_annot", fz_keep_annot(ctx, annot), ffi_gc_fz_annot); +} + #endif /* FZ_ENABLE_PDF */ /* type conversions */ @@ -1362,14 +1479,18 @@ static void ffi_new_Document(js_State *J) fz_catch(ctx) rethrow(J); - js_getregistry(J, "fz_document"); - js_newuserdata(J, "fz_document", doc, ffi_gc_fz_document); + ffi_pushdocument(J, doc); +} + +static void ffi_Document_isPDF(js_State *J) +{ + js_pushboolean(J, js_isuserdata(J, 0, "pdf_document")); } static void ffi_Document_countPages(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_document *doc = js_touserdata(J, 0, "fz_document"); + fz_document *doc = ffi_todocument(J, 0); int count; fz_try(ctx) @@ -1383,7 +1504,7 @@ static void ffi_Document_countPages(js_State *J) static void ffi_Document_loadPage(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_document *doc = js_touserdata(J, 0, "fz_document"); + fz_document *doc = ffi_todocument(J, 0); int number = js_tointeger(J, 1); fz_page *page; @@ -1392,14 +1513,13 @@ static void ffi_Document_loadPage(js_State *J) fz_catch(ctx) rethrow(J); - js_getregistry(J, "fz_page"); - js_newuserdata(J, "fz_page", page, ffi_gc_fz_page); + ffi_pushpage(J, page); } static void ffi_Document_needsPassword(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_document *doc = js_touserdata(J, 0, "fz_document"); + fz_document *doc = ffi_todocument(J, 0); int b; fz_try(ctx) @@ -1413,7 +1533,7 @@ static void ffi_Document_needsPassword(js_State *J) static void ffi_Document_authenticatePassword(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_document *doc = js_touserdata(J, 0, "fz_document"); + fz_document *doc = ffi_todocument(J, 0); const char *password = js_tostring(J, 1); int b; @@ -1427,7 +1547,7 @@ static void ffi_Document_authenticatePassword(js_State *J) static void ffi_Document_getMetaData(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_document *doc = js_touserdata(J, 0, "fz_document"); + fz_document *doc = ffi_todocument(J, 0); const char *key = js_tostring(J, 1); char info[256]; @@ -1442,7 +1562,7 @@ static void ffi_Document_getMetaData(js_State *J) static void ffi_Document_isReflowable(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_document *doc = js_touserdata(J, 0, "fz_document"); + fz_document *doc = ffi_todocument(J, 0); int is_reflowable; fz_try(ctx) @@ -1456,7 +1576,7 @@ static void ffi_Document_isReflowable(js_State *J) static void ffi_Document_layout(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_document *doc = js_touserdata(J, 0, "fz_document"); + fz_document *doc = ffi_todocument(J, 0); float w = js_tonumber(J, 1); float h = js_tonumber(J, 2); float em = js_tonumber(J, 3); @@ -1502,7 +1622,7 @@ static void to_outline(js_State *J, fz_outline *outline) static void ffi_Document_loadOutline(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_document *doc = js_touserdata(J, 0, "fz_document"); + fz_document *doc = ffi_todocument(J, 0); fz_outline *outline; fz_try(ctx) @@ -1515,33 +1635,15 @@ static void ffi_Document_loadOutline(js_State *J) fz_drop_outline(ctx, outline); } -static void ffi_Document_toPDF(js_State *J) +static void ffi_Page_isPDF(js_State *J) { -#if FZ_ENABLE_PDF - fz_context *ctx = js_getcontext(J); - fz_document *doc = js_touserdata(J, 0, "fz_document"); - pdf_document *pdf; - - fz_try(ctx) - pdf = pdf_specifics(ctx, doc); - fz_catch(ctx) - rethrow(J); - - if (pdf) { - js_getregistry(J, "pdf_document"); - js_newuserdata(J, "pdf_document", fz_keep_document(ctx, (fz_document*)pdf), ffi_gc_pdf_document); - } else { - js_pushnull(J); - } -#else - js_pushnull(J); -#endif + js_pushboolean(J, js_isuserdata(J, 0, "pdf_page")); } static void ffi_Page_bound(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_page *page = ffi_topage(J, 0); fz_rect bounds; fz_try(ctx) @@ -1555,7 +1657,7 @@ static void ffi_Page_bound(js_State *J) static void ffi_Page_run(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_page *page = ffi_topage(J, 0); fz_device *device = NULL; fz_matrix ctm = ffi_tomatrix(J, 2); int no_annots = js_isdefined(J, 3) ? js_toboolean(J, 3) : 0; @@ -1589,7 +1691,7 @@ static void ffi_Page_run(js_State *J) static void ffi_Page_toDisplayList(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_page *page = ffi_topage(J, 0); int no_annots = js_isdefined(J, 1) ? js_toboolean(J, 1) : 0; fz_display_list *list; @@ -1608,7 +1710,7 @@ static void ffi_Page_toDisplayList(js_State *J) static void ffi_Page_toPixmap(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_page *page = ffi_topage(J, 0); fz_matrix ctm = ffi_tomatrix(J, 1); fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace"); int alpha = js_toboolean(J, 3); @@ -1630,7 +1732,7 @@ static void ffi_Page_toPixmap(js_State *J) static void ffi_Page_toStructuredText(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_page *page = ffi_topage(J, 0); int options = js_tointeger(J, 1); fz_stext_sheet *sheet = NULL; fz_stext_page *text; @@ -1653,7 +1755,7 @@ static void ffi_Page_toStructuredText(js_State *J) static void ffi_Page_search(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_page *page = ffi_topage(J, 0); const char *needle = js_tostring(J, 1); fz_rect hits[256]; int i, n; @@ -1673,7 +1775,7 @@ static void ffi_Page_search(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_page *page = ffi_topage(J, 0); fz_annot *annot; int i = 0; @@ -1685,8 +1787,7 @@ static void ffi_Page_getAnnotations(js_State *J) rethrow(J); while (annot) { - js_getregistry(J, "fz_annot"); - js_newuserdata(J, "fz_annot", fz_keep_annot(ctx, annot), ffi_gc_fz_annot); + ffi_pushannot(J, annot); js_setindex(J, -2, i++); fz_try(ctx) @@ -1699,7 +1800,7 @@ static void ffi_Page_getAnnotations(js_State *J) static void ffi_Page_getLinks(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_page *page = js_touserdata(J, 0, "fz_page"); + fz_page *page = ffi_topage(J, 0); fz_link *link, *n; int i = 0; @@ -1732,10 +1833,15 @@ static void ffi_Page_getLinks(js_State *J) fz_drop_link(ctx, link); } +static void ffi_Annotation_isPDF(js_State *J) +{ + js_pushboolean(J, js_isuserdata(J, 0, "pdf_annot")); +} + static void ffi_Annotation_bound(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_annot *annot = js_touserdata(J, 0, "fz_annot"); + fz_annot *annot = ffi_toannot(J, 0); fz_rect bounds; fz_try(ctx) @@ -1749,7 +1855,7 @@ static void ffi_Annotation_bound(js_State *J) static void ffi_Annotation_run(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_annot *annot = js_touserdata(J, 0, "fz_annot"); + fz_annot *annot = ffi_toannot(J, 0); fz_device *device = NULL; fz_matrix ctm = ffi_tomatrix(J, 2); @@ -1776,7 +1882,7 @@ static void ffi_Annotation_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_annot *annot = ffi_toannot(J, 0); fz_display_list *list; fz_try(ctx) @@ -1791,7 +1897,7 @@ static void ffi_Annotation_toDisplayList(js_State *J) static void ffi_Annotation_toPixmap(js_State *J) { fz_context *ctx = js_getcontext(J); - fz_annot *annot = js_touserdata(J, 0, "fz_annot"); + fz_annot *annot = ffi_toannot(J, 0); fz_matrix ctm = ffi_tomatrix(J, 1); fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace"); int alpha = js_toboolean(J, 3); @@ -2872,14 +2978,6 @@ static void ffi_new_PDFDocument(js_State *J) js_newuserdata(J, "pdf_document", pdf, ffi_gc_pdf_document); } -static void ffi_PDFDocument_toDocument(js_State *J) -{ - fz_context *ctx = js_getcontext(J); - pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); - js_getregistry(J, "fz_document"); - js_newuserdata(J, "fz_document", fz_keep_document(ctx, (fz_document*)pdf), ffi_gc_fz_document); -} - static void ffi_PDFDocument_getTrailer(js_State *J) { fz_context *ctx = js_getcontext(J); @@ -3571,7 +3669,7 @@ int murun_main(int argc, char **argv) js_newobject(J); { - jsB_propfun(J, "Document.toPDF", ffi_Document_toPDF, 0); + jsB_propfun(J, "Document.isPDF", ffi_Document_isPDF, 0); jsB_propfun(J, "Document.needsPassword", ffi_Document_needsPassword, 0); jsB_propfun(J, "Document.authenticatePassword", ffi_Document_authenticatePassword, 1); //jsB_propfun(J, "Document.hasPermission", ffi_Document_hasPermission, 1); @@ -3586,6 +3684,7 @@ int murun_main(int argc, char **argv) js_newobject(J); { + jsB_propfun(J, "Page.isPDF", ffi_Page_isPDF, 0); jsB_propfun(J, "Page.bound", ffi_Page_bound, 0); jsB_propfun(J, "Page.run", ffi_Page_run, 3); jsB_propfun(J, "Page.toPixmap", ffi_Page_toPixmap, 4); @@ -3599,6 +3698,7 @@ int murun_main(int argc, char **argv) js_newobject(J); { + jsB_propfun(J, "Annotation.isPDF", ffi_Annotation_isPDF, 0); 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); @@ -3770,10 +3870,9 @@ int murun_main(int argc, char **argv) js_setregistry(J, "fz_document_writer"); #if FZ_ENABLE_PDF - js_newobject(J); + js_getregistry(J, "fz_document"); + js_newobjectx(J); { - jsB_propfun(J, "PDFDocument.toDocument", ffi_PDFDocument_toDocument, 0); - jsB_propfun(J, "PDFDocument.getTrailer", ffi_PDFDocument_getTrailer, 0); jsB_propfun(J, "PDFDocument.countObjects", ffi_PDFDocument_countObjects, 0); jsB_propfun(J, "PDFDocument.createObject", ffi_PDFDocument_createObject, 0); @@ -3805,6 +3904,18 @@ int murun_main(int argc, char **argv) } js_setregistry(J, "pdf_document"); + js_getregistry(J, "fz_page"); + js_newobjectx(J); + { + } + js_setregistry(J, "pdf_page"); + + js_getregistry(J, "fz_annot"); + js_newobjectx(J); + { + } + js_setregistry(J, "pdf_annot"); + js_newobject(J); { jsB_propfun(J, "PDFObject.get", ffi_PDFObject_get, 0); |