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 /fitz | |
parent | 0b954421d7908c8b835d96b4a945418c2ae08de7 (diff) | |
download | mupdf-d797d4707564bd9c0e1536d1d6355945aa1be740.tar.xz |
Use chained reader like interface for filters instead of process interface.
Diffstat (limited to 'fitz')
-rw-r--r-- | fitz/filt_basic.c | 624 | ||||
-rw-r--r-- | fitz/filt_dctd.c | 328 | ||||
-rw-r--r-- | fitz/filt_faxd.c | 241 | ||||
-rw-r--r-- | fitz/filt_flate.c | 119 | ||||
-rw-r--r-- | fitz/filt_jbig2d.c | 142 | ||||
-rw-r--r-- | fitz/filt_jpxd.c | 193 | ||||
-rw-r--r-- | fitz/filt_lzwd.c | 207 | ||||
-rw-r--r-- | fitz/filt_pipeline.c | 131 | ||||
-rw-r--r-- | fitz/filt_predict.c | 236 | ||||
-rw-r--r-- | fitz/fitz.h | 208 | ||||
-rw-r--r-- | fitz/stm_buffer.c | 75 | ||||
-rw-r--r-- | fitz/stm_filter.c | 55 | ||||
-rw-r--r-- | fitz/stm_open.c | 128 | ||||
-rw-r--r-- | fitz/stm_read.c | 354 |
14 files changed, 1206 insertions, 1835 deletions
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"); } |