diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-05-18 14:47:05 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-05-20 14:31:08 +0200 |
commit | 0528bc575875c579408ab90bb2c2e3af0750545d (patch) | |
tree | 1b5de9615e17eef3c25988f6b33535e7c9d6c4b3 | |
parent | a4b7981d56e3cb22e2a1c18e40906e88fc331da5 (diff) | |
download | mupdf-0528bc575875c579408ab90bb2c2e3af0750545d.tar.xz |
murun: Add graftObject to javascript bindings.
Add some paranoid checks to pdf_graft_object to prevent user
errors from crashing mupdf.
-rw-r--r-- | docs/mutool/run.html | 11 | ||||
-rw-r--r-- | include/mupdf/pdf.h | 1 | ||||
-rw-r--r-- | include/mupdf/pdf/document.h | 11 | ||||
-rw-r--r-- | include/mupdf/pdf/graft.h | 17 | ||||
-rw-r--r-- | platform/win32/libmupdf.vcproj | 4 | ||||
-rw-r--r-- | source/pdf/pdf-graft.c | 27 | ||||
-rw-r--r-- | source/tools/murun.c | 39 |
7 files changed, 87 insertions, 23 deletions
diff --git a/docs/mutool/run.html b/docs/mutool/run.html index 5d5d73fd..23286f07 100644 --- a/docs/mutool/run.html +++ b/docs/mutool/run.html @@ -589,6 +589,17 @@ Do NOT mix and match objects from one document with another document! </dl> <p> +The following functions can be used to copy objects from one document to another: + +<dl> +<dt>PDFDocument#graftObject(sourceDocument, object, sourceGraftMap) +<dd>Deep copy an object into the destination document. The graft map may be null, but should be used if you +are copying several objects from the same source document using multiple calls to graftObject. +<dt>PDFDocument#newGraftMap() +<dd>Create a graft map for the source document, so that objects that have already been copied can be found again. +</dl> + +<p> All functions that take PDF objects, do automatic translation between JavaScript objects and PDF objects using a few basic rules. Null, booleans, and numbers are translated directly. JavaScript strings are translated to PDF names, unless they are surrounded by parentheses: diff --git a/include/mupdf/pdf.h b/include/mupdf/pdf.h index cb4bbdd5..eab70ee9 100644 --- a/include/mupdf/pdf.h +++ b/include/mupdf/pdf.h @@ -15,7 +15,6 @@ extern "C" { #include "mupdf/pdf/crypt.h" #include "mupdf/pdf/page.h" -#include "mupdf/pdf/graft.h" #include "mupdf/pdf/resource.h" #include "mupdf/pdf/cmap.h" #include "mupdf/pdf/font.h" diff --git a/include/mupdf/pdf/document.h b/include/mupdf/pdf/document.h index 6f73531c..f8ef6bfb 100644 --- a/include/mupdf/pdf/document.h +++ b/include/mupdf/pdf/document.h @@ -270,12 +270,21 @@ struct pdf_document_s pdf_document *pdf_create_document(fz_context *ctx); /* + Deep copy objects between documents. +*/ +typedef struct pdf_graft_map_s pdf_graft_map; + +pdf_graft_map *pdf_new_graft_map(fz_context *ctx, pdf_document *src); +void pdf_drop_graft_map(fz_context *ctx, pdf_graft_map *map); +pdf_obj *pdf_graft_object(fz_context *ctx, pdf_document *dst, pdf_document *src, pdf_obj *obj, pdf_graft_map *map); + +/* pdf_page_write: Create a device that will record the graphical operations given to it into a sequence of pdf operations, together with a set of resources. This sequence/set pair can then be used as the basis for adding a page to the document (see pdf_add_page). - + doc: The document for which these are intended. mediabox: The bbox for the created page. diff --git a/include/mupdf/pdf/graft.h b/include/mupdf/pdf/graft.h deleted file mode 100644 index 0b2d8151..00000000 --- a/include/mupdf/pdf/graft.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef MUPDF_PDF_GRAFT_H -#define MUPDF_PDF_GRAFT_H - -typedef struct pdf_graft_map_s pdf_graft_map; - -struct pdf_graft_map_s -{ - int refs; - int len; - int *dst_from_src; -}; - -pdf_graft_map *pdf_new_graft_map(fz_context *ctx, pdf_document *src); -void pdf_drop_graft_map(fz_context *ctx, pdf_graft_map *map); -pdf_obj *pdf_graft_object(fz_context *ctx, pdf_document *dst, pdf_document *src, pdf_obj *obj, pdf_graft_map *map); - -#endif diff --git a/platform/win32/libmupdf.vcproj b/platform/win32/libmupdf.vcproj index f343bd10..7da59040 100644 --- a/platform/win32/libmupdf.vcproj +++ b/platform/win32/libmupdf.vcproj @@ -1410,10 +1410,6 @@ > </File> <File - RelativePath="..\..\include\mupdf\pdf\graft.h" - > - </File> - <File RelativePath="..\..\include\mupdf\pdf\javascript.h" > </File> diff --git a/source/pdf/pdf-graft.c b/source/pdf/pdf-graft.c index bbe5e17b..758addde 100644 --- a/source/pdf/pdf-graft.c +++ b/source/pdf/pdf-graft.c @@ -1,5 +1,13 @@ #include "mupdf/pdf.h" +struct pdf_graft_map_s +{ + int refs; + int len; + pdf_document *src; + int *dst_from_src; +}; + pdf_graft_map * pdf_new_graft_map(fz_context *ctx, pdf_document *src) { @@ -9,6 +17,7 @@ pdf_new_graft_map(fz_context *ctx, pdf_document *src) fz_try(ctx) { + map->src = (pdf_document*) fz_keep_document(ctx, (fz_document*)src); map->len = pdf_xref_len(ctx, src); map->dst_from_src = fz_calloc(ctx, map->len, sizeof(int)); } @@ -34,6 +43,7 @@ pdf_drop_graft_map(fz_context *ctx, pdf_graft_map *map) { if (map && --map->refs == 0) { + fz_drop_document(ctx, (fz_document*)map->src); fz_free(ctx, map->dst_from_src); fz_free(ctx, map); } @@ -50,15 +60,32 @@ pdf_graft_object(fz_context *ctx, pdf_document *dst, pdf_document *src, pdf_obj pdf_obj *ref = NULL; fz_buffer *buffer = NULL; pdf_graft_map *drop_map = NULL; + pdf_document *bound; int new_num, src_num, len, i; + /* Primitive objects are not bound to a document, so can be re-used as is. */ + if (!pdf_is_indirect(ctx, obj_ref) && !pdf_is_dict(ctx, obj_ref) && !pdf_is_array(ctx, obj_ref)) + return pdf_keep_obj(ctx, obj_ref); + if (map == NULL) drop_map = map = pdf_new_graft_map(ctx, src); + else if (src != map->src) + fz_throw(ctx, FZ_ERROR_GENERIC, "graft map does not belong to the source document"); + + bound = pdf_get_bound_document(ctx, obj_ref); + if (bound && bound != src) + fz_throw(ctx, FZ_ERROR_GENERIC, "grafted object does not belong to the source document"); if (pdf_is_indirect(ctx, obj_ref)) { src_num = pdf_to_num(ctx, obj_ref); + if (src_num < 1 || src_num >= map->len) + { + pdf_drop_graft_map(ctx, drop_map); + fz_throw(ctx, FZ_ERROR_GENERIC, "source object number out of range"); + } + /* Check if we have done this one. If yes, then drop map (if allocated) * and return our indirect ref */ if (map->dst_from_src[src_num] != 0) diff --git a/source/tools/murun.c b/source/tools/murun.c index acaa9850..0adb8bc0 100644 --- a/source/tools/murun.c +++ b/source/tools/murun.c @@ -198,6 +198,12 @@ static void ffi_gc_pdf_obj(js_State *J, void *obj) pdf_drop_obj(ctx, obj); } +static void ffi_gc_pdf_graft_map(js_State *J, void *map) +{ + fz_context *ctx = js_getcontext(J); + pdf_drop_graft_map(ctx, map); +} + static void ffi_gc_fz_page(js_State *J, void *page) { fz_context *ctx = js_getcontext(J); @@ -2711,6 +2717,33 @@ static void ffi_PDFDocument_newDictionary(js_State *J) ffi_pushobj(J, obj); } +static void ffi_PDFDocument_newGraftMap(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + pdf_document *pdf = js_touserdata(J, 0, "pdf_document"); + pdf_graft_map *map; + fz_try(ctx) + map = pdf_new_graft_map(ctx, pdf); + fz_catch(ctx) + rethrow(J); + js_getregistry(J, "pdf_graft_map"); + js_newuserdata(J, "pdf_graft_map", map, ffi_gc_pdf_graft_map); +} + +static void ffi_PDFDocument_graftObject(js_State *J) +{ + fz_context *ctx = js_getcontext(J); + pdf_document *dst = js_touserdata(J, 0, "pdf_document"); + pdf_document *src = js_touserdata(J, 1, "pdf_document"); + pdf_obj *obj = js_touserdata(J, 2, "pdf_obj"); + pdf_graft_map *map = js_iscoercible(J, 3) ? js_touserdata(J, 3, "pdf_graft_map") : NULL; + fz_try(ctx) + obj = pdf_graft_object(ctx, dst, src, obj, map); + fz_catch(ctx) + rethrow(J); + ffi_pushobj(J, obj); +} + static void ffi_PDFObject_get(js_State *J) { pdf_obj *obj = js_touserdata(J, 0, "pdf_obj"); @@ -3219,6 +3252,9 @@ int murun_main(int argc, char **argv) jsB_propfun(J, "PDFDocument.newIndirect", ffi_PDFDocument_newIndirect, 2); jsB_propfun(J, "PDFDocument.newArray", ffi_PDFDocument_newArray, 1); jsB_propfun(J, "PDFDocument.newDictionary", ffi_PDFDocument_newDictionary, 1); + + jsB_propfun(J, "PDFDocument.newGraftMap", ffi_PDFDocument_newGraftMap, 0); + jsB_propfun(J, "PDFDocument.graftObject", ffi_PDFDocument_graftObject, 3); } js_setregistry(J, "pdf_document"); @@ -3244,6 +3280,9 @@ int murun_main(int argc, char **argv) } js_setregistry(J, "pdf_obj"); + js_newobject(J); + js_setregistry(J, "pdf_graft_map"); + js_pushglobal(J); { jsB_propcon(J, "pdf_document", "PDFDocument", ffi_new_PDFDocument, 1); |