diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-10-07 08:37:21 +0200 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-10-07 08:37:21 +0200 |
commit | bd77c6880a7cf32e20865fb0cdb6816df0e6f775 (patch) | |
tree | 1941683df9caf87750c0c76ee57232fc68c364ed /test/pdfmerge.c | |
parent | 94a96e0ce2be0e32f59ea43f1166a884ca30222d (diff) | |
download | mupdf-bd77c6880a7cf32e20865fb0cdb6816df0e6f775.tar.xz |
transplant objects
Diffstat (limited to 'test/pdfmerge.c')
-rw-r--r-- | test/pdfmerge.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/test/pdfmerge.c b/test/pdfmerge.c new file mode 100644 index 00000000..a3041188 --- /dev/null +++ b/test/pdfmerge.c @@ -0,0 +1,237 @@ +#include <fitz.h> +#include <mupdf.h> + +void usage() +{ + fprintf(stderr, + "usage: pdfmerge [options] file.pdf pages ...\n" + " -o -\toutput file name (default out.pdf)\n" + " -d -\tset user password for decryption\n" + " -e\tencrypt outfile\n" + " -U -\tset user password for encryption\n" + " -O -\tset owner password\n" + " -P -\tset permissions\n" + " -N -\tkey length in bits: 40 <= n <= 128\n" + ); + exit(1); +} + +int main(int argc, char **argv) +{ + fz_error *error; + char *savename = "out.pdf"; + pdf_pagetree *srcpages; + fz_obj *srcrefs; + fz_obj *dstrefs; + pdf_xref *dst; + pdf_xref *src; + int rootoid; + int rootgid; + int pagesoid; + int pagesgid; + fz_obj *pagesref; + fz_obj *obj; + int i, k; + int c; + + pdf_crypt *encrypt = 0; + int doencrypt = 0; + + char *userpw = ""; + char *ownerpw = ""; + int perms = -4; /* 0xfffffffc */ + int keylen = 40; + char *password = ""; + + while ((c = getopt(argc, argv, "reo:U:O:P:N:")) != -1) + { + switch (c) + { + case 'e': ++ doencrypt; break; + case 'o': savename = optarg; break; + case 'U': userpw = optarg; break; + case 'O': ownerpw = optarg; break; + case 'P': perms = atoi(optarg); break; + case 'N': keylen = atoi(optarg); break; + case 'd': password = optarg; break; + default: usage(); + } + } + + if (argc - optind < 1) + usage(); + + /* + * Create new blank xref table + */ + + error = pdf_newxref(&dst); + if (error) + fz_abort(error); + + error = pdf_emptyxref(dst, 1.3); + if (error) + fz_abort(error); + + error = fz_newarray(&dstrefs, 100); + if (error) + fz_abort(error); + + /* + * Copy pages saving refs in dstrefs + */ + + for (i = optind; i < argc; i++) + { + error = pdf_newxref(&src); + if (error) + fz_abort(error); + + error = pdf_openxref(src, argv[i]); + if (error) + fz_abort(error); + + error = pdf_decryptxref(src); + if (error) + fz_abort(error); + + if (src->crypt) + { + error = pdf_setpassword(src->crypt, password); + if (error) + fz_abort(error); + } + + error = pdf_loadpagetree(&srcpages, src); + if (error) + fz_abort(error); + + error = fz_newarray(&srcrefs, 100); + if (error) + fz_abort(error); + + for (k = 0; k < srcpages->count; k++) + { + fz_dictdels(srcpages->pobj[k], "Parent"); + fz_dictdels(srcpages->pobj[k], "B"); + fz_dictdels(srcpages->pobj[k], "PieceInfo"); + fz_dictdels(srcpages->pobj[k], "Metadata"); + fz_dictdels(srcpages->pobj[k], "Annots"); + fz_dictdels(srcpages->pobj[k], "Tabs"); + + pdf_saveobject(src, + fz_toobjid(srcpages->pref[k]), + fz_togenid(srcpages->pref[k]), + srcpages->pobj[k]); + error = fz_arraypush(srcrefs, srcpages->pref[k]); + if (error) + fz_abort(error); + } + + error = pdf_transplant(dst, src, &srcrefs, srcrefs); + if (error) + fz_abort(error); + + for (k = 0; k < fz_arraylen(srcrefs); k++) + { + error = fz_arraypush(dstrefs, fz_arrayget(srcrefs, k)); + if (error) + fz_abort(error); + } + + pdf_freepagetree(srcpages); + + pdf_closexref(src); + } + + /* + * Create and relink Pages object + */ + + error = pdf_createobject(dst, &pagesoid, &pagesgid); + if (error) + fz_abort(error); + + error = fz_packobj(&obj, + "<</Type/Pages/Count %i/Kids %o>>", + fz_arraylen(dstrefs), + dstrefs); + if (error) + fz_abort(error); + + error = pdf_saveobject(dst, pagesoid, pagesgid, obj); + if (error) + fz_abort(error); + + fz_dropobj(obj); + + error = fz_newindirect(&pagesref, pagesoid, pagesgid); + if (error) + fz_abort(error); + + for (i = 0; i < fz_arraylen(dstrefs); i++) + { + int oid = fz_toobjid(fz_arrayget(dstrefs, i)); + int gid = fz_togenid(fz_arrayget(dstrefs, i)); + error = pdf_loadobject0(&obj, dst, oid, gid, nil); + if (error) + fz_abort(error); + error = fz_dictputs(obj, "Parent", pagesref); + if (error) + fz_abort(error); + error = pdf_saveobject(dst, oid, gid, obj); + if (error) + fz_abort(error); + fz_dropobj(obj); + } + + fz_dropobj(pagesref); + + /* + * Create Catalog and trailer + */ + + error = pdf_createobject(dst, &rootoid, &rootgid); + if (error) + fz_abort(error); + + error = fz_packobj(&obj, + "<</Type/Catalog/Pages %r>>", + pagesoid, pagesgid); + if (error) + fz_abort(error); + + error = pdf_saveobject(dst, rootoid, rootgid, obj); + if (error) + fz_abort(error); + + fz_dropobj(obj); + + error = fz_packobj(&dst->trailer, "<</Root %r>>", rootoid, rootgid); + if (error) + fz_abort(error); + + /* + * Write out the new PDF + */ + + if (doencrypt) + { + fz_obj *id = fz_dictgets(dst->trailer, "ID"); + if (!id) + fz_packobj(&id, "[(ABCDEFGHIJKLMNOP)(ABCDEFGHIJKLMNOP)]"); + else + fz_keepobj(id); + error = pdf_newencrypt(&encrypt, userpw, ownerpw, perms, keylen, id); + if (error) + fz_abort(error); + fz_dropobj(id); + } + + error = pdf_savepdf(dst, savename, encrypt); + if (error) + fz_abort(error); + + return 0; +} + |