⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdf_stream.c

📁 SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多KB)
💻 C
字号:
#include "fitz.h"#include "mupdf.h"/* * Check if an object is a stream or not. */intpdf_isstream(pdf_xref *xref, int oid, int gen){	fz_error *error;	if (oid < 0 || oid >= xref->len)		return 0;	error = pdf_cacheobject(xref, oid, gen);	if (error)	{		fz_warn("%s", error->msg);		fz_droperror(error);		return 0;	}	return xref->table[oid].stmbuf || xref->table[oid].stmofs;}/* * 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;}/* * 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;}/* * 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;}/* * Construct a filter to decode a stream, without * constraining to stream length, and without decryption. */fz_error *pdf_buildinlinefilter(fz_filter **filterp, fz_obj *stmobj){	fz_error *error;	fz_obj *filters;	fz_obj *params;	filters = fz_dictgetsa(stmobj, "Filter", "F");	params = fz_dictgetsa(stmobj, "DecodeParms", "DP");	if (filters)	{		if (fz_isname(filters))			error = buildonefilter(filterp, filters, params);		else			error = buildfilterchain(filterp, nil, filters, params);	}	else		error = fz_newnullfilter(filterp, -1);	if (error)		return fz_rethrow(error, "cannot create inline filter chain");	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(&params, 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 */}/* * 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 %d R)", oid, gen);	x = xref->table + oid;	error = pdf_cacheobject(xref, oid, gen);	if (error)		return fz_rethrow(error, "cannot load stream object (%d %d R)", oid, gen);	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");}/* * Open a stream for reading uncompressed data.  * Put the opened file in xref->stream. * Using xref->file while a stream is open is a Bad idea. */fz_error *pdf_openstream(fz_stream **stmp, pdf_xref *xref, int oid, int gen){	pdf_xrefentry *x;	fz_error *error;	fz_stream *rawstm;	fz_filter *filter;	if (oid < 0 || oid >= xref->len)		return fz_throw("object id out of range (%d %d R)", oid, gen);	x = xref->table + oid;	error = pdf_cacheobject(xref, oid, gen);	if (error)		return fz_rethrow(error, "cannot load stream object (%d %d R)", oid, gen);	if (x->stmbuf)	{		error = pdf_buildfilter(&filter, xref, x->obj, oid, gen);		if (error)			return fz_rethrow(error, "cannot create filter");		error = fz_openrbuffer(&rawstm, x->stmbuf);		if (error)		{			fz_dropfilter(filter);			return fz_rethrow(error, "cannot open stream from buffer");		}		error = fz_openrfilter(stmp, filter, rawstm);		fz_dropfilter(filter);		fz_dropstream(rawstm);		if (error)			return fz_rethrow(error, "cannot open filter stream");		return fz_okay;	}	if (x->stmofs)	{		error = pdf_buildfilter(&filter, xref, x->obj, oid, gen);		if (error)			return fz_rethrow(error, "cannot create 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");}/* * Load raw (compressed but decrypted) contents of a stream into buf. */fz_error *pdf_loadrawstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen){	fz_error *error;	fz_stream *stm;	error = pdf_openrawstream(&stm, xref, oid, gen);	if (error)		return fz_rethrow(error, "cannot open raw stream (%d %d R)", oid, gen);	error = fz_readall(bufp, stm, 0);	fz_dropstream(stm);	if (error)		return fz_rethrow(error, "cannot load stream into buffer (%d %d R)", oid, gen);	return fz_okay;}/* * Load uncompressed contents of a stream into buf. */fz_error *pdf_loadstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen){	fz_error *error;	fz_stream *stm;	error = pdf_openstream(&stm, xref, oid, gen);	if (error)		return fz_rethrow(error, "cannot open stream (%d %d R)", oid, gen);	error = fz_readall(bufp, stm, 0);	fz_dropstream(stm);	if (error)		return fz_rethrow(error, "cannot load stream into buffer (%d %d R)", oid, gen);	return fz_okay;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -