summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/mutool/run.html11
-rw-r--r--include/mupdf/pdf.h1
-rw-r--r--include/mupdf/pdf/document.h11
-rw-r--r--include/mupdf/pdf/graft.h17
-rw-r--r--platform/win32/libmupdf.vcproj4
-rw-r--r--source/pdf/pdf-graft.c27
-rw-r--r--source/tools/murun.c39
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);