void fz_droppipeline(fz_filter *filter) { fz_pipeline *p = (fz_pipeline*)filter; fz_dropfilter(p->head); fz_dropfilter(p->tail); fz_dropbuffer(p->buffer); }
/* * Open a stream for reading the raw (compressed but decrypted) data. * Using xref->file while this is open is a bad idea. */ fz_error * pdf_openrawstream(fz_stream **stmp, pdf_xref *xref, int oid, int gen) { pdf_xrefentry *x; fz_error *error; fz_filter *filter; if (oid < 0 || oid >= xref->len) return fz_throw("object id out of range (%d)", oid); x = xref->table + oid; error = pdf_cacheobject(xref, oid, gen); if (error) return fz_rethrow(error, "cannot load stream object (%d)", oid); if (x->stmbuf) { error = fz_openrbuffer(stmp, x->stmbuf); if (error) return fz_rethrow(error, "cannot open stream from buffer"); return fz_okay; } if (x->stmofs) { error = buildrawfilter(&filter, xref, x->obj, oid, gen); if (error) return fz_rethrow(error, "cannot create raw filter"); error = fz_seek(xref->file, x->stmofs, 0); if (error) { fz_dropfilter(filter); return fz_rethrow(error, "cannot seek to stream"); } error = fz_openrfilter(stmp, filter, xref->file); fz_dropfilter(filter); if (error) return fz_rethrow(error, "cannot open filter stream"); return fz_okay; } return fz_throw("object is not a stream"); }
void fz_dropstream(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); fz_free(stm); } }
/* * Build a filter for reading raw stream data. * This is a null filter to constrain reading to the * stream length, followed by a decryption filter. */ static fz_error * buildrawfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, int gen) { fz_error *error; fz_filter *base; fz_obj *stmlen; int len; stmlen = fz_dictgets(stmobj, "Length"); error = pdf_resolve(&stmlen, xref); if (error) return fz_rethrow(error, "cannot resolve stream /Length"); len = fz_toint(stmlen); fz_dropobj(stmlen); error = fz_newnullfilter(&base, len); if (error) return fz_rethrow(error, "cannot create null filter"); if (xref->crypt) { fz_filter *crypt; fz_filter *pipe; error = pdf_cryptstream(&crypt, xref->crypt, oid, gen); if (error) { fz_dropfilter(base); return fz_rethrow(error, "cannot create decryption filter"); } error = fz_newpipeline(&pipe, base, crypt); fz_dropfilter(base); fz_dropfilter(crypt); if (error) return fz_rethrow(error, "cannot create pipeline filter"); *filterp = pipe; } else { *filterp = base; } return fz_okay; }
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); }
/* * Build a chain of filters given filter names and param dicts. * If head is given, start filter chain with it. * Assume ownership of head. */ static fz_error * buildfilterchain(fz_filter **filterp, fz_filter *head, fz_obj *fs, fz_obj *ps) { fz_error *error; fz_filter *newhead; fz_filter *tail; fz_obj *f; fz_obj *p; int i; for (i = 0; i < fz_arraylen(fs); i++) { f = fz_arrayget(fs, i); if (fz_isarray(ps)) p = fz_arrayget(ps, i); else p = nil; error = buildonefilter(&tail, f, p); if (error) return fz_rethrow(error, "cannot create filter"); if (head) { error = fz_newpipeline(&newhead, head, tail); fz_dropfilter(head); fz_dropfilter(tail); if (error) { fz_dropfilter(newhead); return fz_rethrow(error, "cannot create pipeline filter"); } head = newhead; } else head = tail; } *filterp = head; return fz_okay; }
void fz_dropstream(fz_stream *stm) { stm->refs --; if (stm->refs == 0) { if (stm->error) { fflush(stdout); fz_printerror(stm->error); fz_droperror(stm->error); fflush(stderr); fz_warn("dropped unhandled ioerror"); } if (stm->mode == FZ_SWRITE) { stm->buffer->eof = 1; fz_flush(stm); } 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); fz_free(stm); } }
/* * Create a filter given a name and param dictionary. */ static fz_error * buildonefilter(fz_filter **fp, fz_obj *f, fz_obj *p) { fz_filter *decompress; fz_filter *predict; fz_error *error; char *s; s = fz_toname(f); if (!strcmp(s, "ASCIIHexDecode") || !strcmp(s, "AHx")) error = fz_newahxd(fp, p); else if (!strcmp(s, "ASCII85Decode") || !strcmp(s, "A85")) error = fz_newa85d(fp, p); else if (!strcmp(s, "CCITTFaxDecode") || !strcmp(s, "CCF")) error = fz_newfaxd(fp, p); else if (!strcmp(s, "DCTDecode") || !strcmp(s, "DCT")) error = fz_newdctd(fp, p); else if (!strcmp(s, "RunLengthDecode") || !strcmp(s, "RL")) error = fz_newrld(fp, p); else if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl")) { if (fz_isdict(p)) { fz_obj *obj = fz_dictgets(p, "Predictor"); if (obj) { error = fz_newflated(&decompress, p); if (error) return fz_rethrow(error, "cannot create deflate filter"); error = fz_newpredictd(&predict, p); if (error) { fz_dropfilter(decompress); return fz_rethrow(error, "cannot create predictor filter"); } error = fz_newpipeline(fp, decompress, predict); fz_dropfilter(decompress); fz_dropfilter(predict); if (error) return fz_rethrow(error, "cannot create pipeline filter"); return fz_okay; } } error = fz_newflated(fp, p); } else if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW")) { if (fz_isdict(p)) { fz_obj *obj = fz_dictgets(p, "Predictor"); if (obj) { error = fz_newlzwd(&decompress, p); if (error) return fz_rethrow(error, "cannot create lzwd filter"); error = fz_newpredictd(&predict, p); if (error) { fz_dropfilter(decompress); return fz_rethrow(error, "cannot create predictor filter"); } error = fz_newpipeline(fp, decompress, predict); fz_dropfilter(decompress); fz_dropfilter(predict); if (error) return fz_rethrow(error, "cannot create pipeline filter"); return fz_okay; } } error = fz_newlzwd(fp, p); } #ifdef HAVE_JBIG2DEC else if (!strcmp(s, "JBIG2Decode")) { /* TODO: extract and feed JBIG2Global */ error = fz_newjbig2d(fp, p); } #endif #ifdef HAVE_JASPER else if (!strcmp(s, "JPXDecode")) error = fz_newjpxd(fp, p); #endif else { return fz_throw("unknown filter name (%s)", s); } if (error) return fz_rethrow(error, "cannot create filter"); return fz_okay; }
/* * Construct a filter to decode a stream, constraining * to stream length and decrypting. */ static fz_error * pdf_buildfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, int gen) { fz_error *error; fz_filter *base, *pipe, *tmp; fz_obj *filters; fz_obj *params; error = buildrawfilter(&base, xref, stmobj, oid, gen); if (error) return fz_rethrow(error, "cannot create raw filter chain"); filters = fz_dictgetsa(stmobj, "Filter", "F"); params = fz_dictgetsa(stmobj, "DecodeParms", "DP"); if (filters) { error = pdf_resolve(&filters, xref); if (error) { error = fz_rethrow(error, "cannot resolve stream /Filter"); goto cleanup0; } if (params) { error = pdf_resolve(¶ms, xref); if (error) { error = fz_rethrow(error, "cannot resolve stream /DecodeParms"); goto cleanup1; } } if (fz_isname(filters)) { error = buildonefilter(&tmp, filters, params); if (error) { error = fz_rethrow(error, "cannot create filter"); goto cleanup2; } error = fz_newpipeline(&pipe, base, tmp); fz_dropfilter(base); fz_dropfilter(tmp); if (error) { error = fz_rethrow(error, "cannot create filter pipeline"); goto cleanup2; } } else { error = buildfilterchain(&pipe, base, filters, params); if (error) { error = fz_rethrow(error, "cannot create filter chain"); goto cleanup2; } } if (params) fz_dropobj(params); fz_dropobj(filters); *filterp = pipe; } else { *filterp = base; } return fz_okay; cleanup2: if (params) fz_dropobj(params); cleanup1: fz_dropobj(filters); cleanup0: fz_dropfilter(base); return error; /* already rethrown */ }
static fz_error * writestream(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen) { fz_error *error; fz_stream *dststm; fz_stream *srcstm; unsigned char buf[4096]; fz_filter *ef; int n; fz_print(out, "stream\n"); if (encrypt) { error = pdf_cryptstream(&ef, encrypt, oid, gen); if (error) return error; error = fz_openrfilter(&dststm, ef, out); fz_dropfilter(ef); if (error) return error; } else { dststm = fz_keepstream(out); } error = pdf_openrawstream(&srcstm, xref, oid, gen); if (error) goto cleanupdst; while (1) { n = fz_read(srcstm, buf, sizeof buf); if (n == 0) break; if (n < 0) { error = fz_ioerror(srcstm); goto cleanupsrc; } n = fz_write(dststm, buf, n); if (n < 0) { error = fz_ioerror(dststm); goto cleanupsrc; } } fz_dropstream(srcstm); fz_dropstream(dststm); fz_print(out, "endstream\n"); return nil; cleanupsrc: fz_dropstream(srcstm); cleanupdst: fz_dropstream(dststm); return error; }
fz_error * pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file) { fz_error *error; pdf_image *img; fz_filter *filter; fz_obj *f; fz_obj *cs; fz_obj *d; int ismask; int i; img = fz_malloc(sizeof(pdf_image)); if (!img) return fz_outofmem; pdf_logimage("load inline image %p {\n", img); img->super.loadtile = pdf_loadtile; img->super.drop = pdf_dropimage; img->super.n = 0; img->super.a = 0; img->super.refs = 0; img->indexed = nil; img->usecolorkey = 0; img->mask = nil; img->super.w = fz_toint(fz_dictgetsa(dict, "Width", "W")); img->super.h = fz_toint(fz_dictgetsa(dict, "Height", "H")); img->bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC")); ismask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM")); d = fz_dictgetsa(dict, "Decode", "D"); cs = fz_dictgetsa(dict, "ColorSpace", "CS"); pdf_logimage("size %dx%d %d\n", img->super.w, img->super.h, img->bpc); if (ismask) { pdf_logimage("is mask\n"); img->super.cs = nil; img->super.n = 0; img->super.a = 1; img->bpc = 1; } if (cs) { img->super.cs = nil; if (fz_isname(cs)) { fz_obj *csd = fz_dictgets(rdb, "ColorSpace"); if (csd) { fz_obj *cso = fz_dictget(csd, cs); img->super.cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, cso); if (img->super.cs) fz_keepcolorspace(img->super.cs); } } if (!img->super.cs) { /* XXX danger! danger! does this resolve? */ error = pdf_loadcolorspace(&img->super.cs, xref, cs); if (error) return error; } if (!strcmp(img->super.cs->name, "Indexed")) { pdf_logimage("indexed\n"); img->indexed = (pdf_indexed*)img->super.cs; img->super.cs = img->indexed->base; } pdf_logimage("colorspace %s\n", img->super.cs->name); img->super.n = img->super.cs->n; img->super.a = 0; } if (fz_isarray(d)) { pdf_logimage("decode array\n"); if (img->indexed) for (i = 0; i < 2; i++) img->decode[i] = fz_toreal(fz_arrayget(d, i)); else for (i = 0; i < (img->super.n + img->super.a) * 2; i++) img->decode[i] = fz_toreal(fz_arrayget(d, i)); } else { if (img->indexed) for (i = 0; i < 2; i++) img->decode[i] = i & 1 ? (1 << img->bpc) - 1 : 0; else for (i = 0; i < (img->super.n + img->super.a) * 2; i++) img->decode[i] = i & 1; } if (img->indexed) img->stride = (img->super.w * img->bpc + 7) / 8; else img->stride = (img->super.w * (img->super.n + img->super.a) * img->bpc + 7) / 8; /* load image data */ f = fz_dictgetsa(dict, "Filter", "F"); if (f) { fz_stream *tempfile; error = pdf_buildinlinefilter(&filter, dict); if (error) return error; error = fz_openrfilter(&tempfile, filter, file); if (error) return error; i = fz_readall(&img->samples, tempfile); if (i < 0) return fz_ioerror(tempfile); fz_dropfilter(filter); fz_dropstream(tempfile); } else { error = fz_newbuffer(&img->samples, img->super.h * img->stride); if (error) return error; i = fz_read(file, img->samples->bp, img->super.h * img->stride); if (i < 0) return fz_ioerror(file); img->samples->wp += img->super.h * img->stride; } /* 0 means opaque and 1 means transparent, so we invert to get alpha */ if (ismask) { unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = ~*p; } pdf_logimage("}\n"); *imgp = img; return nil; }