diff options
-rw-r--r-- | Jamfile | 2 | ||||
-rw-r--r-- | filter/filec.c | 8 | ||||
-rw-r--r-- | filter/filer.c | 1 | ||||
-rw-r--r-- | include/fitz/object.h | 4 | ||||
-rw-r--r-- | include/fitz/pixmap.h | 11 | ||||
-rw-r--r-- | include/fitz/render.h | 11 | ||||
-rw-r--r-- | include/mupdf.h | 105 | ||||
-rw-r--r-- | mupdf/cmap.c | 2 | ||||
-rw-r--r-- | mupdf/doctor.c | 48 | ||||
-rw-r--r-- | mupdf/font.c | 2 | ||||
-rw-r--r-- | mupdf/fontfile.c | 2 | ||||
-rw-r--r-- | mupdf/interpret.c | 2 | ||||
-rw-r--r-- | mupdf/open.c | 190 | ||||
-rw-r--r-- | mupdf/pagetree.c | 6 | ||||
-rw-r--r-- | mupdf/parse.c | 14 | ||||
-rw-r--r-- | mupdf/repair.c | 110 | ||||
-rw-r--r-- | mupdf/resources.c | 2 | ||||
-rw-r--r-- | mupdf/save.c | 206 | ||||
-rw-r--r-- | mupdf/stream.c | 301 | ||||
-rw-r--r-- | mupdf/xref.c | 339 | ||||
-rw-r--r-- | object/simple.c | 4 | ||||
-rw-r--r-- | render/pixmap.c | 85 | ||||
-rw-r--r-- | render/render.c | 190 | ||||
-rw-r--r-- | test/pdfclean.c | 37 | ||||
-rw-r--r-- | test/pdfdebug.c | 61 | ||||
-rw-r--r-- | test/pdfmerge.c | 44 | ||||
-rw-r--r-- | test/pdfrip.c | 39 | ||||
-rw-r--r-- | tests/t-filter.c | 2 | ||||
-rw-r--r-- | tree/debug.c | 1 |
29 files changed, 893 insertions, 936 deletions
@@ -87,12 +87,12 @@ Library libmupdf : mupdf/lex.c mupdf/parse.c mupdf/crypt.c - mupdf/stream.c mupdf/open.c mupdf/repair.c mupdf/save.c mupdf/xref.c + mupdf/stream.c mupdf/doctor.c mupdf/cmap.c diff --git a/filter/filec.c b/filter/filec.c index ec81c873..0c4d034a 100644 --- a/filter/filec.c +++ b/filter/filec.c @@ -93,18 +93,18 @@ fz_openbuffer(fz_file **filep, fz_buffer *buf, int mode) if (mode == FZ_READ) { - file->in = buf; - error = fz_newbuffer(&file->out, FZ_BUFSIZE); + file->out = buf; + error = fz_newbuffer(&file->in, FZ_BUFSIZE); if (error) goto cleanup; } else { - error = fz_newbuffer(&file->in, FZ_BUFSIZE); + error = fz_newbuffer(&file->out, FZ_BUFSIZE); if (error) goto cleanup; - file->out = buf; + file->in = buf; } return nil; diff --git a/filter/filer.c b/filter/filer.c index 7828fb0e..ead97bdc 100644 --- a/filter/filer.c +++ b/filter/filer.c @@ -238,6 +238,7 @@ fz_readfile(fz_buffer **bufp, fz_file *file) real->rp = buf; real->wp = buf + pos; real->ep = buf + pos; + real->eof = 1; return nil; } diff --git a/include/fitz/object.h b/include/fitz/object.h index 2a9ab15f..c564b70b 100644 --- a/include/fitz/object.h +++ b/include/fitz/object.h @@ -92,8 +92,8 @@ float fz_toreal(fz_obj *obj); char *fz_toname(fz_obj *obj); char *fz_tostringbuf(fz_obj *obj); int fz_tostringlen(fz_obj *obj); -int fz_toobjid(fz_obj *obj); -int fz_togenid(fz_obj *obj); +int fz_tonum(fz_obj *obj); +int fz_togen(fz_obj *obj); void *fz_topointer(fz_obj *obj); int fz_arraylen(fz_obj *array); diff --git a/include/fitz/pixmap.h b/include/fitz/pixmap.h index 90071a30..f46c2c05 100644 --- a/include/fitz/pixmap.h +++ b/include/fitz/pixmap.h @@ -3,6 +3,7 @@ typedef struct fz_colorspace_s fz_colorspace; struct fz_pixmap_s { + int refcount; int x, y, w, h; int n, a; int stride; @@ -11,12 +12,10 @@ struct fz_pixmap_s }; fz_error *fz_newpixmap(fz_pixmap **mapp, int x, int y, int w, int h, int n, int a); +fz_pixmap *fz_keeppixmap(fz_pixmap *map); +void fz_droppixmap(fz_pixmap *map); void fz_clearpixmap(fz_pixmap *map); -void fz_freepixmap(fz_pixmap *map); -void fz_blendover(short *C, short *A, short *B, int n); -void fz_blendin(short *C, short *A, short *B, int n); -void fz_blendout(short *C, short *A, short *B, int n); -void fz_blendatop(short *C, short *A, short *B, int n); -void fz_blendxor(short *C, short *A, short *B, int n); +void fz_blendover(fz_pixmap *dst, fz_pixmap *fg, fz_pixmap *bg); +void fz_blendmask(fz_pixmap *dst, fz_pixmap *color, fz_pixmap *shape); diff --git a/include/fitz/render.h b/include/fitz/render.h index 4024bfec..09c439c2 100644 --- a/include/fitz/render.h +++ b/include/fitz/render.h @@ -3,9 +3,10 @@ typedef struct fz_renderer_s fz_renderer; fz_error *fz_newrenderer(fz_renderer **gcp); void fz_freerenderer(fz_renderer *gc); -fz_error *fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm, fz_pixmap *out); -fz_error *fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm, fz_pixmap *out); -fz_error *fz_rendertransform(fz_renderer *gc, fz_transformnode *xform, fz_matrix ctm, fz_pixmap *out); -fz_error *fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm, fz_pixmap *out); -fz_error *fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm, fz_pixmap *out); +fz_error *fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm); +fz_error *fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm); +fz_error *fz_rendertransform(fz_renderer *gc, fz_transformnode *xform, fz_matrix ctm); +fz_error *fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm); +fz_error *fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm); +fz_error *fz_rendertree(fz_pixmap **out, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, fz_rect bbox); diff --git a/include/mupdf.h b/include/mupdf.h index cbacdbd3..8d0da5f2 100644 --- a/include/mupdf.h +++ b/include/mupdf.h @@ -31,7 +31,7 @@ int pdf_lex(fz_file *f, unsigned char *buf, int n, int *len); fz_error *pdf_parsearray(fz_obj **op, fz_file *f, unsigned char *buf, int cap); fz_error *pdf_parsedict(fz_obj **op, fz_file *f, unsigned char *buf, int cap); fz_error *pdf_parsestmobj(fz_obj **op, fz_file *f, unsigned char *buf, int cap); -fz_error *pdf_parseindobj(fz_obj **op, fz_file *f, unsigned char *buf, int cap, int *oid, int *gid, int *stmofsj); +fz_error *pdf_parseindobj(fz_obj **op, fz_file *f, unsigned char *buf, int cap, int *oid, int *gid, int *stmofs); /* * xref and syntax object api @@ -43,23 +43,27 @@ typedef struct pdf_crypt_s pdf_crypt; struct pdf_xref_s { + fz_file *file; + fz_file *stream; float version; + int startxref; + fz_obj *trailer; /* TODO split this into root/info/encrypt/id */ pdf_crypt *crypt; - fz_file *file; - int size; - int capacity; + + int len; + int cap; pdf_xrefentry *table; - fz_obj *trailer; - int startxref; - fz_hashtable *store; }; struct pdf_xrefentry_s { - unsigned int ofs; /* file offset / objstm object number */ - unsigned short gen; /* generation / objstm index */ - char type; /* 0=unset (f)ree i(n)use (o)bjstm (d)elete (a)dd */ - char mark; /* for garbage collection etc */ + unsigned int ofs; /* file offset / objstm object number */ + unsigned short gen; /* generation / objstm index */ + char type; /* 0=unset (f)ree i(n)use (o)bjstm (d)elete (a)dd */ + char mark; /* for garbage collection etc */ + fz_buffer *stmbuf; /* in-memory stream */ + unsigned int stmofs; /* on-disk stream */ + fz_obj *obj; /* stored/cached object */ }; struct pdf_crypt_s @@ -77,16 +81,6 @@ struct pdf_crypt_s int keylen; }; -/* stream.c */ -fz_error *pdf_buildfilter(fz_filter**, pdf_xref*, fz_obj *stm, int oid, int gid); -fz_error *pdf_openrawstream0(pdf_xref*, fz_obj *stmobj, int oid, int gid, int ofs); -fz_error *pdf_readrawstream0(fz_buffer **bufp, pdf_xref*, fz_obj *stmobj, int oid, int gid, int ofs); -fz_error *pdf_openstream0(pdf_xref*, fz_obj *stmobj, int oid, int gid, int ofs); -fz_error *pdf_openstream(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); -void pdf_closestream(pdf_xref*); - /* crypt.c */ fz_error *pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id); fz_error *pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj *id); @@ -95,44 +89,43 @@ fz_error *pdf_cryptstm(fz_filter **fp, pdf_crypt *crypt, int oid, int gid); void pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int oid, int gid); void pdf_freecrypt(pdf_crypt *crypt); -/* repair.c */ -fz_error *pdf_repairxref(pdf_xref*, char *filename); - -/* open.c */ -fz_error *pdf_openxref(pdf_xref*, char *filename); -fz_error *pdf_readobjstm(pdf_xref *xref, int oid, int gid, unsigned char *buf, int cap); - -/* xref.c */ -fz_error *pdf_newxref(pdf_xref **xrefp); -fz_error *pdf_emptyxref(pdf_xref *xref, float version); -fz_error *pdf_decryptxref(pdf_xref *xref); -void pdf_closexref(pdf_xref*); -void pdf_debugxref(pdf_xref*); - -fz_obj *pdf_findstoredobject(fz_hashtable *store, int oid, int gid); -fz_buffer *pdf_findstoredstream(fz_hashtable *store, int oid, int gid); -fz_error *pdf_deletestoredobject(fz_hashtable *store, int oid, int gid); -fz_error *pdf_deletestoredstream(fz_hashtable *store, int oid, int gid); -fz_error *pdf_storeobject(fz_hashtable *store, int oid, int gid, fz_obj *obj); -fz_error *pdf_storestream(fz_hashtable *store, int oid, int gid, fz_buffer *buf); - -fz_error *pdf_createobject(pdf_xref *xref, int *oidp, int *gidp); -fz_error *pdf_deleteobject(pdf_xref *xref, int oid, int gid); -fz_error *pdf_saveobject(pdf_xref *xref, int oid, int gid, fz_obj *obj); -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); - -/* doctor.c */ +/* --- */ + +fz_error *pdf_repairpdf(pdf_xref **, char *filename); +fz_error *pdf_openpdf(pdf_xref **, char *filename); +fz_error *pdf_newpdf(pdf_xref **); + +fz_error *pdf_updatepdf(pdf_xref *, char *filename); +fz_error *pdf_savepdf(pdf_xref *, char *filename, pdf_crypt *encrypt); + +void pdf_debugpdf(pdf_xref *); +void pdf_closepdf(pdf_xref *); + +fz_error *pdf_allocobject(pdf_xref *, int *oidp, int *genp); +fz_error *pdf_deleteobject(pdf_xref *, int oid, int gen); +fz_error *pdf_updateobject(pdf_xref *, int oid, int gen, fz_obj *obj); +fz_error *pdf_updatestream(pdf_xref *, int oid, int gen, fz_buffer *stm); + +fz_error *pdf_cacheobject(pdf_xref *, int oid, int gen); +fz_error *pdf_loadobject(fz_obj **objp, pdf_xref *, int oid, int gen); +fz_error *pdf_loadindirect(fz_obj **objp, pdf_xref *, fz_obj *ref); +fz_error *pdf_resolve(fz_obj **reforobj, pdf_xref *); + +int pdf_isstream(pdf_xref *xref, int oid, int gen); +fz_error *pdf_loadrawstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen); +fz_error *pdf_loadstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen); +fz_error *pdf_openrawstream(pdf_xref *, int oid, int gen); +fz_error *pdf_openstream(pdf_xref *, int oid, int gen); +void pdf_closestream(pdf_xref *); + fz_error *pdf_garbagecollect(pdf_xref *xref); fz_error *pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *old); -/* save.c */ -fz_error *pdf_saveincrementalpdf(pdf_xref *xref, char *path); -fz_error *pdf_savepdf(pdf_xref *xref, char *path, pdf_crypt *encrypt); +/* private */ +fz_error *pdf_loadobjstm(pdf_xref *xref, int oid, int gen, unsigned char *buf, int cap); +fz_error *pdf_decryptpdf(pdf_xref *xref); + +/* --- */ /* * high-level semantic objects for resources and pages diff --git a/mupdf/cmap.c b/mupdf/cmap.c index b043ab61..54ee5b0f 100644 --- a/mupdf/cmap.c +++ b/mupdf/cmap.c @@ -389,7 +389,7 @@ fz_debugobj(stmobj); printf("\n"); fflush(stdout); - error = pdf_openstream(xref, stmref); + error = pdf_openstream(xref, fz_tonum(stmref), fz_togen(stmref)); if (error) goto cleanup; diff --git a/mupdf/doctor.c b/mupdf/doctor.c index c951276b..8596c7ba 100644 --- a/mupdf/doctor.c +++ b/mupdf/doctor.c @@ -42,9 +42,9 @@ sweepref(pdf_xref *xref, fz_obj *ref) fz_obj *obj; int oid; - oid = fz_toobjid(ref); + oid = fz_tonum(ref); - if (oid < 0 || oid >= xref->size) + if (oid < 0 || oid >= xref->len) return fz_throw("rangecheck: object number out of range"); if (xref->table[oid].mark) @@ -52,7 +52,7 @@ sweepref(pdf_xref *xref, fz_obj *ref) xref->table[oid].mark = 1; - error = pdf_loadobject(&obj, xref, ref, nil); + error = pdf_loadindirect(&obj, xref, ref); if (error) return error; @@ -77,26 +77,21 @@ pdf_garbagecollect(pdf_xref *xref) fz_error *error; int i, g; - for (i = 0; i < xref->size; i++) + for (i = 0; i < xref->len; i++) xref->table[i].mark = 0; error = sweepobj(xref, xref->trailer); if (error) return error; - for (i = 0; i < xref->size; i++) + for (i = 0; i < xref->len; i++) { pdf_xrefentry *x = xref->table + i; g = x->gen; if (x->type == 'o') g = 0; - if (!x->mark && x->type != 'f' && x->type != 'd') - { - error = pdf_deleteobject(xref, i, g); - if (error) - return error; - } + pdf_deleteobject(xref, i, g); } return nil; @@ -121,8 +116,8 @@ remaprefs(fz_obj **newp, fz_obj *old, struct pair *map, int n) if (fz_isindirect(old)) { - o = fz_toobjid(old); - g = fz_togenid(old); + o = fz_tonum(old); + g = fz_togen(old); for (i = 0; i < n; i++) if (map[i].soid == o && map[i].sgen == g) return fz_newindirect(newp, map[i].doid, map[i].dgen); @@ -184,17 +179,16 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) struct pair *map; fz_obj *old, *new; fz_buffer *stm; - int stmofs; int i, n; - for (i = 0; i < src->size; i++) + for (i = 0; i < src->len; i++) src->table[i].mark = 0; error = sweepobj(src, root); if (error) return error; - for (n = 0, i = 0; i < src->size; i++) + for (n = 0, i = 0; i < src->len; i++) if (src->table[i].mark) n++; @@ -202,7 +196,7 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) if (!map) return fz_outofmem; - for (n = 0, i = 0; i < src->size; i++) + for (n = 0, i = 0; i < src->len; i++) { if (src->table[i].mark) { @@ -210,7 +204,7 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) map[n].sgen = src->table[i].gen; if (src->table[i].type == 'o') map[n].sgen = 0; - error = pdf_createobject(dst, &map[n].doid, &map[n].dgen); + error = pdf_allocobject(dst, &map[n].doid, &map[n].dgen); if (error) goto cleanup; n++; @@ -223,22 +217,16 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) for (i = 0; i < n; i++) { - error = pdf_loadobject0(&old, src, map[i].soid, map[i].sgen, &stmofs); + error = pdf_loadobject(&old, src, map[i].soid, map[i].sgen); if (error) goto cleanup; - if (stmofs != -1) + if (pdf_isstream(src, map[i].soid, map[i].sgen)) { - error = pdf_readrawstream0(&stm, src, old, - map[i].soid, map[i].sgen, stmofs); + error = pdf_loadrawstream(&stm, src, map[i].soid, map[i].sgen); if (error) goto cleanup; - - error = pdf_savestream(dst, map[i].doid, map[i].dgen, stm); - if (error) { - fz_dropobj(old); - goto cleanup; - } + pdf_updatestream(dst, map[i].doid, map[i].dgen, stm); } error = remaprefs(&new, old, map, n); @@ -246,10 +234,8 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) if (error) goto cleanup; - error = pdf_saveobject(dst, map[i].doid, map[i].dgen, new); + pdf_updateobject(dst, map[i].doid, map[i].dgen, new); fz_dropobj(new); - if (error) - goto cleanup; } fz_free(map); diff --git a/mupdf/font.c b/mupdf/font.c index 7c75f585..258dbe2a 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -565,7 +565,7 @@ printf(" embedded CMap\n"); fz_buffer *buf; int len; - error = pdf_readstream(&buf, xref, cidtogidmap); + error = pdf_loadstream(&buf, xref, fz_tonum(cidtogidmap), fz_togen(cidtogidmap)); if (error) goto cleanup; diff --git a/mupdf/fontfile.c b/mupdf/fontfile.c index d8646a7e..99414b90 100644 --- a/mupdf/fontfile.c +++ b/mupdf/fontfile.c @@ -205,7 +205,7 @@ pdf_loadembeddedfont(void **fontp, pdf_xref *xref, fz_obj *stmref) if (error) return error; - error = pdf_readstream(&buf, xref, stmref); + error = pdf_loadstream(&buf, xref, fz_tonum(stmref), fz_togen(stmref)); if (error) return error; diff --git a/mupdf/interpret.c b/mupdf/interpret.c index 2053422b..57d02f06 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -96,7 +96,7 @@ runextgstate(pdf_gstate *gstate, pdf_resources *rdb, fz_obj *extgstate) { fz_obj *ref, *obj; ref = fz_arrayget(val, 0); - sprintf(name, "$f.%d.%d", fz_toobjid(ref), fz_togenid(ref)); + sprintf(name, "$f.%d.%d", fz_tonum(ref), fz_togen(ref)); obj = fz_dictgets(rdb->font, name); if (!obj) return fz_throw("syntaxerror: missing resource"); diff --git a/mupdf/open.c b/mupdf/open.c index 52ee4f29..7fa94268 100644 --- a/mupdf/open.c +++ b/mupdf/open.c @@ -12,54 +12,56 @@ static inline int iswhite(int ch) */ static fz_error * -loadversion(float *version, fz_file *file) +loadversion(pdf_xref *xref) { char buf[20]; int n; - n = fz_seek(file, 0, 0); + n = fz_seek(xref->file, 0, 0); if (n < 0) - return fz_ferror(file); + return fz_ferror(xref->file); - fz_readline(file, buf, sizeof buf); + fz_readline(xref->file, buf, sizeof buf); if (memcmp(buf, "%PDF-", 5) != 0) - return fz_throw("syntaxerror: missing magic pdf marker"); + return fz_throw("syntaxerror: corrupt version marker"); - *version = atof(buf + 5); + xref->version = atof(buf + 5); return nil; } static fz_error * -readstartxref(int *ofs, fz_file *file) +readstartxref(pdf_xref *xref) { unsigned char buf[1024]; int t, n; int i; - t = fz_seek(file, 0, 2); + t = fz_seek(xref->file, 0, 2); if (t == -1) - return fz_ferror(file); + return fz_ferror(xref->file); - t = fz_seek(file, MAX(0, t - ((int)sizeof buf)), 0); + t = fz_seek(xref->file, MAX(0, t - ((int)sizeof buf)), 0); if (t == -1) - return fz_ferror(file); + return fz_ferror(xref->file); - n = fz_read(file, buf, sizeof buf); + n = fz_read(xref->file, buf, sizeof buf); if (n == -1) - return fz_ferror(file); + return fz_ferror(xref->file); - for (i = n - 9; i >= 0; i--) { - if (memcmp(buf + i, "startxref", 9) == 0) { + for (i = n - 9; i >= 0; i--) + { + if (memcmp(buf + i, "startxref", 9) == 0) + { i += 9; while (iswhite(buf[i]) && i < n) i ++; - *ofs = atoi(buf + i); + xref->startxref = atoi(buf + i); return nil; } } - return fz_throw("syntaxerror: missing startxref"); + return fz_throw("syntaxerror: could not find startxref"); } /* @@ -67,7 +69,7 @@ readstartxref(int *ofs, fz_file *file) */ static fz_error * -readoldtrailer(fz_obj **objp, fz_file *file, unsigned char *buf, int cap) +readoldtrailer(pdf_xref *xref, unsigned char *buf, int cap) { int ofs, len; char *s; @@ -75,64 +77,64 @@ readoldtrailer(fz_obj **objp, fz_file *file, unsigned char *buf, int cap) int t; int c; - fz_readline(file, buf, cap); + fz_readline(xref->file, buf, cap); if (strcmp(buf, "xref") != 0) return fz_throw("syntaxerror: missing xref"); while (1) { - c = fz_peekbyte(file); + c = fz_peekbyte(xref->file); if (!(c >= '0' && c <= '9')) break; - n = fz_readline(file, buf, cap); - if (n < 0) return fz_ferror(file); + n = fz_readline(xref->file, buf, cap); + if (n < 0) return fz_ferror(xref->file); s = buf; ofs = atoi(strsep(&s, " ")); len = atoi(strsep(&s, " ")); - t = fz_tell(file); - if (t < 0) return fz_ferror(file); + t = fz_tell(xref->file); + if (t < 0) return fz_ferror(xref->file); - n = fz_seek(file, t + 20 * len, 0); - if (n < 0) return fz_ferror(file); + n = fz_seek(xref->file, t + 20 * len, 0); + if (n < 0) return fz_ferror(xref->file); } - t = pdf_lex(file, buf, cap, &n); + t = pdf_lex(xref->file, buf, cap, &n); if (t != PDF_TTRAILER) - return fz_throw("syntaxerror: missing trailer"); + return fz_throw("syntaxerror: expected trailer"); - t = pdf_lex(file, buf, cap, &n); + t = pdf_lex(xref->file, buf, cap, &n); if (t != PDF_TODICT) - return fz_throw("syntaxerror: trailer must be dictionary"); + return fz_throw("syntaxerror: expected trailer dictionary"); - return pdf_parsedict(objp, file, buf, cap); + return pdf_parsedict(&xref->trailer, xref->file, buf, cap); } static fz_error * -readnewtrailer(fz_obj **objp, fz_file *file, unsigned char *buf, int cap) +readnewtrailer(pdf_xref *xref, unsigned char *buf, int cap) { - return pdf_parseindobj(objp, file, buf, cap, nil, nil, nil); + return pdf_parseindobj(&xref->trailer, xref->file, buf, cap, nil, nil, nil); } static fz_error * -readtrailer(fz_obj **objp, fz_file *file, int ofs, unsigned char *buf, int cap) +readtrailer(pdf_xref *xref, unsigned char *buf, int cap) { int n; int c; - n = fz_seek(file, ofs, 0); + n = fz_seek(xref->file, xref->startxref, 0); if (n < 0) - return fz_ferror(file); + return fz_ferror(xref->file); - c = fz_peekbyte(file); + c = fz_peekbyte(xref->file); if (c == 'x') - return readoldtrailer(objp, file, buf, cap); + return readoldtrailer(xref, buf, cap); else if (c >= '0' && c <= '9') - return readnewtrailer(objp, file, buf, cap); + return readnewtrailer(xref, buf, cap); - return fz_throw("syntaxerror: missing xref"); + return fz_throw("syntaxerror: could not find xref"); } /* @@ -151,7 +153,7 @@ readoldxref(fz_obj **trailerp, pdf_xref *xref, unsigned char *buf, int cap) fz_readline(xref->file, buf, cap); if (strcmp(buf, "xref") != 0) - return fz_throw("syntaxerror: missing xref"); + return fz_throw("syntaxerror: expected xref"); while (1) { @@ -183,10 +185,10 @@ readoldxref(fz_obj **trailerp, pdf_xref *xref, unsigned char *buf, int cap) t = pdf_lex(xref->file, buf, cap, &n); if (t != PDF_TTRAILER) - return fz_throw("syntaxerror: missing trailer"); + return fz_throw("syntaxerror: expected trailer"); t = pdf_lex(xref->file, buf, cap, &n); if (t != PDF_TODICT) - return fz_throw("syntaxerror: trailer must be dictionary"); + return fz_throw("syntaxerror: expected trailer dictionary"); return pdf_parsedict(trailerp, xref->file, buf, cap); } @@ -197,14 +199,24 @@ readnewxref(fz_obj **trailerp, pdf_xref *xref, unsigned char *buf, int cap) fz_error *error; fz_obj *trailer; fz_obj *obj; - int oid, gid, stmofs; + int oid, gen, stmofs; int size, w0, w1, w2, i0, i1; int i, n; - error = pdf_parseindobj(&trailer, xref->file, buf, cap, &oid, &gid, &stmofs); + error = pdf_parseindobj(&trailer, xref->file, buf, cap, &oid, &gen, &stmofs); if (error) return error; + if (oid < 0 || oid >= xref->len) { + error = fz_throw("rangecheck: object id out of range"); + goto cleanup; + } + + xref->table[oid].type = 'n'; + xref->table[oid].gen = gen; + xref->table[oid].obj = fz_keepobj(trailer); + xref->table[oid].stmofs = stmofs; + obj = fz_dictgets(trailer, "Size"); if (!obj) { error = fz_throw("syntaxerror: xref stream missing Size entry"); @@ -231,12 +243,12 @@ readnewxref(fz_obj **trailerp, pdf_xref *xref, unsigned char *buf, int cap) i1 = size; } - if (i0 < 0 || i1 > xref->size) { + if (i0 < 0 || i1 > xref->len) { error = fz_throw("syntaxerror: xref stream has too many entries"); goto cleanup; } - error = pdf_openstream0(xref, trailer, oid, gid, stmofs); + error = pdf_openstream(xref, oid, gen); if (error) goto cleanup; @@ -246,9 +258,9 @@ readnewxref(fz_obj **trailerp, pdf_xref *xref, unsigned char *buf, int cap) int b = 0; int c = 0; - if (fz_peekbyte(xref->file) == EOF) + if (fz_peekbyte(xref->stream) == EOF) { - error = fz_ferror(xref->file); + error = fz_ferror(xref->stream); if (!error) error = fz_throw("syntaxerror: truncated xref stream"); pdf_closestream(xref); @@ -256,11 +268,11 @@ readnewxref(fz_obj **trailerp, pdf_xref *xref, unsigned char *buf, int cap) } for (n = 0; n < w0; n++) - a = (a << 8) + fz_readbyte(xref->file); + a = (a << 8) + fz_readbyte(xref->stream); for (n = 0; n < w1; n++) - b = (b << 8) + fz_readbyte(xref->file); + b = (b << 8) + fz_readbyte(xref->stream); for (n = 0; n < w2; n++) - c = (c << 8) + fz_readbyte(xref->file); + c = (c << 8) + fz_readbyte(xref->stream); if (!xref->table[i].type) { @@ -298,7 +310,7 @@ readxref(fz_obj **trailerp, pdf_xref *xref, int ofs, unsigned char *buf, int cap else if (c >= '0' && c <= '9') return readnewxref(trailerp, xref, buf, cap); - return fz_throw("syntaxerror: missing xref"); + return fz_throw("syntaxerror: expected xref"); } static fz_error * @@ -343,7 +355,7 @@ cleanup: */ fz_error * -pdf_readobjstm(pdf_xref *xref, int oid, int gid, unsigned char *buf, int cap) +pdf_loadobjstm(pdf_xref *xref, int oid, int gen, unsigned char *buf, int cap) { fz_error *error; fz_obj *objstm; @@ -351,12 +363,11 @@ pdf_readobjstm(pdf_xref *xref, int oid, int gid, unsigned char *buf, int cap) int *ofsbuf; fz_obj *obj; - int stmofs; int first; int count; int i, n, t; - error = pdf_loadobject0(&objstm, xref, oid, gid, &stmofs); + error = pdf_loadobject(&objstm, xref, oid, gen); if (error) return error; @@ -369,13 +380,13 @@ pdf_readobjstm(pdf_xref *xref, int oid, int gid, unsigned char *buf, int cap) ofsbuf = fz_malloc(count * sizeof(int)); if (!ofsbuf) { error = fz_outofmem; goto cleanup2; } - error = pdf_openstream0(xref, objstm, oid, gid, stmofs); + error = pdf_openstream(xref, oid, gen); if (error) goto cleanup3; for (i = 0; i < count; i++) { - t = pdf_lex(xref->file, buf, cap, &n); + t = pdf_lex(xref->stream, buf, cap, &n); if (t != PDF_TINT) { error = fz_throw("syntaxerror: corrupt object stream"); @@ -383,7 +394,7 @@ pdf_readobjstm(pdf_xref *xref, int oid, int gid, unsigned char *buf, int cap) } oidbuf[i] = atoi(buf); - t = pdf_lex(xref->file, buf, cap, &n); + t = pdf_lex(xref->stream, buf, cap, &n); if (t != PDF_TINT) { error = fz_throw("syntaxerror: corrupt object stream"); @@ -392,10 +403,10 @@ pdf_readobjstm(pdf_xref *xref, int oid, int gid, unsigned char *buf, int cap) ofsbuf[i] = atoi(buf); } - n = fz_seek(xref->file, first, 0); + n = fz_seek(xref->stream, first, 0); if (n < 0) { - error = fz_ferror(xref->file); + error = fz_ferror(xref->stream); goto cleanup4; } @@ -403,19 +414,19 @@ pdf_readobjstm(pdf_xref *xref, int oid, int gid, unsigned char *buf, int cap) { /* FIXME: seek to first + ofsbuf[i] */ - error = pdf_parsestmobj(&obj, xref->file, buf, cap); + error = pdf_parsestmobj(&obj, xref->stream, buf, cap); if (error) goto cleanup4; - if (oidbuf[i] < 1 || oidbuf[i] >= xref->size) + if (oidbuf[i] < 1 || oidbuf[i] >= xref->len) { error = fz_throw("rangecheck: object number out of range"); goto cleanup4; } - error = pdf_storeobject(xref->store, oidbuf[i], 0, obj); - if (error) - goto cleanup4; + if (xref->table[oidbuf[i]].obj) + fz_dropobj(xref->table[oidbuf[i]].obj); + xref->table[oidbuf[i]].obj = obj; } pdf_closestream(xref); @@ -440,53 +451,76 @@ cleanup1: */ fz_error * -pdf_openxref(pdf_xref *xref, char *filename) +pdf_openpdf(pdf_xref **xrefp, char *filename) { fz_error *error; + pdf_xref *xref; fz_obj *size; int i; unsigned char buf[65536]; /* yeowch! */ + xref = fz_malloc(sizeof (pdf_xref)); + if (!xref) + return fz_outofmem; + + xref->file = nil; + xref->version = 1.0; + xref->startxref = 0; + xref->trailer = nil; + xref->crypt = nil; + + xref->len = 0; + xref->cap = 0; + xref->table = nil; + error = fz_openfile(&xref->file, filename, FZ_READ); if (error) - return error; + goto cleanup; - error = loadversion(&xref->version, xref->file); + error = loadversion(xref); if (error) - return error; + goto cleanup; - error = readstartxref(&xref->startxref, xref->file); + error = readstartxref(xref); if (error) - return error; + goto cleanup; - error = readtrailer(&xref->trailer, xref->file, xref->startxref, buf, sizeof buf); + error = readtrailer(xref, buf, sizeof buf); if (error) - return error; + goto cleanup; size = fz_dictgets(xref->trailer, "Size"); if (!size) return fz_throw("syntaxerror: trailer missing Size entry"); - xref->capacity = fz_toint(size); - xref->size = fz_toint(size); + xref->cap = fz_toint(size); + xref->len = fz_toint(size); - xref->table = fz_malloc(xref->capacity * sizeof(pdf_xrefentry)); + xref->table = fz_malloc(xref->cap * sizeof(pdf_xrefentry)); if (!xref->table) return fz_outofmem; - for (i = 0; i < xref->size; i++) + for (i = 0; i < xref->len; i++) { xref->table[i].ofs = 0; xref->table[i].gen = 0; xref->table[i].type = 0; xref->table[i].mark = 0; + xref->table[i].stmbuf = nil; + xref->table[i].stmofs = 0; + xref->table[i].obj = nil; } error = readxrefsections(xref, xref->startxref, buf, sizeof buf); if (error) return error; + *xrefp = xref; return nil; + +cleanup: + pdf_closepdf(xref); + return error; } diff --git a/mupdf/pagetree.c b/mupdf/pagetree.c index 6ddc07c9..18d07e41 100644 --- a/mupdf/pagetree.c +++ b/mupdf/pagetree.c @@ -68,7 +68,7 @@ loadpagetree(pdf_xref *xref, pdf_pagetree *pages, { kref = fz_arrayget(kids, i); - err = pdf_loadobject(&kobj, xref, kref, nil); + err = pdf_loadindirect(&kobj, xref, kref); if (err) return err; err = loadpagetree(xref, pages, inherit, kobj, kref); @@ -115,11 +115,11 @@ pdf_loadpagetree(pdf_pagetree **pp, pdf_xref *xref) trailer = xref->trailer; ref = fz_dictgets(trailer, "Root"); - err = pdf_loadobject(&catalog, xref, ref, nil); + err = pdf_loadindirect(&catalog, xref, ref); if (err) goto error; ref = fz_dictgets(catalog, "Pages"); - err = pdf_loadobject(&pages, xref, ref, nil); + err = pdf_loadindirect(&pages, xref, ref); if (err) goto error; ref = fz_dictgets(pages, "Count"); diff --git a/mupdf/parse.c b/mupdf/parse.c index 90f7c453..ef6e93a3 100644 --- a/mupdf/parse.c +++ b/mupdf/parse.c @@ -97,7 +97,7 @@ cleanup: if (obj) fz_dropobj(obj); if (ary) fz_dropobj(ary); if (error) return error; - return fz_throw("syntaxerror in array"); + return fz_throw("syntaxerror: corrupt array"); } fz_error * @@ -184,7 +184,7 @@ cleanup: if (val) fz_dropobj(val); if (dict) fz_dropobj(dict); if (error) return error; - return fz_throw("syntaxerror in dictionary"); + return fz_throw("syntaxerror: corrupt dictionary"); } fz_error * @@ -207,7 +207,7 @@ pdf_parsestmobj(fz_obj **op, fz_file *file, unsigned char *buf, int cap) case PDF_TINT: return fz_newint(op, atoi(buf)); } - return fz_throw("syntaxerror in object stream"); + return fz_throw("syntaxerror: corrupt object stream"); } fz_error * @@ -216,7 +216,7 @@ pdf_parseindobj(fz_obj **op, fz_file *file, unsigned char *buf, int cap, { fz_error *error = nil; fz_obj *obj = nil; - int oid, gid, stmofs; + int oid = 0, gid = 0, stmofs; int tok, len; int a, b; @@ -280,14 +280,14 @@ skip: { c = fz_peekbyte(file); if (c != '\n') - fz_warn("corrupt pdf stream (%d %d)\n", oid, gid); + fz_warn("syntaxerror: corrupt pdf stream (%d %d)\n", oid, gid); else c = fz_readbyte(file); } stmofs = fz_tell(file); } else if (tok == PDF_TENDOBJ) - stmofs = -1; + stmofs = 0; else goto cleanup; @@ -300,6 +300,6 @@ skip: cleanup: if (obj) fz_dropobj(obj); if (error) return error; - return fz_throw("syntaxerror in indirect object"); + return fz_throw("syntaxerror: corrupt indirect object (%d %d)", oid, gid); } diff --git a/mupdf/repair.c b/mupdf/repair.c index d12277b6..8742d15f 100644 --- a/mupdf/repair.c +++ b/mupdf/repair.c @@ -4,13 +4,14 @@ struct entry { int oid; - int gid; + int gen; int ofs; + int stmofs; int stmlen; }; static fz_error * -parseobj(fz_file *file, unsigned char *buf, int cap, int *stmlen, +parseobj(fz_file *file, unsigned char *buf, int cap, int *stmofs, int *stmlen, int *isroot, int *isinfo) { fz_error *error; @@ -19,7 +20,6 @@ parseobj(fz_file *file, unsigned char *buf, int cap, int *stmlen, fz_obj *filter; fz_obj *type; int tok, len; - int stmofs; *stmlen = -1; *isroot = 0; @@ -64,16 +64,16 @@ parseobj(fz_file *file, unsigned char *buf, int cap, int *stmlen, fz_readbyte(file); } - stmofs = fz_tell(file); + *stmofs = fz_tell(file); length = fz_dictgets(dict, "Length"); if (fz_isint(length)) { - fz_seek(file, stmofs + fz_toint(length), 0); + fz_seek(file, *stmofs + fz_toint(length), 0); tok = pdf_lex(file, buf, cap, &len); if (tok == PDF_TENDSTREAM) goto atobjend; - fz_seek(file, stmofs, 0); + fz_seek(file, *stmofs, 0); } fz_read(file, buf, 9); @@ -86,7 +86,7 @@ parseobj(fz_file *file, unsigned char *buf, int cap, int *stmlen, buf[8] = c; } - *stmlen = fz_tell(file) - stmofs - 9; + *stmlen = fz_tell(file) - *stmofs - 9; atobjend: tok = pdf_lex(file, buf, cap, &len); @@ -101,51 +101,50 @@ atobjend: } fz_error * -pdf_repairxref(pdf_xref *xref, char *filename) +pdf_repairpdf(pdf_xref **xrefp, char *filename) { fz_error *error; + pdf_xref *xref; fz_file *file; struct entry *list = nil; int listlen; int listcap; - int maxoid; + int maxoid = 0; unsigned char buf[65536]; - int oid, gid; - int tmpofs, oidofs, gidofs; - int stmlen; - int isroot, rootoid = 0, rootgid = 0; - int isinfo, infooid = 0, infogid = 0; + int oid = 0; + int gen = 0; + int tmpofs, oidofs = 0, genofs = 0; + int isroot, rootoid = 0, rootgen = 0; + int isinfo, infooid = 0, infogen = 0; + int stmofs, stmlen; int tok, len; int next; - int n; int i; - listlen = 0; - listcap = 1024; - list = fz_malloc(listcap * sizeof(struct entry)); - if (!list) + xref = fz_malloc(sizeof (pdf_xref)); + if (!xref) return fz_outofmem; - error = fz_openfile(&xref->file, filename, FZ_READ); + xref->file = nil; + xref->version = 0.0; + xref->startxref = 0; + xref->trailer = nil; + xref->crypt = nil; + + error = fz_openfile(&file, filename, FZ_READ); if (error) goto cleanup; - file = xref->file; + xref->file = file; - n = fz_seek(file, 0, 0); - if (n < 0) { - error = fz_ferror(file); + listlen = 0; + listcap = 1024; + list = fz_malloc(listcap * sizeof(struct entry)); + if (!list) goto cleanup; - } - - maxoid = 0; - oid = 0; - gid = 0; - oidofs = 0; - gidofs = 0; while (1) { @@ -154,26 +153,26 @@ pdf_repairxref(pdf_xref *xref, char *filename) tok = pdf_lex(file, buf, sizeof buf, &len); if (tok == PDF_TINT) { - oidofs = gidofs; - oid = gid; - gidofs = tmpofs; - gid = atoi(buf); + oidofs = genofs; + oid = gen; + genofs = tmpofs; + gen = atoi(buf); } if (tok == PDF_TOBJ) { - error = parseobj(file, buf, sizeof buf, &stmlen, &isroot, &isinfo); + error = parseobj(file, buf, sizeof buf, &stmofs, &stmlen, &isroot, &isinfo); if (error) goto cleanup; if (isroot) { rootoid = oid; - rootgid = gid; + rootgen = gen; } if (isinfo) { infooid = oid; - infogid = gid; + infogen = gen; } if (listlen + 1 == listcap) @@ -189,8 +188,9 @@ pdf_repairxref(pdf_xref *xref, char *filename) } list[listlen].oid = oid; - list[listlen].gid = gid; + list[listlen].gen = gen; list[listlen].ofs = oidofs; + list[listlen].stmofs = stmofs; list[listlen].stmlen = stmlen; listlen ++; @@ -207,14 +207,14 @@ pdf_repairxref(pdf_xref *xref, char *filename) error = fz_packobj(&xref->trailer, "<< /Size %i /Root %r >>", - maxoid + 1, rootoid, rootgid); + maxoid + 1, rootoid, rootgen); if (error) goto cleanup; xref->version = 1.3; /* FIXME */ - xref->size = maxoid + 1; - xref->capacity = xref->size; - xref->table = fz_malloc(xref->capacity * sizeof(pdf_xrefentry)); + xref->len = maxoid + 1; + xref->cap = xref->len; + xref->table = fz_malloc(xref->cap * sizeof(pdf_xrefentry)); if (!xref->table) { error = fz_outofmem; goto cleanup; @@ -225,42 +225,50 @@ pdf_repairxref(pdf_xref *xref, char *filename) xref->table[0].ofs = 0; xref->table[0].gen = 65535; - for (i = 1; i < xref->size; i++) + for (i = 1; i < xref->len; i++) { xref->table[i].type = 'f'; xref->table[i].mark = 0; xref->table[i].ofs = 0; xref->table[i].gen = 0; + xref->table[i].stmbuf = nil; + xref->table[i].stmofs = 0; + xref->table[i].obj = nil; } for (i = 0; i < listlen; i++) { xref->table[list[i].oid].type = 'n'; xref->table[list[i].oid].ofs = list[i].ofs; - xref->table[list[i].oid].gen = list[i].gid; + xref->table[list[i].oid].gen = list[i].gen; xref->table[list[i].oid].mark = 0; + xref->table[list[i].oid].stmofs = list[i].stmofs; + /* corrected stream length */ if (list[i].stmlen >= 0) { fz_obj *dict, *length; - error = pdf_loadobject0(&dict, xref, list[i].oid, list[i].gid, nil); + + error = pdf_loadobject(&dict, xref, list[i].oid, list[i].gen); if (error) goto cleanup; + error = fz_newint(&length, list[i].stmlen); if (error) goto cleanup; error = fz_dictputs(dict, "Length", length); if (error) goto cleanup; - error = pdf_saveobject(xref, list[i].oid, list[i].gid, dict); - if (error) - goto cleanup; + + pdf_updateobject(xref, list[i].oid, list[i].gen, dict); + + fz_dropobj(dict); } } next = 0; - for (i = xref->size - 1; i >= 0; i--) + for (i = xref->len - 1; i >= 0; i--) { if (xref->table[i].type == 'f') { @@ -275,6 +283,8 @@ pdf_repairxref(pdf_xref *xref, char *filename) return nil; cleanup: + fz_closefile(file); + fz_free(xref); fz_free(list); return error; } diff --git a/mupdf/resources.c b/mupdf/resources.c index 050b003d..487f8713 100644 --- a/mupdf/resources.c +++ b/mupdf/resources.c @@ -27,7 +27,7 @@ loadextgstatefonts(pdf_resources *rdb, pdf_xref *xref) return fz_throw("syntaxerror in ExtGState/Font"); ref = fz_arrayget(obj, 0); - sprintf(name, "$f.%d.%d", fz_toobjid(ref), fz_togenid(ref)); + sprintf(name, "$f.%d.%d", fz_tonum(ref), fz_togen(ref)); err = pdf_resolve(&ref, xref); if (err) return err; diff --git a/mupdf/save.c b/mupdf/save.c index d0e44c9b..02401cf3 100644 --- a/mupdf/save.c +++ b/mupdf/save.c @@ -4,162 +4,110 @@ #define TIGHT 0 static fz_error * -writestored(fz_file *out, pdf_xref *xref, pdf_crypt *encrypt, int oid) +writestm(fz_file *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen) { - pdf_xrefentry *x = xref->table + oid; fz_error *error; - fz_obj *obj; - fz_buffer *stm; - fz_filter *filter; - int gid; - - gid = x->gen; - if (x->type == 'o') - gid = 0; - - obj = pdf_findstoredobject(xref->store, oid, gid); - stm = pdf_findstoredstream(xref->store, oid, gid); + unsigned char buf[4096]; + fz_filter *ef; + int n; - if (!obj) - return fz_throw("could not find stored object"); + fz_print(out, "stream\n"); if (encrypt) - pdf_cryptobj(encrypt, obj, oid, gid); - - fz_print(out, "%d %d obj\n", oid, gid); - fz_printobj(out, obj, TIGHT); - fz_print(out, "\n"); - - if (stm) { - fz_print(out, "stream\n"); + error = pdf_cryptstm(&ef, encrypt, oid, gen); + if (error) + return error; - if (encrypt) - { - error = pdf_cryptstm(&filter, encrypt, oid, gid); - if (error) - return error; - error = fz_pushfilter(out, filter); - if (error) { - fz_freefilter(filter); - return error; - } + error = fz_pushfilter(out, ef); + if (error) { + fz_freefilter(ef); + return error; } + } - fz_write(out, stm->rp, stm->wp - stm->rp); - - if (encrypt) - fz_popfilter(out); + error = pdf_openrawstream(xref, oid, gen); + if (error) + goto cleanup; - fz_print(out, "endstream\n"); + while (1) + { + n = fz_read(xref->stream, buf, sizeof buf); + if (n == 0) + break; + if (n < 0) + { + error = fz_ferror(xref->stream); + pdf_closestream(xref); + goto cleanup; + } + fz_write(out, buf, n); } - fz_print(out, "endobj\n\n"); + pdf_closestream(xref); - error = fz_ferror(out); - if (error) - return error; + if (encrypt) + fz_popfilter(out); + + fz_print(out, "endstream\n"); return nil; + +cleanup: + if (encrypt) + fz_popfilter(out); + return error; } static fz_error * -writecopy(fz_file *out, pdf_xref *xref, pdf_crypt *encrypt, int oid) +writeobj(fz_file *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen) { pdf_xrefentry *x = xref->table + oid; fz_error *error; - fz_obj *obj; - int stmofs; - fz_filter *ef; - int gid; - int n; - unsigned char buf[4096]; - gid = x->gen; - if (x->type == 'o') - gid = 0; - - error = pdf_loadobject0(&obj, xref, oid, gid, &stmofs); + error = pdf_cacheobject(xref, oid, gen); if (error) return error; if (encrypt) - pdf_cryptobj(encrypt, obj, oid, gid); + pdf_cryptobj(encrypt, x->obj, oid, gen); - fz_print(out, "%d %d obj\n", oid, gid); - fz_printobj(out, obj, TIGHT); + fz_print(out, "%d %d obj\n", oid, gen); + fz_printobj(out, x->obj, TIGHT); fz_print(out, "\n"); - if (stmofs != -1) - { - fz_print(out, "stream\n"); + if (encrypt) + pdf_cryptobj(encrypt, x->obj, oid, gen); - error = pdf_openrawstream0(xref, obj, oid, gid, stmofs); + if (x->stmbuf || x->stmofs) + { + error = writestm(out, xref, encrypt, oid, gen); if (error) - goto cleanup; - - if (encrypt) - { - error = pdf_cryptstm(&ef, encrypt, oid, gid); - if (error) - return error; - error = fz_pushfilter(out, ef); - if (error) { - fz_freefilter(ef); - goto cleanup; - } - } - - while (1) - { - n = fz_read(xref->file, buf, sizeof buf); - if (n == 0) - break; - if (n < 0) - { - error = fz_ferror(xref->file); - fz_popfilter(xref->file); - goto cleanup; - if (encrypt) - fz_popfilter(out); - } - fz_write(out, buf, n); - } - - if (encrypt) - fz_popfilter(out); - - pdf_closestream(xref); - - fz_print(out, "endstream\n"); + return error; } fz_print(out, "endobj\n\n"); error = fz_ferror(out); if (error) - goto cleanup; - - fz_dropobj(obj); + return error; return nil; - -cleanup: - fz_dropobj(obj); - return error; } +#if 0 + static int countmodified(pdf_xref *xref, int oid) { int i; - for (i = oid; i < xref->size; i++) + for (i = oid; i < xref->len; i++) if (xref->table[i].type != 'a' && xref->table[i].type != 'd') return i - oid; return i - oid; } fz_error * -pdf_saveincrementalpdf(pdf_xref *xref, char *path) +pdf_updatepdf(pdf_xref *xref, char *path) { fz_error *error; fz_file *out; @@ -174,12 +122,12 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path) fz_print(out, "\n"); - for (oid = 0; oid < xref->size; oid++) + for (oid = 0; oid < xref->len; oid++) { if (xref->table[oid].type == 'a') { xref->table[oid].ofs = fz_tell(out); - error = writestored(out, xref, xref->crypt, oid); + error = writestoredobj(out, xref, xref->crypt, oid, xref->table[oid].gen); if (error) goto cleanup; } @@ -192,7 +140,7 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path) fz_print(out, "xref\n"); oid = 0; - while (oid < xref->size) + while (oid < xref->len) { n = countmodified(xref, oid); @@ -212,7 +160,7 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path) } oid += n; - while (oid < xref->size && + while (oid < xref->len && xref->table[oid].type != 'a' && xref->table[oid].type != 'd') oid ++; @@ -220,7 +168,7 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path) fz_print(out, "\n"); - fz_print(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->len, xref->startxref); obj = fz_dictgets(xref->trailer, "Root"); fz_print(out,"\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj)); @@ -257,6 +205,8 @@ cleanup: return error; } +#endif + fz_error * pdf_savepdf(pdf_xref *xref, char *path, pdf_crypt *encrypt) { @@ -267,7 +217,7 @@ pdf_savepdf(pdf_xref *xref, char *path, pdf_crypt *encrypt) int *ofsbuf; fz_obj *obj; - ofsbuf = fz_malloc(sizeof(int) * xref->size); + ofsbuf = fz_malloc(sizeof(int) * xref->len); if (!ofsbuf) return fz_outofmem; @@ -281,53 +231,47 @@ pdf_savepdf(pdf_xref *xref, char *path, pdf_crypt *encrypt) 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++) + for (oid = 0; oid < xref->len; oid++) { - if (xref->table[oid].type == 'n' || xref->table[oid].type == 'o') - { - ofsbuf[oid] = fz_tell(out); - error = writecopy(out, xref, encrypt, oid); - if (error) - goto cleanup; - } - else if (xref->table[oid].type == 'a') + pdf_xrefentry *x = xref->table + oid; + if (x->type == 'n' || x->type == 'o' || x->type == 'a') { ofsbuf[oid] = fz_tell(out); - error = writestored(out, xref, encrypt, oid); + error = writeobj(out, xref, encrypt, oid, x->type == 'o' ? 0 : x->gen); if (error) goto cleanup; } else { - ofsbuf[oid] = xref->table[oid].ofs; + ofsbuf[oid] = x->ofs; } } startxref = fz_tell(out); fz_print(out, "xref\n"); - fz_print(out, "0 %d\n", xref->size); + fz_print(out, "0 %d\n", xref->len); - for (oid = 0; oid < xref->size; oid++) + for (oid = 0; oid < xref->len; oid++) { - int gid = xref->table[oid].gen; + int gen = xref->table[oid].gen; int type = xref->table[oid].type; if (type == 'o') - gid = 0; + gen = 0; if (type == 'a' || type == 'o') type = 'n'; if (type == 'd') type = 'f'; - fz_print(out, "%010d %05d %c \n", ofsbuf[oid], gid, type); + fz_print(out, "%010d %05d %c \n", ofsbuf[oid], gen, type); } fz_print(out, "\n"); - fz_print(out, "trailer\n<<\n /Size %d", xref->size); + fz_print(out, "trailer\n<<\n /Size %d", xref->len); obj = fz_dictgets(xref->trailer, "Root"); - fz_print(out, "\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj)); + fz_print(out, "\n /Root %d %d R", fz_tonum(obj), fz_togen(obj)); obj = fz_dictgets(xref->trailer, "Info"); if (obj) - fz_print(out, "\n /Info %d %d R", fz_toobjid(obj), fz_togenid(obj)); + fz_print(out, "\n /Info %d %d R", fz_tonum(obj), fz_togen(obj)); if (encrypt) { fz_print(out, "\n /Encrypt "); diff --git a/mupdf/stream.c b/mupdf/stream.c index 0359c461..95703f4f 100644 --- a/mupdf/stream.c +++ b/mupdf/stream.c @@ -1,11 +1,13 @@ #include <fitz.h> #include <mupdf.h> +/* TODO: error cleanup */ + static fz_error * -makefilter(fz_filter **fp, fz_obj *f, fz_obj *p) +buildonefilter(fz_filter **fp, fz_obj *f, fz_obj *p) { - fz_filter *predf = nil; - fz_filter *realf = nil; + fz_filter *predf; + fz_filter *realf; fz_error *error; char *s; @@ -31,15 +33,13 @@ makefilter(fz_filter **fp, fz_obj *f, fz_obj *p) if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl")) { - if (fz_isdict(p)) { + if (fz_isdict(p)) + { fz_obj *obj = fz_dictgets(p, "Predictor"); if (obj) { error = fz_newflated(&realf, p); - if (error) goto cleanup; error = fz_newpredictd(&predf, p); - if (error) goto cleanup; error = fz_newpipeline(fp, realf, predf); - if (error) goto cleanup; return nil; } } @@ -48,15 +48,13 @@ makefilter(fz_filter **fp, fz_obj *f, fz_obj *p) if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW")) { - if (fz_isdict(p)) { + if (fz_isdict(p)) + { fz_obj *obj = fz_dictgets(p, "Predictor"); if (obj) { error = fz_newlzwd(&realf, p); - if (error) goto cleanup; error = fz_newpredictd(&predf, p); - if (error) goto cleanup; error = fz_newpipeline(fp, realf, predf); - if (error) goto cleanup; return nil; } } @@ -69,19 +67,13 @@ makefilter(fz_filter **fp, fz_obj *f, fz_obj *p) } return fz_throw("syntaxerror: unknown filter: %s", s); - -cleanup: - if (realf) fz_freefilter(realf); - if (predf) fz_freefilter(predf); - return error; } static fz_error * -makepipeline(fz_filter **fp, fz_obj *fs, fz_obj *ps) +buildfilters(fz_filter **filterp, fz_filter *head, fz_obj *fs, fz_obj *ps) { fz_error *error; - fz_filter *filter = nil; - fz_filter *pipe = nil; + fz_filter *tail; fz_obj *f; fz_obj *p; int i; @@ -89,245 +81,186 @@ makepipeline(fz_filter **fp, fz_obj *fs, fz_obj *ps) for (i = 0; i < fz_arraylen(fs); i++) { f = fz_arrayget(fs, i); - if (fz_isarray(ps)) p = fz_arrayget(ps, i); else p = nil; - error = makefilter(&filter, f, p); - if (error) { if (pipe) fz_freefilter(pipe); return error; } - - if (pipe) { - fz_filter *np; - error = fz_newpipeline(&np, pipe, filter); - if (error) { fz_freefilter(pipe); return error; } - pipe = np; - } - else pipe = filter; + error = buildonefilter(&tail, f, p); + error = fz_newpipeline(&head, head, tail); } - *fp = pipe; + *filterp = head; return nil; } -fz_error * -pdf_buildfilter(fz_filter **fp, pdf_xref *xref, fz_obj *stmobj, int oid, int gid) +static fz_error * +makerawfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, int gen) { fz_error *error; - fz_filter *filter; - fz_obj *filters; - fz_obj *params; - fz_obj *obj; - int len; + fz_filter *pipe, *cf; + fz_obj *stmlen; - obj = fz_dictgets(stmobj, "Length"); - error = pdf_resolve(&obj, xref); - if (error) - return error; - len = fz_toint(obj); - fz_dropobj(obj); + stmlen = fz_dictgets(stmobj, "Length"); + error = pdf_resolve(&stmlen, xref); - filters = fz_dictgets(stmobj, "Filter"); - params = fz_dictgets(stmobj, "DecodeParms"); + error = fz_newnullfilter(&pipe, fz_toint(stmlen)); - if (!filters) + if (xref->crypt) { - error = fz_newnullfilter(&filter, len); - if (error) - return error; + error = pdf_cryptstm(&cf, xref->crypt, oid, gen); + error = fz_newpipeline(&pipe, pipe, cf); } - else if (fz_isname(filters)) - { - error = makefilter(&filter, filters, params); - if (error) - return error; - } + fz_dropobj(stmlen); - else if (fz_isarray(filters)) - { - if (fz_arraylen(filters) == 0) - error = fz_newnullfilter(&filter, len); - else - error = makepipeline(&filter, filters, params); - if (error) - return error; - } + *filterp = pipe; + return nil; +} - else - { - return fz_throw("typecheck in buildstream"); - } +static fz_error * +makedecodefilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, int gen) +{ + fz_error *error; + fz_filter *pipe, *tmp; + fz_obj *filters; + fz_obj *params; - if (xref->crypt) - { - fz_filter *cryptfilter; - fz_filter *pipeline; + error = makerawfilter(&pipe, xref, stmobj, oid, gen); - error = pdf_cryptstm(&cryptfilter, xref->crypt, oid, gid); - if (error) - { - fz_freefilter(filter); - return error; - } + filters = fz_dictgets(stmobj, "Filter"); + params = fz_dictgets(stmobj, "DecodeParms"); - error = fz_newpipeline(&pipeline, cryptfilter, filter); - if (error) + if (filters) + { + error = pdf_resolve(&filters, xref); + if (params) + error = pdf_resolve(¶ms, xref); + + if (fz_isname(filters)) { - fz_freefilter(cryptfilter); - fz_freefilter(filter); - return error; + error = buildonefilter(&tmp, filters, params); + error = fz_newpipeline(&pipe, pipe, tmp); } + else + error = buildfilters(&pipe, pipe, filters, params); - filter = pipeline; + if (params) + fz_dropobj(params); + fz_dropobj(filters); } - *fp = filter; + *filterp = pipe; return nil; } -fz_error * -pdf_openrawstream0(pdf_xref *xref, fz_obj *stmobj, int oid, int gid, int ofs) +int +pdf_isstream(pdf_xref *xref, int oid, int gen) { fz_error *error; - fz_filter *nf = nil; - fz_filter *cf = nil; - fz_filter *pipe = nil; - fz_obj *obj; - int length; - int n; - - obj = fz_dictgets(stmobj, "Length"); - error = pdf_resolve(&obj, xref); - if (error) - return error; - length = fz_toint(obj); - fz_dropobj(obj); - n = fz_seek(xref->file, ofs, 0); - if (n < 0) - return fz_ferror(xref->file); + if (oid < 0 || oid >= xref->len) + return 0; - if (xref->crypt) - { - error = fz_newnullfilter(&nf, length); - if (error) - return error; - - error = pdf_cryptstm(&cf, xref->crypt, oid, gid); - if (error) { - fz_freefilter(nf); - return error; - } - - error = fz_newpipeline(&pipe, nf, cf); - if (error) { - fz_freefilter(nf); - fz_freefilter(cf); - return error; - } - } - - else - { - error = fz_newnullfilter(&pipe, length); - if (error) - return error; - } - - error = fz_pushfilter(xref->file, pipe); + error = pdf_cacheobject(xref, oid, gen); if (error) { - fz_freefilter(pipe); - return error; + fz_warn("%s", error); + fz_freeerror(error); + return 0; } - return nil; + return xref->table[oid].stmbuf || xref->table[oid].stmofs; } fz_error * -pdf_openstream0(pdf_xref *xref, fz_obj *stmobj, int oid, int gid, int ofs) +pdf_openrawstream(pdf_xref *xref, int oid, int gen) { + pdf_xrefentry *x; fz_error *error; fz_filter *filter; + int n; - error = pdf_buildfilter(&filter, xref, stmobj, oid, gid); - if (error) - return error; + if (oid < 0 || oid >= xref->len) + return fz_throw("rangecheck: object id out of range"); + + x = xref->table + oid; + + error = pdf_cacheobject(xref, oid, gen); - ofs = fz_seek(xref->file, ofs, 0); - if (ofs < 0) { - fz_freefilter(filter); - return fz_ferror(xref->file); + if (x->stmbuf) + { + return fz_openbuffer(&xref->stream, x->stmbuf, FZ_READ); } - error = fz_pushfilter(xref->file, filter); - if (error) { - fz_freefilter(filter); - return error; + if (x->stmofs) + { + error = makerawfilter(&filter, xref, x->obj, oid, gen); + n = fz_seek(xref->file, x->stmofs, 0); + error = fz_pushfilter(xref->file, filter); + xref->stream = xref->file; + return nil; } - return nil; + return fz_throw("syntaxerror: object is not a stream"); } fz_error * -pdf_openstream(pdf_xref *xref, fz_obj *stmref) +pdf_openstream(pdf_xref *xref, int oid, int gen) { + pdf_xrefentry *x; fz_error *error; - fz_obj *stmobj; - int oid, gid, ofs; + fz_filter *filter; + int n; - oid = fz_toobjid(stmref); - gid = fz_togenid(stmref); + if (oid < 0 || oid >= xref->len) + return fz_throw("rangecheck: object id out of range"); - error = pdf_loadobject0(&stmobj, xref, oid, gid, &ofs); - if (error) - return error; + x = xref->table + oid; - error = pdf_openstream0(xref, stmobj, oid, gid, ofs); - if (error) { - fz_dropobj(stmobj); - return error; + error = pdf_cacheobject(xref, oid, gen); + + if (x->stmbuf) + { + error = makedecodefilter(&filter, xref, x->obj, oid, gen); + error = fz_openbuffer(&xref->stream, x->stmbuf, FZ_READ); + error = fz_pushfilter(xref->stream, filter); + return nil; } - fz_dropobj(stmobj); + if (x->stmofs) + { + error = makedecodefilter(&filter, xref, x->obj, oid, gen); + n = fz_seek(xref->file, x->stmofs, 0); + error = fz_pushfilter(xref->file, filter); + xref->stream = xref->file; + return nil; + } - return nil; + return fz_throw("syntaxerror: object is not a stream"); } void pdf_closestream(pdf_xref *xref) { - fz_popfilter(xref->file); + if (xref->stream == xref->file) + fz_popfilter(xref->file); + else + fz_closefile(xref->stream); + xref->stream = nil; } -fz_error * -pdf_readrawstream0(fz_buffer **bufp, pdf_xref *xref, fz_obj *stmobj, int oid, int gid, int ofs) -{ - fz_error *error; - - error = pdf_openrawstream0(xref, stmobj, oid, gid, ofs); - if (error) - return error; - - error = fz_readfile(bufp, xref->file); - - pdf_closestream(xref); - - return error; -} fz_error * -pdf_readstream0(fz_buffer **bufp, pdf_xref *xref, fz_obj *stmobj, int oid, int gid, int ofs) +pdf_loadrawstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen) { fz_error *error; - error = pdf_openstream0(xref, stmobj, oid, gid, ofs); + error = pdf_openrawstream(xref, oid, gen); if (error) return error; - error = fz_readfile(bufp, xref->file); + error = fz_readfile(bufp, xref->stream); pdf_closestream(xref); @@ -335,15 +268,15 @@ pdf_readstream0(fz_buffer **bufp, pdf_xref *xref, fz_obj *stmobj, int oid, int g } fz_error * -pdf_readstream(fz_buffer **bufp, pdf_xref *xref, fz_obj *stmref) +pdf_loadstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen) { fz_error *error; - error = pdf_openstream(xref, stmref); + error = pdf_openstream(xref, oid, gen); if (error) return error; - error = fz_readfile(bufp, xref->file); + error = fz_readfile(bufp, xref->stream); pdf_closestream(xref); diff --git a/mupdf/xref.c b/mupdf/xref.c index 4089c852..ae11ebb7 100644 --- a/mupdf/xref.c +++ b/mupdf/xref.c @@ -2,68 +2,51 @@ #include <mupdf.h> /* - * initialize xref + * initialize new empty xref */ fz_error * -pdf_newxref(pdf_xref **xrefp) +pdf_newpdf(pdf_xref **xrefp) { - fz_error *error; pdf_xref *xref; - xref = *xrefp = fz_malloc(sizeof(pdf_xref)); + xref = fz_malloc(sizeof (pdf_xref)); if (!xref) return fz_outofmem; - xref->version = 1.3; - xref->crypt = nil; xref->file = nil; - xref->size = 0; - xref->capacity = 0; - xref->table = nil; + xref->version = 1.3; + xref->startxref = 0; xref->trailer = nil; - xref->startxref = -1; + xref->crypt = nil; - error = fz_newhash(&xref->store, 256, sizeof(int) * 3); - if (error) - { + xref->cap = 256; + xref->len = 1; + xref->table = fz_malloc(xref->cap * sizeof(pdf_xrefentry)); + if (!xref->table) { fz_free(xref); - return error; - } - - return nil; -} - -fz_error * -pdf_emptyxref(pdf_xref *xref, float version) -{ - assert(xref->table == nil); - - xref->version = version; - xref->capacity = 256; - xref->size = 1; - xref->table = fz_malloc(xref->capacity * sizeof(pdf_xrefentry)); - if (!xref->table) return fz_outofmem; + } xref->table[0].type = 'f'; xref->table[0].mark = 0; xref->table[0].ofs = 0; xref->table[0].gen = 65535; + xref->table[0].stmbuf = nil; + xref->table[0].stmofs = 0; + xref->table[0].obj = nil; + *xrefp = xref; return nil; } fz_error * -pdf_decryptxref(pdf_xref *xref) +pdf_decryptpdf(pdf_xref *xref) { fz_error *error; fz_obj *encrypt; fz_obj *id; - if (xref->size < 0) - return fz_throw("rangecheck: xref missing first slot"); - encrypt = fz_dictgets(xref->trailer, "Encrypt"); id = fz_dictgets(xref->trailer, "ID"); @@ -94,159 +77,45 @@ cleanup: } void -pdf_closexref(pdf_xref *xref) +pdf_closepdf(pdf_xref *xref) { - int *key; - void *val; int i; - if (xref->store) + if (xref->table) { - for (i = 0; i < fz_hashlen(xref->store); i++) + for (i = 0; i < xref->len; i++) { - key = fz_hashgetkey(xref->store, i); - val = fz_hashgetval(xref->store, i); - if (val && key[2] == 0) - fz_dropobj((fz_obj*)val); - if (val && key[2] == 1) - fz_freebuffer((fz_buffer*)val); + if (xref->table[i].stmbuf) + fz_freebuffer(xref->table[i].stmbuf); + if (xref->table[i].obj) + fz_dropobj(xref->table[i].obj); } - fz_freehash(xref->store); + fz_free(xref->table); } - if (xref->table) - fz_free(xref->table); - if (xref->trailer) - fz_dropobj(xref->trailer); if (xref->file) fz_closefile(xref->file); + + if (xref->trailer) + fz_dropobj(xref->trailer); + fz_free(xref); } void -pdf_debugxref(pdf_xref *xref) +pdf_debugpdf(pdf_xref *xref) { int i; - printf("%%!PDF-%g\n", xref->version); - printf("xref\n0 %d\n", xref->size); - for (i = 0; i < xref->size; i++) + printf("xref\n0 %d\n", xref->len); + for (i = 0; i < xref->len; i++) { - printf("%010d %05d %c \n", + printf("%010d %05d %c | %d %d\n", xref->table[i].ofs, xref->table[i].gen, - xref->table[i].type); + xref->table[i].type, + xref->table[i].obj ? xref->table[i].obj->refcount : 0, + xref->table[i].stmofs); } - printf("trailer\n"); - fz_debugobj(xref->trailer); - printf("\n"); -} - -/* - * object and stream store (cached from objstm and saved for mutation) - */ - -void -pdf_debugstore(fz_hashtable *store) -{ - int *key; - void *val; - int i; - - printf("object store (%d)\n", fz_hashlen(store)); - for (i = 0; i < fz_hashlen(store); i++) - { - key = fz_hashgetkey(store, i); - val = fz_hashgetval(store, i); - if (val) - { - printf("slot %d: %d %d ", i, key[0], key[1]); - if (key[2] == 0) - printf("obj[%d] ", ((fz_obj*)val)->refcount), fz_debugobj(val); - if (key[2] == 1) - printf("stream %d", ((fz_buffer*)val)->wp - ((fz_buffer*)val)->rp); - printf("\n"); - } - } -} - -fz_obj * -pdf_findstoredobject(fz_hashtable *store, int oid, int gid) -{ - int key[3]; - key[0] = oid; - key[1] = gid; - key[2] = 0; - return fz_hashfind(store, key); -} - -fz_buffer * -pdf_findstoredstream(fz_hashtable *store, int oid, int gid) -{ - int key[3]; - key[0] = oid; - key[1] = gid; - key[2] = 1; - return fz_hashfind(store, key); -} - -fz_error * -pdf_deletestoredobject(fz_hashtable *store, int oid, int gid) -{ - int key[3]; - fz_obj *obj; - key[0] = oid; - key[1] = gid; - key[2] = 0; - obj = fz_hashfind(store, key); - if (obj) - fz_dropobj(obj); - return fz_hashremove(store, key); -} - -fz_error * -pdf_deletestoredstream(fz_hashtable *store, int oid, int gid) -{ - int key[3]; - fz_buffer *stm; - key[0] = oid; - key[1] = gid; - key[2] = 1; - stm = fz_hashfind(store, key); - if (stm) - fz_freebuffer(stm); - return fz_hashremove(store, key); -} - -fz_error * -pdf_storeobject(fz_hashtable *store, int oid, int gid, fz_obj *obj) -{ - int key[3]; - fz_obj *old; - key[0] = oid; - key[1] = gid; - key[2] = 0; - old = fz_hashfind(store, key); - if (old) { - fz_hashremove(store, key); - fz_dropobj(old); - } - return fz_hashinsert(store, key, fz_keepobj(obj)); -} - -fz_error * -pdf_storestream(fz_hashtable *store, int oid, int gid, fz_buffer *stm) -{ - int key[3]; - fz_buffer *old; - key[0] = oid; - key[1] = gid; - key[2] = 1; - old = fz_hashfind(store, key); - if (old) { - fz_hashremove(store, key); - fz_freebuffer(old); - } - return fz_hashinsert(store, key, stm); } /* @@ -265,14 +134,14 @@ static int findprev(pdf_xref *xref, int oid) static int findnext(pdf_xref *xref, int oid) { int next; - for (next = oid + 1; next < xref->size; next++) + for (next = oid + 1; next < xref->len; next++) if (xref->table[next].type == 'f' || xref->table[next].type == 'd') return next; return 0; } fz_error * -pdf_createobject(pdf_xref *xref, int *oidp, int *gidp) +pdf_allocobject(pdf_xref *xref, int *oidp, int *genp) { pdf_xrefentry *x; int prev, next; @@ -287,7 +156,7 @@ pdf_createobject(pdf_xref *xref, int *oidp, int *gidp) if (x->gen < 65535) { *oidp = oid; - *gidp = x->gen; + *genp = x->gen; x->type = 'a'; x->ofs = 0; @@ -307,9 +176,9 @@ pdf_createobject(pdf_xref *xref, int *oidp, int *gidp) break; } - if (xref->size + 1 >= xref->capacity) + if (xref->len + 1 >= xref->cap) { - int newcap = xref->capacity + 256; + int newcap = xref->cap + 256; pdf_xrefentry *newtable; newtable = fz_realloc(xref->table, sizeof(pdf_xrefentry) * newcap); @@ -317,18 +186,21 @@ pdf_createobject(pdf_xref *xref, int *oidp, int *gidp) return fz_outofmem; xref->table = newtable; - xref->capacity = newcap; + xref->cap = newcap; } - oid = xref->size ++; + oid = xref->len ++; xref->table[oid].type = 'a'; xref->table[oid].mark = 0; xref->table[oid].ofs = 0; xref->table[oid].gen = 0; + xref->table[oid].stmbuf = nil; + xref->table[oid].stmofs = 0; + xref->table[oid].obj = nil; *oidp = oid; - *gidp = 0; + *genp = 0; prev = findprev(xref, oid); next = findnext(xref, oid); @@ -339,23 +211,28 @@ pdf_createobject(pdf_xref *xref, int *oidp, int *gidp) } fz_error * -pdf_deleteobject(pdf_xref *xref, int oid, int gid) +pdf_deleteobject(pdf_xref *xref, int oid, int gen) { pdf_xrefentry *x; int prev; - if (oid < 0 || oid >= xref->size) - return fz_throw("rangecheck: invalid object number"); + if (oid < 0 || oid >= xref->len) + return fz_throw("rangecheck: object number out of range: %d", oid); x = xref->table + oid; - if (x->type != 'n' && x->type != 'o' && x->type == 'a') - return fz_throw("rangecheck: delete nonexistant object"); - x->type = 'd'; x->ofs = findnext(xref, oid); x->gen ++; + if (x->stmbuf) + fz_freebuffer(x->stmbuf); + x->stmbuf = nil; + + if (x->obj) + fz_dropobj(x->obj); + x->obj = nil; + prev = findprev(xref, oid); xref->table[prev].type = 'd'; xref->table[prev].ofs = oid; @@ -364,20 +241,20 @@ pdf_deleteobject(pdf_xref *xref, int oid, int gid) } fz_error * -pdf_saveobject(pdf_xref *xref, int oid, int gid, fz_obj *obj) +pdf_updateobject(pdf_xref *xref, int oid, int gen, fz_obj *obj) { - fz_error *error; pdf_xrefentry *x; - if (oid < 0 || oid >= xref->size) - return fz_throw("rangecheck: invalid object number"); - - error = pdf_storeobject(xref->store, oid, gid, obj); - if (error) - return error; + if (oid < 0 || oid >= xref->len) + return fz_throw("rangecheck: object number out of range: %d", oid); x = xref->table + oid; + if (x->obj) + fz_dropobj(x->obj); + + x->obj = fz_keepobj(obj); + if (x->type == 'f' || x->type == 'd') { int prev = findprev(xref, oid); @@ -392,15 +269,20 @@ pdf_saveobject(pdf_xref *xref, int oid, int gid, fz_obj *obj) } fz_error * -pdf_savestream(pdf_xref *xref, int oid, int gid, fz_buffer *stm) +pdf_updatestream(pdf_xref *xref, int oid, int gen, fz_buffer *stm) { - return pdf_storestream(xref->store, oid, gid, stm); -} + pdf_xrefentry *x; -fz_error * -pdf_deletestream(pdf_xref *xref, int oid, int gid) -{ - return pdf_deletestoredstream(xref->store, oid, gid); + if (oid < 0 || oid >= xref->len) + return fz_throw("rangecheck: object number out of range: %d", oid); + + x = xref->table + oid; + + if (x->stmbuf) + fz_freebuffer(x->stmbuf); + x->stmbuf = stm; + + return nil; } /* @@ -408,84 +290,83 @@ pdf_deletestream(pdf_xref *xref, int oid, int gid) */ fz_error * -pdf_loadobject0(fz_obj **objp, pdf_xref *xref, int oid, int gid, int *stmofs) +pdf_cacheobject(pdf_xref *xref, int oid, int gen) { unsigned char buf[65536]; /* yeowch! */ fz_error *error; pdf_xrefentry *x; - int roid, rgid; + int roid, rgen; int n; - if (oid < 0 || oid >= xref->size) + if (oid < 0 || oid >= xref->len) return fz_throw("rangecheck: object number out of range: %d", oid); - if (stmofs) - *stmofs = -1; - x = &xref->table[oid]; + if (x->obj) + return nil; + if (x->type == 'f' || x->type == 'd') return fz_throw("rangecheck: tried to load free object"); - else if (x->type == 'n') + if (x->type == 'n') { n = fz_seek(xref->file, x->ofs, 0); if (n < 0) return fz_ferror(xref->file); - error = pdf_parseindobj(objp, xref->file, buf, sizeof buf, - &roid, &rgid, stmofs); + error = pdf_parseindobj(&x->obj, xref->file, buf, sizeof buf, + &roid, &rgen, &x->stmofs); if (error) return error; + if (roid != oid || rgen != gen) + return fz_throw("syntaxerror: found wrong object"); + if (xref->crypt) - pdf_cryptobj(xref->crypt, *objp, oid, gid); + pdf_cryptobj(xref->crypt, x->obj, oid, gen); } else if (x->type == 'o') { - *objp = pdf_findstoredobject(xref->store, oid, gid); - if (*objp) { - fz_keepobj(*objp); - return nil; + if (!x->obj) + { + error = pdf_loadobjstm(xref, x->ofs, 0, buf, sizeof buf); + if (error) + return error; } + } - error = pdf_readobjstm(xref, x->ofs, 0, buf, sizeof buf); - if (error) - return error; + return nil; +} - *objp = pdf_findstoredobject(xref->store, oid, gid); - if (!*objp) - return fz_throw("rangecheck: could not find object"); - fz_keepobj(*objp); - } +fz_error * +pdf_loadobject(fz_obj **objp, pdf_xref *xref, int oid, int gen) +{ + fz_error *error; - else if (x->type == 'a') - { - *objp = pdf_findstoredobject(xref->store, oid, gid); - if (!*objp) - return fz_throw("rangecheck: could not find object"); - fz_keepobj(*objp); - } + error = pdf_cacheobject(xref, oid, gen); + if (error) + return error; - else - return fz_throw("rangecheck: unknown object type"); + *objp = fz_keepobj(xref->table[oid].obj); return nil; } fz_error * -pdf_loadobject(fz_obj **objp, pdf_xref *xref, fz_obj *ref, int *stmofs) +pdf_loadindirect(fz_obj **objp, pdf_xref *xref, fz_obj *ref) { - return pdf_loadobject0(objp, xref, fz_toobjid(ref), fz_togenid(ref), stmofs); + assert(ref != nil); + return pdf_loadobject(objp, xref, fz_tonum(ref), fz_togen(ref)); } fz_error * pdf_resolve(fz_obj **objp, pdf_xref *xref) { if (fz_isindirect(*objp)) - return pdf_loadobject(objp, xref, *objp, nil); + return pdf_loadindirect(objp, xref, *objp); fz_keepobj(*objp); return nil; } diff --git a/object/simple.c b/object/simple.c index 02da3cec..bee7cf46 100644 --- a/object/simple.c +++ b/object/simple.c @@ -205,7 +205,7 @@ fz_tostringlen(fz_obj *obj) } int -fz_toobjid(fz_obj *obj) +fz_tonum(fz_obj *obj) { if (fz_isindirect(obj)) return obj->u.r.oid; @@ -213,7 +213,7 @@ fz_toobjid(fz_obj *obj) } int -fz_togenid(fz_obj *obj) +fz_togen(fz_obj *obj) { if (fz_isindirect(obj)) return obj->u.r.gid; diff --git a/render/pixmap.c b/render/pixmap.c index 57402d81..ac99de80 100644 --- a/render/pixmap.c +++ b/render/pixmap.c @@ -29,11 +29,22 @@ fz_newpixmap(fz_pixmap **pixp, int x, int y, int w, int h, int n, int a) return nil; } +fz_pixmap * +fz_keeppixmap(fz_pixmap *pix) +{ + pix->refcount ++; + return pix; +} + void -fz_freepixmap(fz_pixmap *pix) +fz_droppixmap(fz_pixmap *pix) { - fz_free(pix->samples); - fz_free(pix); + pix->refcount --; + if (pix->refcount == 0) + { + fz_free(pix->samples); + fz_free(pix); + } } void @@ -46,15 +57,77 @@ void fz_debugpixmap(fz_pixmap *pix) { int x, y; + assert(pix->n == 3 && pix->a == 1); FILE *f = fopen("out.ppm", "w"); fprintf(f, "P6\n%d %d\n255\n", pix->w, pix->h); for (y = 0; y < pix->h; y++) for (x = 0; x < pix->w; x++) { - putc(255 - pix->samples[x + y * pix->stride], f); - putc(255 - pix->samples[x + y * pix->stride], f); - putc(255 - pix->samples[x + y * pix->stride], f); + int r = (pix->samples[x * 4 + y * pix->stride + 0] * 255) >> 14; + int g = (pix->samples[x * 4 + y * pix->stride + 1] * 255) >> 14; + int b = (pix->samples[x * 4 + y * pix->stride + 2] * 255) >> 14; + putc(r, f); + putc(g, f); + putc(b, f); } fclose(f); } +void +fz_blendover(fz_pixmap *dst, fz_pixmap *fg, fz_pixmap *bg) +{ + int x, y; + +printf("dst=%d,%d fg=%d,%d bg=%d,%d\n", +dst->n, dst->a, +fg->n, fg->a, +bg->n, bg->a); + + assert(fg->n == bg->n); + assert(fg->n == 3); + assert(fg->a == 1); + assert(bg->a == 1); + + for (y = 0; y < dst->h; y++) + { + short *bgp = &fg->samples[y * fg->stride]; + short *fgp = &bg->samples[y * bg->stride]; + short *dstp = &dst->samples[y * dst->stride]; + for (x = 0; x < dst->w; x++) + { + dstp[0] = ((fgp[3] * (fgp[0] - bgp[0])) >> 14) + bgp[0]; + dstp[1] = ((fgp[3] * (fgp[1] - bgp[1])) >> 14) + bgp[1]; + dstp[2] = ((fgp[3] * (fgp[2] - bgp[2])) >> 14) + bgp[2]; + dstp[3] = ((fgp[3] * (fgp[3] - bgp[3])) >> 14) + bgp[3]; + dstp += 4; + fgp += 4; + bgp += 4; + } + } +} + +void +fz_blendmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *mask) +{ + int x, y, k; + + assert(src->n == dst->n); + assert(src->a == 0); + assert(mask->n == 0); + assert(mask->a == 1); + assert(dst->a == 1); + + for (y = 0; y < dst->h; y++) + { + short *dstp = &dst->samples[y * dst->stride]; + short *srcp = &src->samples[y * src->stride]; + short *mskp = &mask->samples[y * mask->stride]; + for (x = 0; x < dst->w; x++) + { + for (k = 0; k < dst->n; k++) + *dstp++ = *srcp++; + *dstp++ = *mskp++; + } + } +} + diff --git a/render/render.c b/render/render.c index bb875ee3..d7359d90 100644 --- a/render/render.c +++ b/render/render.c @@ -1,10 +1,16 @@ #include <fitz.h> +enum { NONE, OVER, MASK }; + struct fz_renderer_s { fz_glyphcache *cache; fz_gel *gel; fz_ael *ael; + int mode; + int x, y, w, h; + fz_pixmap *tmp; + fz_pixmap *acc; }; fz_error * @@ -20,6 +26,9 @@ fz_newrenderer(fz_renderer **gcp) gc->cache = nil; gc->gel = nil; gc->ael = nil; + gc->mode = NONE; + gc->tmp = nil; + gc->acc = nil; error = fz_newglyphcache(&gc->cache, 1024, 65536); if (error) @@ -56,50 +65,118 @@ fz_freerenderer(fz_renderer *gc) fz_freegel(gc->gel); if (gc->ael) fz_freeael(gc->ael); + if (gc->tmp) + fz_droppixmap(gc->tmp); + if (gc->acc) + fz_droppixmap(gc->acc); fz_free(gc); } fz_error * -fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm, fz_pixmap *out) +fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm) { fz_error *error; fz_node *node; + int oldmode; + + oldmode = gc->mode; + gc->mode = OVER; + +printf("renderover ; acc=3,1\n"); + + error = fz_newpixmap(&gc->acc, gc->x, gc->y, gc->w, gc->h, 3, 1); + if (error) + return error; + + fz_clearpixmap(gc->acc); for (node = over->super.child; node; node = node->next) { - error = fz_rendernode(gc, node, ctm, out); + gc->tmp = nil; + error = fz_rendernode(gc, node, ctm); if (error) return error; + if (gc->tmp) + { +printf(" over -> %d,%d\n", gc->tmp->n, gc->tmp->a); + fz_blendover(gc->acc, gc->tmp, gc->acc); + fz_droppixmap(gc->tmp); + } +else printf(" -> nil\n"); } + gc->tmp = gc->acc; + gc->acc = nil; + + gc->mode = oldmode; + return nil; } fz_error * -fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm, fz_pixmap *out) +fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm) { fz_error *error; - fz_node *node; + fz_pixmap *colorpix; + fz_pixmap *shapepix; + fz_node *color; + fz_node *shape; + int oldmode; - for (node = mask->super.child; node; node = node->next) - { - error = fz_rendernode(gc, node, ctm, out); - if (error) - return error; - } + color = mask->super.child; + shape = color->next; + +// if (fz_ispathnode(shape) && fz_iscolornode(color)) +// return rcolorpath(gc, shape, color, ctm); +// if (fz_istextnode(shape) && fz_iscolornode(color)) +// return rcolortext(gc, shape, color, ctm); + + oldmode = gc->mode; + gc->mode = MASK; + +printf("rendermask\n"); + + gc->tmp = nil; + error = fz_rendernode(gc, color, ctm); + if (error) + return error; + colorpix = gc->tmp; + +printf(" -> color %d,%d\n", colorpix->n, colorpix->a); + + gc->tmp = nil; + error = fz_rendernode(gc, shape, ctm); + if (error) + return error; + shapepix = gc->tmp; + +printf(" -> shape %d,%d\n", shapepix->n, shapepix->a); + + error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, colorpix->n, 1); + if (error) + return error; + +printf(" -> blend %d,%d\n", gc->tmp->n, gc->tmp->a); + + fz_blendmask(gc->tmp, colorpix, shapepix); + + fz_droppixmap(shapepix); + fz_droppixmap(colorpix); + + gc->mode = oldmode; return nil; } fz_error * -fz_rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm, fz_pixmap *out) +fz_rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm) { +printf("rendertransform\n"); ctm = fz_concat(ctm, transform->m); - return fz_rendernode(gc, transform->super.child, ctm, out); + return fz_rendernode(gc, transform->super.child, ctm); } - -void composite(fz_pixmap *out, fz_glyph *gl, int xo, int yo) +static void blitglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo) { int sx, sy, dx, dy, a, b, c; @@ -107,8 +184,8 @@ void composite(fz_pixmap *out, fz_glyph *gl, int xo, int yo) { for (sx = 0; sx < gl->w; sx++) { - dx = xo + sx + gl->lsb; - dy = yo - sy + gl->top; + dx = xo + sx + gl->lsb - out->x; + dy = yo - sy + gl->top - out->y; if (dx < 0) continue; if (dy < 0) continue; @@ -124,7 +201,7 @@ void composite(fz_pixmap *out, fz_glyph *gl, int xo, int yo) } fz_error * -fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm, fz_pixmap *out) +fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm) { fz_error *error; fz_glyph gl; @@ -132,6 +209,12 @@ fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm, fz_pixmap *out) int g, i, ix, iy; fz_matrix tm, trm; +printf("rendertext ; tmp=0,1\n"); + + error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 0, 1); + if (error) + return error; + tm = text->trm; for (i = 0; i < text->len; i++) @@ -154,30 +237,91 @@ fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm, fz_pixmap *out) if (error) return error; - composite(out, &gl, ix, iy); + blitglyph(gc->tmp, &gl, ix, iy); } return nil; } fz_error * -fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm, fz_pixmap *out) +fz_renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm) { +printf("renderpath ; tmp=nil\n"); + return nil; +} + +fz_error * +fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm) +{ + fz_error *error; + short r = color->r * (1 << 14); + short g = color->g * (1 << 14); + short b = color->b * (1 << 14); + int x, y; + +printf("rendercolor %d %d %d ; tmp=3,0\n", r, g, b); + + error = fz_newpixmap(&gc->tmp, gc->x, gc->y, gc->w, gc->h, 3, 0); + if (error) + return error; + + for (y = 0; y < gc->tmp->h; y++) + { + short *p = &gc->tmp->samples[y * gc->tmp->stride]; + for (x = 0; x < gc->tmp->w; x++) + { + *p++ = r; + *p++ = g; + *p++ = b; + } + } + + return nil; +} + +fz_error * +fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm) +{ + assert(gc->tmp == nil); + if (!node) return nil; switch (node->kind) { case FZ_NOVER: - return fz_renderover(gc, (fz_overnode*)node, ctm, out); + return fz_renderover(gc, (fz_overnode*)node, ctm); case FZ_NMASK: - return fz_rendermask(gc, (fz_masknode*)node, ctm, out); + return fz_rendermask(gc, (fz_masknode*)node, ctm); case FZ_NTRANSFORM: - return fz_rendertransform(gc, (fz_transformnode*)node, ctm, out); + return fz_rendertransform(gc, (fz_transformnode*)node, ctm); + case FZ_NCOLOR: + return fz_rendercolor(gc, (fz_colornode*)node, ctm); + case FZ_NPATH: + return fz_renderpath(gc, (fz_pathnode*)node, ctm); case FZ_NTEXT: - return fz_rendertext(gc, (fz_textnode*)node, ctm, out); + return fz_rendertext(gc, (fz_textnode*)node, ctm); default: return nil; } } +fz_error * +fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, fz_rect bbox) +{ + fz_error *error; + + gc->x = floor(bbox.min.x); + gc->y = floor(bbox.min.y); + gc->w = ceil(bbox.max.x) - floor(bbox.min.x); + gc->h = ceil(bbox.max.y) - floor(bbox.min.y); + + error = fz_rendernode(gc, tree->root, ctm); + if (error) + return error; + + *outp = gc->tmp; + + return nil; +} + diff --git a/test/pdfclean.c b/test/pdfclean.c index 58e8b828..7dd15427 100644 --- a/test/pdfclean.c +++ b/test/pdfclean.c @@ -24,11 +24,11 @@ void preloadobjstms(pdf_xref *xref) fz_obj *obj; int i; - for (i = 0; i < xref->size; i++) + for (i = 0; i < xref->len; i++) { if (xref->table[i].type == 'o') { - error = pdf_loadobject0(&obj, xref, i, 0, nil); + error = pdf_loadobject(&obj, xref, i, 0); if (error) fz_abort(error); fz_dropobj(obj); } @@ -39,23 +39,22 @@ void expandstreams(pdf_xref *xref) { fz_error *error; fz_obj *stmobj; - int stmofs; fz_buffer *buf; fz_obj *stmlen; int i, gen; - for (i = 0; i < xref->size; i++) + for (i = 0; i < xref->len; 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) + if (pdf_isstream(xref, i, gen)) { - error = pdf_readstream0(&buf, xref, stmobj, i, gen, stmofs); + error = pdf_loadobject(&stmobj, xref, i, gen); + if (error) fz_abort(error); + + error = pdf_loadstream(&buf, xref, i, gen); if (error) fz_abort(error); fz_dictdels(stmobj, "Filter"); @@ -67,10 +66,10 @@ void expandstreams(pdf_xref *xref) 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); + pdf_updateobject(xref, i, gen, stmobj); + pdf_updatestream(xref, i, gen, buf); + + fz_dropobj(stmobj); } } } @@ -119,18 +118,14 @@ int main(int argc, char **argv) infile = argv[optind++]; outfile = argv[optind++]; - error = pdf_newxref(&xref); - if (error) - fz_abort(error); - if (dorepair) - error = pdf_repairxref(xref, infile); + error = pdf_repairpdf(&xref, infile); else - error = pdf_openxref(xref, infile); + error = pdf_openpdf(&xref, infile); if (error) fz_abort(error); - error = pdf_decryptxref(xref); + error = pdf_decryptpdf(xref); if (error) fz_abort(error); @@ -167,7 +162,7 @@ int main(int argc, char **argv) if (error) fz_abort(error); - pdf_closexref(xref); + pdf_closepdf(xref); return 0; } diff --git a/test/pdfdebug.c b/test/pdfdebug.c index 7536e7e0..eefa0a74 100644 --- a/test/pdfdebug.c +++ b/test/pdfdebug.c @@ -41,86 +41,73 @@ void printsafe(unsigned char *buf, int n) } } -void decodestream(pdf_xref *xref, fz_obj *stream, int oid, int gid, int ofs) +void decodestream(pdf_xref *xref, int oid, int gid) { fz_error *error; unsigned char buf[512]; safecol = 0; - error = pdf_openstream0(xref, stream, oid, gid, ofs); + error = pdf_openstream(xref, oid, gid); if (error) fz_abort(error); while (1) { - int n = fz_read(xref->file, buf, sizeof buf); + int n = fz_read(xref->stream, buf, sizeof buf); if (n == 0) break; if (n < 0) - fz_abort(fz_ferror(xref->file)); + fz_abort(fz_ferror(xref->stream)); printsafe(buf, n); } pdf_closestream(xref); } -void copystream(pdf_xref *xref, fz_obj *stream, int ofs) +void copystream(pdf_xref *xref, int oid, int gid) { fz_error *error; unsigned char buf[512]; - fz_filter *filter; - fz_obj *obj; - int len; safecol = 0; - obj = fz_dictgets(stream, "Length"); - error = pdf_resolve(&obj, xref); - if (error) fz_abort(error); - len = fz_toint(obj); - fz_dropobj(obj); - - error = fz_newnullfilter(&filter, len); - if (error) fz_abort(error); - - fz_seek(xref->file, ofs, 0); - - error = fz_pushfilter(xref->file, filter); + error = pdf_openrawstream(xref, oid, gid); if (error) fz_abort(error); while (1) { - int n = fz_read(xref->file, buf, sizeof buf); + int n = fz_read(xref->stream, buf, sizeof buf); if (n == 0) break; if (n < 0) - fz_abort(fz_ferror(xref->file)); + fz_abort(fz_ferror(xref->stream)); printsafe(buf, n); } - fz_popfilter(xref->file); + pdf_closestream(xref); } void printobject(pdf_xref *xref, int oid, int gid) { fz_error *error; - int stmofs; fz_obj *obj; - error = pdf_loadobject0(&obj, xref, oid, gid, &stmofs); + error = pdf_loadobject(&obj, xref, oid, gid); if (error) fz_abort(error); printf("%d %d obj\n", oid, gid); fz_debugobj(obj); printf("\n"); - if (stmofs != -1) { + + if (xref->table[oid].stmofs) { printf("stream\n"); if (dodecode) - decodestream(xref, obj, oid, gid, stmofs); + decodestream(xref, oid, gid); else - copystream(xref, obj, stmofs); + copystream(xref, oid, gid); printf("endstream\n"); } + printf("endobj\n"); fz_dropobj(obj); @@ -159,18 +146,14 @@ int main(int argc, char **argv) filename = argv[optind++]; - error = pdf_newxref(&xref); - if (error) - fz_abort(error); - if (dorepair) - error = pdf_repairxref(xref, filename); + error = pdf_repairpdf(&xref, filename); else - error = pdf_openxref(xref, filename); + error = pdf_openpdf(&xref, filename); if (error) fz_abort(error); - error = pdf_decryptxref(xref); + error = pdf_decryptpdf(xref); if (error) fz_abort(error); @@ -180,9 +163,6 @@ int main(int argc, char **argv) if (error) fz_abort(error); } - if (doprintxref) - pdf_debugxref(xref); - if (optind == argc) { printf("trailer\n"); @@ -196,7 +176,10 @@ int main(int argc, char **argv) printf("\n"); } - pdf_closexref(xref); + if (doprintxref) + pdf_debugpdf(xref); + + pdf_closepdf(xref); return 0; } diff --git a/test/pdfmerge.c b/test/pdfmerge.c index a3041188..0ccaeaa4 100644 --- a/test/pdfmerge.c +++ b/test/pdfmerge.c @@ -65,11 +65,7 @@ int main(int argc, char **argv) * Create new blank xref table */ - error = pdf_newxref(&dst); - if (error) - fz_abort(error); - - error = pdf_emptyxref(dst, 1.3); + error = pdf_newpdf(&dst); if (error) fz_abort(error); @@ -83,15 +79,11 @@ int main(int argc, char **argv) for (i = optind; i < argc; i++) { - error = pdf_newxref(&src); - if (error) - fz_abort(error); - - error = pdf_openxref(src, argv[i]); + error = pdf_openpdf(&src, argv[i]); if (error) fz_abort(error); - error = pdf_decryptxref(src); + error = pdf_decryptpdf(src); if (error) fz_abort(error); @@ -119,9 +111,9 @@ int main(int argc, char **argv) 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]), + pdf_updateobject(src, + fz_tonum(srcpages->pref[k]), + fz_togen(srcpages->pref[k]), srcpages->pobj[k]); error = fz_arraypush(srcrefs, srcpages->pref[k]); if (error) @@ -141,14 +133,14 @@ int main(int argc, char **argv) pdf_freepagetree(srcpages); - pdf_closexref(src); + pdf_closepdf(src); } /* * Create and relink Pages object */ - error = pdf_createobject(dst, &pagesoid, &pagesgid); + error = pdf_allocobject(dst, &pagesoid, &pagesgid); if (error) fz_abort(error); @@ -159,9 +151,7 @@ int main(int argc, char **argv) if (error) fz_abort(error); - error = pdf_saveobject(dst, pagesoid, pagesgid, obj); - if (error) - fz_abort(error); + pdf_updateobject(dst, pagesoid, pagesgid, obj); fz_dropobj(obj); @@ -171,17 +161,15 @@ int main(int argc, char **argv) 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); + int oid = fz_tonum(fz_arrayget(dstrefs, i)); + int gid = fz_togen(fz_arrayget(dstrefs, i)); + error = pdf_loadobject(&obj, dst, oid, gid); 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); + pdf_updateobject(dst, oid, gid, obj); fz_dropobj(obj); } @@ -191,7 +179,7 @@ int main(int argc, char **argv) * Create Catalog and trailer */ - error = pdf_createobject(dst, &rootoid, &rootgid); + error = pdf_allocobject(dst, &rootoid, &rootgid); if (error) fz_abort(error); @@ -201,9 +189,7 @@ int main(int argc, char **argv) if (error) fz_abort(error); - error = pdf_saveobject(dst, rootoid, rootgid, obj); - if (error) - fz_abort(error); + pdf_updateobject(dst, rootoid, rootgid, obj); fz_dropobj(obj); diff --git a/test/pdfrip.c b/test/pdfrip.c index 2bcceada..34d6a141 100644 --- a/test/pdfrip.c +++ b/test/pdfrip.c @@ -15,10 +15,10 @@ void runcsi(pdf_xref *xref, pdf_csi *csi, pdf_resources *rdb, fz_obj *stmref) { fz_error *error; - error = pdf_openstream(xref, stmref); + error = pdf_openstream(xref, fz_tonum(stmref), fz_togen(stmref)); if (error) fz_abort(error); - error = pdf_runcsi(csi, rdb, xref->file); + error = pdf_runcsi(csi, rdb, xref->stream); if (error) fz_abort(error); pdf_closestream(xref); @@ -84,25 +84,27 @@ printf("\nfitz tree:\n"); fz_pixmap *pix; fz_renderer *gc; fz_matrix ctm; + fz_rect bbox; #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); + bbox.min.x = 0; + bbox.min.y = 0; + bbox.max.x = W; + bbox.max.y = H; + + ctm = fz_concat(fz_translate(0, -H), fz_scale(1,-1)); printf("rendering!\n"); - fz_rendernode(gc, csi->tree->root, ctm, pix); + fz_rendertree(&pix, gc, csi->tree, ctm, bbox); printf("done!\n"); + fz_debugpixmap(pix); + fz_droppixmap(pix); - fz_freepixmap(pix); fz_freerenderer(gc); } @@ -118,13 +120,11 @@ int main(int argc, char **argv) int c; char *password = ""; - int dorepair = 0; - while ((c = getopt(argc, argv, "rp:")) != -1) + while ((c = getopt(argc, argv, "p:")) != -1) { switch (c) { - case 'r': dorepair ++; break; case 'p': password = optarg; break; default: usage(); } @@ -135,18 +135,11 @@ int main(int argc, char **argv) filename = argv[optind++]; - error = pdf_newxref(&xref); - if (error) - fz_abort(error); - - if (dorepair) - error = pdf_repairxref(xref, filename); - else - error = pdf_openxref(xref, filename); + error = pdf_openpdf(&xref, filename); if (error) fz_abort(error); - error = pdf_decryptxref(xref); + error = pdf_decryptpdf(xref); if (error) fz_abort(error); @@ -175,7 +168,7 @@ int main(int argc, char **argv) showpage(xref, pages->pobj[page - 1]); } - pdf_closexref(xref); + pdf_closepdf(xref); return 0; } diff --git a/tests/t-filter.c b/tests/t-filter.c index c7bc2c7f..50479bea 100644 --- a/tests/t-filter.c +++ b/tests/t-filter.c @@ -82,7 +82,7 @@ main(int argc, char **argv) pipe = filter; } - err = fz_openfile(&file, "/dev/stdin", O_RDONLY); + err = fz_openfile(&file, "/dev/stdin", FZ_READ); if (err) fz_abort(err); if (pipe) diff --git a/tree/debug.c b/tree/debug.c index 8e16c612..a70f971d 100644 --- a/tree/debug.c +++ b/tree/debug.c @@ -157,6 +157,7 @@ static void lispnode(fz_node *node, int level) case FZ_NPATH: lisppath((fz_pathnode*)node, level); break; case FZ_NTEXT: lisptext((fz_textnode*)node, level); break; case FZ_NIMAGE: lispimage((fz_imagenode*)node, level); break; + case FZ_NSHADE: break;//lispshade((fz_shadenode*)node, level); break; case FZ_NLINK: lisplink((fz_linknode*)node, level); break; } } |