diff options
author | Tor Andersson <tor@ghostscript.com> | 2010-07-29 23:17:46 +0000 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2010-07-29 23:17:46 +0000 |
commit | d797d4707564bd9c0e1536d1d6355945aa1be740 (patch) | |
tree | b6aef992de0ce2aa306c4dd330512852c1a63ede | |
parent | 0b954421d7908c8b835d96b4a945418c2ae08de7 (diff) | |
download | mupdf-d797d4707564bd9c0e1536d1d6355945aa1be740.tar.xz |
Use chained reader like interface for filters instead of process interface.
38 files changed, 1418 insertions, 2260 deletions
@@ -98,7 +98,6 @@ FITZ_SRC := \ fitz/filt_jbig2d.c \ fitz/filt_jpxd.c \ fitz/filt_lzwd.c \ - fitz/filt_pipeline.c \ fitz/filt_predict.c \ fitz/obj_array.c \ fitz/obj_dict.c \ @@ -111,7 +110,6 @@ FITZ_SRC := \ fitz/res_shade.c \ fitz/res_text.c \ fitz/stm_buffer.c \ - fitz/stm_filter.c \ fitz/stm_open.c \ fitz/stm_read.c FITZ_OBJ := $(FITZ_SRC:fitz/%.c=$(OBJDIR)/%.o) diff --git a/apps/pdfapp.c b/apps/pdfapp.c index 5a2d2322..1393d4e3 100644 --- a/apps/pdfapp.c +++ b/apps/pdfapp.c @@ -106,7 +106,7 @@ void pdfapp_open(pdfapp_t *app, char *filename, int fd) error = pdf_openxrefwithstream(&app->xref, file, NULL); if (error) pdfapp_error(app, fz_rethrow(error, "cannot open document '%s'", filename)); - fz_dropstream(file); + fz_close(file); /* * Handle encrypted PDF files diff --git a/apps/pdfclean.c b/apps/pdfclean.c index 27c8693c..aca76e2a 100644 --- a/apps/pdfclean.c +++ b/apps/pdfclean.c @@ -380,7 +380,7 @@ static void copystream(fz_obj *obj, int num, int gen) fprintf(out, "%d %d obj\n", num, gen); fz_fprintobj(out, obj, !doexpand); fprintf(out, "stream\n"); - fwrite(buf->rp, 1, buf->wp - buf->rp, out); + fwrite(buf->data, 1, buf->len, out); fprintf(out, "endstream\nendobj\n\n"); fz_dropbuffer(buf); @@ -400,14 +400,14 @@ static void expandstream(fz_obj *obj, int num, int gen) fz_dictdels(newdict, "Filter"); fz_dictdels(newdict, "DecodeParms"); - newlen = fz_newint(buf->wp - buf->rp); + newlen = fz_newint(buf->len); fz_dictputs(newdict, "Length", newlen); fz_dropobj(newlen); fprintf(out, "%d %d obj\n", num, gen); fz_fprintobj(out, newdict, !doexpand); fprintf(out, "stream\n"); - fwrite(buf->rp, 1, buf->wp - buf->rp, out); + fwrite(buf->data, 1, buf->len, out); fprintf(out, "endstream\nendobj\n\n"); fz_dropobj(newdict); diff --git a/apps/pdfextract.c b/apps/pdfextract.c index e0da93e6..cb10e117 100644 --- a/apps/pdfextract.c +++ b/apps/pdfextract.c @@ -92,8 +92,8 @@ static void savefont(fz_obj *dict, int num) fz_obj *obj; char *ext = ""; FILE *f; - unsigned char *p; char *fontname = "font"; + int n; obj = fz_dictgets(dict, "FontName"); if (obj) @@ -148,13 +148,14 @@ static void savefont(fz_obj *dict, int num) f = fopen(name, "wb"); if (f == NULL) - die(fz_throw("Error creating image file")); + die(fz_throw("Error creating font file")); - for (p = buf->rp; p < buf->wp; p ++) - fprintf(f, "%c", *p); + n = fwrite(buf, 1, buf->len, f); + if (n < buf->len) + die(fz_throw("Error writing font file")); if (fclose(f) < 0) - die(fz_throw("Error closing image file")); + die(fz_throw("Error closing font file")); fz_dropbuffer(buf); } diff --git a/apps/pdfshow.c b/apps/pdfshow.c index cb15fd99..b05f6013 100644 --- a/apps/pdfshow.c +++ b/apps/pdfshow.c @@ -111,9 +111,9 @@ static void showstream(int num, int gen) while (1) { - error = fz_read(&n, stm, buf, sizeof buf); - if (error) - die(error); + n = fz_read(stm, buf, sizeof buf); + if (n < 0) + die(n); if (n == 0) break; if (showbinary) @@ -122,7 +122,7 @@ static void showstream(int num, int gen) showsafe(buf, n); } - fz_dropstream(stm); + fz_close(stm); } static void showobject(int num, int gen) diff --git a/fitz/filt_basic.c b/fitz/filt_basic.c index b9ec347e..90be39ee 100644 --- a/fitz/filt_basic.c +++ b/fitz/filt_basic.c @@ -1,97 +1,51 @@ #include "fitz.h" -/* Identity filter */ +/* Pretend we have a filter that just copies data forever */ -fz_filter * -fz_newcopyfilter(void) +fz_stream * +fz_opencopy(fz_stream *chain) { - FZ_NEWFILTER(fz_filter, f, copyfilter); - return f; + return fz_keepstream(chain); } -void -fz_dropcopyfilter(fz_filter *f) -{ -} - -fz_error -fz_processcopyfilter(fz_filter *filter, fz_buffer *in, fz_buffer *out) -{ - int n; - - while (1) - { - if (in->rp + 1 > in->wp) - { - if (in->eof) - return fz_iodone; - return fz_ioneedin; - } - - if (out->wp + 1 > out->ep) - return fz_ioneedout; - - n = MIN(in->wp - in->rp, out->ep - out->wp); - if (n) - { - memcpy(out->wp, in->rp, n); - in->rp += n; - out->wp += n; - } - } -} - -/* Null filter copies data until a specified length */ - -typedef struct fz_nullfilter_s fz_nullfilter; +/* Null filter copies a specified amount of data */ -struct fz_nullfilter_s +struct nullfilter { - fz_filter super; - int len; - int cur; + fz_stream *chain; + int remain; }; -fz_filter * -fz_newnullfilter(int len) +static int +readnull(fz_stream *stm, unsigned char *buf, int len) { - FZ_NEWFILTER(fz_nullfilter, f, nullfilter); - f->len = len; - f->cur = 0; - return (fz_filter *)f; + struct nullfilter *state = stm->state; + int amount = MIN(len, state->remain); + int n = fz_read(state->chain, buf, amount); + if (n < 0) + return fz_rethrow(n, "read error in null filter"); + state->remain -= n; + return n; } -void -fz_dropnullfilter(fz_filter *f) +static void +closenull(fz_stream *stm) { + struct nullfilter *state = stm->state; + fz_close(state->chain); + fz_free(state); } -fz_error -fz_processnullfilter(fz_filter *filter, fz_buffer *in, fz_buffer *out) +fz_stream * +fz_opennull(fz_stream *chain, int len) { - fz_nullfilter *f = (fz_nullfilter*)filter; - int n; - - n = MIN(in->wp - in->rp, out->ep - out->wp); - if (f->len >= 0) - n = MIN(n, f->len - f->cur); - - if (n) - { - memcpy(out->wp, in->rp, n); - in->rp += n; - out->wp += n; - f->cur += n; - } + struct nullfilter *state; - if (f->cur == f->len) - return fz_iodone; - if (in->rp == in->wp) - return fz_ioneedin; - if (out->wp == out->ep) - return fz_ioneedout; + state = fz_malloc(sizeof(struct nullfilter)); + state->chain = chain; + state->remain = len; - return fz_throw("braindead programmer trapped in nullfilter"); + return fz_newstream(state, readnull, closenull); } /* ASCII Hex Decode */ @@ -100,9 +54,8 @@ typedef struct fz_ahxd_s fz_ahxd; struct fz_ahxd_s { - fz_filter super; - int odd; - int a; + fz_stream *chain; + int eod; }; static inline int iswhite(int a) @@ -133,58 +86,71 @@ static inline int fromhex(int a) return 0; } -fz_filter * -fz_newahxd(fz_obj *params) -{ - FZ_NEWFILTER(fz_ahxd, f, ahxd); - f->odd = 0; - f->a = 0; - return (fz_filter *)f; -} - -void -fz_dropahxd(fz_filter *f) +static int +readahxd(fz_stream *stm, unsigned char *buf, int len) { -} + fz_ahxd *state = stm->state; + unsigned char *p = buf; + int a, b, c, odd; -fz_error -fz_processahxd(fz_filter *filter, fz_buffer *in, fz_buffer *out) -{ - fz_ahxd *f = (fz_ahxd*)filter; - int b, c; + odd = 0; - while (1) + while (p < buf + len) { - if (in->rp == in->wp) - return fz_ioneedin; + if (state->eod) + return p - buf; - if (out->wp == out->ep) - return fz_ioneedout; + c = fz_readbyte(state->chain); + if (c < 0) + return p - buf; - c = *in->rp++; - - if (ishex(c)) { - if (!f->odd) { - f->a = fromhex(c); - f->odd = 1; + if (ishex(c)) + { + if (!odd) + { + a = fromhex(c); + odd = 1; } - else { + else + { b = fromhex(c); - *out->wp++ = (f->a << 4) | b; - f->odd = 0; + *p++ = (a << 4) | b; + odd = 0; } } - - else if (c == '>') { - if (f->odd) - *out->wp++ = (f->a << 4); - return fz_iodone; + else if (c == '>') + { + if (odd) + *p++ = (a << 4); + state->eod = 1; } - - else if (!iswhite(c)) { + else if (!iswhite(c)) + { return fz_throw("bad data in ahxd: '%c'", c); } } + + return p - buf; +} + +static void +closeahxd(fz_stream *stm) +{ + fz_ahxd *state = stm->state; + fz_close(state->chain); + fz_free(state); +} + +fz_stream * +fz_openahxd(fz_stream *chain) +{ + fz_ahxd *state; + + state = fz_malloc(sizeof(fz_ahxd)); + state->chain = chain; + state->eod = 0; + + return fz_newstream(state, readahxd, closeahxd); } /* ASCII 85 Decode */ @@ -193,187 +159,207 @@ typedef struct fz_a85d_s fz_a85d; struct fz_a85d_s { - fz_filter super; - unsigned long word; - int count; + fz_stream *chain; + unsigned char buf[4]; + int remain; + int eod; }; -fz_filter * -fz_newa85d(fz_obj *params) -{ - FZ_NEWFILTER(fz_a85d, f, a85d); - f->word = 0; - f->count = 0; - return (fz_filter *)f; -} - -void -fz_dropa85d(fz_filter *f) -{ -} - -fz_error -fz_processa85d(fz_filter *filter, fz_buffer *in, fz_buffer *out) +static int +reada85d(fz_stream *stm, unsigned char *buf, int len) { - fz_a85d *f = (fz_a85d*)filter; + fz_a85d *state = stm->state; + unsigned char *p = buf; + int count = 0; + int word = 0; int c; - while (1) - { - if (in->rp == in->wp) - return fz_ioneedin; + while (state->remain > 0 && p < buf + len) + *p++ = state->buf[4 - state->remain]; - c = *in->rp++; + while (p < buf + len) + { + if (state->eod) + return p - buf; - if (c >= '!' && c <= 'u') { - if (f->count == 4) { - if (out->wp + 4 > out->ep) { - in->rp --; - return fz_ioneedout; - } + c = fz_readbyte(state->chain); + if (c < 0) + return p - buf; - f->word = f->word * 85 + (c - '!'); + if (c >= '!' && c <= 'u') + { + if (count == 4) + { + word = word * 85 + (c - '!'); - *out->wp++ = (f->word >> 24) & 0xff; - *out->wp++ = (f->word >> 16) & 0xff; - *out->wp++ = (f->word >> 8) & 0xff; - *out->wp++ = (f->word) & 0xff; + state->buf[0] = (word >> 24) & 0xff; + state->buf[1] = (word >> 16) & 0xff; + state->buf[2] = (word >> 8) & 0xff; + state->buf[3] = (word) & 0xff; + state->remain = 4; - f->word = 0; - f->count = 0; + word = 0; + count = 0; } - else { - f->word = f->word * 85 + (c - '!'); - f->count ++; + else + { + word = word * 85 + (c - '!'); + count ++; } } - else if (c == 'z' && f->count == 0) { - if (out->wp + 4 > out->ep) { - in->rp --; - return fz_ioneedout; - } - *out->wp++ = 0; - *out->wp++ = 0; - *out->wp++ = 0; - *out->wp++ = 0; + else if (c == 'z' && count == 0) + { + state->buf[0] = 0; + state->buf[1] = 0; + state->buf[2] = 0; + state->buf[3] = 0; + state->remain = 4; } - else if (c == '~') { - if (in->rp == in->wp) { - in->rp --; - return fz_ioneedin; - } - - c = *in->rp++; - - if (c != '>') { + else if (c == '~') + { + c = fz_readbyte(state->chain); + if (c != '>') return fz_throw("bad eod marker in a85d"); - } - - if (out->wp + f->count - 1 > out->ep) { - in->rp -= 2; - return fz_ioneedout; - } - switch (f->count) { + switch (count) { case 0: break; case 1: return fz_throw("partial final byte in a85d"); case 2: - f->word = f->word * (85L * 85 * 85) + 0xffffffL; - goto o1; + word = word * (85 * 85 * 85) + 0xffffff; + state->buf[0] = word >> 24; + state->remain = 1; + break; case 3: - f->word = f->word * (85L * 85) + 0xffffL; - goto o2; + word = word * (85 * 85) + 0xffff; + state->buf[0] = word >> 24; + state->buf[1] = word >> 16; + state->remain = 2; + break; case 4: - f->word = f->word * 85 + 0xffL; - *(out->wp+2) = f->word >> 8; - o2: *(out->wp+1) = f->word >> 16; - o1: *(out->wp+0) = f->word >> 24; - out->wp += f->count - 1; + word = word * 85 + 0xff; + state->buf[0] = word >> 24; + state->buf[1] = word >> 16; + state->buf[2] = word >> 8; + state->remain = 3; break; } - return fz_iodone; + state->eod = 1; } - else if (!iswhite(c)) { + else if (!iswhite(c)) + { return fz_throw("bad data in a85d: '%c'", c); } + + while (state->remain > 0 && p < buf + len) + *p++ = state->buf[4 - state->remain]; } -} -/* Run Length Decode */ + return p - buf; +} -fz_filter * -fz_newrld(fz_obj *params) +static void +closea85d(fz_stream *stm) { - FZ_NEWFILTER(fz_filter, f, rld); - return f; + fz_a85d *state = stm->state; + fz_close(state->chain); + fz_free(state); } -void -fz_droprld(fz_filter *rld) +fz_stream * +fz_opena85d(fz_stream *chain) { + fz_a85d *state; + + state = fz_malloc(sizeof(fz_a85d)); + state->chain = chain; + state->remain = 0; + state->eod = 0; + + return fz_newstream(state, reada85d, closea85d); } -fz_error -fz_processrld(fz_filter *filter, fz_buffer *in, fz_buffer *out) +/* Run Length Decode */ + +typedef struct fz_rld_s fz_rld; + +struct fz_rld_s +{ + fz_stream *chain; + int run, n, c; +}; + +static int +readrld(fz_stream *stm, unsigned char *buf, int len) { - int run, i; - unsigned char c; + fz_rld *state = stm->state; + unsigned char *p = buf; - while (1) + while (p < buf + len) { - if (in->rp == in->wp) + if (state->run == 128) + return p - buf; + + if (state->n == 0) { - if (in->eof) + state->run = fz_readbyte(state->chain); + if (state->run < 0) + state->run = 128; + if (state->run < 128) + state->n = state->run + 1; + if (state->run > 128) { - return fz_iodone; + state->n = 257 - state->run; + state->c = fz_readbyte(state->chain); + if (state->c < 0) + return fz_throw("premature end of data in run length decode"); } - return fz_ioneedin; } - if (out->wp == out->ep) - return fz_ioneedout; - - run = *in->rp++; - - if (run == 128) + if (state->run < 128) { - return fz_iodone; - } - - else if (run < 128) { - run = run + 1; - if (in->rp + run > in->wp) { - in->rp --; - return fz_ioneedin; - } - if (out->wp + run > out->ep) { - in->rp --; - return fz_ioneedout; + while (p < buf + len && state->n--) + { + int c = fz_readbyte(state->chain); + if (c < 0) + return fz_throw("premature end of data in run length decode"); + *p++ = c; } - for (i = 0; i < run; i++) - *out->wp++ = *in->rp++; } - else if (run > 128) { - run = 257 - run; - if (in->rp + 1 > in->wp) { - in->rp --; - return fz_ioneedin; - } - if (out->wp + run > out->ep) { - in->rp --; - return fz_ioneedout; - } - c = *in->rp++; - for (i = 0; i < run; i++) - *out->wp++ = c; + if (state->run > 128) + { + while (p < buf + len && state->n--) + *p++ = state->c; } } + + return p - buf; +} + +static void +closerld(fz_stream *stm) +{ + fz_rld *state = stm->state; + fz_close(state->chain); + fz_free(state); +} + +fz_stream * +fz_openrld(fz_stream *chain) +{ + fz_rld *state; + + state = fz_malloc(sizeof(fz_rld)); + state->run = 0; + state->n = 0; + state->c = 0; + + return fz_newstream(state, readrld, closerld); } /* RC4 Filter */ @@ -382,44 +368,43 @@ typedef struct fz_arc4c_s fz_arc4c; struct fz_arc4c_s { - fz_filter super; + fz_stream *chain; fz_arc4 arc4; }; -fz_filter * -fz_newarc4filter(unsigned char *key, unsigned keylen) +static int +readarc4(fz_stream *stm, unsigned char *buf, int len) { - FZ_NEWFILTER(fz_arc4c, f, arc4filter); - fz_arc4init(&f->arc4, key, keylen); - return (fz_filter *)f; + fz_arc4c *state = stm->state; + int n; + + n = fz_read(state->chain, buf, len); + if (n < 0) + return fz_rethrow(n, "read error in arc4 filter"); + + fz_arc4encrypt(&state->arc4, buf, buf, n); + + return n; } -void -fz_droparc4filter(fz_filter *f) +static void +closearc4(fz_stream *stm) { + fz_arc4c *state = stm->state; + fz_close(state->chain); + fz_free(state); } -fz_error -fz_processarc4filter(fz_filter *filter, fz_buffer *in, fz_buffer *out) +fz_stream * +fz_openarc4(fz_stream *chain, unsigned char *key, unsigned keylen) { - fz_arc4c *f = (fz_arc4c*)filter; - int n; + fz_arc4c *state; - while (1) - { - if (in->rp + 1 > in->wp) { - if (in->eof) - return fz_iodone; - return fz_ioneedin; - } - if (out->wp + 1 > out->ep) - return fz_ioneedout; + state = fz_malloc(sizeof(fz_arc4c)); + state->chain = chain; + fz_arc4init(&state->arc4, key, keylen); - n = MIN(in->wp - in->rp, out->ep - out->wp); - fz_arc4encrypt(&f->arc4, out->wp, in->rp, n); - in->rp += n; - out->wp += n; - } + return fz_newstream(state, readarc4, closearc4); } /* AES Filter */ @@ -428,65 +413,80 @@ typedef struct fz_aesd_s fz_aesd; struct fz_aesd_s { - fz_filter super; + fz_stream *chain; fz_aes aes; unsigned char iv[16]; int ivcount; + unsigned char buf[16]; + int remain; }; -fz_filter * -fz_newaesdfilter(unsigned char *key, unsigned keylen) +static int +readaesd(fz_stream *stm, unsigned char *buf, int len) { - FZ_NEWFILTER(fz_aesd, f, aesdfilter); - aes_setkey_dec(&f->aes, key, keylen * 8); - f->ivcount = 0; - return (fz_filter *)f; -} + fz_aesd *state = stm->state; + unsigned char *p = buf; -void -fz_dropaesdfilter(fz_filter *f) -{ -} + while (state->ivcount < 16) + { + int c = fz_readbyte(state->chain); + if (c < 0) + return fz_throw("premature end in AES filter"); + state->iv[state->ivcount++] = c; + } -fz_error -fz_processaesdfilter(fz_filter *filter, fz_buffer *in, fz_buffer *out) -{ - fz_aesd *f = (fz_aesd*)filter; - int n; + while (p < buf + len && state->remain-- > 0) + *p++ = state->buf[16 - state->remain]; - while (1) + while (p < buf + len) { - if (in->rp + 16 > in->wp) + while (state->remain < 16) { - if (in->eof) - return fz_iodone; - return fz_ioneedin; + int c = fz_readbyte(state->chain); + if (c < 0) + { + if (state->remain > 0) + return fz_throw("premature end in AES filter"); + return p - buf; + } + state->buf[state->remain++] = c; } - if (f->ivcount < 16) + aes_crypt_cbc(&state->aes, AES_DECRYPT, 16, state->iv, state->buf, state->buf); + + /* strip padding at end of file */ + if (fz_peekbyte(state->chain) == EOF) { - f->iv[f->ivcount++] = *in->rp++; + int pad = state->buf[15]; + if (pad < 1 || pad > 16) + return fz_throw("aes padding out of range: %d", pad); + state->remain -= pad; } - else - { - if (out->wp + 16 > out->ep) - return fz_ioneedout; - n = MIN(in->wp - in->rp, out->ep - out->wp); - n = (n / 16) * 16; + while (p < buf + len && state->remain-- > 0) + *p++ = state->buf[16 - state->remain]; + } - aes_crypt_cbc(&f->aes, AES_DECRYPT, n, f->iv, in->rp, out->wp); - in->rp += n; - out->wp += n; + return p - buf; +} - /* Remove padding bytes */ - if (in->eof && in->rp == in->wp) - { - int pad = out->wp[-1]; - if (pad < 1 || pad > 16) - return fz_throw("aes padding out of range: %d", pad); - out->wp -= pad; - } - } - } +static void +closeaesd(fz_stream *stm) +{ + fz_aesd *state = stm->state; + fz_close(state->chain); + fz_free(state); +} + +fz_stream * +fz_openaesd(fz_stream *chain, unsigned char *key, unsigned keylen) +{ + fz_aesd *state; + + state = fz_malloc(sizeof(fz_aesd)); + state->chain = chain; + aes_setkey_dec(&state->aes, key, keylen * 8); + state->ivcount = 0; + + return fz_newstream(state, readaesd, closeaesd); } diff --git a/fitz/filt_dctd.c b/fitz/filt_dctd.c index 3b3cc415..e260b34c 100644 --- a/fitz/filt_dctd.c +++ b/fitz/filt_dctd.c @@ -5,254 +5,212 @@ typedef struct fz_dctd_s fz_dctd; -struct myerrmgr +struct fz_dctd_s { - struct jpeg_error_mgr super; + fz_stream *chain; + int colortransform; + int init, done; + unsigned char *scanline; + int stride; + int remain; + struct jpeg_decompress_struct cinfo; + struct jpeg_source_mgr srcmgr; + struct jpeg_error_mgr errmgr; jmp_buf jb; char msg[JMSG_LENGTH_MAX]; }; -static void myerrexit(j_common_ptr cinfo) +static void error_exit(j_common_ptr cinfo) { - struct myerrmgr *err = (struct myerrmgr *)cinfo->err; - char msgbuf[JMSG_LENGTH_MAX]; - err->super.format_message(cinfo, msgbuf); - fz_strlcpy(err->msg, msgbuf, sizeof err->msg); - longjmp(err->jb, 1); + fz_dctd *state = cinfo->client_data; + cinfo->err->format_message(cinfo, state->msg); + longjmp(state->jb, 1); } -static void myoutmess(j_common_ptr cinfo) +static void init_source(j_decompress_ptr cinfo) { - struct myerrmgr *err = (struct myerrmgr *)cinfo->err; - char msgbuf[JMSG_LENGTH_MAX]; - err->super.format_message(cinfo, msgbuf); - fz_warn("jpeg error: %s", msgbuf); + /* nothing to do */ } -static void myiniterr(struct myerrmgr *err) +static void term_source(j_decompress_ptr cinfo) { - jpeg_std_error(&err->super); - err->super.error_exit = myerrexit; - err->super.output_message = myoutmess; + /* nothing to do */ } -struct mysrcmgr +static boolean fill_input_buffer(j_decompress_ptr cinfo) { - struct jpeg_source_mgr super; - fz_buffer *buf; - int skip; -}; + struct jpeg_source_mgr *src = cinfo->src; + fz_dctd *state = cinfo->client_data; + fz_stream *chain = state->chain; -struct fz_dctd_s -{ - fz_filter super; - struct jpeg_decompress_struct cinfo; - struct mysrcmgr src; - struct myerrmgr err; - int colortransform; - int stage; -}; + if (chain->rp == chain->wp) + fz_fillbuffer(chain); -static void myinitsource(j_decompress_ptr cinfo) { /* empty */ } -static int myfillinput(j_decompress_ptr cinfo) { return FALSE; } -static void mytermsource(j_decompress_ptr cinfo) { /* empty */ } - -static void myskipinput(j_decompress_ptr cinfo, long n) -{ - struct mysrcmgr *src = (struct mysrcmgr *)cinfo->src; - fz_buffer *in = src->buf; + src->next_input_byte = chain->rp; + src->bytes_in_buffer = chain->wp - chain->rp; + chain->rp = chain->wp; - assert(src->skip == 0); - - in->rp = in->wp - src->super.bytes_in_buffer; - - if (in->rp + n > in->wp) { - src->skip = (in->rp + n) - in->wp; - in->rp = in->wp; - } - else { - src->skip = 0; - in->rp += n; - } - - src->super.bytes_in_buffer = in->wp - in->rp; - src->super.next_input_byte = in->rp; -} - -fz_filter * -fz_newdctd(fz_obj *params) -{ - fz_obj *obj; - int colortransform; - - FZ_NEWFILTER(fz_dctd, d, dctd); - - colortransform = -1; /* "unset" */ - - if (params) + if (src->bytes_in_buffer == 0) { - obj = fz_dictgets(params, "ColorTransform"); - if (obj) - colortransform = fz_toint(obj); + static unsigned char eoi[2] = { 0xFF, JPEG_EOI }; + fz_warn("premature end of file in jpeg"); + src->next_input_byte = eoi; + src->bytes_in_buffer = 2; } - d->colortransform = colortransform; - d->stage = 0; - - /* setup error callback first thing */ - myiniterr(&d->err); - d->cinfo.err = (struct jpeg_error_mgr*) &d->err; - - if (setjmp(d->err.jb)) - fz_warn("cannot initialise jpeg: %s", d->err.msg); - - /* create decompression object. this zeroes cinfo except for err. */ - jpeg_create_decompress(&d->cinfo); - - /* prepare source manager */ - d->cinfo.src = (struct jpeg_source_mgr *)&d->src; - d->src.super.init_source = myinitsource; - d->src.super.fill_input_buffer = myfillinput; - d->src.super.skip_input_data = myskipinput; - d->src.super.resync_to_restart = jpeg_resync_to_restart; - d->src.super.term_source = mytermsource; - - d->src.super.bytes_in_buffer = 0; - d->src.super.next_input_byte = nil; - d->src.skip = 0; - - return (fz_filter *)d; + return 1; } -void -fz_dropdctd(fz_filter *filter) +static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { - fz_dctd *d = (fz_dctd*)filter; - if (setjmp(d->err.jb)) { - fz_warn("jpeg error: jpeg_destroy_decompress: %s", d->err.msg); - return; + struct jpeg_source_mgr *src = cinfo->src; + if (num_bytes > 0) + { + while (num_bytes > src->bytes_in_buffer) + { + num_bytes -= src->bytes_in_buffer; + (void) src->fill_input_buffer(cinfo); + } + src->next_input_byte += num_bytes; + src->bytes_in_buffer -= num_bytes; } - jpeg_destroy_decompress(&d->cinfo); } -fz_error -fz_processdctd(fz_filter *filter, fz_buffer *in, fz_buffer *out) +static int +readdctd(fz_stream *stm, unsigned char *buf, int len) { - fz_dctd *d = (fz_dctd*)filter; - int b; - int i; - int stride; - JSAMPROW scanlines[1]; - - d->src.buf = in; + fz_dctd *state = stm->state; + j_decompress_ptr cinfo = &state->cinfo; + unsigned char *p = buf; - /* skip any bytes left over from myskipinput() */ - if (d->src.skip > 0) { - if (in->rp + d->src.skip > in->wp) { - d->src.skip = (in->rp + d->src.skip) - in->wp; - in->rp = in->wp; - goto needinput; - } - else { - in->rp += d->src.skip; - d->src.skip = 0; - } - } - - d->src.super.bytes_in_buffer = in->wp - in->rp; - d->src.super.next_input_byte = in->rp; - - if (setjmp(d->err.jb)) + if (setjmp(state->jb)) { - return fz_throw("cannot decode jpeg: %s", d->err.msg); + state->done = 1; + return fz_throw("jpeg error: %s", state->msg); } - switch (d->stage) + if (!state->init) { - case 0: - i = jpeg_read_header(&d->cinfo, TRUE); - if (i == JPEG_SUSPENDED) - goto needinput; + cinfo->client_data = state; + cinfo->err = &state->errmgr; + jpeg_std_error(cinfo->err); + cinfo->err->error_exit = error_exit; + jpeg_create_decompress(cinfo); + + cinfo->src = &state->srcmgr; + cinfo->src->init_source = init_source; + cinfo->src->fill_input_buffer = fill_input_buffer; + cinfo->src->skip_input_data = skip_input_data; + cinfo->src->resync_to_restart = jpeg_resync_to_restart; + cinfo->src->term_source = term_source; + cinfo->src->next_input_byte = state->chain->rp; + cinfo->src->bytes_in_buffer = 0; + + jpeg_read_header(cinfo, 1); /* speed up jpeg decoding a bit */ - d->cinfo.dct_method = JDCT_FASTEST; - d->cinfo.do_fancy_upsampling = FALSE; + cinfo->dct_method = JDCT_FASTEST; + cinfo->do_fancy_upsampling = FALSE; /* default value if ColorTransform is not set */ - if (d->colortransform == -1) + if (state->colortransform == -1) { - if (d->cinfo.num_components == 3) - d->colortransform = 1; + if (state->cinfo.num_components == 3) + state->colortransform = 1; else - d->colortransform = 0; + state->colortransform = 0; } - if (d->cinfo.saw_Adobe_marker) - d->colortransform = d->cinfo.Adobe_transform; + if (cinfo->saw_Adobe_marker) + state->colortransform = cinfo->Adobe_transform; /* Guess the input colorspace, and set output colorspace accordingly */ - switch (d->cinfo.num_components) + switch (cinfo->num_components) { case 3: - if (d->colortransform) - d->cinfo.jpeg_color_space = JCS_YCbCr; + if (state->colortransform) + cinfo->jpeg_color_space = JCS_YCbCr; else - d->cinfo.jpeg_color_space = JCS_RGB; + cinfo->jpeg_color_space = JCS_RGB; break; case 4: - if (d->colortransform) - d->cinfo.jpeg_color_space = JCS_YCCK; + if (state->colortransform) + cinfo->jpeg_color_space = JCS_YCCK; else - d->cinfo.jpeg_color_space = JCS_CMYK; + cinfo->jpeg_color_space = JCS_CMYK; break; } - /* fall through */ - d->stage = 1; + jpeg_start_decompress(cinfo); + + state->stride = cinfo->output_width * cinfo->output_components; + state->remain = 0; + state->scanline = fz_malloc(state->stride); - case 1: - b = jpeg_start_decompress(&d->cinfo); - if (b == FALSE) - goto needinput; + state->init = 1; + } - /* fall through */ - d->stage = 2; + while (state->remain > 0 && p < buf + len) + *p++ = state->scanline[state->stride - state->remain--]; - case 2: - stride = d->cinfo.output_width * d->cinfo.output_components; + while (p < buf + len) + { + if (state->done) + return p - buf; - while (d->cinfo.output_scanline < d->cinfo.output_height) + if (cinfo->output_scanline == cinfo->output_height) { - if (out->wp + stride > out->ep) - goto needoutput; + state->done = 1; + jpeg_finish_decompress(cinfo); + jpeg_destroy_decompress(cinfo); + return p - buf; + } - scanlines[0] = out->wp; + if (p + state->stride <= buf + len) + { + jpeg_read_scanlines(cinfo, &p, 1); + p += state->stride; + } + else + { + jpeg_read_scanlines(cinfo, &state->scanline, 1); + state->remain = state->stride; + } - i = jpeg_read_scanlines(&d->cinfo, scanlines, 1); + while (state->remain > 0 && p < buf + len) + *p++ = state->scanline[state->stride - state->remain--]; + } - if (i == 0) - goto needinput; + return p - buf; +} - out->wp += stride; - } +static void +closedctd(fz_stream *stm) +{ + fz_dctd *state = stm->state; + fz_free(state->scanline); + fz_close(state->chain); + fz_free(state); +} - /* fall through */ - d->stage = 3; +fz_stream * +fz_opendctd(fz_stream *chain, fz_obj *params) +{ + fz_dctd *state; + fz_obj *obj; - case 3: - b = jpeg_finish_decompress(&d->cinfo); - if (b == FALSE) - goto needinput; - d->stage = 4; - in->rp = in->wp - d->src.super.bytes_in_buffer; - return fz_iodone; - } + state = fz_malloc(sizeof(fz_dctd)); + state->chain = chain; + state->colortransform = -1; /* unset */ + state->init = 0; + state->done = 0; + state->scanline = nil; + state->stride = 0; + state->remain = 0; -needinput: - in->rp = in->wp - d->src.super.bytes_in_buffer; - return fz_ioneedin; + obj = fz_dictgets(params, "ColorTransform"); + if (obj) + state->colortransform = fz_toint(obj); -needoutput: - in->rp = in->wp - d->src.super.bytes_in_buffer; - return fz_ioneedout; + return fz_newstream(state, readdctd, closedctd); } diff --git a/fitz/filt_faxd.c b/fitz/filt_faxd.c index 7361735d..57e206bf 100644 --- a/fitz/filt_faxd.c +++ b/fitz/filt_faxd.c @@ -261,11 +261,13 @@ findchangingcolor(const unsigned char *line, int x, int w, int color) return x; } -static const unsigned char lm[8] = -{ 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 }; +static const unsigned char lm[8] = { + 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 +}; -static const unsigned char rm[8] = -{ 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE }; +static const unsigned char rm[8] = { + 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE +}; static inline void setbits(unsigned char *line, int x0, int x1) @@ -300,12 +302,13 @@ typedef enum fax_stage_e SNORMAL, /* neutral state, waiting for any code */ SMAKEUP, /* got a 1d makeup code, waiting for terminating code */ SEOL, /* at eol, needs output buffer space */ - SH1, SH2 /* in H part 1 and 2 (both makeup and terminating codes) */ + SH1, SH2, /* in H part 1 and 2 (both makeup and terminating codes) */ + SDONE /* all done */ } fax_stage_e; struct fz_faxd_s { - fz_filter super; + fz_stream *chain; int k; int endofline; @@ -326,95 +329,31 @@ struct fz_faxd_s int a, c, dim, eolc; unsigned char *ref; unsigned char *dst; + int remain; }; -fz_filter * -fz_newfaxd(fz_obj *params) -{ - fz_obj *obj; - - FZ_NEWFILTER(fz_faxd, fax, faxd); - - fax->ref = nil; - fax->dst = nil; - - fax->k = 0; - fax->endofline = 0; - fax->encodedbytealign = 0; - fax->columns = 1728; - fax->rows = 0; - fax->endofblock = 1; - fax->blackis1 = 0; - - obj = fz_dictgets(params, "K"); - if (obj) fax->k = fz_toint(obj); - - obj = fz_dictgets(params, "EndOfLine"); - if (obj) fax->endofline = fz_tobool(obj); - - obj = fz_dictgets(params, "EncodedByteAlign"); - if (obj) fax->encodedbytealign = fz_tobool(obj); - - obj = fz_dictgets(params, "Columns"); - if (obj) fax->columns = fz_toint(obj); - - obj = fz_dictgets(params, "Rows"); - if (obj) fax->rows = fz_toint(obj); - - obj = fz_dictgets(params, "EndOfBlock"); - if (obj) fax->endofblock = fz_tobool(obj); - - obj = fz_dictgets(params, "BlackIs1"); - if (obj) fax->blackis1 = fz_tobool(obj); - - fax->stride = ((fax->columns - 1) >> 3) + 1; - fax->ridx = 0; - fax->bidx = 32; - fax->word = 0; - - fax->stage = SNORMAL; - fax->a = -1; - fax->c = 0; - fax->dim = fax->k < 0 ? 2 : 1; - fax->eolc = 0; - - fax->ref = fz_malloc(fax->stride); - fax->dst = fz_malloc(fax->stride); - - memset(fax->ref, 0, fax->stride); - memset(fax->dst, 0, fax->stride); - - return (fz_filter*)fax; -} - -void -fz_dropfaxd(fz_filter *p) -{ - fz_faxd *fax = (fz_faxd*) p; - fz_free(fax->ref); - fz_free(fax->dst); -} - -static inline void eatbits(fz_faxd *fax, int nbits) +static inline void +eatbits(fz_faxd *fax, int nbits) { fax->word <<= nbits; fax->bidx += nbits; } -static inline fz_error fillbits(fz_faxd *fax, fz_buffer *in) +static inline int +fillbits(fz_faxd *fax) { while (fax->bidx >= 8) { - if (in->rp + 1 > in->wp) - return fz_ioneedin; + int c = fz_readbyte(fax->chain); + if (c == EOF) + return EOF; fax->bidx -= 8; - fax->word |= *in->rp << fax->bidx; - in->rp ++; + fax->word |= c << fax->bidx; } - return fz_okay; + return 0; } -static int +static inline int getcode(fz_faxd *fax, const cfd_node *table, int initialbits) { unsigned int word = fax->word; @@ -602,33 +541,30 @@ dec2d(fz_faxd *fax) return 0; } -fz_error -fz_processfaxd(fz_filter *f, fz_buffer *in, fz_buffer *out) +static int +readfaxd(fz_stream *stm, unsigned char *buf, int len) { - fz_faxd *fax = (fz_faxd*)f; + fz_faxd *fax = stm->state; + unsigned char *p = buf; + unsigned char *tmp; fz_error error; int i; - unsigned char *tmp; + + if (fax->stage == SDONE) + return 0; if (fax->stage == SEOL) goto eol; loop: - if (fillbits(fax, in)) + if (fillbits(fax)) { - if (in->eof) + if (fax->bidx > 31) { - if (fax->bidx > 31) - { - if (fax->a > 0) - goto eol; - goto rtc; - } - } - else - { - return fz_ioneedin; + if (fax->a > 0) + goto eol; + goto rtc; } } @@ -667,14 +603,15 @@ loop: { fax->eolc = 0; error = dec1d(fax); - if (error) return error; /* can be fz_io* or real error */ - + if (error) + return fz_rethrow(error, "cannot decode 1d code"); } else if (fax->dim == 2) { fax->eolc = 0; error = dec2d(fax); - if (error) return error; /* can be fz_io* or real error */ + if (error) + return fz_rethrow(error, "cannot decode 2d code"); } /* no eol check after makeup codes nor in the middle of an H code */ @@ -694,24 +631,27 @@ loop: eol: fax->stage = SEOL; - if (out->wp + fax->stride > out->ep) - return fz_ioneedout; if (fax->blackis1) - memcpy(out->wp, fax->dst, fax->stride); - else { - unsigned char * restrict d = out->wp; - unsigned char * restrict s = fax->dst; - int w = fax->stride; - for (i = 0; i < w; i++) - *d++ = *s++ ^ 0xff; + { + while (p < buf + len && fax->remain-- > 0) + *p++ = fax->dst[fax->stride - fax->remain]; + } + else + { + while (p < buf + len && fax->remain-- > 0) + *p++ = fax->dst[fax->stride - fax->remain] ^ 0xff; } + if (fax->remain > 0) + return p - buf; + + fax->remain = fax->stride; + tmp = fax->ref; fax->ref = fax->dst; fax->dst = tmp; memset(fax->dst, 0, fax->stride); - out->wp += fax->stride; fax->stage = SNORMAL; fax->c = 0; @@ -745,9 +685,84 @@ eol: goto loop; rtc: + fax->stage = SDONE; + + /* try to put back any extra bytes we read */ i = (32 - fax->bidx) / 8; - while (i-- && in->rp > in->bp) - in->rp --; + while (i--) + fz_unreadbyte(fax->chain); + + return p - buf; +} + +static void +closefaxd(fz_stream *stm) +{ + fz_faxd *fax = stm->state; + fz_close(fax->chain); + fz_free(fax->ref); + fz_free(fax->dst); + fz_free(fax); +} + +fz_stream * +fz_openfaxd(fz_stream *chain, fz_obj *params) +{ + fz_faxd *fax; + fz_obj *obj; + + fax = fz_malloc(sizeof(fz_faxd)); + fax->chain = chain; + + fax->ref = nil; + fax->dst = nil; + + fax->k = 0; + fax->endofline = 0; + fax->encodedbytealign = 0; + fax->columns = 1728; + fax->rows = 0; + fax->endofblock = 1; + fax->blackis1 = 0; + + obj = fz_dictgets(params, "K"); + if (obj) fax->k = fz_toint(obj); + + obj = fz_dictgets(params, "EndOfLine"); + if (obj) fax->endofline = fz_tobool(obj); + + obj = fz_dictgets(params, "EncodedByteAlign"); + if (obj) fax->encodedbytealign = fz_tobool(obj); + + obj = fz_dictgets(params, "Columns"); + if (obj) fax->columns = fz_toint(obj); + + obj = fz_dictgets(params, "Rows"); + if (obj) fax->rows = fz_toint(obj); + + obj = fz_dictgets(params, "EndOfBlock"); + if (obj) fax->endofblock = fz_tobool(obj); + + obj = fz_dictgets(params, "BlackIs1"); + if (obj) fax->blackis1 = fz_tobool(obj); + + fax->stride = ((fax->columns - 1) >> 3) + 1; + fax->ridx = 0; + fax->bidx = 32; + fax->word = 0; + + fax->stage = SNORMAL; + fax->a = -1; + fax->c = 0; + fax->dim = fax->k < 0 ? 2 : 1; + fax->eolc = 0; + + fax->ref = fz_malloc(fax->stride); + fax->dst = fz_malloc(fax->stride); + fax->remain = fax->stride; + + memset(fax->ref, 0, fax->stride); + memset(fax->dst, 0, fax->stride); - return fz_iodone; + return fz_newstream(fax, readfaxd, closefaxd); } diff --git a/fitz/filt_flate.c b/fitz/filt_flate.c index 96a7a09a..bb3ac692 100644 --- a/fitz/filt_flate.c +++ b/fitz/filt_flate.c @@ -6,97 +6,88 @@ typedef struct fz_flate_s fz_flate; struct fz_flate_s { - fz_filter super; + fz_stream *chain; z_stream z; }; -static void * -zmalloc(void *opaque, unsigned int items, unsigned int size) +static void * zmalloc(void *opaque, unsigned int items, unsigned int size) { return fz_malloc(items * size); } -static void -zfree(void *opaque, void *ptr) +static void zfree(void *opaque, void *ptr) { fz_free(ptr); } -fz_filter * -fz_newflated(fz_obj *params) +static int +readflated(fz_stream *stm, unsigned char *outbuf, int outlen) { - int ei; + fz_flate *state = stm->state; + fz_stream *chain = state->chain; + z_streamp zp = &state->z; + int inlen, code; + + if (chain->rp == chain->wp) + fz_fillbuffer(chain); - FZ_NEWFILTER(fz_flate, f, flated); + inlen = chain->wp - chain->rp; + zp->next_in = chain->rp; + zp->avail_in = inlen; + zp->next_out = outbuf; + zp->avail_out = outlen; - f->z.zalloc = zmalloc; - f->z.zfree = zfree; - f->z.opaque = nil; - f->z.next_in = nil; - f->z.avail_in = 0; + code = inflate(zp, Z_SYNC_FLUSH); - ei = inflateInit(&f->z); + chain->rp = chain->wp - zp->avail_in; - if (ei != Z_OK) + if (code == Z_STREAM_END || code == Z_OK) { - fz_warn("zlib error: inflateInit: %s", f->z.msg); + return outlen - zp->avail_out; + } + else if (code == Z_DATA_ERROR && inlen == 0) + { + fz_warn("ignoring zlib error: %s", zp->msg); + return outlen - zp->avail_out; + } + else + { + return fz_throw("zlib error: %s", zp->msg); } - - return (fz_filter*)f; } -void -fz_dropflated(fz_filter *f) +static void +closeflated(fz_stream *stm) { - z_streamp zp = &((fz_flate*)f)->z; - int err; + fz_flate *state = stm->state; + int code; + + code = inflateEnd(&state->z); + if (code != Z_OK) + fz_warn("zlib error: inflateEnd: %s", state->z.msg); - err = inflateEnd(zp); - if (err != Z_OK) - fz_warn("inflateEnd: %s", zp->msg); + fz_close(state->chain); + fz_free(state); } -fz_error -fz_processflated(fz_filter *f, fz_buffer *in, fz_buffer *out) +fz_stream * +fz_openflated(fz_stream *chain) { - z_streamp zp = &((fz_flate*)f)->z; - int err; - - if (in->rp == in->wp && !in->eof) - return fz_ioneedin; - if (out->wp == out->ep) - return fz_ioneedout; + fz_flate *state; + int code; - zp->next_in = in->rp; - zp->avail_in = in->wp - in->rp; + state = fz_malloc(sizeof(fz_flate)); + state->chain = chain; - zp->next_out = out->wp; - zp->avail_out = out->ep - out->wp; + state->z.zalloc = zmalloc; + state->z.zfree = zfree; + state->z.opaque = nil; + state->z.next_in = nil; + state->z.avail_in = 0; - err = inflate(zp, Z_SYNC_FLUSH); + code = inflateInit(&state->z); + if (code != Z_OK) + fz_warn("zlib error: inflateInit: %s", state->z.msg); - in->rp = in->wp - zp->avail_in; - out->wp = out->ep - zp->avail_out; - - if (err == Z_DATA_ERROR && in->eof && in->rp == in->wp) - { - fz_warn("ignoring zlib error: %s", zp->msg); - return fz_iodone; - } - else if (err == Z_STREAM_END || err == Z_BUF_ERROR) - { - return fz_iodone; - } - else if (err == Z_OK) - { - if (in->rp == in->wp && !in->eof) - return fz_ioneedin; - if (out->wp == out->ep) - return fz_ioneedout; - return fz_ioneedin; /* hmm, what's going on here? */ - } - else - { - return fz_throw("zlib error: inflate: %s", zp->msg); - } + return fz_newstream(state, readflated, closeflated); } diff --git a/fitz/filt_jbig2d.c b/fitz/filt_jbig2d.c index b079ba7f..37d976ea 100644 --- a/fitz/filt_jbig2d.c +++ b/fitz/filt_jbig2d.c @@ -1,17 +1,5 @@ #include "fitz.h" -/* TODO: complete rewrite with error checking and use fitz memctx */ - -/* -<rillian> so to use a global_ctx, you run your global data through a normal ctx -<rillian> then call jbig2_make_global_ctx with the normal context -<rillian> that does the (currently null) conversion -<maskros> make_global_ctx after i fed it all the global stream data? -<rillian> maskros: yes -<rillian> and you pass the new global ctx object to jbig2_ctx_new() when you -+create the per-page ctx -*/ - #ifdef _WIN32 /* Microsoft Visual C++ */ typedef signed char int8_t; @@ -33,90 +21,82 @@ typedef struct fz_jbig2d_s fz_jbig2d; struct fz_jbig2d_s { - fz_filter super; + fz_stream *chain; Jbig2Ctx *ctx; Jbig2GlobalCtx *gctx; Jbig2Image *page; int idx; }; -fz_filter * -fz_newjbig2d(fz_obj *params) +static void +closejbig2d(fz_stream *stm) { - FZ_NEWFILTER(fz_jbig2d, d, jbig2d); - d->ctx = jbig2_ctx_new(nil, JBIG2_OPTIONS_EMBEDDED, nil, nil, nil); - d->gctx = nil; - d->page = nil; - d->idx = 0; - return (fz_filter*)d; + fz_jbig2d *state = stm->state; + if (state->page) + jbig2_release_page(state->ctx, state->page); + if (state->gctx) + jbig2_global_ctx_free(state->gctx); + jbig2_ctx_free(state->ctx); + fz_close(state->chain); + fz_free(state); } -void -fz_dropjbig2d(fz_filter *filter) +static int +readjbig2d(fz_stream *stm, unsigned char *buf, int len) { - fz_jbig2d *d = (fz_jbig2d*)filter; - if (d->gctx) - jbig2_global_ctx_free(d->gctx); - jbig2_ctx_free(d->ctx); -} + fz_jbig2d *state = stm->state; + unsigned char tmp[4096]; + unsigned char *p = buf; + unsigned char *s; + int x, w, n; -fz_error -fz_setjbig2dglobalstream(fz_filter *filter, unsigned char *buf, int len) -{ - fz_jbig2d *d = (fz_jbig2d*)filter; - jbig2_data_in(d->ctx, buf, len); - d->gctx = jbig2_make_global_ctx(d->ctx); - d->ctx = jbig2_ctx_new(nil, JBIG2_OPTIONS_EMBEDDED, d->gctx, nil, nil); - return fz_okay; + if (!state->page) + { + while (1) + { + n = fz_read(state->chain, tmp, sizeof tmp); + if (n < 0) + return fz_rethrow(n, "read error in jbig2 filter"); + if (n == 0) + break; + jbig2_data_in(state->ctx, tmp, n); + } + + jbig2_complete_page(state->ctx); + + state->page = jbig2_page_out(state->ctx); + if (!state->page) + return fz_throw("jbig2_page_out failed"); + } + + s = state->page->data; + w = state->page->height * state->page->stride; + x = state->idx; + while (p < buf + len && x < w) + *p++ = s[x++] ^ 0xff; + state->idx = x; + + return p - buf; } -fz_error -fz_processjbig2d(fz_filter *filter, fz_buffer *in, fz_buffer *out) +fz_stream * +fz_openjbig2d(fz_stream *chain, fz_buffer *globals) { - fz_jbig2d *d = (fz_jbig2d*)filter; - int len; - int i; + fz_jbig2d *state; + + state = fz_malloc(sizeof(fz_jbig2d)); + state->chain = chain; + state->ctx = jbig2_ctx_new(nil, JBIG2_OPTIONS_EMBEDDED, nil, nil, nil); + state->gctx = nil; + state->page = nil; + state->idx = 0; - while (1) + if (globals) { - if (in->rp == in->wp) { - if (!in->eof) - return fz_ioneedin; - - if (!d->page) { - jbig2_complete_page(d->ctx); - d->page = jbig2_page_out(d->ctx); - if (!d->page) - return fz_throw("jbig2_page_out failed"); - } - - if (out->wp == out->ep) - return fz_ioneedout; - - len = out->ep - out->wp; - if (d->idx + len > d->page->height * d->page->stride) - len = d->page->height * d->page->stride - d->idx; - - /* XXX memcpy(out->wp, d->page->data + d->idx, len); */ - { - unsigned char * restrict p = &d->page->data[d->idx]; - unsigned char * restrict o = out->wp; - for (i = 0; i < len; i++) - *o++ = 0xff ^ *p++; - } - - out->wp += len; - d->idx += len; - - if (d->idx == d->page->height * d->page->stride) { - jbig2_release_page(d->ctx, d->page); - return fz_iodone; - } - } - else { - len = in->wp - in->rp; - jbig2_data_in(d->ctx, in->rp, len); - in->rp += len; - } + jbig2_data_in(state->ctx, globals->data, globals->len); + state->gctx = jbig2_make_global_ctx(state->ctx); + state->ctx = jbig2_ctx_new(nil, JBIG2_OPTIONS_EMBEDDED, state->gctx, nil, nil); } + + return fz_newstream(state, readjbig2d, closejbig2d); } diff --git a/fitz/filt_jpxd.c b/fitz/filt_jpxd.c index 4580224a..01f15c1b 100644 --- a/fitz/filt_jpxd.c +++ b/fitz/filt_jpxd.c @@ -7,12 +7,8 @@ typedef struct fz_jpxd_s fz_jpxd; struct fz_jpxd_s { - fz_filter super; - opj_event_mgr_t evtmgr; - opj_dparameters_t params; - opj_dinfo_t *info; + fz_stream *chain; opj_image_t *image; - int stage; int x, y, k; }; @@ -31,136 +27,129 @@ static void fz_opj_info_callback(const char *msg, void *client_data) /* fprintf(stdout, "openjpeg info: %s", msg); */ } -fz_filter * -fz_newjpxd(fz_obj *params) -{ - FZ_NEWFILTER(fz_jpxd, d, jpxd); - - d->info = nil; - d->image = nil; - d->stage = 0; - - d->x = 0; - d->y = 0; - d->k = 0; - - return (fz_filter*)d; -} - -void -fz_dropjpxd(fz_filter *filter) +static int +readjpxd(fz_stream *stm, unsigned char *outbuf, int outlen) { - fz_jpxd *d = (fz_jpxd*)filter; - if (d->image) - opj_image_destroy(d->image); - if (d->info) - opj_destroy_decompress(d->info); -} - -fz_error -fz_processjpxd(fz_filter *filter, fz_buffer *in, fz_buffer *out) -{ - fz_jpxd *d = (fz_jpxd*)filter; + fz_jpxd *state = stm->state; + unsigned char *p = outbuf; + opj_event_mgr_t evtmgr; + opj_dparameters_t params; + opj_dinfo_t *info; + opj_cio_t *cio; int format; int n, w, h, depth, sgnd; int k, v; - opj_cio_t *cio; - - switch (d->stage) + if (!state->image) { - case 0: goto input; - case 1: goto decode; - case 2: goto output; - } - -input: - /* Wait until we have the entire file in the input buffer */ - if (!in->eof) - return fz_ioneedin; + fz_error error; + fz_buffer *buf; - d->stage = 1; + error = fz_readall(&buf, state->chain); + if (error) + return fz_throw("read error in jpx filter"); -decode: - memset(&d->evtmgr, 0, sizeof(d->evtmgr)); - d->evtmgr.error_handler = fz_opj_error_callback; - d->evtmgr.warning_handler = fz_opj_warning_callback; - d->evtmgr.info_handler = fz_opj_info_callback; + if (buf->len < 2) + { + fz_dropbuffer(buf); + return fz_throw("not enough data to determine image format"); + } - opj_set_default_decoder_parameters(&d->params); + /* Check for SOC marker -- if found we have a bare J2K stream */ + if (buf->data[0] == 0xFF && buf->data[1] == 0x4F) + format = CODEC_J2K; + else + format = CODEC_JP2; - if (in->wp - in->rp < 2) - return fz_throw("not enough data to determine image format"); + memset(&evtmgr, 0, sizeof(evtmgr)); + evtmgr.error_handler = fz_opj_error_callback; + evtmgr.warning_handler = fz_opj_warning_callback; + evtmgr.info_handler = fz_opj_info_callback; - /* Check for SOC marker -- if found we have a bare J2K stream */ - if (in->rp[0] == 0xFF && in->rp[1] == 0x4F) - format = CODEC_J2K; - else - format = CODEC_JP2; + opj_set_default_decoder_parameters(¶ms); - d->info = opj_create_decompress(format); - if (!d->info) - fz_warn("assert: opj_create_decompress failed"); + info = opj_create_decompress(format); + opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr); + opj_setup_decoder(info, ¶ms); - opj_set_event_mgr((opj_common_ptr)d->info, &d->evtmgr, stderr); - opj_setup_decoder(d->info, &d->params); + cio = opj_cio_open((opj_common_ptr)info, buf->data, buf->len); - cio = opj_cio_open((opj_common_ptr)d->info, in->rp, in->wp - in->rp); - in->rp = in->wp; + state->image = opj_decode(info, cio); - d->image = opj_decode(d->info, cio); - if (!d->image) - { opj_cio_close(cio); - return fz_throw("opj_decode failed"); - } + opj_destroy_decompress(info); + fz_dropbuffer(buf); - opj_cio_close(cio); + if (!state->image) + return fz_throw("opj_decode failed"); - for (k = 1; k < d->image->numcomps; k++) - { - if (d->image->comps[k].w != d->image->comps[0].w) - return fz_throw("image components have different width"); - if (d->image->comps[k].h != d->image->comps[0].h) - return fz_throw("image components have different height"); - if (d->image->comps[k].prec != d->image->comps[0].prec) - return fz_throw("image components have different precision"); + for (k = 1; k < state->image->numcomps; k++) + { + if (state->image->comps[k].w != state->image->comps[0].w) + return fz_throw("image components have different width"); + if (state->image->comps[k].h != state->image->comps[0].h) + return fz_throw("image components have different height"); + if (state->image->comps[k].prec != state->image->comps[0].prec) + return fz_throw("image components have different precision"); + } } - d->stage = 2; + n = state->image->numcomps; + w = state->image->comps[0].w; + h = state->image->comps[0].h; + depth = state->image->comps[0].prec; + sgnd = state->image->comps[0].sgnd; -output: - n = d->image->numcomps; - w = d->image->comps[0].w; - h = d->image->comps[0].h; - depth = d->image->comps[0].prec; - sgnd = d->image->comps[0].sgnd; - - while (d->y < h) + while (state->y < h) { - while (d->x < w) + while (state->x < w) { - while (d->k < n) + while (state->k < n) { - if (out->wp == out->ep) - return fz_ioneedout; + if (p == outbuf + outlen) + return p - outbuf; - v = d->image->comps[d->k].data[d->y * w + d->x]; + v = state->image->comps[state->k].data[state->y * w + state->x]; if (sgnd) v = v + (1 << (depth - 1)); if (depth > 8) v = v >> (depth - 8); - *out->wp++ = v; + *p++ = v; - d->k ++; + state->k ++; } - d->x ++; - d->k = 0; + state->x ++; + state->k = 0; } - d->y ++; - d->x = 0; + state->y ++; + state->x = 0; } - return fz_iodone; + return p - outbuf; +} + +static void +closejpxd(fz_stream *stm) +{ + fz_jpxd *state = stm->state; + if (state->image) + opj_image_destroy(state->image); + fz_close(state->chain); + fz_free(state); +} + +fz_stream * +fz_openjpxd(fz_stream *chain) +{ + fz_jpxd *state; + + state = fz_malloc(sizeof(fz_jpxd)); + state->chain = chain; + state->image = nil; + state->x = 0; + state->y = 0; + state->k = 0; + + return fz_newstream(state, readjpxd, closejpxd); } diff --git a/fitz/filt_lzwd.c b/fitz/filt_lzwd.c index b441c245..5e3c836e 100644 --- a/fitz/filt_lzwd.c +++ b/fitz/filt_lzwd.c @@ -9,7 +9,8 @@ enum NUMCODES = (1 << MAXBITS), LZW_CLEAR = 256, LZW_EOD = 257, - LZW_FIRST = 258 + LZW_FIRST = 258, + MAXLENGTH = 4097 }; typedef struct lzw_code_s lzw_code; @@ -26,69 +27,24 @@ typedef struct fz_lzwd_s fz_lzwd; struct fz_lzwd_s { - fz_filter super; + fz_stream *chain; + int eod; int earlychange; unsigned int word; /* bits loaded from data */ int bidx; - int resume; /* resume output of code from needout */ int codebits; /* num bits/code */ int code; /* current code */ int oldcode; /* previously recognized code */ int nextcode; /* next free entry */ lzw_code table[NUMCODES]; -}; - -fz_filter * -fz_newlzwd(fz_obj *params) -{ - int i; - - FZ_NEWFILTER(fz_lzwd, lzw, lzwd); - - lzw->earlychange = 1; - - if (params) - { - fz_obj *obj; - obj = fz_dictgets(params, "EarlyChange"); - if (obj) lzw->earlychange = fz_toint(obj) != 0; - } - lzw->bidx = 32; - lzw->word = 0; - - for (i = 0; i < 256; i++) - { - lzw->table[i].value = i; - lzw->table[i].firstchar = i; - lzw->table[i].length = 1; - lzw->table[i].prev = -1; - } - - for (i = 256; i < NUMCODES; i++) - { - lzw->table[i].value = 0; - lzw->table[i].firstchar = 0; - lzw->table[i].length = 0; - lzw->table[i].prev = -1; - } - - lzw->codebits = MINBITS; - lzw->code = -1; - lzw->nextcode = LZW_FIRST; - lzw->oldcode = -1; - lzw->resume = 0; - - return (fz_filter *)lzw; -} - -void -fz_droplzwd(fz_filter *filter) -{ -} + unsigned char output[MAXLENGTH]; + int outlen; + int remain; +}; static inline void eatbits(fz_lzwd *lzw, int nbits) { @@ -96,54 +52,48 @@ static inline void eatbits(fz_lzwd *lzw, int nbits) lzw->bidx += nbits; } -static inline fz_error fillbits(fz_lzwd *lzw, fz_buffer *in) +static inline int fillbits(fz_lzwd *lzw) { while (lzw->bidx >= 8) { - if (in->rp + 1 > in->wp) - return fz_ioneedin; + int c = fz_readbyte(lzw->chain); + if (c == EOF) + return EOF; lzw->bidx -= 8; - lzw->word |= *in->rp << lzw->bidx; - in->rp ++; + lzw->word |= c << lzw->bidx; } - return fz_okay; + return 0; } -static inline void unstuff(fz_lzwd *lzw, fz_buffer *in) +static inline void unstuff(fz_lzwd *lzw) { int i = (32 - lzw->bidx) / 8; - while (i-- && in->rp > in->bp) - in->rp --; + while (i--) + fz_unreadbyte(lzw->chain); } -fz_error -fz_processlzwd(fz_filter *filter, fz_buffer *in, fz_buffer *out) +static int +readlzwd(fz_stream *stm, unsigned char *buf, int len) { - fz_lzwd *lzw = (fz_lzwd*)filter; + fz_lzwd *lzw = stm->state; + unsigned char *p = buf; unsigned char *s; - int len; - if (lzw->resume) - { - lzw->resume = 0; - goto output; - } + while (lzw->remain > 0 && p < buf + len) + *p++ = lzw->output[lzw->outlen - lzw->remain]; - while (1) + while (p < buf + len) { - if (fillbits(lzw, in)) + if (lzw->eod) + return 0; + + if (fillbits(lzw)) { - if (in->eof) + if (lzw->bidx > 32 - lzw->codebits) { - if (lzw->bidx > 32 - lzw->codebits) - { - unstuff(lzw, in); - return fz_iodone; - } - } - else - { - return fz_ioneedin; + unstuff(lzw); + lzw->eod = 1; + return p - buf; } } @@ -153,8 +103,9 @@ fz_processlzwd(fz_filter *filter, fz_buffer *in, fz_buffer *out) if (lzw->code == LZW_EOD) { - unstuff(lzw, in); - return fz_iodone; + unstuff(lzw); + lzw->eod = 1; + return p - buf; } if (lzw->code == LZW_CLEAR) @@ -195,36 +146,86 @@ fz_processlzwd(fz_filter *filter, fz_buffer *in, fz_buffer *out) lzw->oldcode = lzw->code; output: + /* code maps to a string, copy to output (in reverse...) */ if (lzw->code > 255) { - if (out->wp + lzw->table[lzw->code].length > out->ep) - { - lzw->resume = 1; - return fz_ioneedout; - } - - len = lzw->table[lzw->code].length; - s = out->wp + len; + assert(lzw->table[lzw->code].length < MAXLENGTH); - do - { + lzw->outlen = lzw->table[lzw->code].length; + lzw->remain = lzw->outlen; + s = lzw->output + lzw->remain; + do { *(--s) = lzw->table[lzw->code].value; lzw->code = lzw->table[lzw->code].prev; - } while (lzw->code >= 0 && s > out->wp); - out->wp += len; + } while (lzw->code >= 0 && s > lzw->output); } /* ... or just a single character */ else { - if (out->wp + 1 > out->ep) - { - lzw->resume = 1; - return fz_ioneedout; - } - - *out->wp++ = lzw->code; + lzw->output[0] = lzw->code; + lzw->outlen = 1; + lzw->remain = 1; } + + /* copy to output */ + while (lzw->remain > 0 && p < buf + len) + *p++ = lzw->output[lzw->outlen - lzw->remain]; + } + + return p - buf; +} + +static void +closelzwd(fz_stream *stm) +{ + fz_lzwd *lzw = stm->state; + fz_close(lzw->chain); + fz_free(lzw); +} + +fz_stream * +fz_openlzwd(fz_stream *chain, fz_obj *params) +{ + fz_lzwd *lzw; + fz_obj *obj; + int i; + + lzw = fz_malloc(sizeof(fz_lzwd)); + lzw->chain = chain; + lzw->eod = 0; + lzw->earlychange = 1; + + obj = fz_dictgets(params, "EarlyChange"); + if (obj) + lzw->earlychange = !!fz_toint(obj); + + lzw->bidx = 32; + lzw->word = 0; + + for (i = 0; i < 256; i++) + { + lzw->table[i].value = i; + lzw->table[i].firstchar = i; + lzw->table[i].length = 1; + lzw->table[i].prev = -1; + } + + for (i = 256; i < NUMCODES; i++) + { + lzw->table[i].value = 0; + lzw->table[i].firstchar = 0; + lzw->table[i].length = 0; + lzw->table[i].prev = -1; } + + lzw->codebits = MINBITS; + lzw->code = -1; + lzw->nextcode = LZW_FIRST; + lzw->oldcode = -1; + lzw->remain = 0; + lzw->outlen = 0; + + return fz_newstream(lzw, readlzwd, closelzwd); } diff --git a/fitz/filt_pipeline.c b/fitz/filt_pipeline.c deleted file mode 100644 index cb496546..00000000 --- a/fitz/filt_pipeline.c +++ /dev/null @@ -1,131 +0,0 @@ -#include "fitz.h" - -typedef struct fz_pipeline_s fz_pipeline; - -fz_error fz_processpipeline(fz_filter *filter, fz_buffer *in, fz_buffer *out); - -struct fz_pipeline_s -{ - fz_filter super; - fz_filter *head; - fz_buffer *buffer; - fz_filter *tail; - int tailneedsin; -}; - -fz_filter * -fz_chainpipeline(fz_filter *head, fz_filter *tail, fz_buffer *buf) -{ - FZ_NEWFILTER(fz_pipeline, p, pipeline); - p->head = fz_keepfilter(head); - p->tail = fz_keepfilter(tail); - p->tailneedsin = 1; - p->buffer = fz_keepbuffer(buf); - return (fz_filter*)p; -} - -void -fz_unchainpipeline(fz_filter *filter, fz_filter **oldfp, fz_buffer **oldbp) -{ - fz_pipeline *p = (fz_pipeline*)filter; - - *oldfp = fz_keepfilter(p->head); - *oldbp = fz_keepbuffer(p->buffer); - - fz_dropfilter(filter); -} - -fz_filter * -fz_newpipeline(fz_filter *head, fz_filter *tail) -{ - FZ_NEWFILTER(fz_pipeline, p, pipeline); - - p->buffer = fz_newbuffer(FZ_BUFSIZE); - p->head = fz_keepfilter(head); - p->tail = fz_keepfilter(tail); - p->tailneedsin = 1; - - return (fz_filter*)p; -} - -void -fz_droppipeline(fz_filter *filter) -{ - fz_pipeline *p = (fz_pipeline*)filter; - fz_dropfilter(p->head); - fz_dropfilter(p->tail); - fz_dropbuffer(p->buffer); -} - -fz_error -fz_processpipeline(fz_filter *filter, fz_buffer *in, fz_buffer *out) -{ - fz_pipeline *p = (fz_pipeline*)filter; - fz_error e; - - if (p->buffer->eof) - goto tail; - - if (p->tailneedsin && p->head->produced) - goto tail; - -head: - e = fz_process(p->head, in, p->buffer); - - if (e == fz_ioneedin) - return fz_ioneedin; - - else if (e == fz_ioneedout) - { - if (p->tailneedsin && !p->head->produced) - { - if (p->buffer->rp > p->buffer->bp) - fz_rewindbuffer(p->buffer); - else - fz_growbuffer(p->buffer); - goto head; - } - goto tail; - } - - else if (e == fz_iodone) - goto tail; - - else if (e) - return fz_rethrow(e, "cannot process head filter"); - - else - return fz_okay; - -tail: - e = fz_process(p->tail, p->buffer, out); - - if (e == fz_ioneedin) - { - if (p->buffer->eof) - return fz_throw("ioerror: premature eof in pipeline"); - p->tailneedsin = 1; - goto head; - } - - else if (e == fz_ioneedout) - { - p->tailneedsin = 0; - return fz_ioneedout; - } - - else if (e == fz_iodone) - { - /* The head may still contain end-of-data markers or garbage */ - e = fz_process(p->head, in, p->buffer); - if (e != fz_iodone) - fz_catch(e, "head filter not done"); - return fz_iodone; - } - - else if (e) - return fz_rethrow(e, "cannot process tail filter"); - - else - return fz_okay; -} diff --git a/fitz/filt_predict.c b/fitz/filt_predict.c index 78bd19b2..b0ef8d3c 100644 --- a/fitz/filt_predict.c +++ b/fitz/filt_predict.c @@ -8,7 +8,7 @@ typedef struct fz_predict_s fz_predict; struct fz_predict_s { - fz_filter super; + fz_stream *chain; int predictor; int columns; @@ -17,71 +17,12 @@ struct fz_predict_s int stride; int bpp; - unsigned char *refbuf; + unsigned char *in; + unsigned char *out; unsigned char *ref; + int outlen, outidx; }; -fz_filter * -fz_newpredictd(fz_obj *params) -{ - fz_obj *obj; - - FZ_NEWFILTER(fz_predict, p, predict); - - p->predictor = 1; - p->columns = 1; - p->colors = 1; - p->bpc = 8; - - obj = fz_dictgets(params, "Predictor"); - if (obj) - p->predictor = fz_toint(obj); - - if (p->predictor != 1 && p->predictor != 2 && - p->predictor != 10 && p->predictor != 11 && - p->predictor != 12 && p->predictor != 13 && - p->predictor != 14 && p->predictor != 15) - { - fz_warn("invalid predictor: %d", p->predictor); - p->predictor = 1; - } - - obj = fz_dictgets(params, "Columns"); - if (obj) - p->columns = fz_toint(obj); - - obj = fz_dictgets(params, "Colors"); - if (obj) - p->colors = fz_toint(obj); - - obj = fz_dictgets(params, "BitsPerComponent"); - if (obj) - p->bpc = fz_toint(obj); - - p->stride = (p->bpc * p->colors * p->columns + 7) / 8; - p->bpp = (p->bpc * p->colors + 7) / 8; - - if (p->predictor >= 10) - { - p->refbuf = fz_malloc(p->stride); - memset(p->refbuf, 0, p->stride); - } - else - { - p->refbuf = nil; - } - p->ref = nil; - - return (fz_filter*)p; -} - -void -fz_droppredict(fz_filter *filter) -{ - fz_predict *p = (fz_predict*)filter; - fz_free(p->refbuf); -} - static inline int getcomponent(unsigned char *buf, int x, int bpc) { @@ -118,40 +59,34 @@ paeth(int a, int b, int c) return pa <= pb && pa <= pc ? a : pb <= pc ? b : c; } -static inline void -fz_predictnone(fz_predict *p, unsigned char *in, int len, unsigned char *out) -{ - memcpy(out, in, len); -} - static void -fz_predicttiff(fz_predict *p, unsigned char *in, int len, unsigned char *out) +fz_predicttiff(fz_predict *state, unsigned char *out, unsigned char *in, int len) { int left[MAXC]; int i, k; - for (k = 0; k < p->colors; k++) + for (k = 0; k < state->colors; k++) left[k] = 0; - for (i = 0; i < p->columns; i++) + for (i = 0; i < state->columns; i++) { - for (k = 0; k < p->colors; k++) + for (k = 0; k < state->colors; k++) { - int a = getcomponent(in, i * p->colors + k, p->bpc); + int a = getcomponent(in, i * state->colors + k, state->bpc); int b = a + left[k]; - int c = b % (1 << p->bpc); - putcomponent(out, i * p->colors + k, p->bpc, c); + int c = b % (1 << state->bpc); + putcomponent(out, i * state->colors + k, state->bpc, c); left[k] = c; } } } static void -fz_predictpng(fz_predict *p, unsigned char *in, int len, unsigned char *out, int predictor) +fz_predictpng(fz_predict *state, unsigned char *out, unsigned char *in, int len, int predictor) { - int bpp = p->bpp; + int bpp = state->bpp; int i; - unsigned char *ref = p->ref; + unsigned char *ref = state->ref; switch (predictor) { @@ -186,7 +121,7 @@ fz_predictpng(fz_predict *p, unsigned char *in, int len, unsigned char *out, int } for (i = len - bpp; i > 0; i--) { - *out = *in++ + (out[-bpp] + *ref++)/2; + *out = *in++ + (out[-bpp] + *ref++) / 2; out++; } break; @@ -205,62 +140,105 @@ fz_predictpng(fz_predict *p, unsigned char *in, int len, unsigned char *out, int } } -fz_error -fz_processpredict(fz_filter *filter, fz_buffer *in, fz_buffer *out) +static int +readpredict(fz_stream *stm, unsigned char *buf, int len) { - fz_predict *dec = (fz_predict*)filter; - int remaining, toconsume, toproduce; - int ispng = dec->predictor >= 10; + fz_predict *state = stm->state; + unsigned char *p = buf; + int ispng = state->predictor >= 10; + int n; - dec->ref = dec->refbuf; - while (1) - { - remaining = in->wp - in->rp; - toconsume = MIN(remaining, dec->stride + ispng); - toproduce = MIN(remaining - ispng, dec->stride); + while (state->outidx < state->outlen && p < buf + len) + *p++ = state->out[state->outidx++]; - if (remaining < dec->stride + ispng && !in->eof) + while (p < buf + len) + { + n = fz_read(state->chain, state->in, state->stride + ispng); + if (n < 0) + return fz_rethrow(n, "read error in prediction filter"); + if (n == 0) + return p - buf; + + if (state->predictor == 1) + memcpy(state->out, state->in, n); + else if (state->predictor == 2) + fz_predicttiff(state, state->out, state->in, n); + else { - return fz_ioneedin; + fz_predictpng(state, state->out, state->in + 1, n - 1, state->in[0]); + memcpy(state->ref, state->out, state->stride); } - if (out->wp + toproduce > out->ep) - { - return fz_ioneedout; - } + state->outlen = n - ispng; + state->outidx = 0; - if (toconsume > 0) - { - if (dec->predictor == 1) - { - fz_predictnone(dec, in->rp, toconsume, out->wp); - } - else if (dec->predictor == 2) - { - if (dec->bpc != 8) - memset(out->wp, 0, toconsume); - fz_predicttiff(dec, in->rp, toconsume, out->wp); - } - else - { - int predictor = *in->rp++; - toconsume -= ispng; - fz_predictpng(dec, in->rp, toconsume, out->wp, predictor); - } - - if (dec->refbuf) - { - memcpy(dec->refbuf, out->wp, toproduce); - dec->ref = dec->refbuf; - } - - in->rp += toconsume; - out->wp += toproduce; - } + while (state->outidx < state->outlen && p < buf + len) + *p++ = state->out[state->outidx++]; + } - if (in->eof && (in->wp - in->rp <= 0)) - { - return fz_iodone; - } + return p - buf; +} + +static void +closepredict(fz_stream *stm) +{ + fz_predict *state = stm->state; + fz_close(state->chain); + fz_free(state->in); + fz_free(state->out); + fz_free(state->ref); + fz_free(state); +} + +fz_stream * +fz_openpredict(fz_stream *chain, fz_obj *params) +{ + fz_predict *state; + fz_obj *obj; + + state = fz_malloc(sizeof(fz_predict)); + state->chain = chain; + + state->predictor = 1; + state->columns = 1; + state->colors = 1; + state->bpc = 8; + + obj = fz_dictgets(params, "Predictor"); + if (obj) + state->predictor = fz_toint(obj); + + if (state->predictor != 1 && state->predictor != 2 && + state->predictor != 10 && state->predictor != 11 && + state->predictor != 12 && state->predictor != 13 && + state->predictor != 14 && state->predictor != 15) + { + fz_warn("invalid predictor: %d", state->predictor); + state->predictor = 1; } + + obj = fz_dictgets(params, "Columns"); + if (obj) + state->columns = fz_toint(obj); + + obj = fz_dictgets(params, "Colors"); + if (obj) + state->colors = fz_toint(obj); + + obj = fz_dictgets(params, "BitsPerComponent"); + if (obj) + state->bpc = fz_toint(obj); + + state->stride = (state->bpc * state->colors * state->columns + 7) / 8; + state->bpp = (state->bpc * state->colors + 7) / 8; + + state->in = fz_malloc(state->stride + 1); + state->out = fz_malloc(state->stride); + state->ref = fz_malloc(state->stride); + state->outlen = 0; + state->outidx = 0; + + memset(state->ref, 0, state->stride); + + return fz_newstream(state, readpredict, closepredict); } diff --git a/fitz/fitz.h b/fitz/fitz.h index 89a1cc63..696a9017 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -440,17 +440,7 @@ void fz_debugobj(fz_obj *obj); char *fz_objkindstr(fz_obj *obj); /* - * Data buffers for streams and filters. - * - * bp is the pointer to the allocated memory - * rp is read-position (*in->rp++ to read data) - * wp is write-position (*out->wp++ to write data) - * ep is the sentinel - * - * Only the data between rp and wp is valid data. - * - * Writers set eof to true at the end. - * Readers look at eof. + * Data buffers. * * A buffer owns the memory it has allocated, unless ownsdata is false, * in which case the creator of the buffer owns it. @@ -463,112 +453,22 @@ typedef struct fz_buffer_s fz_buffer; struct fz_buffer_s { int refs; - int ownsdata; - unsigned char *bp; - unsigned char *rp; - unsigned char *wp; - unsigned char *ep; - int eof; + unsigned char *data; + int cap, len; }; fz_buffer * fz_newbuffer(int size); fz_buffer * fz_newbufferwithmemory(unsigned char *data, int size); void fz_resizebuffer(fz_buffer *buf, int size); -void fz_rewindbuffer(fz_buffer *buf); void fz_growbuffer(fz_buffer *buf); fz_buffer *fz_keepbuffer(fz_buffer *buf); void fz_dropbuffer(fz_buffer *buf); /* - * Data filters for encryption, compression and decompression. - * - * A filter has one method, process, that takes an input and an output buffer. - * - * It returns one of three statuses: - * ioneedin -- input buffer exhausted, please give me more data (wp-rp) - * ioneedout -- output buffer exhausted, please provide more space (ep-wp) - * iodone -- finished, please never call me again. ever! - * or... - * any other error code -- oops, something blew up. - * - * To make using the filter easier, three variables are updated: - * produced -- if we actually produced any new data - * consumed -- like above - * count -- number of bytes produced in total since the beginning - * done -- remember if we've ever returned fz_iodone - * - * Most filters take fz_obj as a way to specify parameters. - * In most cases, this is a dictionary that contains the same keys - * that the corresponding PDF filter would expect. - * - * The pipeline filter is special, and needs some care when chaining - * and unchaining new filters. - */ - -typedef struct fz_filter_s fz_filter; - -#define fz_ioneedin ((fz_error)1) -#define fz_ioneedout ((fz_error)2) -#define fz_iodone ((fz_error)3) - -/* - * Evil looking macro to create an initialize a filter struct. - */ - -#define FZ_NEWFILTER(TYPE,VAR,NAME) \ - fz_error fz_process ## NAME (fz_filter*,fz_buffer*,fz_buffer*); \ - void fz_drop ## NAME (fz_filter*); \ - TYPE *VAR; \ - VAR = fz_malloc(sizeof(TYPE)); \ - ((fz_filter*)VAR)->refs = 1; \ - ((fz_filter*)VAR)->process = fz_process ## NAME ; \ - ((fz_filter*)VAR)->drop = fz_drop ## NAME ; \ - ((fz_filter*)VAR)->consumed = 0; \ - ((fz_filter*)VAR)->produced = 0; \ - ((fz_filter*)VAR)->count = 0; \ - ((fz_filter*)VAR)->done = 0; - -struct fz_filter_s -{ - int refs; - fz_error (*process)(fz_filter *filter, fz_buffer *in, fz_buffer *out); - void (*drop)(fz_filter *filter); - int consumed; - int produced; - int count; - int done; -}; - -fz_error fz_process(fz_filter *f, fz_buffer *in, fz_buffer *out); -fz_filter *fz_keepfilter(fz_filter *f); -void fz_dropfilter(fz_filter *f); - -fz_filter * fz_newpipeline(fz_filter *head, fz_filter *tail); -fz_filter * fz_chainpipeline(fz_filter *head, fz_filter *tail, fz_buffer *buf); -void fz_unchainpipeline(fz_filter *pipe, fz_filter **oldfp, fz_buffer **oldbp); - -fz_filter * fz_newnullfilter(int len); -fz_filter * fz_newcopyfilter(); -fz_filter * fz_newarc4filter(unsigned char *key, unsigned keylen); -fz_filter * fz_newaesdfilter(unsigned char *key, unsigned keylen); -fz_filter * fz_newa85d(fz_obj *param); -fz_filter * fz_newahxd(fz_obj *param); -fz_filter * fz_newrld(fz_obj *param); -fz_filter * fz_newdctd(fz_obj *param); -fz_filter * fz_newfaxd(fz_obj *param); -fz_filter * fz_newflated(fz_obj *param); -fz_filter * fz_newlzwd(fz_obj *param); -fz_filter * fz_newpredictd(fz_obj *param); -fz_filter * fz_newjbig2d(fz_obj *param); -fz_filter * fz_newjpxd(fz_obj *param); - -fz_error fz_setjbig2dglobalstream(fz_filter *filter, unsigned char *buf, int len); - -/* - * Stream API for Fitz. - * Read and write data to and from files, memory buffers and filters. + * Buffered reader. + * Only the data between rp and wp is valid data. */ typedef struct fz_stream_s fz_stream; @@ -578,77 +478,77 @@ enum { FZ_SFILE, FZ_SBUFFER, FZ_SFILTER }; struct fz_stream_s { int refs; - int kind; int dead; - fz_buffer *buffer; - fz_filter *filter; - fz_stream *chain; - fz_error error; /* delayed error from readbyte and peekbyte */ - int file; + int pos; + unsigned char *bp, *rp, *wp, *ep; + void *state; + int (*read)(fz_stream *stm, unsigned char *buf, int len); + void (*close)(fz_stream *stm); + void (*seek)(fz_stream *stm, int offset, int whence); + unsigned char buf[4096]; }; -/* - * Various stream creation functions. - */ - -fz_stream * fz_openfile(int file); -fz_stream * fz_openmemory(unsigned char *mem, int len); -fz_stream * fz_openbuffer(fz_buffer *buf); -fz_stream * fz_openfilter(fz_filter *flt, fz_stream *chain); - -/* - * Functions that are common to both input and output streams. - */ +fz_stream *fz_openfile(int file); +fz_stream *fz_openbuffer(fz_buffer *buf); +void fz_close(fz_stream *stm); +fz_stream *fz_newstream(void*, int(*)(fz_stream*, unsigned char*, int), void(*)(fz_stream *)); fz_stream *fz_keepstream(fz_stream *stm); -void fz_dropstream(fz_stream *stm); +void fz_fillbuffer(fz_stream *stm); int fz_tell(fz_stream *stm); -fz_error fz_seek(fz_stream *stm, int offset, int whence); - -/* - * Input stream functions. - */ +void fz_seek(fz_stream *stm, int offset, int whence); -fz_error fz_readimp(fz_stream *stm); -fz_error fz_read(int *np, fz_stream *stm, unsigned char *buf, int len); -fz_error fz_readline(fz_stream *stm, char *buf, int max); -fz_buffer * fz_readall(fz_stream *stm, int sizehint); - -/* - * Error handling when reading with readbyte/peekbyte is non-standard. - * The cause of an error is stuck into the stream struct, - * and EOF is returned. Not good, but any other way is too painful. - * So we have to be careful to check the error status eventually. - */ - -fz_error fz_readerror(fz_stream *stm); -int fz_readbytex(fz_stream *stm); -int fz_peekbytex(fz_stream *stm); +int fz_read(fz_stream *stm, unsigned char *buf, int len); +void fz_readline(fz_stream *stm, char *buf, int max); +fz_error fz_readall(fz_buffer **bufp, fz_stream *stm); static inline int fz_readbyte(fz_stream *stm) { - fz_buffer *buf = stm->buffer; - if (buf->rp < buf->wp) - return *buf->rp++; - return fz_readbytex(stm); + if (stm->rp == stm->wp) + { + fz_fillbuffer(stm); + return stm->rp < stm->wp ? *stm->rp++ : EOF; + } + return *stm->rp++; } static inline int fz_peekbyte(fz_stream *stm) { - fz_buffer *buf = stm->buffer; - if (buf->rp < buf->wp) - return *buf->rp; - return fz_peekbytex(stm); + if (stm->rp == stm->wp) + { + fz_fillbuffer(stm); + return stm->rp < stm->wp ? *stm->rp : EOF; + } + return *stm->rp; } static inline void fz_unreadbyte(fz_stream *stm) { - fz_buffer *buf = stm->buffer; - buf->rp--; + if (stm->rp > stm->bp) + stm->rp--; } /* + * Data filters. + */ + +fz_stream * fz_opencopy(fz_stream *chain); +fz_stream * fz_opennull(fz_stream *chain, int len); +fz_stream * fz_openarc4(fz_stream *chain, unsigned char *key, unsigned keylen); +fz_stream * fz_openaesd(fz_stream *chain, unsigned char *key, unsigned keylen); +fz_stream * fz_opena85d(fz_stream *chain); +fz_stream * fz_openahxd(fz_stream *chain); +fz_stream * fz_openrld(fz_stream *chain); +fz_stream * fz_opendctd(fz_stream *chain, fz_obj *param); +fz_stream * fz_openfaxd(fz_stream *chain, fz_obj *param); +fz_stream * fz_openflated(fz_stream *chain); +fz_stream * fz_openlzwd(fz_stream *chain, fz_obj *param); +fz_stream * fz_openpredict(fz_stream *chain, fz_obj *param); +fz_stream * fz_openjbig2d(fz_stream *chain, fz_buffer *global); +fz_stream * fz_openjpxd(fz_stream *chain); + +/* * Resources and other graphics related objects. */ diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c index f7da8289..00530071 100644 --- a/fitz/stm_buffer.c +++ b/fitz/stm_buffer.c @@ -9,29 +9,9 @@ fz_newbuffer(int size) b = fz_malloc(sizeof(fz_buffer)); b->refs = 1; - b->ownsdata = 1; - b->bp = fz_malloc(size); - b->rp = b->bp; - b->wp = b->bp; - b->ep = b->bp + size; - b->eof = 0; - - return b; -} - -fz_buffer * -fz_newbufferwithmemory(unsigned char *data, int size) -{ - fz_buffer *b; - - b = fz_malloc(sizeof(fz_buffer)); - b->refs = 1; - b->ownsdata = 0; - b->bp = data; - b->rp = b->bp; - b->wp = b->bp + size; - b->ep = b->bp + size; - b->eof = 0; + b->data = fz_malloc(size); + b->cap = size; + b->len = 0; return b; } @@ -48,8 +28,7 @@ fz_dropbuffer(fz_buffer *buf) { if (--buf->refs == 0) { - if (buf->ownsdata) - fz_free(buf->bp); + fz_free(buf->data); fz_free(buf); } } @@ -57,50 +36,14 @@ fz_dropbuffer(fz_buffer *buf) void fz_resizebuffer(fz_buffer *buf, int size) { - int rp = MIN(buf->rp - buf->bp, size); - int wp = MIN(buf->wp - buf->bp, size); - - if (!buf->ownsdata) - { - fz_warn("assert: resize borrowed memory"); - return; - } - - buf->bp = fz_realloc(buf->bp, size); - buf->rp = buf->bp + rp; - buf->wp = buf->bp + wp; - buf->ep = buf->bp + size; + buf->data = fz_realloc(buf->data, size); + buf->cap = size; + if (buf->len > buf->cap) + buf->len = buf->cap; } void fz_growbuffer(fz_buffer *buf) { - int rp = buf->rp - buf->bp; - int wp = buf->wp - buf->bp; - int ep = buf->ep - buf->bp; - - if (!buf->ownsdata) - { - fz_warn("assert: grow borrowed memory"); - return; - } - - buf->bp = fz_realloc(buf->bp, (ep * 3) / 2); - buf->rp = buf->bp + rp; - buf->wp = buf->bp + wp; - buf->ep = buf->bp + (ep * 3) / 2; -} - -void -fz_rewindbuffer(fz_buffer *buf) -{ - if (!buf->ownsdata) - { - fz_warn("assert: rewind borrowed memory"); - return; - } - - memmove(buf->bp, buf->rp, buf->wp - buf->rp); - buf->wp = buf->bp + (buf->wp - buf->rp); - buf->rp = buf->bp; + fz_resizebuffer(buf, (buf->cap * 3) / 2); } diff --git a/fitz/stm_filter.c b/fitz/stm_filter.c deleted file mode 100644 index b4da7773..00000000 --- a/fitz/stm_filter.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "fitz.h" - -fz_error -fz_process(fz_filter *f, fz_buffer *in, fz_buffer *out) -{ - fz_error reason; - unsigned char *oldrp; - unsigned char *oldwp; - - oldrp = in->rp; - oldwp = out->wp; - - if (f->done) - return fz_iodone; - - assert(!out->eof); - - reason = f->process(f, in, out); - - assert(in->rp <= in->wp); - assert(out->wp <= out->ep); - - f->consumed = in->rp > oldrp; - f->produced = out->wp > oldwp; - f->count += out->wp - oldwp; - - /* iodone or error */ - if (reason != fz_ioneedin && reason != fz_ioneedout) - { - if (reason != fz_iodone) - reason = fz_rethrow(reason, "cannot process filter"); - out->eof = 1; - f->done = 1; - } - - return reason; -} - -fz_filter * -fz_keepfilter(fz_filter *f) -{ - f->refs ++; - return f; -} - -void -fz_dropfilter(fz_filter *f) -{ - if (--f->refs == 0) - { - if (f->drop) - f->drop(f); - fz_free(f); - } -} diff --git a/fitz/stm_open.c b/fitz/stm_open.c index e70a4580..d59062cc 100644 --- a/fitz/stm_open.c +++ b/fitz/stm_open.c @@ -1,21 +1,27 @@ #include "fitz.h" -static fz_stream * -fz_newstream(int kind) +fz_stream * +fz_newstream(void *state, + int(*read)(fz_stream *stm, unsigned char *buf, int len), + void(*close)(fz_stream *stm)) { fz_stream *stm; stm = fz_malloc(sizeof(fz_stream)); stm->refs = 1; - stm->kind = kind; stm->dead = 0; - stm->error = fz_okay; - stm->buffer = nil; + stm->pos = 0; + + stm->bp = stm->buf; + stm->rp = stm->bp; + stm->wp = stm->bp; + stm->ep = stm->buf + sizeof stm->buf; - stm->chain = nil; - stm->filter = nil; - stm->file = -1; + stm->state = state; + stm->read = read; + stm->close = close; + stm->seek = nil; return stm; } @@ -28,81 +34,97 @@ fz_keepstream(fz_stream *stm) } void -fz_dropstream(fz_stream *stm) +fz_close(fz_stream *stm) { stm->refs --; if (stm->refs == 0) { - if (stm->error) - { - fz_catch(stm->error, "dropped unhandled ioerror"); - stm->error = fz_okay; - } - - switch (stm->kind) - { - case FZ_SFILE: - close(stm->file); - break; - case FZ_SFILTER: - fz_dropfilter(stm->filter); - fz_dropstream(stm->chain); - break; - case FZ_SBUFFER: - break; - } - - fz_dropbuffer(stm->buffer); + if (stm->close) + stm->close(stm); fz_free(stm); } } -fz_stream * -fz_openfile(int fd) +/* File stream */ + +static int readfile(fz_stream *stm, unsigned char *buf, int len) { - fz_stream *stm; + int n = read(*(int*)stm->state, buf, len); + if (n < 0) + return fz_throw("read error: %s", strerror(errno)); + return n; +} - stm = fz_newstream(FZ_SFILE); - stm->buffer = fz_newbuffer(FZ_BUFSIZE); - stm->file = fd; +static void seekfile(fz_stream *stm, int offset, int whence) +{ + int n = lseek(*(int*)stm->state, offset, whence); + if (n < 0) + fz_warn("cannot lseek: %s", strerror(errno)); + stm->pos = n; + stm->rp = stm->bp; + stm->wp = stm->bp; +} - return stm; +static void closefile(fz_stream *stm) +{ + int n = close(*(int*)stm->state); + if (n < 0) + fz_warn("close error: %s", strerror(errno)); + fz_free(stm->state); } fz_stream * -fz_openfilter(fz_filter *flt, fz_stream *src) +fz_openfile(int fd) { fz_stream *stm; + int *state; + + state = fz_malloc(sizeof(int)); + *state = fd; - stm = fz_newstream(FZ_SFILTER); - stm->buffer = fz_newbuffer(FZ_BUFSIZE); - stm->chain = fz_keepstream(src); - stm->filter = fz_keepfilter(flt); + stm = fz_newstream(state, readfile, closefile); + stm->seek = seekfile; return stm; } -fz_stream * -fz_openbuffer(fz_buffer *buf) +/* Memory stream */ + +static int readbuffer(fz_stream *stm, unsigned char *buf, int len) { - fz_stream *stm; + return 0; +} - stm = fz_newstream(FZ_SBUFFER); - stm->buffer = fz_keepbuffer(buf); - stm->buffer->eof = 1; +static void seekbuffer(fz_stream *stm, int offset, int whence) +{ + if (whence == 0) + stm->rp = stm->bp + offset; + if (whence == 1) + stm->rp += offset; + if (whence == 2) + stm->rp = stm->wp - offset; + stm->rp = CLAMP(stm->rp, stm->bp, stm->wp); +} - return stm; +static void closebuffer(fz_stream *stm) +{ + fz_dropbuffer(stm->state); } fz_stream * -fz_openmemory(unsigned char *mem, int len) +fz_openbuffer(fz_buffer *buf) { - fz_buffer *buf; fz_stream *stm; - buf = fz_newbufferwithmemory(mem, len); - stm = fz_openbuffer(buf); - fz_dropbuffer(buf); + stm = fz_newstream(fz_keepbuffer(buf), readbuffer, closebuffer); + stm->seek = seekbuffer; + + stm->bp = buf->data; + stm->rp = buf->data; + stm->wp = buf->data + buf->len; + stm->ep = buf->data + buf->len; + + stm->pos = buf->len; return stm; } diff --git a/fitz/stm_read.c b/fitz/stm_read.c index d4d27f66..3bdddade 100644 --- a/fitz/stm_read.c +++ b/fitz/stm_read.c @@ -1,283 +1,91 @@ #include "fitz.h" -fz_error -fz_readimp(fz_stream *stm) -{ - fz_buffer *buf = stm->buffer; - fz_error error; - fz_error reason; - int produced; - int n; - - if (stm->dead) - return fz_throw("assert: read from dead stream"); - - if (buf->eof) - return fz_okay; - - fz_rewindbuffer(buf); - if (buf->ep - buf->wp == 0) - fz_growbuffer(buf); - - switch (stm->kind) - { - - case FZ_SFILE: - n = read(stm->file, buf->wp, buf->ep - buf->wp); - if (n == -1) - { - stm->dead = 1; - return fz_throw("syserr: read: %s", strerror(errno)); - } - - if (n == 0) - buf->eof = 1; - buf->wp += n; - - return fz_okay; - - case FZ_SFILTER: - produced = 0; - - while (1) - { - reason = fz_process(stm->filter, stm->chain->buffer, buf); - - if (stm->filter->produced) - produced = 1; - - if (reason == fz_ioneedin) - { - error = fz_readimp(stm->chain); - if (error) - { - stm->dead = 1; - return fz_rethrow(error, "cannot read from input stream"); - } - } - - else if (reason == fz_ioneedout) - { - if (produced) - return 0; - - if (buf->rp > buf->bp) - fz_rewindbuffer(buf); - else - fz_growbuffer(buf); - } - - else if (reason == fz_iodone) - { - return fz_okay; - } - - else - { - stm->dead = 1; - return fz_rethrow(reason, "cannot process filter"); - } - } - - case FZ_SBUFFER: - return fz_okay; - - default: - return fz_throw("assert: unknown stream type"); - } -} - int -fz_tell(fz_stream *stm) +fz_read(fz_stream *stm, unsigned char *buf, int len) { - fz_buffer *buf = stm->buffer; - int t; - - if (stm->dead) - return EOF; + int avail, count; - switch (stm->kind) + avail = stm->wp - stm->rp; + if (avail) { - case FZ_SFILE: - t = lseek(stm->file, 0, 1); - if (t < 0) - { - fz_warn("syserr: lseek: %s", strerror(errno)); - stm->dead = 1; - return EOF; - } - return t - (buf->wp - buf->rp); - - case FZ_SFILTER: - return stm->filter->count - (buf->wp - buf->rp); - - case FZ_SBUFFER: - return buf->rp - buf->bp; - - default: - return EOF; + count = MIN(len, avail); + memcpy(buf, stm->rp, count); + stm->rp += count; } -} - -fz_error -fz_seek(fz_stream *stm, int offset, int whence) -{ - fz_error error; - fz_buffer *buf = stm->buffer; - int t, c; - - if (stm->dead) - return fz_throw("assert: seek in dead stream"); - - if (whence == 1) + else { - int cur = fz_tell(stm); - if (cur < 0) - return fz_throw("cannot tell current position"); - offset = cur + offset; - whence = 0; + count = 0; } - buf->eof = 0; + if (stm->dead) + return count; - switch (stm->kind) + while (len > count) { - case FZ_SFILE: - t = lseek(stm->file, offset, whence); - if (t < 0) + int n = stm->read(stm, buf + count, len - count); + if (n < 0) { stm->dead = 1; - return fz_throw("syserr: lseek: %s", strerror(errno)); - } - - buf->rp = buf->bp; - buf->wp = buf->bp; - - return fz_okay; - - case FZ_SFILTER: - if (whence == 0) - { - if (offset < fz_tell(stm)) - { - stm->dead = 1; - return fz_throw("assert: seek backwards in filter"); - } - while (fz_tell(stm) < offset) - { - c = fz_readbyte(stm); - if (c == EOF) - { - error = fz_readerror(stm); - if (error) - return fz_rethrow(error, "cannot seek forward in filter"); - break; - } - } - return fz_okay; + return fz_rethrow(n, "read error"); } - - stm->dead = 1; - return fz_throw("assert: relative seek in filter"); - - case FZ_SBUFFER: - if (whence == 0) - buf->rp = CLAMP(buf->bp + offset, buf->bp, buf->ep); - else - buf->rp = CLAMP(buf->ep + offset, buf->bp, buf->ep); - return fz_okay; - - default: - return fz_throw("unknown stream type"); + if (n == 0) + break; + stm->pos += n; + count += n; } + + return count; } -fz_error -fz_read(int *np, fz_stream *stm, unsigned char *mem, int n) +void +fz_fillbuffer(fz_stream *stm) { - fz_error error; - fz_buffer *buf = stm->buffer; - int i = 0; - - while (i < n) - { - while (buf->rp < buf->wp && i < n) - mem[i++] = *buf->rp++; + int n; - if (buf->rp == buf->wp) - { - if (buf->eof) - { - *np = i; - return fz_okay; - } + assert(stm->rp == stm->wp); - error = fz_readimp(stm); - if (error) - return fz_rethrow(error, "cannot produce data"); - } + n = fz_read(stm, stm->bp, stm->ep - stm->bp); + if (n < 0) + fz_catch(n, "read error; treating as end of file"); + else + { + stm->rp = stm->bp; + stm->wp = stm->bp + n; } - - *np = i; - return fz_okay; } fz_error -fz_readerror(fz_stream *stm) +fz_readall(fz_buffer **bufp, fz_stream *stm) { - fz_error error; - if (stm->error) - { - error = stm->error; - stm->error = fz_okay; - return fz_rethrow(error, "delayed read error"); - } - return fz_okay; -} + fz_buffer *buf; + int n; -int -fz_readbytex(fz_stream *stm) -{ - fz_buffer *buf = stm->buffer; + buf = fz_newbuffer(16 * 1024); - if (buf->rp == buf->wp) + while (1) { - if (!buf->eof && !stm->error) - { - fz_error error = fz_readimp(stm); - if (error) - stm->error = fz_rethrow(error, "cannot read data"); - } - } - - return buf->rp < buf->wp ? *buf->rp++ : EOF ; -} - -int -fz_peekbytex(fz_stream *stm) -{ - fz_buffer *buf = stm->buffer; + if (buf->len == buf->cap) + fz_growbuffer(buf); - if (buf->rp == buf->wp) - { - if (!buf->eof && !stm->error) + n = fz_read(stm, buf->data + buf->len, buf->cap - buf->len); + if (n < 0) { - fz_error error = fz_readimp(stm); - if (error) - stm->error = fz_rethrow(error, "cannot read data"); + fz_dropbuffer(buf); + return fz_rethrow(n, "read error"); } + if (n == 0) + break; + + buf->len += n; } - return buf->rp < buf->wp ? *buf->rp : EOF ; + *bufp = buf; + return fz_okay; } -/* Read a line terminated by LF or CR or CRLF. */ - -fz_error +void fz_readline(fz_stream *stm, char *mem, int n) { - fz_error error; - char *s = mem; int c = EOF; while (n > 1) @@ -298,57 +106,29 @@ fz_readline(fz_stream *stm, char *mem, int n) } if (n) *s = '\0'; - - error = fz_readerror(stm); - if (error) - return fz_rethrow(error, "cannot read line"); - return fz_okay; } -static inline int -fz_fillbuf(fz_stream *stm, fz_buffer *buf) +int +fz_tell(fz_stream *stm) { - int remaining = buf->ep - buf->wp; - int available = stm->buffer->wp - stm->buffer->rp; - - if (available == 0 && remaining > 0) - { - int c = fz_readbytex(stm); - if (c == EOF) - return EOF; - - *buf->wp++ = c; - - remaining = buf->ep - buf->wp; - available = stm->buffer->wp - stm->buffer->rp; - } - - memmove(buf->wp, stm->buffer->rp, MIN(remaining, available)); - buf->wp += MIN(remaining, available); - stm->buffer->rp += MIN(remaining, available); - - if (stm->buffer->rp == stm->buffer->wp && stm->buffer->eof) - return EOF; - return 0; + return stm->pos - (stm->wp - stm->rp); } -/* Read the contents of an input stream into a new buffer. */ - -fz_buffer * -fz_readall(fz_stream *stm, int sizehint) +void +fz_seek(fz_stream *stm, int offset, int whence) { - fz_buffer *buf; - - if (sizehint == 0) - sizehint = 4 * 1024; - - buf = fz_newbuffer(sizehint); - - while (fz_fillbuf(stm, buf) != EOF) + if (stm->seek) + stm->seek(stm, offset, whence); + else if (whence != 2) { - if (buf->wp == buf->ep) - fz_growbuffer(buf); + if (whence == 0) + offset -= fz_tell(stm); + if (offset < 0) + fz_warn("cannot seek backwards"); + /* dog slow, but rare enough */ + while (offset-- > 0) + fz_readbyte(stm); } - - return buf; + else + fz_warn("cannot seek"); } diff --git a/mupdf/cmapdump.c b/mupdf/cmapdump.c index 51e30255..b08b5628 100644 --- a/mupdf/cmapdump.c +++ b/mupdf/cmapdump.c @@ -10,7 +10,6 @@ #include "../fitz/base_memory.c" #include "../fitz/base_string.c" #include "../fitz/stm_buffer.c" -#include "../fitz/stm_filter.c" #include "../fitz/stm_open.c" #include "../fitz/stm_read.c" @@ -170,7 +169,7 @@ main(int argc, char **argv) fprintf(fo, "};\n\n"); - fz_dropstream(fi); + fz_close(fi); } if (fclose(fo)) diff --git a/mupdf/mupdf.h b/mupdf/mupdf.h index abd9c9ec..fa42f30d 100644 --- a/mupdf/mupdf.h +++ b/mupdf/mupdf.h @@ -104,7 +104,7 @@ fz_error pdf_newcrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id); void pdf_freecrypt(pdf_crypt *crypt); fz_error pdf_parsecryptfilter(pdf_cryptfilter *cf, fz_obj *dict, int defaultlength); -fz_filter * pdf_cryptstream(pdf_crypt *crypt, pdf_cryptfilter *cf, int num, int gen); +fz_stream * pdf_opencrypt(fz_stream *chain, pdf_crypt *crypt, pdf_cryptfilter *cf, int num, int gen); void pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int num, int gen); int pdf_needspassword(pdf_xref *xref); @@ -153,7 +153,7 @@ fz_error pdf_loadobject(fz_obj **objp, pdf_xref *, int num, int gen); void pdf_updateobject( pdf_xref *xref, int num, int gen, fz_obj *newobj); int pdf_isstream(pdf_xref *xref, int num, int gen); -fz_filter * pdf_buildinlinefilter(pdf_xref *xref, fz_obj *stmobj, int length); +fz_stream * pdf_openinlinestream(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int length); fz_error pdf_loadrawstream(fz_buffer **bufp, pdf_xref *xref, int num, int gen); fz_error pdf_loadstream(fz_buffer **bufp, pdf_xref *xref, int num, int gen); fz_error pdf_openrawstream(fz_stream **stmp, pdf_xref *, int num, int gen); diff --git a/mupdf/pdf_cmap_load.c b/mupdf/pdf_cmap_load.c index e031aad2..eae52d8d 100644 --- a/mupdf/pdf_cmap_load.c +++ b/mupdf/pdf_cmap_load.c @@ -36,7 +36,7 @@ pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmobj) goto cleanup; } - fz_dropstream(file); + fz_close(file); wmode = fz_dictgets(stmobj, "WMode"); if (fz_isint(wmode)) @@ -80,7 +80,7 @@ pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmobj) cleanup: if (file) - fz_dropstream(file); + fz_close(file); if (cmap) pdf_dropcmap(cmap); return error; /* already rethrown */ diff --git a/mupdf/pdf_colorspace.c b/mupdf/pdf_colorspace.c index ad793264..e0a3ab8e 100644 --- a/mupdf/pdf_colorspace.c +++ b/mupdf/pdf_colorspace.c @@ -243,7 +243,7 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) fz_obj *highobj = fz_arrayget(array, 2); fz_obj *lookup = fz_arrayget(array, 3); fz_colorspace *base; - int n; + int i, n; pdf_logrsrc("load Indexed {\n"); @@ -267,7 +267,6 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) if (fz_isstring(lookup) && fz_tostrlen(lookup) == n) { unsigned char *buf; - int i; pdf_logrsrc("string lookup\n"); @@ -277,22 +276,26 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) } else if (fz_isindirect(lookup)) { - fz_buffer *buf; - int i; + fz_stream *file; pdf_logrsrc("stream lookup\n"); - error = pdf_loadstream(&buf, xref, fz_tonum(lookup), fz_togen(lookup)); + /* TODO: openstream, read, close instead */ + error = pdf_openstream(&file, xref, fz_tonum(lookup), fz_togen(lookup)); if (error) { fz_dropcolorspace(cs); - return fz_rethrow(error, "cannot load colorpsace lookup table (%d %d R)", fz_tonum(lookup), fz_togen(lookup)); + return fz_rethrow(error, "cannot open colorspace lookup table (%d 0 R)", fz_tonum(lookup)); } - for (i = 0; i < n && i < (buf->wp - buf->rp); i++) - idx->lookup[i] = buf->rp[i]; + i = fz_read(file, idx->lookup, n); + if (i < 0) + { + fz_dropcolorspace(cs); + return fz_throw("cannot read colorspace lookup table (%d 0 R)", fz_tonum(lookup)); + } - fz_dropbuffer(buf); + fz_close(file); } else { diff --git a/mupdf/pdf_crypt.c b/mupdf/pdf_crypt.c index d5d496aa..1b0f0787 100644 --- a/mupdf/pdf_crypt.c +++ b/mupdf/pdf_crypt.c @@ -588,8 +588,8 @@ pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int num, int gen) * * Create filter suitable for de/encrypting a stream. */ -fz_filter * -pdf_cryptstream(pdf_crypt * crypt, pdf_cryptfilter * stmf, int num, int gen) +fz_stream * +pdf_opencrypt(fz_stream *chain, pdf_crypt *crypt, pdf_cryptfilter *stmf, int num, int gen) { unsigned char key[16]; int len; @@ -597,10 +597,10 @@ pdf_cryptstream(pdf_crypt * crypt, pdf_cryptfilter * stmf, int num, int gen) len = pdf_computeobjectkey(crypt, stmf, num, gen, key); if (stmf->method == PDF_CRYPT_RC4) - return fz_newarc4filter(key, len); + return fz_openarc4(chain, key, len); if (stmf->method == PDF_CRYPT_AESV2) - return fz_newaesdfilter(key, len); + return fz_openaesd(chain, key, len); - return fz_newcopyfilter(); + return fz_opencopy(chain); } diff --git a/mupdf/pdf_font.c b/mupdf/pdf_font.c index eaa567e3..0758f0a8 100644 --- a/mupdf/pdf_font.c +++ b/mupdf/pdf_font.c @@ -648,10 +648,10 @@ loadcidfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *enco if (error) goto cleanup; - fontdesc->ncidtogid = (buf->wp - buf->rp) / 2; + fontdesc->ncidtogid = (buf->len) / 2; fontdesc->cidtogid = fz_malloc(fontdesc->ncidtogid * sizeof(unsigned short)); for (i = 0; i < fontdesc->ncidtogid; i++) - fontdesc->cidtogid[i] = (buf->rp[i * 2] << 8) + buf->rp[i * 2 + 1]; + fontdesc->cidtogid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1]; fz_dropbuffer(buf); } diff --git a/mupdf/pdf_fontfile.c b/mupdf/pdf_fontfile.c index c461823f..b0bf828a 100644 --- a/mupdf/pdf_fontfile.c +++ b/mupdf/pdf_fontfile.c @@ -277,14 +277,14 @@ pdf_loadembeddedfont(pdf_fontdesc *fontdesc, pdf_xref *xref, fz_obj *stmref) if (error) return fz_rethrow(error, "cannot load font stream (%d %d R)", fz_tonum(stmref), fz_togen(stmref)); - error = fz_newfontfrombuffer(&fontdesc->font, buf->rp, buf->wp - buf->rp, 0); + error = fz_newfontfrombuffer(&fontdesc->font, buf->data, buf->len, 0); if (error) { fz_dropbuffer(buf); return fz_rethrow(error, "cannot load embedded font (%d %d R)", fz_tonum(stmref), fz_togen(stmref)); } - fontdesc->buffer = buf->rp; /* save the buffer so we can free it later */ + fontdesc->buffer = buf->data; /* save the buffer so we can free it later */ fz_free(buf); /* only free the fz_buffer struct, not the contained data */ fontdesc->isembedded = 1; diff --git a/mupdf/pdf_function.c b/mupdf/pdf_function.c index 0f7107a1..603759e1 100644 --- a/mupdf/pdf_function.c +++ b/mupdf/pdf_function.c @@ -508,13 +508,13 @@ loadpostscriptfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, in error = pdf_lex(&tok, stream, buf, sizeof buf, &len); if (error) { - fz_dropstream(stream); + fz_close(stream); return fz_rethrow(error, "stream is not a calculator function"); } if (tok != PDF_TOBRACE) { - fz_dropstream(stream); + fz_close(stream); return fz_throw("stream is not a calculator function"); } @@ -525,11 +525,11 @@ loadpostscriptfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, in error = parsecode(func, stream, &codeptr); if (error) { - fz_dropstream(stream); + fz_close(stream); return fz_rethrow(error, "cannot parse calculator function (%d %d R)", num, gen); } - fz_dropstream(stream); + fz_close(stream); return fz_okay; } @@ -1057,10 +1057,7 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int ge { if (fz_peekbyte(stream) == EOF && bits == 0) { - error = fz_readerror(stream); - fz_dropstream(stream); - if (error) - return fz_rethrow(error, "truncated sample stream"); + fz_close(stream); return fz_throw("truncated sample stream"); } @@ -1089,13 +1086,9 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int num, int ge func->u.sa.samples[i] = s; } - - error = fz_readerror(stream); - if (error) - return fz_rethrow(error, "truncated sample stream"); } - fz_dropstream(stream); + fz_close(stream); pdf_logrsrc("}\n"); diff --git a/mupdf/pdf_image.c b/mupdf/pdf_image.c index 6350c858..b10133e8 100644 --- a/mupdf/pdf_image.c +++ b/mupdf/pdf_image.c @@ -142,9 +142,8 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, { fz_error error; pdf_image *img; - fz_filter *filter; fz_stream *subfile; - int n; + int i, n; pdf_logimage("load inline image {\n"); @@ -152,27 +151,25 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, if (error) return fz_rethrow(error, "cannot load inline image"); - filter = pdf_buildinlinefilter(xref, dict, img->stride * img->h); - subfile = fz_openfilter(filter, file); + subfile = pdf_openinlinestream(file, xref, dict, img->stride * img->h); img->samples = fz_newbuffer(img->h * img->stride); - error = fz_read(&n, subfile, img->samples->bp, img->h * img->stride); - if (error) + n = fz_read(subfile, img->samples->data, img->h * img->stride); + if (n < 0) { pdf_dropimage(img); - return fz_rethrow(error, "cannot load inline image data"); + return fz_rethrow(n, "cannot load inline image data"); } - img->samples->wp += n; + img->samples->len = n; - fz_dropstream(subfile); - fz_dropfilter(filter); + fz_close(subfile); if (img->imagemask) { /* 0=opaque and 1=transparent so we need to invert */ - unsigned char *p; - for (p = img->samples->bp; p < img->samples->ep; p++) - *p = ~*p; + unsigned char *p = img->samples->data; + for (i = 0; i < img->samples->len; i++) + p[i] = ~p[i]; } pdf_logimage("}\n"); @@ -185,7 +182,9 @@ fz_error pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) { fz_error error; + fz_stream *stm; pdf_image *img; + int i, n; if ((*imgp = pdf_finditem(xref->store, pdf_dropimage, dict))) { @@ -199,28 +198,39 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) if (error) return fz_rethrow(error, "cannot load image (%d %d R)", fz_tonum(dict), fz_togen(dict)); - error = pdf_loadstream(&img->samples, xref, fz_tonum(dict), fz_togen(dict)); + error = pdf_openstream(&stm, xref, fz_tonum(dict), fz_togen(dict)); if (error) { pdf_dropimage(img); return fz_rethrow(error, "cannot load image data (%d %d R)", fz_tonum(dict), fz_togen(dict)); } + img->samples = fz_newbuffer(img->h * img->stride); + n = fz_read(stm, img->samples->data, img->h * img->stride); + if (n < 0) + { + pdf_dropimage(img); + fz_close(stm); + return fz_rethrow(n, "cannot load inline image data"); + } + img->samples->len = n; + + fz_close(stm); + /* Pad truncated images */ - if (img->samples->wp - img->samples->bp < img->stride * img->h) + if (img->samples->len < img->stride * img->h) { fz_warn("padding truncated image"); - fz_resizebuffer(img->samples, img->stride * img->h); - memset(img->samples->wp, 0, img->samples->ep - img->samples->wp); - img->samples->wp = img->samples->bp + img->stride * img->h; + memset(img->samples->data + img->samples->len, 0, img->samples->cap - img->samples->len); + img->samples->len = img->samples->cap; } if (img->imagemask) { /* 0=opaque and 1=transparent so we need to invert */ - unsigned char *p; - for (p = img->samples->bp; p < img->samples->ep; p++) - *p = ~*p; + unsigned char *p = img->samples->data; + for (i = 0; i < img->samples->len; i++) + p[i] = ~p[i]; } pdf_logimage("}\n"); @@ -269,7 +279,7 @@ pdf_loadtile(pdf_image *img /* ...bbox/y+h should go here... */) } } - fz_unpacktile(tile, img->samples->bp, img->n, img->bpc, img->stride, scale); + fz_unpacktile(tile, img->samples->data, img->n, img->bpc, img->stride, scale); if (img->usecolorkey) pdf_maskcolorkey(tile, img->n, img->colorkey); diff --git a/mupdf/pdf_interpret.c b/mupdf/pdf_interpret.c index 95f2ed42..8faad1d0 100644 --- a/mupdf/pdf_interpret.c +++ b/mupdf/pdf_interpret.c @@ -1452,9 +1452,6 @@ pdf_runcsifile(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen if (ch == '\r') if (fz_peekbyte(file) == '\n') fz_readbyte(file); - error = fz_readerror(file); - if (error) - return fz_rethrow(error, "cannot parse whitespace before inline image"); error = pdf_runinlineimage(csi, rdb, file, obj); fz_dropobj(obj); @@ -1482,11 +1479,9 @@ pdf_runcsibuffer(pdf_csi *csi, fz_obj *rdb, fz_buffer *contents) { fz_stream *file; fz_error error; - contents->rp = contents->bp; file = fz_openbuffer(contents); error = pdf_runcsifile(csi, rdb, file, csi->xref->scratch, sizeof csi->xref->scratch); - fz_dropstream(file); - contents->rp = contents->bp; + fz_close(file); if (error) return fz_rethrow(error, "cannot parse content stream"); return fz_okay; diff --git a/mupdf/pdf_lex.c b/mupdf/pdf_lex.c index d4f98bc0..16e12a13 100644 --- a/mupdf/pdf_lex.c +++ b/mupdf/pdf_lex.c @@ -389,17 +389,14 @@ pdf_tokenfromkeyword(char *key) fz_error pdf_lex(pdf_token_e *tok, fz_stream *f, char *buf, int n, int *sl) { - fz_error error; - int c; - while (1) { - c = fz_readbyte(f); + int c = fz_readbyte(f); switch (c) { case EOF: *tok = PDF_TEOF; - goto cleanupokay; + return fz_okay; case ISWHITE: lexwhite(f); break; @@ -410,11 +407,11 @@ pdf_lex(pdf_token_e *tok, fz_stream *f, char *buf, int n, int *sl) lexname(f, buf, n); *sl = strlen(buf); *tok = PDF_TNAME; - goto cleanupokay; + return fz_okay; case '(': *sl = lexstring(f, buf, n); *tok = PDF_TSTRING; - goto cleanupokay; + return fz_okay; case ')': *tok = PDF_TERROR; goto cleanuperror; @@ -430,57 +427,42 @@ pdf_lex(pdf_token_e *tok, fz_stream *f, char *buf, int n, int *sl) *sl = lexhexstring(f, buf, n); *tok = PDF_TSTRING; } - goto cleanupokay; + return fz_okay; case '>': c = fz_readbyte(f); if (c == '>') { *tok = PDF_TCDICT; - goto cleanupokay; + return fz_okay; } *tok = PDF_TERROR; goto cleanuperror; case '[': *tok = PDF_TOARRAY; - goto cleanupokay; + return fz_okay; case ']': *tok = PDF_TCARRAY; - goto cleanupokay; + return fz_okay; case '{': *tok = PDF_TOBRACE; - goto cleanupokay; + return fz_okay; case '}': *tok = PDF_TCBRACE; - goto cleanupokay; + return fz_okay; case ISNUMBER: fz_unreadbyte(f); *sl = lexnumber(f, buf, n, tok); - goto cleanupokay; + return fz_okay; default: /* isregular: !isdelim && !iswhite && c != EOF */ fz_unreadbyte(f); lexname(f, buf, n); *sl = strlen(buf); *tok = pdf_tokenfromkeyword(buf); - goto cleanupokay; + return fz_okay; } } -cleanupokay: - error = fz_readerror(f); - if (error) - { - *tok = PDF_TERROR; - return fz_rethrow(error, "cannot read token"); - } - return fz_okay; - cleanuperror: - error = fz_readerror(f); - if (error) - { - *tok = PDF_TERROR; - return fz_rethrow(error, "cannot read token"); - } *tok = PDF_TERROR; return fz_throw("lexical error"); } diff --git a/mupdf/pdf_page.c b/mupdf/pdf_page.c index 2edada66..75e10eeb 100644 --- a/mupdf/pdf_page.c +++ b/mupdf/pdf_page.c @@ -9,10 +9,12 @@ pdf_loadpagecontentsarray(fz_buffer **bigbufp, pdf_xref *xref, fz_obj *list) fz_error error; fz_buffer *big; fz_buffer *one; - int i, n; + int i; pdf_logpage("multiple content streams: %d\n", fz_arraylen(list)); + /* TODO: openstream, read, close into big buffer at once */ + big = fz_newbuffer(32 * 1024); for (i = 0; i < fz_arraylen(list); i++) @@ -25,12 +27,11 @@ pdf_loadpagecontentsarray(fz_buffer **bigbufp, pdf_xref *xref, fz_obj *list) return fz_rethrow(error, "cannot load content stream part %d/%d (%d %d R)", i + 1, fz_arraylen(list), fz_tonum(stm), fz_togen(stm)); } - n = one->wp - one->rp; - while (big->wp + n + 1 > big->ep) - fz_growbuffer(big); - memcpy(big->wp, one->rp, n); - big->wp += n; - *big->wp++ = ' '; + if (big->len + one->len + 1 > big->cap) + fz_resizebuffer(big, big->len + one->len + 1); + memcpy(big->data + big->len, one->data, one->len); + big->data[big->len + one->len] = ' '; + big->len += one->len + 1; fz_dropbuffer(one); } diff --git a/mupdf/pdf_parse.c b/mupdf/pdf_parse.c index 94b0504c..942c5d33 100644 --- a/mupdf/pdf_parse.c +++ b/mupdf/pdf_parse.c @@ -506,12 +506,6 @@ skip: else fz_readbyte(file); } - error = fz_readerror(file); - if (error) - { - fz_dropobj(obj); - return fz_rethrow(error, "cannot parse indirect object (%d %d R)", num, gen); - } stmofs = fz_tell(file); } else if (tok == PDF_TENDOBJ) diff --git a/mupdf/pdf_repair.c b/mupdf/pdf_repair.c index 9404b1f2..1652073a 100644 --- a/mupdf/pdf_repair.c +++ b/mupdf/pdf_repair.c @@ -69,32 +69,24 @@ fz_repairobj(fz_stream *file, char *buf, int cap, int *stmofsp, int *stmlenp, in fz_readbyte(file); } - error = fz_readerror(file); - if (error) - return fz_rethrow(error, "cannot read from file"); - *stmofsp = fz_tell(file); if (*stmofsp < 0) return fz_throw("cannot seek in file"); if (stmlen > 0) { - error = fz_seek(file, *stmofsp + stmlen, 0); - if (error) - return fz_rethrow(error, "cannot seek in file"); + fz_seek(file, *stmofsp + stmlen, 0); error = pdf_lex(&tok, file, buf, cap, &len); if (error) fz_catch(error, "cannot find endstream token, falling back to scanning"); if (tok == PDF_TENDSTREAM) goto atobjend; - error = fz_seek(file, *stmofsp, 0); - if (error) - return fz_rethrow(error, "cannot seek in file"); + fz_seek(file, *stmofsp, 0); } - error = fz_read(&n, file, (unsigned char *) buf, 9); - if (error) - return fz_rethrow(error, "cannot read from file"); + n = fz_read(file, (unsigned char *) buf, 9); + if (n < 0) + return fz_rethrow(n, "cannot read from file"); while (memcmp(buf, "endstream", 9) != 0) { @@ -105,10 +97,6 @@ fz_repairobj(fz_stream *file, char *buf, int cap, int *stmofsp, int *stmlenp, in buf[8] = c; } - error = fz_readerror(file); - if (error) - return fz_rethrow(error, "cannot read from file"); - *stmlenp = fz_tell(file) - *stmofsp - 9; atobjend: @@ -149,9 +137,7 @@ pdf_repairxref(pdf_xref *xref, char *buf, int bufsize) pdf_logxref("repairxref %p\n", xref); - error = fz_seek(xref->file, 0, 0); - if (error) - return fz_rethrow(error, "cannot seek to beginning of file"); + fz_seek(xref->file, 0, 0); listlen = 0; listcap = 1024; diff --git a/mupdf/pdf_shade.c b/mupdf/pdf_shade.c index 51a73ca4..2aacef31 100644 --- a/mupdf/pdf_shade.c +++ b/mupdf/pdf_shade.c @@ -1261,7 +1261,7 @@ pdf_loadshadingdict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix t goto cleanup; if (stream) - fz_dropstream(stream); + fz_close(stream); for (i = 0; i < funcs; i++) if (func[i]) pdf_dropfunction(func[i]); @@ -1273,7 +1273,7 @@ pdf_loadshadingdict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix t cleanup: if (stream) - fz_dropstream(stream); + fz_close(stream); for (i = 0; i < funcs; i++) if (func[i]) pdf_dropfunction(func[i]); diff --git a/mupdf/pdf_stream.c b/mupdf/pdf_stream.c index 539b4b3f..2e4032c9 100644 --- a/mupdf/pdf_stream.c +++ b/mupdf/pdf_stream.c @@ -35,17 +35,15 @@ pdf_streamhascrypt(fz_obj *stm) filters = fz_dictgetsa(stm, "Filter", "F"); if (filters) { - if (fz_isname(filters)) - if (!strcmp(fz_toname(filters), "Crypt")) - return 1; + if (!strcmp(fz_toname(filters), "Crypt")) + return 1; if (fz_isarray(filters)) { for (i = 0; i < fz_arraylen(filters); i++) { obj = fz_arrayget(filters, i); - if (fz_isname(obj)) - if (!strcmp(fz_toname(obj), "Crypt")) - return 1; + if (!strcmp(fz_toname(obj), "Crypt")) + return 1; } } } @@ -55,60 +53,43 @@ pdf_streamhascrypt(fz_obj *stm) /* * Create a filter given a name and param dictionary. */ -static fz_filter * -buildonefilter(pdf_xref * xref, fz_obj * f, fz_obj * p, int num, int gen) +static fz_stream * +buildfilter(fz_stream *chain, pdf_xref * xref, fz_obj * f, fz_obj * p, int num, int gen) { - fz_filter *decompress; - fz_filter *predict; - fz_filter *pipe; fz_error error; char *s; s = fz_toname(f); if (!strcmp(s, "ASCIIHexDecode") || !strcmp(s, "AHx")) - return fz_newahxd(p); + return fz_openahxd(chain); else if (!strcmp(s, "ASCII85Decode") || !strcmp(s, "A85")) - return fz_newa85d(p); + return fz_opena85d(chain); else if (!strcmp(s, "CCITTFaxDecode") || !strcmp(s, "CCF")) - return fz_newfaxd(p); + return fz_openfaxd(chain, p); else if (!strcmp(s, "DCTDecode") || !strcmp(s, "DCT")) - return fz_newdctd(p); + return fz_opendctd(chain, p); else if (!strcmp(s, "RunLengthDecode") || !strcmp(s, "RL")) - return fz_newrld(p); + return fz_openrld(chain); else if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl")) { fz_obj *obj = fz_dictgets(p, "Predictor"); - if (obj) - { - decompress = fz_newflated(p); - predict = fz_newpredictd(p); - pipe = fz_newpipeline(decompress, predict); - fz_dropfilter(decompress); - fz_dropfilter(predict); - return pipe; - } - return fz_newflated(p); + if (fz_toint(obj) > 1) + return fz_openpredict(fz_openflated(chain), p); + return fz_openflated(chain); } else if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW")) { fz_obj *obj = fz_dictgets(p, "Predictor"); - if (obj) - { - decompress = fz_newlzwd(p); - predict = fz_newpredictd(p); - pipe = fz_newpipeline(decompress, predict); - fz_dropfilter(decompress); - fz_dropfilter(predict); - return pipe; - } - return fz_newlzwd(p); + if (fz_toint(obj) > 1) + return fz_openpredict(fz_openlzwd(chain, p), p); + return fz_openlzwd(chain, p); } else if (!strcmp(s, "JBIG2Decode")) @@ -117,29 +98,18 @@ buildonefilter(pdf_xref * xref, fz_obj * f, fz_obj * p, int num, int gen) if (obj) { fz_buffer *globals; - fz_filter *dec; - - dec = fz_newjbig2d(p); - error = pdf_loadstream(&globals, xref, fz_tonum(obj), fz_togen(obj)); if (error) fz_catch(error, "cannot load jbig2 global segments"); - else - { - error = fz_setjbig2dglobalstream(dec, globals->rp, globals->wp - globals->rp); - if (error) - fz_catch(error, "cannot apply jbig2 global segments"); - } - + chain = fz_openjbig2d(chain, globals); fz_dropbuffer(globals); - - return dec; + return chain; } - return fz_newjbig2d(p); + return fz_openjbig2d(chain, nil); } else if (!strcmp(s, "JPXDecode")) - return fz_newjpxd(p); + return fz_openjpxd(chain); else if (!strcmp(s, "Crypt")) { @@ -149,7 +119,7 @@ buildonefilter(pdf_xref * xref, fz_obj * f, fz_obj * p, int num, int gen) if (!xref->crypt) { fz_warn("crypt filter in unencrypted document"); - return fz_newcopyfilter(); + return chain; } name = fz_dictgets(p, "Name"); @@ -162,14 +132,15 @@ buildonefilter(pdf_xref * xref, fz_obj * f, fz_obj * p, int num, int gen) if (error) fz_catch(error, "cannot parse crypt filter (%d %d R)", fz_tonum(obj), fz_togen(obj)); else - return pdf_cryptstream(xref->crypt, &cf, num, gen); + return pdf_opencrypt(chain, xref->crypt, &cf, num, gen); } } - return fz_newcopyfilter(); + + return chain; } fz_warn("unknown filter name (%s)", s); - return fz_newcopyfilter(); + return chain; } /* @@ -177,12 +148,9 @@ buildonefilter(pdf_xref * xref, fz_obj * f, fz_obj * p, int num, int gen) * If head is given, start filter chain with it. * Assume ownership of head. */ -static fz_filter * -buildfilterchain(pdf_xref *xref, fz_filter *head, - fz_obj *fs, fz_obj *ps, int num, int gen) +static fz_stream * +buildfilterchain(fz_stream *chain, pdf_xref *xref, fz_obj *fs, fz_obj *ps, int num, int gen) { - fz_filter *newhead; - fz_filter *tail; fz_obj *f; fz_obj *p; int i; @@ -190,24 +158,11 @@ buildfilterchain(pdf_xref *xref, fz_filter *head, 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; - - tail = buildonefilter(xref, f, p, num, gen); - if (head) - { - newhead = fz_newpipeline(head, tail); - fz_dropfilter(head); - fz_dropfilter(tail); - head = newhead; - } - else - head = tail; + p = fz_arrayget(ps, i); + chain = buildfilter(chain, xref, f, p, num, gen); } - return head; + return chain; } /* @@ -215,41 +170,31 @@ buildfilterchain(pdf_xref *xref, fz_filter *head, * This is a null filter to constrain reading to the * stream length, followed by a decryption filter. */ -static fz_filter * -buildrawfilter(pdf_xref *xref, fz_obj *stmobj, int num, int gen) +static fz_stream * +pdf_openrawfilter(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int num, int gen) { - fz_filter *base; - fz_obj *stmlen; - int len; int hascrypt; + int len; - hascrypt = pdf_streamhascrypt(stmobj); - - stmlen = fz_dictgets(stmobj, "Length"); - len = fz_toint(stmlen); + /* don't close chain when we close this filter */ + fz_keepstream(chain); - base = fz_newnullfilter(len); + len = fz_toint(fz_dictgets(stmobj, "Length")); + chain = fz_opennull(chain, len); + hascrypt = pdf_streamhascrypt(stmobj); if (xref->crypt && !hascrypt) - { - fz_filter *crypt; - fz_filter *pipe; - crypt = pdf_cryptstream(xref->crypt, &xref->crypt->stmf, num, gen); - pipe = fz_newpipeline(base, crypt); - fz_dropfilter(base); - fz_dropfilter(crypt); - return pipe; - } + chain = pdf_opencrypt(chain, xref->crypt, &xref->crypt->stmf, num, gen); - return base; + return chain; } /* - * Construct a filter to decode a stream, without - * constraining to stream length, and without decryption. + * Construct a filter to decode a stream, constraining + * to stream length and decrypting. */ -fz_filter * -pdf_buildinlinefilter(pdf_xref *xref, fz_obj *stmobj, int length) +static fz_stream * +pdf_openfilter(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int num, int gen) { fz_obj *filters; fz_obj *params; @@ -257,48 +202,38 @@ pdf_buildinlinefilter(pdf_xref *xref, fz_obj *stmobj, int length) filters = fz_dictgetsa(stmobj, "Filter", "F"); params = fz_dictgetsa(stmobj, "DecodeParms", "DP"); + chain = pdf_openrawfilter(chain, xref, stmobj, num, gen); + if (fz_isname(filters)) - return buildonefilter(xref, filters, params, 0, 0); + return buildfilter(chain, xref, filters, params, num, gen); if (fz_arraylen(filters) > 0) - return buildfilterchain(xref, nil, filters, params, 0, 0); + return buildfilterchain(chain, xref, filters, params, num, gen); - return fz_newnullfilter(length); + return chain; } /* - * Construct a filter to decode a stream, constraining - * to stream length and decrypting. + * Construct a filter to decode a stream, without + * constraining to stream length, and without decryption. */ -static fz_filter * -pdf_buildfilter(pdf_xref *xref, fz_obj *stmobj, int num, int gen) +fz_stream * +pdf_openinlinestream(fz_stream *chain, pdf_xref *xref, fz_obj *stmobj, int length) { - fz_filter *base, *pipe, *tmp; fz_obj *filters; fz_obj *params; filters = fz_dictgetsa(stmobj, "Filter", "F"); params = fz_dictgetsa(stmobj, "DecodeParms", "DP"); - base = buildrawfilter(xref, stmobj, num, gen); + /* don't close chain when we close this filter */ + fz_keepstream(chain); - if (filters) - { - if (fz_isname(filters)) - { - tmp = buildonefilter(xref, filters, params, num, gen); - pipe = fz_newpipeline(base, tmp); - fz_dropfilter(base); - fz_dropfilter(tmp); - return pipe; - } - else - { - /* The pipeline chain takes ownership of base */ - return buildfilterchain(xref, base, filters, params, num, gen); - } - } + if (fz_isname(filters)) + return buildfilter(chain, xref, filters, params, 0, 0); + if (fz_arraylen(filters) > 0) + return buildfilterchain(chain, xref, filters, params, 0, 0); - return base; + return fz_opennull(chain, length); } /* @@ -310,7 +245,6 @@ pdf_openrawstream(fz_stream **stmp, pdf_xref *xref, int num, int gen) { pdf_xrefentry *x; fz_error error; - fz_filter *filter; if (num < 0 || num >= xref->len) return fz_throw("object id out of range (%d %d R)", num, gen); @@ -323,14 +257,8 @@ pdf_openrawstream(fz_stream **stmp, pdf_xref *xref, int num, int gen) if (x->stmofs) { - filter = buildrawfilter(xref, x->obj, num, gen); - - error = fz_seek(xref->file, x->stmofs, 0); - if (error) - return fz_rethrow(error, "cannot seek to stream"); - - *stmp = fz_openfilter(filter, xref->file); - fz_dropfilter(filter); + *stmp = pdf_openrawfilter(xref->file, xref, x->obj, num, gen); + fz_seek(xref->file, x->stmofs, 0); return fz_okay; } @@ -347,7 +275,6 @@ pdf_openstream(fz_stream **stmp, pdf_xref *xref, int num, int gen) { pdf_xrefentry *x; fz_error error; - fz_filter *filter; if (num < 0 || num >= xref->len) return fz_throw("object id out of range (%d %d R)", num, gen); @@ -360,14 +287,8 @@ pdf_openstream(fz_stream **stmp, pdf_xref *xref, int num, int gen) if (x->stmofs) { - filter = pdf_buildfilter(xref, x->obj, num, gen); - - error = fz_seek(xref->file, x->stmofs, 0); - if (error) - return fz_rethrow(error, "cannot seek to stream"); - - *stmp = fz_openfilter(filter, xref->file); - fz_dropfilter(filter); + *stmp = pdf_openfilter(xref->file, xref, x->obj, num, gen); + fz_seek(xref->file, x->stmofs, 0); return fz_okay; } @@ -377,22 +298,12 @@ pdf_openstream(fz_stream **stmp, pdf_xref *xref, int num, int gen) fz_error pdf_openstreamat(fz_stream **stmp, pdf_xref *xref, int num, int gen, fz_obj *dict, int stmofs) { - fz_error error; - fz_filter *filter; - if (stmofs) { - filter = pdf_buildfilter(xref, dict, num, gen); - - error = fz_seek(xref->file, stmofs, 0); - if (error) - return fz_rethrow(error, "cannot seek to stream"); - - *stmp = fz_openfilter(filter, xref->file); - fz_dropfilter(filter); + *stmp = pdf_openfilter(xref->file, xref, dict, num, gen); + fz_seek(xref->file, stmofs, 0); return fz_okay; } - return fz_throw("object is not a stream"); } @@ -404,24 +315,19 @@ pdf_loadrawstream(fz_buffer **bufp, pdf_xref *xref, int num, int gen) { fz_error error; fz_stream *stm; - fz_buffer *buf; error = pdf_openrawstream(&stm, xref, num, gen); if (error) return fz_rethrow(error, "cannot open raw stream (%d %d R)", num, gen); - buf = fz_readall(stm, 0); - error = fz_readerror(stm); + error = fz_readall(bufp, stm); if (error) { - fz_dropbuffer(buf); - fz_dropstream(stm); + fz_close(stm); return fz_rethrow(error, "cannot read raw stream (%d %d R)", num, gen); } - fz_dropstream(stm); - - *bufp = buf; + fz_close(stm); return fz_okay; } @@ -433,23 +339,18 @@ pdf_loadstream(fz_buffer **bufp, pdf_xref *xref, int num, int gen) { fz_error error; fz_stream *stm; - fz_buffer *buf; error = pdf_openstream(&stm, xref, num, gen); if (error) return fz_rethrow(error, "cannot open stream (%d %d R)", num, gen); - buf = fz_readall(stm, 0); - error = fz_readerror(stm); + error = fz_readall(bufp, stm); if (error) { - fz_dropbuffer(buf); - fz_dropstream(stm); + fz_close(stm); return fz_rethrow(error, "cannot read raw stream (%d %d R)", num, gen); } - fz_dropstream(stm); - - *bufp = buf; + fz_close(stm); return fz_okay; } diff --git a/mupdf/pdf_xobject.c b/mupdf/pdf_xobject.c index 9a9fc212..8f94eccf 100644 --- a/mupdf/pdf_xobject.c +++ b/mupdf/pdf_xobject.c @@ -75,7 +75,7 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict) return fz_rethrow(error, "cannot load xobject content stream (%d %d R)", fz_tonum(dict), fz_togen(dict)); } - pdf_logrsrc("stream %d bytes\n", form->contents->wp - form->contents->rp); + pdf_logrsrc("stream %d bytes\n", form->contents->len); pdf_logrsrc("}\n"); *formp = form; diff --git a/mupdf/pdf_xref.c b/mupdf/pdf_xref.c index 196b633e..c9734e71 100644 --- a/mupdf/pdf_xref.c +++ b/mupdf/pdf_xref.c @@ -15,16 +15,10 @@ static inline int iswhite(int ch) static fz_error pdf_loadversion(pdf_xref *xref) { - fz_error error; char buf[20]; - error = fz_seek(xref->file, 0, 0); - if (error) - return fz_rethrow(error, "cannot seek to beginning of file"); - - error = fz_readline(xref->file, buf, sizeof buf); - if (error) - return fz_rethrow(error, "cannot read version marker"); + fz_seek(xref->file, 0, 0); + fz_readline(xref->file, buf, sizeof buf); if (memcmp(buf, "%PDF-", 5) != 0) return fz_throw("cannot recognize version marker"); @@ -38,25 +32,20 @@ pdf_loadversion(pdf_xref *xref) static fz_error pdf_readstartxref(pdf_xref *xref) { - fz_error error; unsigned char buf[1024]; int t, n; int i; - error = fz_seek(xref->file, 0, 2); - if (error) - return fz_rethrow(error, "cannot seek to end of file"); + fz_seek(xref->file, 0, 2); xref->filesize = fz_tell(xref->file); t = MAX(0, xref->filesize - (int)sizeof buf); - error = fz_seek(xref->file, t, 0); - if (error) - return fz_rethrow(error, "cannot seek to offset %d", t); + fz_seek(xref->file, t, 0); - error = fz_read(&n, xref->file, buf, sizeof buf); - if (error) - return fz_rethrow(error, "cannot read from file"); + n = fz_read(xref->file, buf, sizeof buf); + if (n < 0) + return fz_rethrow(n, "cannot read from file"); for (i = n - 9; i >= 0; i--) { @@ -91,9 +80,7 @@ pdf_readoldtrailer(pdf_xref *xref, char *buf, int cap) pdf_logxref("load old xref format trailer\n"); - error = fz_readline(xref->file, buf, cap); - if (error) - return fz_rethrow(error, "cannot read xref marker"); + fz_readline(xref->file, buf, cap); if (strncmp(buf, "xref", 4) != 0) return fz_throw("cannot find xref marker"); @@ -103,10 +90,7 @@ pdf_readoldtrailer(pdf_xref *xref, char *buf, int cap) if (!(c >= '0' && c <= '9')) break; - error = fz_readline(xref->file, buf, cap); - if (error) - return fz_rethrow(error, "cannot read xref count"); - + fz_readline(xref->file, buf, cap); s = buf; fz_strsep(&s, " "); /* ignore ofs */ if (!s) @@ -115,25 +99,15 @@ pdf_readoldtrailer(pdf_xref *xref, char *buf, int cap) /* broken pdfs where the section is not on a separate line */ if (s && *s != '\0') - { - error = fz_seek(xref->file, -(2 + (int)strlen(s)), 1); - if (error) - return fz_rethrow(error, "cannot seek in file"); - } + fz_seek(xref->file, -(2 + (int)strlen(s)), 1); t = fz_tell(xref->file); if (t < 0) return fz_throw("cannot tell in file"); - error = fz_seek(xref->file, t + 20 * len, 0); - if (error) - return fz_rethrow(error, "cannot seek in file"); + fz_seek(xref->file, t + 20 * len, 0); } - error = fz_readerror(xref->file); - if (error) - return fz_rethrow(error, "cannot read from file"); - error = pdf_lex(&tok, xref->file, buf, cap, &n); if (error) return fz_rethrow(error, "cannot parse trailer"); @@ -171,18 +145,12 @@ pdf_readtrailer(pdf_xref *xref, char *buf, int cap) fz_error error; int c; - error = fz_seek(xref->file, xref->startxref, 0); - if (error) - return fz_rethrow(error, "cannot seek to startxref"); + fz_seek(xref->file, xref->startxref, 0); while (iswhite(fz_peekbyte(xref->file))) fz_readbyte(xref->file); c = fz_peekbyte(xref->file); - error = fz_readerror(xref->file); - if (error) - return fz_rethrow(error, "cannot read trailer"); - if (c == 'x') { error = pdf_readoldtrailer(xref, buf, cap); @@ -220,9 +188,7 @@ pdf_readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) pdf_logxref("load old xref format\n"); - error = fz_readline(xref->file, buf, cap); - if (error) - return fz_rethrow(error, "cannot read xref marker"); + fz_readline(xref->file, buf, cap); if (strncmp(buf, "xref", 4) != 0) return fz_throw("cannot find xref marker"); @@ -232,10 +198,7 @@ pdf_readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) if (!(c >= '0' && c <= '9')) break; - error = fz_readline(xref->file, buf, cap); - if (error) - return fz_rethrow(error, "cannot read xref count"); - + fz_readline(xref->file, buf, cap); s = buf; ofs = atoi(fz_strsep(&s, " ")); len = atoi(fz_strsep(&s, " ")); @@ -244,14 +207,11 @@ pdf_readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) if (s && *s != '\0') { fz_warn("broken xref section. proceeding anyway."); - error = fz_seek(xref->file, -(2 + (int)strlen(s)), 1); - if (error) - return fz_rethrow(error, "cannot seek to xref"); + fz_seek(xref->file, -(2 + (int)strlen(s)), 1); } - /* broken pdfs where size in trailer undershoots - entries in xref sections */ - if ((ofs + len) > xref->cap) + /* broken pdfs where size in trailer undershoots entries in xref sections */ + if (ofs + len > xref->cap) { fz_warn("broken xref section, proceeding anyway."); xref->cap = ofs + len; @@ -273,9 +233,9 @@ pdf_readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) for (i = ofs; i < ofs + len; i++) { - error = fz_read(&n, xref->file, (unsigned char *) buf, 20); - if (error) - return fz_rethrow(error, "cannot read xref table"); + n = fz_read(xref->file, (unsigned char *) buf, 20); + if (n < 0) + return fz_rethrow(n, "cannot read xref table"); if (!xref->table[i].type) { s = buf; @@ -315,7 +275,6 @@ pdf_readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) static fz_error pdf_readnewxrefsection(pdf_xref *xref, fz_stream *stm, int i0, int i1, int w0, int w1, int w2) { - fz_error error; int i, n; if (i0 < 0 || i0 + i1 > xref->len) @@ -328,12 +287,7 @@ pdf_readnewxrefsection(pdf_xref *xref, fz_stream *stm, int i0, int i1, int w0, i int c = 0; if (fz_peekbyte(stm) == EOF) - { - error = fz_readerror(stm); - if (error) - return fz_rethrow(error, "truncated xref stream"); return fz_throw("truncated xref stream"); - } for (n = 0; n < w0; n++) a = (a << 8) + fz_readbyte(stm); @@ -342,10 +296,6 @@ pdf_readnewxrefsection(pdf_xref *xref, fz_stream *stm, int i0, int i1, int w0, i for (n = 0; n < w2; n++) c = (c << 8) + fz_readbyte(stm); - error = fz_readerror(stm); - if (error) - return fz_rethrow(error, "truncated xref stream"); - if (!xref->table[i].type) { int t = w0 ? a : 1; @@ -447,7 +397,7 @@ pdf_readnewxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) error = pdf_readnewxrefsection(xref, stm, 0, size, w0, w1, w2); if (error) { - fz_dropstream(stm); + fz_close(stm); fz_dropobj(trailer); return fz_rethrow(error, "cannot read xref stream (%d %d R)", num, gen); } @@ -461,14 +411,14 @@ pdf_readnewxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) error = pdf_readnewxrefsection(xref, stm, i0, i1, w0, w1, w2); if (error) { - fz_dropstream(stm); + fz_close(stm); fz_dropobj(trailer); return fz_rethrow(error, "cannot read xref stream section (%d %d R)", num, gen); } } } - fz_dropstream(stm); + fz_close(stm); *trailerp = trailer; @@ -481,18 +431,12 @@ pdf_readxref(fz_obj **trailerp, pdf_xref *xref, int ofs, char *buf, int cap) fz_error error; int c; - error = fz_seek(xref->file, ofs, 0); - if (error) - return fz_rethrow(error, "cannot seek to xref"); + fz_seek(xref->file, ofs, 0); while (iswhite(fz_peekbyte(xref->file))) fz_readbyte(xref->file); c = fz_peekbyte(xref->file); - error = fz_readerror(xref->file); - if (error) - return fz_rethrow(error, "cannot read trailer"); - if (c == 'x') { error = pdf_readoldxref(trailerp, xref, buf, cap); @@ -728,7 +672,7 @@ pdf_freexref(pdf_xref *xref) } if (xref->file) - fz_dropstream(xref->file); + fz_close(xref->file); if (xref->trailer) fz_dropobj(xref->trailer); if (xref->crypt) @@ -812,21 +756,11 @@ pdf_loadobjstm(pdf_xref *xref, int num, int gen, char *buf, int cap) ofsbuf[i] = atoi(buf); } - error = fz_seek(stm, first, 0); - if (error) - { - error = fz_rethrow(error, "cannot seek in object stream (%d %d R)", num, gen); - goto cleanupstm; - } + fz_seek(stm, first, 0); for (i = 0; i < count; i++) { - error = fz_seek(stm, first + ofsbuf[i], 0); - if (error) - { - error = fz_rethrow(error, "cannot seek in object stream (%d %d R)", num, gen); - goto cleanupstm; - } + fz_seek(stm, first + ofsbuf[i], 0); error = pdf_parsestmobj(&obj, xref, stm, buf, cap); if (error) @@ -854,14 +788,14 @@ pdf_loadobjstm(pdf_xref *xref, int num, int gen, char *buf, int cap) } } - fz_dropstream(stm); + fz_close(stm); fz_free(ofsbuf); fz_free(numbuf); fz_dropobj(objstm); return fz_okay; cleanupstm: - fz_dropstream(stm); + fz_close(stm); cleanupbuf: fz_free(ofsbuf); fz_free(numbuf); @@ -895,9 +829,7 @@ pdf_cacheobject(pdf_xref *xref, int num, int gen) } else if (x->type == 'n') { - error = fz_seek(xref->file, x->ofs, 0); - if (error) - return fz_rethrow(error, "cannot seek to object (%d %d R) offset %d", num, gen, x->ofs); + fz_seek(xref->file, x->ofs, 0); error = pdf_parseindobj(&x->obj, xref, xref->file, xref->scratch, sizeof xref->scratch, &rnum, &rgen, &x->stmofs); @@ -987,7 +919,7 @@ pdf_openxref(pdf_xref **xrefp, char *filename, char *password) error = pdf_openxrefwithstream(&xref, file, password); if (error) return fz_rethrow(error, "cannot load document '%s'", filename); - fz_dropstream(file); + fz_close(file); *xrefp = xref; return fz_okay; diff --git a/win32/mupdf/mupdf.vcproj b/win32/mupdf/mupdf.vcproj index c0d19e3e..ac0af2e9 100644 --- a/win32/mupdf/mupdf.vcproj +++ b/win32/mupdf/mupdf.vcproj @@ -381,10 +381,6 @@ >
</File>
<File
- RelativePath="..\..\fitz\filt_pipeline.c"
- >
- </File>
- <File
RelativePath="..\..\fitz\filt_predict.c"
>
</File>
@@ -437,10 +433,6 @@ >
</File>
<File
- RelativePath="..\..\fitz\stm_filter.c"
- >
- </File>
- <File
RelativePath="..\..\fitz\stm_open.c"
>
</File>
|