summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-10-05 09:52:44 +0200
committerTor Andersson <tor@ghostscript.com>2004-10-05 09:52:44 +0200
commit9ce9759c580d5522ad2d3812b26aff49644d8881 (patch)
tree2eb3aa263955f7bdfe4461624aa3dfe8d9992e83
parent7ad0eac4b8c81c5123ef5a62b23ba2895dd997c8 (diff)
downloadmupdf-9ce9759c580d5522ad2d3812b26aff49644d8881.tar.xz
improved reading to buffers and writing files
-rw-r--r--filter/buffer.c2
-rw-r--r--filter/filec.c9
-rw-r--r--filter/filer.c23
-rw-r--r--filter/filew.c7
-rw-r--r--include/fitz/file.h2
-rw-r--r--include/mupdf.h6
-rw-r--r--mupdf/font.c12
-rw-r--r--mupdf/fontfile.c9
-rw-r--r--mupdf/save.c140
-rw-r--r--mupdf/stream.c20
-rw-r--r--mupdf/xref.c12
-rw-r--r--test/pdfclean.c526
-rw-r--r--test/pdfdebug.c152
13 files changed, 239 insertions, 681 deletions
diff --git a/filter/buffer.c b/filter/buffer.c
index 25e30a55..aae27474 100644
--- a/filter/buffer.c
+++ b/filter/buffer.c
@@ -32,7 +32,7 @@ fz_newbufferwithdata(fz_buffer **bp, unsigned char *data, int size)
b->bp = data;
b->rp = b->bp;
- b->wp = b->bp;
+ b->wp = b->bp + size;
b->ep = b->bp + size;
b->eof = 0;
diff --git a/filter/filec.c b/filter/filec.c
index f62d1265..fc5599e1 100644
--- a/filter/filec.c
+++ b/filter/filec.c
@@ -13,15 +13,20 @@ fz_openfile(fz_file **filep, char *path, int mode)
{
fz_error *error;
fz_file *file;
+ int realmode;
int fd;
- assert(mode == O_RDONLY || mode == O_WRONLY);
+ assert(mode == O_RDONLY || mode == O_WRONLY || mode == O_APPEND);
+
+ realmode = mode;
+ if (mode == O_WRONLY)
+ realmode = O_WRONLY | O_CREAT | O_TRUNC;
file = *filep = fz_malloc(sizeof(fz_file));
if (!file)
return fz_outofmem;
- fd = open(path, mode, 0);
+ fd = open(path, realmode, 0644);
if (fd == -1)
return fz_throw("ioerror: open '%s': %s", path, strerror(errno));
diff --git a/filter/filer.c b/filter/filer.c
index 804d7f7e..368f9dbe 100644
--- a/filter/filer.c
+++ b/filter/filer.c
@@ -175,11 +175,12 @@ fz_readline(fz_file *f, char *buf, int n)
* a freshly allocated buffer; realloced and trimmed to size.
*/
-enum { CHUNKSIZE = 4096 };
+enum { CHUNKSIZE = 1024 * 32 };
fz_error *
-fz_readfile(unsigned char **bufp, int *lenp, fz_file *file)
+fz_readfile(fz_buffer **bufp, fz_file *file)
{
+ fz_buffer *real;
unsigned char *newbuf;
unsigned char *buf;
int len;
@@ -187,7 +188,6 @@ fz_readfile(unsigned char **bufp, int *lenp, fz_file *file)
int n;
*bufp = nil;
- *lenp = 0;
len = 0;
pos = 0;
@@ -209,8 +209,6 @@ fz_readfile(unsigned char **bufp, int *lenp, fz_file *file)
n = fz_read(file, buf + pos, len - pos);
-printf("fz_read %d bytes\n", n);
-
if (n < 0)
{
fz_free(buf);
@@ -228,8 +226,19 @@ printf("fz_read %d bytes\n", n);
return fz_outofmem;
}
- *bufp = newbuf;
- *lenp = pos;
+ real = *bufp = fz_malloc(sizeof(fz_buffer));
+ if (!real)
+ {
+ fz_free(newbuf);
+ return fz_outofmem;
+ }
+
+ real->ownsdata = 1;
+ real->bp = buf;
+ real->rp = buf;
+ real->wp = buf + pos;
+ real->ep = buf + pos;
+
return nil;
}
}
diff --git a/filter/filew.c b/filter/filew.c
index 0422e60e..a7b15664 100644
--- a/filter/filew.c
+++ b/filter/filew.c
@@ -99,7 +99,12 @@ fz_write(fz_file *f, char *buf, int n)
return -1;
}
- fz_rewindbuffer(f->in);
+ if (f->in->rp > f->in->bp)
+ f->error = fz_rewindbuffer(f->in);
+ else
+ f->error = fz_growbuffer(f->in);
+ if (f->error)
+ return -1;
}
}
diff --git a/include/fitz/file.h b/include/fitz/file.h
index 7807570c..2d6dc977 100644
--- a/include/fitz/file.h
+++ b/include/fitz/file.h
@@ -26,7 +26,7 @@ int fz_peekbyte(fz_file *f);
int fz_readline(fz_file *f, char *buf, int n);
int fz_read(fz_file *f, char *buf, int n);
-fz_error *fz_readfile(unsigned char **bufp, int *lenp, fz_file *file);
+fz_error *fz_readfile(fz_buffer **bufp, fz_file *file);
int fz_printstring(fz_file *f, char *s);
int fz_printobj(fz_file *f, fz_obj *o, int tight);
diff --git a/include/mupdf.h b/include/mupdf.h
index c5dcc133..98f40c62 100644
--- a/include/mupdf.h
+++ b/include/mupdf.h
@@ -81,7 +81,8 @@ fz_error *pdf_buildfilter(fz_filter**, pdf_xref*, fz_obj *stm, int oid, int gid)
fz_error *pdf_openstream0(pdf_xref*, fz_obj *stmobj, int oid, int gid, int ofs);
fz_error *pdf_openstream(pdf_xref*, fz_obj *stmref);
void pdf_closestream(pdf_xref*);
-fz_error *pdf_readstream(unsigned char **bufp, int *lenp, pdf_xref*, fz_obj *stmref);
+fz_error *pdf_readstream0(fz_buffer **bufp, pdf_xref*, fz_obj *stmobj, int oid, int gid, int ofs);
+fz_error *pdf_readstream(fz_buffer **bufp, pdf_xref*, fz_obj *stmref);
/* crypt.c */
fz_error *pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id);
@@ -118,6 +119,9 @@ fz_error *pdf_loadobject0(fz_obj **, pdf_xref*, int oid, int gid, int *stmofs);
fz_error *pdf_loadobject(fz_obj **, pdf_xref*, fz_obj *ref, int *stmofs);
fz_error *pdf_resolve(fz_obj **, pdf_xref*);
+fz_error *pdf_savestream(pdf_xref *xref, int oid, int gid, fz_buffer *buf);
+fz_error *pdf_deletestream(pdf_xref *xref, int oid, int gid);
+
/* save.c */
fz_error *pdf_saveincrementalpdf(pdf_xref *xref, char *path);
fz_error *pdf_savepdf(pdf_xref *xref, char *path);
diff --git a/mupdf/font.c b/mupdf/font.c
index 6d499c60..7c75f585 100644
--- a/mupdf/font.c
+++ b/mupdf/font.c
@@ -562,17 +562,19 @@ printf(" embedded CMap\n");
cidtogidmap = fz_dictgets(dict, "CIDToGIDMap");
if (fz_isindirect(cidtogidmap))
{
- unsigned char *buf;
+ fz_buffer *buf;
int len;
- error = pdf_readstream(&buf, &len, xref, cidtogidmap);
+ error = pdf_readstream(&buf, xref, cidtogidmap);
if (error)
goto cleanup;
+ len = buf->wp - buf->rp;
+
font->cidtogidlen = len / 2;
font->cidtogidmap = fz_malloc((len / 2) * sizeof(int));
if (!font->cidtogidmap) {
- fz_free(buf);
+ fz_freebuffer(buf);
error = fz_outofmem;
goto cleanup;
}
@@ -580,7 +582,9 @@ printf(" embedded CMap\n");
printf(" cidtogidmap %d\n", len / 2);
for (i = 0; i < len / 2; i++)
- font->cidtogidmap[i] = (buf[i * 2] << 8) + buf[i * 2 + 1];
+ font->cidtogidmap[i] = (buf->rp[i * 2] << 8) + buf->rp[i * 2 + 1];
+
+ fz_freebuffer(buf);
}
/* TODO: if truetype font is external, cidtogidmap should not be identity */
diff --git a/mupdf/fontfile.c b/mupdf/fontfile.c
index 3c0470f7..21a379b2 100644
--- a/mupdf/fontfile.c
+++ b/mupdf/fontfile.c
@@ -194,20 +194,17 @@ pdf_loadembeddedfont(void **fontp, pdf_xref *xref, fz_obj *stmref)
fz_error *error;
int fterr;
FT_Face face;
- unsigned char *buf;
- int len;
+ fz_buffer *buf;
error = initfontlibs();
if (error)
return error;
- error = pdf_readstream(&buf, &len, xref, stmref);
+ error = pdf_readstream(&buf, xref, stmref);
if (error)
return error;
-printf("readstream $%p %d\n", buf, len);
-
- fterr = FT_New_Memory_Face(ftlib, buf, len, 0, &face);
+ fterr = FT_New_Memory_Face(ftlib, buf->rp, buf->wp - buf->rp, 0, &face);
if (fterr) {
fz_free(buf);
diff --git a/mupdf/save.c b/mupdf/save.c
index 1698fc23..32dda709 100644
--- a/mupdf/save.c
+++ b/mupdf/save.c
@@ -1,9 +1,12 @@
#include <fitz.h>
#include <mupdf.h>
-static fz_error *writestored(FILE *out, pdf_xref *xref, int oid)
+#define TIGHT 0
+
+static fz_error *writestored(fz_file *out, pdf_xref *xref, int oid)
{
pdf_xrefentry *x = xref->table + oid;
+ fz_error *error;
fz_obj *obj;
fz_buffer *stm;
@@ -16,26 +19,27 @@ static fz_error *writestored(FILE *out, pdf_xref *xref, int oid)
if (xref->crypt)
pdf_cryptobj(xref->crypt, obj, oid, x->gen);
- fprintf(out, "%d %d obj\n", oid, x->gen);
- fz_debugobj(obj);
- fprintf(out, "\n");
+ fz_print(out, "%d %d obj\n", oid, x->gen);
+ fz_printobj(out, obj, TIGHT);
+ fz_print(out, "\n");
if (stm)
{
- fprintf(out, "stream\n");
- fwrite(stm->rp, 1, stm->wp - stm->rp, out);
- fprintf(out, "endstream\n");
+ fz_print(out, "stream\n");
+ fz_write(out, stm->rp, stm->wp - stm->rp);
+ fz_print(out, "endstream\n");
}
- fprintf(out, "endobj\n\n");
+ fz_print(out, "endobj\n\n");
- if (ferror(out))
- return fz_throw("ioerror: write failed");
+ error = fz_ferror(out);
+ if (error)
+ return error;
return nil;
}
-static fz_error *writecopy(FILE *out, pdf_xref *xref, int oid)
+static fz_error *writecopy(fz_file *out, pdf_xref *xref, int oid)
{
pdf_xrefentry *x = xref->table + oid;
fz_error *error;
@@ -52,13 +56,13 @@ static fz_error *writecopy(FILE *out, pdf_xref *xref, int oid)
if (error)
return error;
- fprintf(out, "%d %d obj\n", oid, x->gen);
- fz_debugobj(obj);
- fprintf(out, "\n");
+ fz_print(out, "%d %d obj\n", oid, x->gen);
+ fz_printobj(out, obj, TIGHT);
+ fz_print(out, "\n");
if (stmofs != -1)
{
- fprintf(out, "stream\n");
+ fz_print(out, "stream\n");
length = fz_dictgets(obj, "Length");
error = pdf_resolve(&length, xref);
@@ -98,20 +102,21 @@ static fz_error *writecopy(FILE *out, pdf_xref *xref, int oid)
fz_popfilter(xref->file);
goto cleanup;
}
- fwrite(buf, 1, n, out);
+ fz_write(out, buf, n);
}
fz_popfilter(xref->file);
- fprintf(out, "endstream\n");
+ fz_print(out, "endstream\n");
}
- fprintf(out, "endobj\n\n");
+ fz_print(out, "endobj\n\n");
- fz_dropobj(obj);
+ error = fz_ferror(out);
+ if (error)
+ goto cleanup;
- if (ferror(out))
- return fz_throw("ioerror: write failed");
+ fz_dropobj(obj);
return nil;
@@ -133,22 +138,23 @@ fz_error *
pdf_saveincrementalpdf(pdf_xref *xref, char *path)
{
fz_error *error;
- FILE *out;
+ fz_file *out;
int oid;
int i, n;
int startxref;
fz_obj *obj;
- out = fopen(path, "ab");
- if (!out)
- return fz_throw("ioerror: could not open '%s': %s", path, strerror(errno));
- fprintf(out, "\n");
+ error = fz_openfile(&out, path, O_APPEND);
+ if (error)
+ return error;
+
+ fz_print(out, "\n");
for (oid = 0; oid < xref->size; oid++)
{
if (xref->table[oid].type == 'a')
{
- xref->table[oid].ofs = ftell(out);
+ xref->table[oid].ofs = fz_tell(out);
error = writestored(out, xref, oid);
if (error)
goto cleanup;
@@ -158,15 +164,15 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path)
/* always write out entry 0 in appended xref sections */
xref->table[0].type = 'd';
- startxref = ftell(out);
- fprintf(out, "xref\n");
+ startxref = fz_tell(out);
+ fz_print(out, "xref\n");
oid = 0;
while (oid < xref->size)
{
n = countmodified(xref, oid);
- fprintf(out, "%d %d\n", oid, n);
+ fz_print(out, "%d %d\n", oid, n);
for (i = 0; i < n; i++)
{
@@ -175,7 +181,7 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path)
if (xref->table[oid + i].type == 'a')
xref->table[oid + i].type = 'n';
- fprintf(out, "%010d %05d %c \n",
+ fz_print(out, "%010d %05d %c \n",
xref->table[oid + i].ofs,
xref->table[oid + i].gen,
xref->table[oid + i].type);
@@ -188,42 +194,42 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path)
oid ++;
}
- fprintf(out, "\n");
+ fz_print(out, "\n");
- fprintf(out, "trailer\n<<\n /Size %d\n /Prev %d", xref->size, xref->startxref);
+ fz_print(out, "trailer\n<<\n /Size %d\n /Prev %d", xref->size, xref->startxref);
obj = fz_dictgets(xref->trailer, "Root");
- fprintf(out,"\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj));
+ fz_print(out,"\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj));
obj = fz_dictgets(xref->trailer, "Info");
if (obj)
- fprintf(out,"\n /Info %d %d R", fz_toobjid(obj), fz_togenid(obj));
+ fz_print(out,"\n /Info %d %d R", fz_toobjid(obj), fz_togenid(obj));
obj = fz_dictgets(xref->trailer, "Encrypt");
if (obj) {
- fprintf(out,"\n /Encrypt ");
- fz_debugobj(obj);
+ fz_print(out,"\n /Encrypt ");
+ fz_printobj(out, obj, TIGHT);
}
obj = fz_dictgets(xref->trailer, "ID");
if (obj) {
- fprintf(out,"\n /ID ");
- fz_debugobj(obj);
+ fz_print(out,"\n /ID ");
+ fz_printobj(out, obj, TIGHT);
}
- fprintf(out, "\n>>\n\n");
+ fz_print(out, "\n>>\n\n");
- fprintf(out, "startxref\n");
- fprintf(out, "%d\n", startxref);
- fprintf(out, "%%%%EOF\n");
+ fz_print(out, "startxref\n");
+ fz_print(out, "%d\n", startxref);
+ fz_print(out, "%%%%EOF\n");
xref->startxref = startxref;
- fclose(out);
+ fz_closefile(out);
return nil;
cleanup:
- fclose(out);
+ fz_closefile(out);
return error;
}
@@ -231,7 +237,7 @@ fz_error *
pdf_savepdf(pdf_xref *xref, char *path)
{
fz_error *error;
- FILE *out;
+ fz_file *out;
int oid;
int startxref;
int *ofsbuf;
@@ -241,28 +247,28 @@ pdf_savepdf(pdf_xref *xref, char *path)
if (!ofsbuf)
return fz_outofmem;
- out = fopen(path, "wb");
- if (!out)
+ error = fz_openfile(&out, path, O_WRONLY);
+ if (error)
{
fz_free(ofsbuf);
- return fz_throw("ioerror: could not open '%s': %s", path, strerror(errno));
+ return error;
}
- fprintf(out, "%%PDF-%1.1f\n", xref->version);
- fprintf(out, "%%\342\343\317\323\n\n");
+ fz_print(out, "%%PDF-%1.1f\n", xref->version);
+ fz_print(out, "%%\342\343\317\323\n\n");
for (oid = 0; oid < xref->size; oid++)
{
if (xref->table[oid].type == 'n' || xref->table[oid].type == 'o')
{
- ofsbuf[oid] = ftell(out);
+ ofsbuf[oid] = fz_tell(out);
error = writecopy(out, xref, oid);
if (error)
goto cleanup;
}
else if (xref->table[oid].type == 'a')
{
- ofsbuf[oid] = ftell(out);
+ ofsbuf[oid] = fz_tell(out);
error = writestored(out, xref, oid);
if (error)
goto cleanup;
@@ -273,9 +279,9 @@ pdf_savepdf(pdf_xref *xref, char *path)
}
}
- startxref = ftell(out);
- fprintf(out, "xref\n");
- fprintf(out, "0 %d\n", xref->size);
+ startxref = fz_tell(out);
+ fz_print(out, "xref\n");
+ fz_print(out, "0 %d\n", xref->size);
for (oid = 0; oid < xref->size; oid++)
{
@@ -284,30 +290,30 @@ pdf_savepdf(pdf_xref *xref, char *path)
type = 'n';
if (type == 'd')
type = 'f';
- fprintf(out, "%010d %05d %c \n", ofsbuf[oid], xref->table[oid].gen, type);
+ fz_print(out, "%010d %05d %c \n", ofsbuf[oid], xref->table[oid].gen, type);
}
- fprintf(out, "\n");
+ fz_print(out, "\n");
- fprintf(out, "trailer\n<<\n /Size %d", xref->size);
+ fz_print(out, "trailer\n<<\n /Size %d", xref->size);
obj = fz_dictgets(xref->trailer, "Root");
- fprintf(out,"\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj));
+ fz_print(out,"\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj));
obj = fz_dictgets(xref->trailer, "Info");
if (obj)
- fprintf(out,"\n /Info %d %d R", fz_toobjid(obj), fz_togenid(obj));
- fprintf(out, "\n>>\n\n");
+ fz_print(out,"\n /Info %d %d R", fz_toobjid(obj), fz_togenid(obj));
+ fz_print(out, "\n>>\n\n");
- fprintf(out, "startxref\n");
- fprintf(out, "%d\n", startxref);
- fprintf(out, "%%%%EOF\n");
+ fz_print(out, "startxref\n");
+ fz_print(out, "%d\n", startxref);
+ fz_print(out, "%%%%EOF\n");
xref->startxref = startxref;
- fclose(out);
+ fz_closefile(out);
return nil;
cleanup:
- fclose(out);
+ fz_closefile(out);
return error;
}
diff --git a/mupdf/stream.c b/mupdf/stream.c
index f3f40e53..ab051865 100644
--- a/mupdf/stream.c
+++ b/mupdf/stream.c
@@ -245,7 +245,23 @@ pdf_closestream(pdf_xref *xref)
}
fz_error *
-pdf_readstream(unsigned char **bufp, int *lenp, pdf_xref *xref, fz_obj *stmref)
+pdf_readstream0(fz_buffer **bufp, pdf_xref *xref, fz_obj *stmobj, int oid, int gid, int ofs)
+{
+ fz_error *error;
+
+ error = pdf_openstream0(xref, stmobj, oid, gid, ofs);
+ if (error)
+ return error;
+
+ error = fz_readfile(bufp, xref->file);
+
+ pdf_closestream(xref);
+
+ return error;
+}
+
+fz_error *
+pdf_readstream(fz_buffer **bufp, pdf_xref *xref, fz_obj *stmref)
{
fz_error *error;
@@ -253,7 +269,7 @@ pdf_readstream(unsigned char **bufp, int *lenp, pdf_xref *xref, fz_obj *stmref)
if (error)
return error;
- error = fz_readfile(bufp, lenp, xref->file);
+ error = fz_readfile(bufp, xref->file);
pdf_closestream(xref);
diff --git a/mupdf/xref.c b/mupdf/xref.c
index 53b9f239..08ab8621 100644
--- a/mupdf/xref.c
+++ b/mupdf/xref.c
@@ -325,6 +325,18 @@ pdf_saveobject(pdf_xref *xref, int oid, int gid, fz_obj *obj)
return nil;
}
+fz_error *
+pdf_savestream(pdf_xref *xref, int oid, int gid, fz_buffer *buf)
+{
+ return pdf_storestream(xref->store, oid, gid, buf);
+}
+
+fz_error *
+pdf_deletestream(pdf_xref *xref, int oid, int gid)
+{
+ return pdf_deletestoredstream(xref->store, oid, gid);
+}
+
/*
* object loading
*/
diff --git a/test/pdfclean.c b/test/pdfclean.c
index 00721842..7eb72cda 100644
--- a/test/pdfclean.c
+++ b/test/pdfclean.c
@@ -1,30 +1,6 @@
#include <fitz.h>
#include <mupdf.h>
-#define encrypt encrypt3am
-
-int (*printobj)(FILE*,fz_obj*) = fz_fprintobj;
-
-/*
- * Rewrite PDF with cleaned up syntax, and consolidate the xref table.
- * Remove encryption while we're at it :)
- */
-
-static FILE *out;
-
-static pdf_xref *xt;
-
-static int *ofslist;
-static int *genlist;
-static int *uselist;
-
-static int dorebuild = 0;
-static int doexpand = 0;
-static pdf_crypt *encrypt = nil;
-static fz_obj *encryptdict = nil;
-static fz_obj *id = nil;
-static int dogc = 0;
-
void usage()
{
fprintf(stderr,
@@ -32,469 +8,129 @@ void usage()
" -r\treconstruct broken xref table\n"
" -g\tgarbage collect unused objects\n"
" -x\texpand compressed streams\n"
- " -c\twrite compact objects\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"
+ " -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);
}
-void garbagecollect(fz_obj *ref);
-
-void gc0(fz_obj *obj)
-{
- int i;
-
- if (fz_isdict(obj))
- for (i = 0; i < fz_dictlen(obj); i++)
- gc0(fz_dictgetval(obj, i));
-
- if (fz_isarray(obj))
- for (i = 0; i < fz_arraylen(obj); i++)
- gc0(fz_arrayget(obj, i));
-
- if (fz_isindirect(obj))
- garbagecollect(obj);
-}
-
-void garbagecollect(fz_obj *ref)
-{
- fz_obj *obj;
- int stmofs;
-
- if (uselist[fz_toobjid(ref)])
- return;
-
- uselist[fz_toobjid(ref)] = 1;
-
- pdf_loadindirect(&obj, xt, ref, &stmofs);
-
- if (stmofs != -1) {
- fz_obj *len = fz_dictgets(obj, "Length");
- if (fz_isindirect(len)) {
- pdf_loadindirect(&len, xt, len, nil);
- fz_dictputs(obj, "Length", len);
- }
- }
-
- gc0(obj);
-}
-
-void decodestream(fz_obj *obj, int ofs, int oid, int gid)
-{
- fz_error *error;
- unsigned char buf[512];
- fz_filter *filter;
- fz_file *sf;
- int n;
- int len;
- fz_obj *lenobj;
- fz_obj *newdict;
-
- /* count length of decoded data */
- len = 0;
-
- error = pdf_buildstream(&filter, xt, obj, oid, gid);
- if (error) fz_abort(error);
-
- n = fz_seek(xt->file, ofs);
-
- fz_chainfile(&sf, xt->file, filter);
-
- while (1) {
- n = fz_read(sf, buf, sizeof buf);
- if (n < 0)
- fz_abort(fz_ferror(sf));
- if (n == 0)
- break;
- len += n;
- }
-
- fz_unchainfile(sf);
-
- /* change dictionary of object... */
- fz_copydict(&newdict, obj);
-
- fz_newint(&lenobj, len);
- fz_dictputs(newdict, "Length", lenobj);
- fz_dropobj(lenobj);
-
- fz_dictdels(newdict, "Filter");
- fz_dictdels(newdict, "DecodeParms");
-
- /* save object */
- fprintf(out, "%d %d obj\n", oid, gid);
- printobj(out, newdict);
- fprintf(out, "\n");
- fprintf(out, "stream\n");
-
- fz_dropobj(newdict);
-
- /* now decode stream for real */
- error = pdf_buildstream(&filter, xt, obj, oid, gid);
- if (error) fz_abort(error);
-
- fz_seek(xt->file, ofs);
-
- if (encrypt) {
- fz_filter *cf;
- pdf_cryptstm(&cf, encrypt, oid, gid);
- fz_newpipeline(&filter, filter, cf);
- }
-
- fz_chainfile(&sf, xt->file, filter);
- while (1) {
- n = fz_read(sf, buf, sizeof buf);
- if (n < 0)
- fz_abort(fz_ferror(sf));
- if (n == 0)
- break;
- fwrite(buf, 1, n, out);
- }
- fz_unchainfile(sf);
-
- /* the end */
- fprintf(out, "endstream\nendobj\n\n");
-
- return;
-}
-
-void savestream(fz_obj *obj, int ofs, int oid, int gid)
-{
- unsigned char buf[512];
- fz_filter *filter;
- fz_file *sf;
- int len;
- int n;
-
- /* save object */
- fprintf(out, "%d %d obj\n", oid, gid);
- printobj(out, obj);
- fprintf(out, "\n");
- fprintf(out, "stream\n");
-
- /* copy stream */
- obj = fz_dictgets(obj, "Length");
- if (fz_isindirect(obj)) {
- pdf_loadindirect(&obj, xt, obj, nil);
- len = fz_toint(obj);
- fz_dropobj(obj);
- }
- else {
- len = fz_toint(obj);
- }
-
- fz_newnullfilter(&filter, len);
-
- if (xt->crypt) {
- fz_filter *cf;
- pdf_cryptstm(&cf, xt->crypt, oid, gid);
- fz_newpipeline(&filter, cf, filter);
- }
-
- if (encrypt) {
- fz_filter *cf;
- pdf_cryptstm(&cf, encrypt, oid, gid);
- fz_newpipeline(&filter, filter, cf);
- }
-
- fz_seek(xt->file, ofs);
- fz_chainfile(&sf, xt->file, filter);
- while (1)
- {
- n = fz_read(sf, buf, sizeof buf);
- if (n == 0)
- break;
- if (n < 0)
- fz_abort(fz_ferror(sf));
- fwrite(buf, 1, n, out);
- }
- fz_unchainfile(sf);
-
- /* the end */
- fprintf(out, "endstream\nendobj\n\n");
-}
-
-void deleteobject(int oid, int gid)
-{
- uselist[oid] = 0;
-}
-
-void saveobject(int oid, int gid)
+void expandstreams(pdf_xref *xref)
{
fz_error *error;
- fz_obj *obj;
- fz_obj *t;
+ fz_obj *stmobj;
int stmofs;
+ fz_buffer *buf;
+ fz_obj *stmlen;
+ int i, gen;
- error = pdf_loadobj(&obj, xt, oid, gid, &stmofs);
- if (error) fz_abort(error);
-
- /* trash ObjStm and XrefStm objects */
- if (fz_isdict(obj)) {
- t = fz_dictgets(obj, "Type");
- if (fz_isname(t) && strcmp(fz_toname(t), "ObjStm") == 0) {
- deleteobject(oid, gid);
- fz_dropobj(obj);
- return;
- }
- if (fz_isname(t) && strcmp(fz_toname(t), "XRef") == 0) {
- deleteobject(oid, gid);
- fz_dropobj(obj);
- return;
+ for (i = 0; i < xref->size; i++)
+ {
+ if (xref->table[i].type == 'n')
+ {
+ gen = xref->table[i].gen;
+
+ error = pdf_loadobject0(&stmobj, xref, i, gen, &stmofs);
+ if (error) fz_abort(error);
+
+ if (stmofs != -1)
+ {
+ error = pdf_readstream0(&buf, xref, stmobj, i, gen, stmofs);
+ if (error) fz_abort(error);
+
+ fz_dictdels(stmobj, "Filter");
+ fz_dictdels(stmobj, "DecodeParms");
+
+ error = fz_newint(&stmlen, buf->wp - buf->rp);
+ if (error) fz_abort(error);
+ error = fz_dictputs(stmobj, "Length", stmlen);
+ if (error) fz_abort(error);
+ fz_dropobj(stmlen);
+
+ error = pdf_saveobject(xref, i, gen, stmobj);
+ if (error) fz_abort(error);
+ error = pdf_savestream(xref, i, gen, buf);
+ if (error) fz_abort(error);
+ }
}
}
-
- if (encrypt)
- pdf_cryptobj(encrypt, obj, oid, gid);
-
- if (stmofs == -1) {
- fprintf(out, "%d %d obj\n", oid, gid);
- printobj(out, obj);
- fprintf(out, "\nendobj\n\n");
- }
- else if (doexpand) {
- decodestream(obj, stmofs, oid, gid);
- }
- else {
- savestream(obj, stmofs, oid, gid);
- }
-
- fz_dropobj(obj);
-}
-
-void savexref(void)
-{
- fz_obj *newtrailer;
- fz_obj *obj;
- int startxref;
- int i;
-
- startxref = ftell(out);
-
- fprintf(out, "xref\n0 %d\n", xt->size);
- for (i = 0; i < xt->size; i++) {
- if (uselist[i])
- fprintf(out, "%010d %05d n \n", ofslist[i], genlist[i]);
- else
- fprintf(out, "%010d %05d f \n", ofslist[i], genlist[i]);
- }
- fprintf(out, "\n");
-
- fz_newdict(&newtrailer, 5);
-
- fz_newint(&obj, xt->size);
- fz_dictputs(newtrailer, "Size", obj);
- fz_dropobj(obj);
-
- obj = fz_dictgets(xt->trailer, "Info");
- if (obj) fz_dictputs(newtrailer, "Info", obj);
-
- obj = fz_dictgets(xt->trailer, "Root");
- if (obj) fz_dictputs(newtrailer, "Root", obj);
-
- fz_dictputs(newtrailer, "ID", id);
-
- if (encryptdict) {
- fz_newindirect(&obj, xt->size - 1, 0);
- fz_dictputs(newtrailer, "Encrypt", obj);
- fz_dropobj(obj);
- }
-
- fprintf(out, "trailer\n");
- printobj(out, newtrailer);
- fprintf(out, "\n\n");
-
- fprintf(out, "startxref\n%d\n%%%%EOF\n", startxref);
}
int main(int argc, char **argv)
{
fz_error *error;
- fz_obj *obj;
- int lastfree;
- char *filename;
- int i;
+ char *infile;
+ char *outfile;
+ pdf_xref *xref;
int c;
int doencrypt = 0;
- char *password = "";
+ int dorepair = 0;
+ int doexpand = 0;
+ int dogc = 0;
+
char *userpw = "";
char *ownerpw = "";
int perms = -4; /* 0xfffffffc */
int keylen = 40;
+ char *password = "";
- while (1)
+ while ((c = getopt(argc, argv, "rgxd:eu:o:p:n:")) != -1)
{
- c = getopt(argc, argv, "rcxgeu:o:p:n:d:");
-
- if (c == -1)
- break;
-
switch (c)
{
- case 'r':
- dorebuild ++;
- break;
- case 'x':
- doexpand ++;
- break;
- case 'g':
- dogc ++;
- break;
- case 'c':
- printobj = fz_fprintcobj;
- break;
- case 'd':
- password = optarg;
- break;
- case 'e':
- doencrypt ++;
- break;
- case 'u':
- userpw = optarg;
- break;
- case 'o':
- ownerpw = optarg;
- break;
- case 'p':
- perms = atoi(optarg);
- break;
- case 'n':
- keylen = atoi(optarg);
- break;
- default:
- usage();
+ case 'r': ++ dorepair; break;
+ case 'x': ++ doexpand; break;
+ case 'g': ++ dogc; break;
+ case 'e': ++ doencrypt; 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 != 2)
+ if (argc - optind < 2)
usage();
- filename = argv[optind];
+ infile = argv[optind++];
+ outfile = argv[optind++];
- if (dorebuild)
- error = pdf_rebuildxref(&xt, filename);
- else
- error = pdf_openxref(&xt, filename);
- if (error) fz_abort(error);
-
- if (doencrypt && keylen > 40 && xt->version < 1.4)
- xt->version = 1.4;
-
- id = fz_dictgets(xt->trailer, "ID");
- obj = fz_dictgets(xt->trailer, "Encrypt");
- if (fz_isindirect(obj)) {
- pdf_loadindirect(&obj, xt, obj, nil);
- }
- if (obj && id) {
- pdf_newdecrypt(&xt->crypt, obj, id);
- error = pdf_setpassword(xt->crypt, password);
- if (error) fz_abort(error);
- }
-
- id = fz_dictgets(xt->trailer, "ID");
- if (!id)
- fz_parseobj(&id, "[ (foobar) (foobar) ]");
-
- if (doencrypt)
- pdf_newencrypt(&encrypt, &encryptdict, userpw, ownerpw, perms, keylen, id);
-
- out = fopen(argv[optind + 1], "w");
- if (!out) {
- fz_abort(fz_throw("open(%s): %s", argv[optind + 1], strerror(errno)));
- }
-
- fprintf(out, "%%PDF-%.1f\n\n", xt->version);
-
- ofslist = fz_malloc(sizeof(int) * (xt->size + 1));
- genlist = fz_malloc(sizeof(int) * (xt->size + 1));
- uselist = fz_malloc(sizeof(int) * (xt->size + 1));
-
- lastfree = 0;
-
- ofslist[0] = 0;
- genlist[0] = 65535;
- uselist[0] = 0;
-
- for (i = 1; i < xt->size; i++) {
- ofslist[i] = 0;
- genlist[i] = 0;
- uselist[i] = 1;
- }
+ error = pdf_newxref(&xref);
+ if (error)
+ fz_abort(error);
- /* garbage collect from roots in trailer */
- if (dogc)
- {
- for (i = 1; i < xt->size; i++)
- uselist[i] = 0;
-
- obj = fz_dictgets(xt->trailer, "Info");
- if (fz_isindirect(obj))
- garbagecollect(obj);
-
- obj = fz_dictgets(xt->trailer, "Root");
- if (fz_isindirect(obj))
- garbagecollect(obj);
+ if (dorepair)
+ error = pdf_repairxref(xref, infile);
+ else
+ error = pdf_openxref(xref, infile);
+ if (error)
+ fz_abort(error);
- obj = fz_dictgets(xt->trailer, "ID");
- if (fz_isindirect(obj))
- garbagecollect(obj);
- }
+ error = pdf_decryptxref(xref);
+ if (error)
+ fz_abort(error);
- /* pretty print objects */
- for (i = 0; i < xt->size; i++)
+ if (xref->crypt)
{
- if (xt->table[i].type == 0)
- uselist[i] = 0;
-
- if (xt->table[i].type == 0)
- genlist[i] = xt->table[i].gen;
- if (xt->table[i].type == 1)
- genlist[i] = xt->table[i].gen;
- if (xt->table[i].type == 2)
- genlist[i] = 0;
-
- if (dogc && !uselist[i])
- continue;
-
- if (xt->table[i].type == 1 || xt->table[i].type == 2)
- {
- ofslist[i] = ftell(out);
- saveobject(i, genlist[i]);
- }
- }
-
- /* add encryption dictionary if we crypted */
- if (encryptdict) {
- xt->size ++;
- ofslist[xt->size - 1] = ftell(out);
- genlist[xt->size - 1] = 0;
- uselist[xt->size - 1] = 1;
- fprintf(out, "%d %d obj\n", xt->size - 1, 0);
- printobj(out, encryptdict);
- fprintf(out, "\nendobj\n\n");
- }
-
- /* construct linked list of free object slots */
- lastfree = 0;
- for (i = 1; i < xt->size; i++) {
- if (!uselist[i]) {
- genlist[i] ++;
- ofslist[lastfree] = i;
- lastfree = i;
- }
+ error = pdf_setpassword(xref->crypt, password);
+ if (error) fz_abort(error);
}
- savexref();
+ if (doexpand)
+ expandstreams(xref);
- pdf_closexref(xt);
+printf("saving %s...\n", outfile);
+ error = pdf_savepdf(xref, outfile);
+ if (error)
+ fz_abort(error);
- fclose(out);
+ pdf_closexref(xref);
return 0;
}
diff --git a/test/pdfdebug.c b/test/pdfdebug.c
index d63a720c..ddc10dff 100644
--- a/test/pdfdebug.c
+++ b/test/pdfdebug.c
@@ -5,11 +5,10 @@ static char *password = "";
static int dodecode = 0;
static int dorepair = 0;
static int doprintxref = 0;
-static int doprintpages = 0;
void usage()
{
- fprintf(stderr, "usage: mupdf [-drxp] [-u password] file.pdf\n");
+ fprintf(stderr, "usage: pdfdebug [-drx] [-u password] file.pdf [oid ...]\n");
exit(1);
}
@@ -127,114 +126,11 @@ void printobject(pdf_xref *xref, int oid, int gid)
fz_dropobj(obj);
}
-/*
- * Draw page
- */
-
-void runcsi(pdf_xref *xref, pdf_csi *csi, pdf_resources *rdb, fz_obj *stmref)
-{
- fz_error *error;
-
- error = pdf_openstream(xref, stmref);
- if (error) fz_abort(error);
-
- error = pdf_runcsi(csi, rdb, xref->file);
- if (error) fz_abort(error);
-
- pdf_closestream(xref);
-}
-
-void showpage(pdf_xref *xref, fz_obj *page)
-{
- fz_error *error;
- pdf_csi *csi;
- pdf_resources *rdb = nil;
- fz_obj *resources;
- fz_obj *contents;
- int i;
-
- fz_debugobj(page);
- printf("\n");
-
- resources = fz_dictgets(page, "Resources");
- if (resources)
- {
- error = pdf_resolve(&resources, xref);
- if (error) fz_abort(error);
-
- error = pdf_loadresources(&rdb, xref, resources);
- if (error) fz_abort(error);
-
- // parse resources into native res dict
- fz_dropobj(resources);
- }
- else
- fz_abort(fz_throw("syntaxerror: missing resource dictionary"));
-
-printf("resources:\n");
-printf(" font:\n");
-fz_debugobj(rdb->font);
-printf("\n extgstate:\n");
-fz_debugobj(rdb->extgstate);
-printf("\nfitz tree:\n");
-
- error = pdf_newcsi(&csi);
- if (error) fz_abort(error);
-
- contents = fz_dictgets(page, "Contents");
- if (contents)
- {
- if (fz_isarray(contents))
- {
- for (i = 0; i < fz_arraylen(contents); i++)
- {
- runcsi(xref, csi, rdb, fz_arrayget(contents, i));
- }
- }
- else
- {
- // XXX resolve and check if it is an array
- runcsi(xref, csi, rdb, contents);
- }
- }
-
- fz_debugtree(csi->tree);
-
- {
- fz_pixmap *pix;
- fz_renderer *gc;
- fz_matrix ctm;
-
-#define W 612
-#define H 792
-
-#define xW 1106
-#define xH 1548
-
- fz_newrenderer(&gc);
- fz_newpixmap(&pix, 0, 0, W, H, 1, 0);
- ctm = fz_concat(fz_translate(0, -H), fz_scale(1,-1));
-
- memset(pix->samples, 0x00, pix->stride * pix->h * 2);
-
-printf("rendering!\n");
- fz_rendernode(gc, csi->tree->root, ctm, pix);
-printf("done!\n");
- fz_debugpixmap(pix);
-
- fz_freepixmap(pix);
- fz_freerenderer(gc);
- }
-
- pdf_freecsi(csi);
-}
-
int main(int argc, char **argv)
{
fz_error *error;
char *filename;
pdf_xref *xref;
- pdf_pagetree *pages;
int c;
while ((c = getopt(argc, argv, "drxopu:")) != -1)
@@ -250,9 +146,6 @@ int main(int argc, char **argv)
case 'x':
doprintxref ++;
break;
- case 'p':
- doprintpages ++;
- break;
case 'u':
password = optarg;
break;
@@ -290,48 +183,19 @@ int main(int argc, char **argv)
if (doprintxref)
pdf_debugxref(xref);
- if (doprintpages)
+ if (optind == argc)
{
- error = pdf_loadpagetree(&pages, xref);
- if (error) fz_abort(error);
-
- if (optind == argc)
- {
- printf("pagetree\n");
- pdf_debugpagetree(pages);
- printf("\n");
- }
- else
- {
- for ( ; optind < argc; optind++)
- {
- int page = atoi(argv[optind]);
- if (page < 1 || page > pages->count)
- fprintf(stderr, "page out of bounds: %d\n", page);
- printf("page %d\n", page);
- showpage(xref, pages->pobj[page - 1]);
- }
- }
+ printf("trailer\n");
+ fz_debugobj(xref->trailer);
+ printf("\n");
}
- else
+ for ( ; optind < argc; optind++)
{
- if (optind == argc)
- {
- printf("trailer\n");
- fz_debugobj(xref->trailer);
- printf("\n");
- }
-
- for ( ; optind < argc; optind++)
- {
- printobject(xref, atoi(argv[optind]), 0);
- printf("\n");
- }
+ printobject(xref, atoi(argv[optind]), 0);
+ printf("\n");
}
-printf("done.\n");
-
pdf_closexref(xref);
return 0;