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

📄 pdf_function.c.svn-base

📁 SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多KB)
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
#include "fitz.h"#include "mupdf.h"/* this mess is seokgyo's doing */enum{	MAXN = FZ_MAXCOLORS,	MAXM = FZ_MAXCOLORS,	MAXK = 32};typedef struct psobj_s psobj;enum{	SAMPLE = 0,	EXPONENTIAL = 2,	STITCHING = 3,	POSTSCRIPT = 4};struct pdf_function_s{	int refs;	int type;				/* 0=sample 2=exponential 3=stitching 4=postscript */	int m;					/* number of input values */	int n;					/* number of output values */	float domain[MAXM][2];	/* even index : min value, odd index : max value */	float range[MAXN][2];	/* even index : min value, odd index : max value */	int hasrange;	union	{		struct {			unsigned short bps;			int size[MAXM];			float encode[MAXM][2];			float decode[MAXN][2];			int *samples;		} sa;		struct {			float n;			float c0[MAXN];			float c1[MAXN];		} e;		struct {			int k;			pdf_function *funcs[MAXK];			float bounds[MAXK-1];			float encode[MAXK][2];		} st;		struct {			psobj *code;			int cap;		} p;	} u;};/* * PostScript calculator */#define RADIAN 57.2957795#define LERP(x, xmin, xmax, ymin, ymax) \	(ymin) + ((x) - (xmin)) * ((ymax) - (ymin)) / ((xmax) - (xmin))enum { PSBOOL, PSINT, PSREAL, PSOPERATOR, PSBLOCK };enum{	PSOABS, PSOADD, PSOAND, PSOATAN, PSOBITSHIFT, PSOCEILING,	PSOCOPY, PSOCOS, PSOCVI, PSOCVR, PSODIV, PSODUP, PSOEQ,	PSOEXCH, PSOEXP, PSOFALSE, PSOFLOOR, PSOGE, PSOGT, PSOIDIV,	PSOINDEX, PSOLE, PSOLN, PSOLOG, PSOLT, PSOMOD, PSOMUL,	PSONE, PSONEG, PSONOT, PSOOR, PSOPOP, PSOROLL, PSOROUND,	PSOSIN, PSOSQRT, PSOSUB, PSOTRUE, PSOTRUNCATE, PSOXOR,	PSOIF, PSOIFELSE, PSORETURN};static char *psopnames[] ={	"abs", "add", "and", "atan", "bitshift", "ceiling", "copy",	"cos", "cvi", "cvr", "div", "dup", "eq", "exch", "exp",	"false", "floor", "ge", "gt", "idiv", "index", "le", "ln",	"log", "lt", "mod", "mul", "ne", "neg", "not", "or", "pop",	"roll", "round", "sin", "sqrt", "sub", "true", "truncate",	"xor", "if", "ifelse", "return"};struct psobj_s{	int type;	union	{		int b;				/* boolean (stack only) */		int i;				/* integer (stack and code) */		float f;			/* real (stack and code) */		int op;				/* operator (code only) */		int block;			/* if/ifelse block pointer (code only) */	} u;};enum { PSSTACKSIZE = 100 };#define fz_stackoverflow fz_throw("stack overflow in calculator function")#define fz_stackunderflow fz_throw("stack underflow in calculator function")#define fz_stacktypemismatch fz_throw("type mismatch in calculator function")typedef struct psstack_s psstack;struct psstack_s{	psobj stack[PSSTACKSIZE];	int sp;};static voidpsinitstack(psstack *st){	memset(st->stack, 0, sizeof(st->stack));	st->sp = PSSTACKSIZE;}static intpscheckoverflow(psstack *st, int n){	return st->sp >= n;}static intpscheckunderflow(psstack *st){	return st->sp != PSSTACKSIZE;}static intpschecktype(psstack *st, unsigned short type){	return st->stack[st->sp].type == type;}static fz_error *pspushbool(psstack *st, int booln){	if (!pscheckoverflow(st, 1))		return fz_stackoverflow;	st->stack[--st->sp].type = PSBOOL;	st->stack[st->sp].u.b = booln;	return fz_okay;}static fz_error *pspushint(psstack *st, int intg){	if (!pscheckoverflow(st, 1))		return fz_stackoverflow;	st->stack[--st->sp].type = PSINT;	st->stack[st->sp].u.i = intg;	return fz_okay;}static fz_error *pspushreal(psstack *st, float real){	if (!pscheckoverflow(st, 1))		return fz_stackoverflow;	st->stack[--st->sp].type = PSREAL;	st->stack[st->sp].u.f = real;	return fz_okay;}static fz_error *pspopbool(psstack *st, int *booln){	if (!pscheckunderflow(st))		return fz_stackunderflow;	if (!pschecktype(st, PSBOOL))		return fz_stacktypemismatch;	*booln = st->stack[st->sp++].u.b;	return fz_okay;}static fz_error *pspopint(psstack *st, int *intg){	if (!pscheckunderflow(st))		return fz_stackunderflow;	if (!pschecktype(st, PSINT))		return fz_stacktypemismatch;	*intg = st->stack[st->sp++].u.i;	return fz_okay;}static fz_error *pspopnum(psstack *st, float *real){	if (!pscheckunderflow(st))		return fz_stackunderflow;	if (!pschecktype(st, PSINT) && !pschecktype(st, PSREAL))		return fz_stacktypemismatch;	*real = (st->stack[st->sp].type == PSINT) ?		st->stack[st->sp].u.i : st->stack[st->sp].u.f;	++st->sp;	return fz_okay;}static intpstopisint(psstack *st){	return st->sp < PSSTACKSIZE && st->stack[st->sp].type == PSINT;}static intpstoptwoareints(psstack *st){	return st->sp < PSSTACKSIZE - 1 &&		st->stack[st->sp].type == PSINT &&		st->stack[st->sp + 1].type == PSINT;}static intpstopisreal(psstack *st){	return st->sp < PSSTACKSIZE && st->stack[st->sp].type == PSREAL;}static intpstoptwoarenums(psstack *st){	return st->sp < PSSTACKSIZE - 1 &&		(st->stack[st->sp].type == PSINT || st->stack[st->sp].type == PSREAL) &&		(st->stack[st->sp + 1].type == PSINT || st->stack[st->sp + 1].type == PSREAL);}static fz_error *pscopy(psstack *st, int n){	int i;	if (!pscheckoverflow(st, n))		return fz_stackoverflow;	for (i = 0; i < n; i++)	{		st->stack[st->sp - n + i] = st->stack[st->sp + i];	}	st->sp -= n;	return fz_okay;}static voidpsroll(psstack *st, int n, int j){	psobj obj;	int i, k;	if (j >= 0)	{		j %= n;	}	else	{		j = -j % n;		if (j != 0)		{			j = n - j;		}	}	if (n <= 0 || j == 0)	{		return;	}	for (i = 0; i < j; ++i)	{		/* FIXME check for underflow? */		obj = st->stack[st->sp];		for (k = st->sp; k < st->sp + n - 1; ++k)		{			st->stack[k] = st->stack[k + 1];		}		st->stack[st->sp + n - 1] = obj;	}}static fz_error *psindex(psstack *st, int i){	if (!pscheckoverflow(st, 1))		return fz_stackoverflow;	--st->sp;	st->stack[st->sp] = st->stack[st->sp + 1 + i];	return fz_okay;}static fz_error *pspop(psstack *st){	if (!pscheckoverflow(st, 1))		return fz_stackoverflow;	++st->sp;	return fz_okay;}static fz_error *resizecode(pdf_function *func, int newsize){	if (newsize >= func->u.p.cap)	{		int newcodecap = func->u.p.cap + 64;		psobj *newcode;		newcode = fz_realloc(func->u.p.code, newcodecap * sizeof(psobj));		if (!newcode)			return fz_throw("outofmem: calculator function code");		func->u.p.cap = newcodecap;		func->u.p.code = newcode;	}	return fz_okay;}static fz_error *parsecode(pdf_function *func, fz_stream *stream, int *codeptr){	fz_error *error;	char buf[64];	int len;	pdf_token_e tok;	int opptr, elseptr;	int a, b, mid, cmp;	memset(buf, 0, sizeof(buf));	while (1)	{		error = pdf_lex(&tok, stream, buf, sizeof buf, &len);		if (error)			return fz_rethrow(error, "calculator function lexical error");		switch(tok)		{		case PDF_TEOF:			return fz_throw("truncated calculator function");		case PDF_TINT:			error = resizecode(func, *codeptr);			if (error)				return fz_rethrow(error, "resize calculator function code");			func->u.p.code[*codeptr].type = PSINT;			func->u.p.code[*codeptr].u.i = atoi(buf);			++*codeptr;			break;		case PDF_TREAL:			error = resizecode(func, *codeptr);			if (error)				return fz_rethrow(error, "resize calculator function code");			func->u.p.code[*codeptr].type = PSREAL;			func->u.p.code[*codeptr].u.f = atof(buf);			++*codeptr;			break;		case PDF_TOBRACE:			opptr = *codeptr;			*codeptr += 3;			error = resizecode(func, opptr + 2);			if (error)				return fz_rethrow(error, "resize calculator function code");			error = parsecode(func, stream, codeptr);			if (error)				return fz_rethrow(error, "error in 'if' branch");			error = pdf_lex(&tok, stream, buf, sizeof buf, &len);			if (error)				return fz_rethrow(error, "calculator function syntax error");			if (tok == PDF_TOBRACE)			{				elseptr = *codeptr;				error = parsecode(func, stream, codeptr);				if (error)					return fz_rethrow(error, "error in 'else' branch");				error = pdf_lex(&tok, stream, buf, sizeof buf, &len);				if (error)					return fz_rethrow(error, "calculator function syntax error");			}			else 			{				elseptr = -1;			}			if (tok == PDF_TKEYWORD)			{				if (!strcmp(buf, "if"))				{					if (elseptr >= 0)						return fz_throw("too many branches for 'if'");					func->u.p.code[opptr].type = PSOPERATOR;					func->u.p.code[opptr].u.op = PSOIF;					func->u.p.code[opptr+2].type = PSBLOCK;					func->u.p.code[opptr+2].u.block = *codeptr;				}				else if (!strcmp(buf, "ifelse"))				{					if (elseptr < 0)						return fz_throw("not enough branches for 'ifelse'");					func->u.p.code[opptr].type = PSOPERATOR;					func->u.p.code[opptr].u.op = PSOIFELSE;					func->u.p.code[opptr+1].type = PSBLOCK;					func->u.p.code[opptr+1].u.block = elseptr;					func->u.p.code[opptr+2].type = PSBLOCK;					func->u.p.code[opptr+2].u.block = *codeptr;				}				else				{					return fz_throw("unknown keyword in 'if-else' context: '%s'", buf);				}			}			else			{				return fz_throw("missing keyword in 'if-else' context");			}			break;		case PDF_TCBRACE:			error = resizecode(func, *codeptr);			if (error)				return fz_rethrow(error, "resize calculator function code");			func->u.p.code[*codeptr].type = PSOPERATOR;			func->u.p.code[*codeptr].u.op = PSORETURN;			++*codeptr;			return fz_okay;		case PDF_TKEYWORD:			cmp = -1;			a = -1;			b = sizeof(psopnames) / sizeof(psopnames[0]);			while (b - a > 1)			{				mid = (a + b) / 2;				cmp = strcmp(buf, psopnames[mid]);				if (cmp > 0)					a = mid;				else if (cmp < 0)					b = mid;				else					a = b = mid;			}			if (cmp != 0)				return fz_throw("unknown operator: '%s'", buf);			error = resizecode(func, *codeptr);			if (error)				return fz_rethrow(error, "resize calculator function code");			func->u.p.code[*codeptr].type = PSOPERATOR;			func->u.p.code[*codeptr].u.op = a;			++*codeptr;			break;		default:			return fz_throw("calculator function syntax error");		}	}}static fz_error *loadpostscriptfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gen){	fz_error *error;	fz_stream *stream;	int codeptr;	pdf_logrsrc("load postscript function (%d %d R)\n", oid, gen);	error = pdf_openstream(&stream, xref, oid, gen);	if (error)		return fz_rethrow(error, "cannot open calculator function stream");	if (fz_readbyte(stream) != '{')	{		fz_dropstream(stream);		return fz_throw("stream is not a calculator function");	}	func->u.p.code = nil;	func->u.p.cap = 0;	codeptr = 0;	error = parsecode(func, stream, &codeptr);	if (error)	{		fz_dropstream(stream);		return fz_rethrow(error, "cannot parse calculator function");	}	fz_dropstream(stream);	return fz_okay;}#define SAFE_RETHROW            if (error) fz_rethrow(error, "runtime error in calculator function")#define SAFE_PUSHINT(st, a)	{ error = pspushint(st, a); SAFE_RETHROW; }#define SAFE_PUSHREAL(st, a)	{ error = pspushreal(st, a); SAFE_RETHROW; }#define SAFE_PUSHBOOL(st, a)	{ error = pspushbool(st, a); SAFE_RETHROW; }#define SAFE_POPINT(st, a)	{ error = pspopint(st, a); SAFE_RETHROW; }#define SAFE_POPNUM(st, a)	{ error = pspopnum(st, a); SAFE_RETHROW; }#define SAFE_POPBOOL(st, a)	{ error = pspopbool(st, a); SAFE_RETHROW; }#define SAFE_POP(st)		{ error = pspop(st); SAFE_RETHROW; }#define SAFE_INDEX(st, i)	{ error = psindex(st, i); SAFE_RETHROW; }#define SAFE_COPY(st, n)	{ error = pscopy(st, n); SAFE_RETHROW; }static fz_error *evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr){	fz_error *error;	int i1, i2;	float r1, r2;	int b1, b2;	while (1)	{		switch (func->u.p.code[codeptr].type)		{		case PSINT:			SAFE_PUSHINT(st, func->u.p.code[codeptr++].u.i);			break;		case PSREAL:			SAFE_PUSHREAL(st, func->u.p.code[codeptr++].u.f);			break;		case PSOPERATOR:			switch (func->u.p.code[codeptr++].u.op)			{			case PSOABS:				if (pstopisint(st)) {					SAFE_POPINT(st, &i1);

⌨️ 快捷键说明

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