summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jamfile2
-rw-r--r--filter/filec.c8
-rw-r--r--filter/filer.c1
-rw-r--r--include/fitz/object.h4
-rw-r--r--include/fitz/pixmap.h11
-rw-r--r--include/fitz/render.h11
-rw-r--r--include/mupdf.h105
-rw-r--r--mupdf/cmap.c2
-rw-r--r--mupdf/doctor.c48
-rw-r--r--mupdf/font.c2
-rw-r--r--mupdf/fontfile.c2
-rw-r--r--mupdf/interpret.c2
-rw-r--r--mupdf/open.c190
-rw-r--r--mupdf/pagetree.c6
-rw-r--r--mupdf/parse.c14
-rw-r--r--mupdf/repair.c110
-rw-r--r--mupdf/resources.c2
-rw-r--r--mupdf/save.c206
-rw-r--r--mupdf/stream.c301
-rw-r--r--mupdf/xref.c339
-rw-r--r--object/simple.c4
-rw-r--r--render/pixmap.c85
-rw-r--r--render/render.c190
-rw-r--r--test/pdfclean.c37
-rw-r--r--test/pdfdebug.c61
-rw-r--r--test/pdfmerge.c44
-rw-r--r--test/pdfrip.c39
-rw-r--r--tests/t-filter.c2
-rw-r--r--tree/debug.c1
29 files changed, 893 insertions, 936 deletions
diff --git a/Jamfile b/Jamfile
index c63f3735..4adafe43 100644
--- a/Jamfile
+++ b/Jamfile
@@ -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(&params, 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;
}
}