summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-05-04 21:45:41 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-05-13 11:42:00 +0200
commitae9780583c18c949bf975131a24eb8b8361ddbf6 (patch)
tree86711cd73c0f6062ccb10db405d93939bc2246fb
parentb557ece715c9324d4e3cde10bda94d6ae90311cc (diff)
downloadmupdf-ae9780583c18c949bf975131a24eb8b8361ddbf6.tar.xz
murun: Add document writer object.
-rw-r--r--docs/mutool/run.html63
-rw-r--r--source/pdf/pdf-write.c3
-rw-r--r--source/tools/murun.c83
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);