diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-05-04 21:45:41 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-05-13 11:42:00 +0200 |
commit | ae9780583c18c949bf975131a24eb8b8361ddbf6 (patch) | |
tree | 86711cd73c0f6062ccb10db405d93939bc2246fb | |
parent | b557ece715c9324d4e3cde10bda94d6ae90311cc (diff) | |
download | mupdf-ae9780583c18c949bf975131a24eb8b8361ddbf6.tar.xz |
murun: Add document writer object.
-rw-r--r-- | docs/mutool/run.html | 63 | ||||
-rw-r--r-- | source/pdf/pdf-write.c | 3 | ||||
-rw-r--r-- | source/tools/murun.c | 83 |
3 files changed, 136 insertions, 13 deletions
diff --git a/docs/mutool/run.html b/docs/mutool/run.html index ac76a7f5..5d5d73fd 100644 --- a/docs/mutool/run.html +++ b/docs/mutool/run.html @@ -465,6 +465,56 @@ but may be used to decode a down-scaled pixmap. </dl> <h2> +Document Writer +</h2> + +<p> +Document writer objects are used to create new documents in several formats. + +<dl> +<dt>new DocumentWriter(filename, format, options) +<dd>Create a new document writer to create a document with the specified format and output options. +If format is null it is inferred from the filename suffix. The options argument is a comma separated list +of flags and key-value pairs. See below for more details. +<dt>DocumentWriter#beginPage(mediabox, transform) +<dd>Begin rendering a new page. Returns a Device that can be used to render the page graphics. +The transform argument must be an empty array which is set to the transform matrix to be +used with the device functions. +<dt>DocumentWriter#endPage(device) +<dd>Finish the page rendering. +The argument must be the same device object that was returned by the beginPage method. +<dt>DocumentWriter#close() +<dd>Finish the document and flush any pending output. +</dl> + +<p> +The current output formats supported are CBZ and PDF. + +<p> +The CBZ output options are: +<dl> +<dt>resolution=N +<dd>Render each page to an image at N pixels per inch. +</dl> + +<p id="pdf-write-options"> +The PDF output options are: +<dl> +<dt>linearize<dd>optimize for web browsers. +<dt>garbage +<dd>remove unused objects. +<dt>garbage=compact<dd>Remove unused objects, and compact cross reference table. +<dt>garbage=deduplicate<dd>Remove unused objects, compact cross reference table, and remove duplicate objects. +<dt>pretty<dd>Pretty-print objects with indentation. +<dt>ascii<dd>ASCII hex encode binary streams. +<dt>compress-fonts<dd>Compress embedded fonts. +<dt>compress-images<dd>Compress images. +<dt>compress<dd>Compress all streams. +<dt>decompress<dd>Decompress all streams (except when compress-fonts or compress-images). +<dt>sanitize<dd>Clean up graphics commands in content streams. +</dl> + +<h2> PDFDocument and PDFObject </h2> @@ -483,18 +533,7 @@ using low level access to the objects and streams contained in a PDF file. <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: -<br>linearize (optimize for "web"), -<br>garbage (remove unused objects), -<br>or garbage=compact (... and compact xref table), -<br>or garbage=deduplicate (... and remove duplicate objects), -<br>pretty (pretty-print objects), -<br>ascii (ascii hex encode streams), -<br>compress-fonts (compress embedded font data), -<br>compress-images (compress image data), -<br>compress (compress all streams), -<br>decompress (decompress all streams (except fonts or images if compress-fonts/images)), -<br>sanitize (sanitize content streams). +The write options are a string of comma separated options (see the document writer <a href="#pdf-write-options">options</a>). </dl> <h3> diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c index 5154f818..ade277ce 100644 --- a/source/pdf/pdf-write.c +++ b/source/pdf/pdf-write.c @@ -3136,12 +3136,13 @@ pdf_writer_end_page(fz_context *ctx, fz_document_writer *wri_, fz_device *dev) fz_try(ctx) { - fz_drop_device(ctx, dev); + fz_close_device(ctx, dev); obj = pdf_add_page(ctx, wri->pdf, &wri->mediabox, 0, wri->resources, wri->contents); pdf_insert_page(ctx, wri->pdf, -1, obj); } fz_always(ctx) { + fz_drop_device(ctx, dev); pdf_drop_obj(ctx, obj); fz_drop_buffer(ctx, wri->contents); wri->contents = NULL; diff --git a/source/tools/murun.c b/source/tools/murun.c index 9b52558f..acaa9850 100644 --- a/source/tools/murun.c +++ b/source/tools/murun.c @@ -258,6 +258,12 @@ static void ffi_gc_fz_device(js_State *J, void *device) fz_drop_device(ctx, device); } +static void ffi_gc_fz_document_writer(js_State *J, void *wri) +{ + fz_context *ctx = js_getcontext(J); + fz_drop_document_writer(ctx, wri); +} + /* type conversions */ struct color { @@ -289,6 +295,16 @@ static void ffi_pushmatrix(js_State *J, fz_matrix matrix) js_pushnumber(J, matrix.f); js_setindex(J, -2, 5); } +static void ffi_setmatrix(js_State *J, int idx, fz_matrix matrix) +{ + js_pushnumber(J, matrix.a); js_setindex(J, idx, 0); + js_pushnumber(J, matrix.b); js_setindex(J, idx, 1); + js_pushnumber(J, matrix.c); js_setindex(J, idx, 2); + js_pushnumber(J, matrix.d); js_setindex(J, idx, 3); + js_pushnumber(J, matrix.e); js_setindex(J, idx, 4); + js_pushnumber(J, matrix.f); js_setindex(J, idx, 5); +} + static fz_rect ffi_torect(js_State *J, int idx) { fz_rect rect; @@ -2269,6 +2285,64 @@ static void ffi_new_DrawDevice(js_State *J) js_newuserdata(J, "fz_device", device, ffi_gc_fz_device); } +static void ffi_new_DocumentWriter(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + const char *filename = js_tostring(J, 1); + const char *format = js_iscoercible(J, 2) ? js_tostring(J, 2) : NULL; + const char *options = js_iscoercible(J, 3) ? js_tostring(J, 3) : NULL; + fz_document_writer *wri; + + fz_try(ctx) + wri = fz_new_document_writer(ctx, filename, format, options); + fz_catch(ctx) + rethrow(J); + + js_getregistry(J, "fz_document_writer"); + js_newuserdata(J, "fz_document_writer", wri, ffi_gc_fz_document_writer); +} + +static void ffi_DocumentWriter_beginPage(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer"); + fz_rect mediabox = ffi_torect(J, 1); + fz_matrix ctm = fz_identity; + fz_device *device; + + fz_try(ctx) + device = fz_begin_page(ctx, wri, &mediabox, &ctm); + fz_catch(ctx) + rethrow(J); + + ffi_setmatrix(J, 2, ctm); + + js_getregistry(J, "fz_device"); + js_newuserdata(J, "fz_device", fz_keep_device(ctx, device), ffi_gc_fz_device); +} + +static void ffi_DocumentWriter_endPage(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer"); + fz_device *device = js_touserdata(J, 1, "fz_device"); + fz_try(ctx) + fz_end_page(ctx, wri, device); + fz_catch(ctx) + rethrow(J); +} + + +static void ffi_DocumentWriter_close(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer"); + fz_try(ctx) + fz_close_document_writer(ctx, wri); + fz_catch(ctx) + rethrow(J); +} + /* PDF specifics */ static void ffi_new_PDFDocument(js_State *J) @@ -3110,6 +3184,14 @@ int murun_main(int argc, char **argv) js_newobject(J); { + jsB_propfun(J, "DocumentWriter.beginPage", ffi_DocumentWriter_beginPage, 2); + jsB_propfun(J, "DocumentWriter.endPage", ffi_DocumentWriter_endPage, 1); + jsB_propfun(J, "DocumentWriter.close", ffi_DocumentWriter_close, 1); + } + js_setregistry(J, "fz_document_writer"); + + js_newobject(J); + { jsB_propfun(J, "PDFDocument.toDocument", ffi_PDFDocument_toDocument, 0); jsB_propfun(J, "PDFDocument.getTrailer", ffi_PDFDocument_getTrailer, 0); @@ -3176,6 +3258,7 @@ int murun_main(int argc, char **argv) jsB_propcon(J, "fz_display_list", "DisplayList", ffi_new_DisplayList, 0); jsB_propcon(J, "fz_device", "DrawDevice", ffi_new_DrawDevice, 1); jsB_propcon(J, "fz_device", "DisplayListDevice", ffi_new_DisplayListDevice, 1); + jsB_propcon(J, "fz_document_writer", "DocumentWriter", ffi_new_DocumentWriter, 3); jsB_propfun(J, "readFile", ffi_readFile, 1); |