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

📄 pdf_interpret.c

📁 SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多KB)
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "fitz.h"#include "mupdf.h"fz_error *pdf_newcsi(pdf_csi **csip, int maskonly){	fz_error *error;	pdf_csi *csi;	fz_node *node;	csi = fz_malloc(sizeof(pdf_csi));	if (!csi)		return fz_throw("outofmem: interpreter struct");	pdf_initgstate(&csi->gstate[0]);	csi->gtop = 0;	csi->top = 0;	csi->array = nil;	csi->xbalance = 0;	error = fz_newpathnode(&csi->path);	if (error) {		fz_free(csi);		return fz_rethrow(error, "cannot create path node");	}	error = fz_newtree(&csi->tree);	if (error) {		fz_dropnode((fz_node*)csi->path);		fz_free(csi);		return fz_rethrow(error, "cannot create tree");	}	error = fz_newovernode(&node);	csi->tree->root = node;	csi->gstate[0].head = node;	if (maskonly)	{		csi->gstate[0].fill.kind = PDF_MNONE;		csi->gstate[0].stroke.kind = PDF_MNONE;	}	csi->clip = 0;	csi->clipevenodd = 0;	csi->textclip = nil;	csi->textmode = 0;	csi->text = nil;	csi->tm = fz_identity();	csi->tlm = fz_identity();	*csip = csi;	return fz_okay;}static voidclearstack(pdf_csi *csi){	int i;	for (i = 0; i < csi->top; i++)		fz_dropobj(csi->stack[i]);	csi->top = 0;}static pdf_material *pdf_keepmaterial(pdf_material *mat){	if (mat->cs)		fz_keepcolorspace(mat->cs);	if (mat->indexed)		fz_keepcolorspace(&mat->indexed->super);	if (mat->pattern)		pdf_keeppattern(mat->pattern);	if (mat->shade)		fz_keepshade(mat->shade);	return mat;}static pdf_material *pdf_dropmaterial(pdf_material *mat){	if (mat->cs)		fz_dropcolorspace(mat->cs);	if (mat->indexed)		fz_dropcolorspace(&mat->indexed->super);	if (mat->pattern)		pdf_droppattern(mat->pattern);	if (mat->shade)		fz_dropshade(mat->shade);	return mat;}static fz_error *gsave(pdf_csi *csi){	pdf_gstate *gs = csi->gstate + csi->gtop;	if (csi->gtop == 31)		return fz_throw("gstate overflow in content stream");	memcpy(&csi->gstate[csi->gtop + 1], &csi->gstate[csi->gtop], sizeof(pdf_gstate));	csi->gtop ++;	pdf_keepmaterial(&gs->stroke);	pdf_keepmaterial(&gs->fill);	return fz_okay;}static fz_error *grestore(pdf_csi *csi){	pdf_gstate *gs = csi->gstate + csi->gtop;	if (csi->gtop == 0)		return fz_throw("gstate underflow in content stream");	pdf_dropmaterial(&gs->stroke);	pdf_dropmaterial(&gs->fill);	csi->gtop --;	return fz_okay;}voidpdf_dropcsi(pdf_csi *csi){	while (csi->gtop)		grestore(csi); /* no need to check for impossible errors */	if (csi->gstate[csi->gtop].fill.cs)		fz_dropcolorspace(csi->gstate[csi->gtop].fill.cs);	if (csi->gstate[csi->gtop].stroke.cs)		fz_dropcolorspace(csi->gstate[csi->gtop].stroke.cs);	if (csi->path) fz_dropnode((fz_node*)csi->path);	if (csi->textclip) fz_dropnode((fz_node*)csi->textclip);	if (csi->text) fz_dropnode((fz_node*)csi->text);	if (csi->array) fz_dropobj(csi->array);	clearstack(csi);	fz_free(csi);}/* * Do some magic to call the xobject subroutine. * Push gstate, set transform, clip, run, pop gstate. */static fz_error *runxobject(pdf_csi *csi, pdf_xref *xref, pdf_xobject *xobj, int istransparency){	fz_error *error;	fz_node *transform;	fz_node *blend;	fz_stream *file;	pdf_gstate *gstate;	/* gsave */	error = gsave(csi);	if (error)		return fz_rethrow(error, "cannot push graphics state");	gstate = csi->gstate + csi->gtop;	/* reset alpha to 1.0 when starting a new Transparency group */	if (istransparency) {	    gstate->stroke.alpha = 1.0;	    gstate->fill.alpha = 1.0;	}	/* push transform */	error = fz_newtransformnode(&transform, xobj->matrix);	if (error)		return fz_rethrow(error, "cannot create transform node");	error = pdf_addtransform(gstate, transform);	if (error)	{		fz_dropnode(transform);		return fz_rethrow(error, "cannot add transform node");	}	if (xobj->isolated || xobj->knockout)	{	    error = fz_newblendnode(&blend, FZ_BNORMAL, xobj->isolated, xobj->knockout);	    if (error)		return fz_rethrow(error, "cannot create blend node");	    fz_insertnodelast(gstate->head, blend);	    gstate->head = blend;	}	/* run contents */	xobj->contents->rp = xobj->contents->bp;	error = fz_openrbuffer(&file, xobj->contents);	if (error)		return fz_rethrow(error, "cannot open XObject stream");	error = pdf_runcsi(csi, xref, xobj->resources, file);	fz_dropstream(file);	if (error)		return fz_rethrow(error, "cannot interpret XObject stream");	/* grestore */	error = grestore(csi);	if (error)		return fz_rethrow(error, "cannot pop graphics state");	return fz_okay;}/* * Decode inline image and insert into page. */static fz_error *runinlineimage(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, fz_obj *dict){	fz_error *error;	pdf_image *img;	char buf[256];	pdf_token_e tok;	int len;	error = pdf_loadinlineimage(&img, xref, rdb, dict, file);	if (error)		return fz_rethrow(error, "cannot load inline image");	error = pdf_lex(&tok, file, buf, sizeof buf, &len);	if (error)	{		fz_dropimage((fz_image*)img);		return fz_rethrow(error, "syntax error after inline image");	}	if (tok != PDF_TKEYWORD || strcmp("EI", buf))	{		fz_dropimage((fz_image*)img);		return fz_throw("syntax error after inline image");	}	error = pdf_showimage(csi, img);	if (error)	{		fz_dropimage((fz_image*)img);		return fz_rethrow(error, "cannot draw image");	}	fz_dropimage((fz_image*)img);	return fz_okay;}/* * Set gstate params from an ExtGState dictionary. */static fz_error *runextgstate(pdf_gstate *gstate, pdf_xref *xref, fz_obj *extgstate){	int i, k;	for (i = 0; i < fz_dictlen(extgstate); i++)	{		fz_obj *key = fz_dictgetkey(extgstate, i);		fz_obj *val = fz_dictgetval(extgstate, i);		char *s = fz_toname(key);		if (!strcmp(s, "Font"))		{			if (fz_isarray(val) && fz_arraylen(val) == 2)			{				gstate->font = pdf_finditem(xref->store, PDF_KFONT, fz_arrayget(val, 0));				if (!gstate->font)					return fz_throw("cannot find font in store");				gstate->size = fz_toreal(fz_arrayget(val, 1));			}			else				return fz_throw("malformed /Font");		}		else if (!strcmp(s, "LW"))			gstate->linewidth = fz_toreal(val);		else if (!strcmp(s, "LC"))			gstate->linecap = fz_toint(val);		else if (!strcmp(s, "LJ"))			gstate->linejoin = fz_toint(val);		else if (!strcmp(s, "ML"))			gstate->miterlimit = fz_toreal(val);		else if (!strcmp(s, "D"))		{			if (fz_isarray(val) && fz_arraylen(val) == 2)			{				fz_obj *dashes = fz_arrayget(val, 0);				gstate->dashlen = MAX(fz_arraylen(dashes), 32);				for (k = 0; k < gstate->dashlen; k++)					gstate->dashlist[k] = fz_toreal(fz_arrayget(dashes, k));				gstate->dashphase = fz_toreal(fz_arrayget(val, 1));			}			else				return fz_throw("malformed /D");		}		else if (!strcmp(s, "CA"))			gstate->stroke.alpha = fz_toreal(val);		else if (!strcmp(s, "ca"))			gstate->fill.alpha = fz_toreal(val);		else if (!strcmp(s, "BM"))		{			fz_error *error;			fz_node *blend;			static const struct { const char *name; fz_blendkind mode; } bm[] = {				{ "Normal", FZ_BNORMAL },				{ "Multiply", FZ_BMULTIPLY },				{ "Screen", FZ_BSCREEN },				{ "Overlay", FZ_BOVERLAY },				{ "Darken", FZ_BDARKEN },				{ "Lighten", FZ_BLIGHTEN },				{ "Colordodge", FZ_BCOLORDODGE },				{ "Hardlight", FZ_BHARDLIGHT },				{ "Softlight", FZ_BSOFTLIGHT },				{ "Difference", FZ_BDIFFERENCE },				{ "Exclusion", FZ_BEXCLUSION },				{ "Hue", FZ_BHUE },				{ "Saturation", FZ_BSATURATION },				{ "Color", FZ_BCOLOR },				{ "Luminosity", FZ_BLUMINOSITY }			};			char *n = fz_toname(val);			gstate->blendmode = FZ_BNORMAL;			for (k = 0; k < nelem(bm); k++) {				if (!strcmp(bm[k].name, n)) {					gstate->blendmode = bm[k].mode;					/* printf("blend mode %s:%d\n", n, gstate->blendmode); */					break;				}			}			if (gstate->blendmode == FZ_BNORMAL)			    error = fz_newovernode(&blend);			else			    error = fz_newblendnode(&blend, gstate->blendmode, 0, 0);			if (error)				return fz_rethrow(error, "cannot create blend node");			fz_insertnodelast(gstate->head, blend);			gstate->head = blend;		}		else if (!strcmp(s, "SMask"))		{			fz_error *error = pdf_resolve(&val, xref);			if (error)				return error;			if (fz_isdict(val))			{			    fz_obj *g = fz_dictgets(val, "G");			    error = pdf_resolve(&g, xref);			    if (error)				return error;			    /* TODO: we should do something here, like inserting a mask node for the S key in val */			    /* TODO: how to deal with the non-recursive nature of pdf soft masks? */			    /*puts("we encountered a soft mask");*/			}			fz_dropobj(val);		}	}	return fz_okay;}/* * The meat of the interpreter... */static fz_error *runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf){	pdf_gstate *gstate = csi->gstate + csi->gtop;	fz_error *error;	float a, b, c, d, e, f;	float x, y, w, h;	fz_matrix m;	float v[FZ_MAXCOLORS];	int what;	int i;	if (strlen(buf) > 1)	{		if (!strcmp(buf, "BX"))		{			if (csi->top != 0)				goto syntaxerror;			csi->xbalance ++;		}		else if (!strcmp(buf, "EX"))		{			if (csi->top != 0)				goto syntaxerror;			csi->xbalance --;		}		else if (!strcmp(buf, "MP"))		{			if (csi->top != 1)				goto syntaxerror;		}		else if (!strcmp(buf, "DP"))		{			if (csi->top != 2)				goto syntaxerror;		}		else if (!strcmp(buf, "BMC"))		{			if (csi->top != 1)				goto syntaxerror;		}		else if (!strcmp(buf, "BDC"))		{			if (csi->top != 2)				goto syntaxerror;		}		else if (!strcmp(buf, "EMC"))		{			if (csi->top != 0)				goto syntaxerror;		}		else if (!strcmp(buf, "cm"))		{			fz_matrix m;			fz_node *transform;			if (csi->top != 6)				goto syntaxerror;			m.a = fz_toreal(csi->stack[0]);			m.b = fz_toreal(csi->stack[1]);			m.c = fz_toreal(csi->stack[2]);			m.d = fz_toreal(csi->stack[3]);			m.e = fz_toreal(csi->stack[4]);			m.f = fz_toreal(csi->stack[5]);			error = fz_newtransformnode(&transform, m);			if (error)				return fz_rethrow(error, "cannot concatenate matrix");

⌨️ 快捷键说明

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