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

📄 pdf_function.c

📁 SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多KB)
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* encode input coordinates */	for (i = 0; i < func->m; i++)	{		x = CLAMP(in[i], func->domain[i][0], func->domain[i][1]);		x = LERP(x, func->domain[i][0], func->domain[i][1],				func->u.sa.encode[i][0], func->u.sa.encode[i][1]);		x = CLAMP(x, 0, func->u.sa.size[i] - 1);		e[0][i] = floor(x);		e[1][i] = ceil(x);		efrac[i] = x - floor(x);	}	if (func->m > 4)	{		s0 = fz_malloc((1 << func->m) * 2 * sizeof(float));		s1 = s0 + (1 << func->m);		if (!s0)			return fz_throw("outofmem: scratch buffer");	}	/* FIXME i think this is wrong... test with 2 samples it gets wrong idxs */	for (i = 0; i < func->n; i++)	{		/* pull 2^m values out of the sample array */		for (j = 0; j < (1 << func->m); ++j)		{			idx = 0;			for (k = func->m - 1; k >= 0; --k)				idx = idx * func->u.sa.size[k] + e[(j >> k) & 1][k];			idx = idx * func->n + i;			s0[j] = func->u.sa.samples[idx];		}		/* do m sets of interpolations */		for (j = 0; j < func->m; ++j)		{			for (k = 0; k < (1 << (func->m - j)); k += 2)				s1[k >> 1] = (1 - efrac[j]) * s0[k] + efrac[j] * s0[k+1];			memcpy(s0, s1, (1 << (func->m - j - 1)) * sizeof(float));		}		/* decode output values */		out[i] = LERP(s0[0], 0, (1 << func->u.sa.bps) - 1,				func->u.sa.decode[i][0], func->u.sa.decode[i][1]);		out[i] = CLAMP(out[i], func->range[i][0], func->range[i][1]);	}	if (func->m > 4)		fz_free(s0);	return fz_okay;}/* * Exponential function */static fz_error *loadexponentialfunc(pdf_function *func, fz_obj *dict){	fz_obj *obj;	int i;	pdf_logrsrc("exponential function {\n");	if (func->m != 1)		return fz_throw("/Domain must be one dimension (%d)", func->m);	obj = fz_dictgets(dict, "N");	if (!fz_isint(obj) && !fz_isreal(obj))		return fz_throw("malformed /N");	func->u.e.n = fz_toreal(obj);	pdf_logrsrc("n %g\n", func->u.e.n);	obj = fz_dictgets(dict, "C0");	if (fz_isarray(obj))	{		func->n = fz_arraylen(obj);		for (i = 0; i < func->n; ++i)			func->u.e.c0[i] = fz_toreal(fz_arrayget(obj, i));		pdf_logrsrc("c0 %d\n", func->n);	}	else	{		func->n = 1;		func->u.e.c0[0] = 0;	}	obj = fz_dictgets(dict, "C1");	if (fz_isarray(obj))	{		if (fz_arraylen(obj) != func->n)			return fz_throw("/C1 must match /C0 length");		for (i = 0; i < func->n; ++i)			func->u.e.c1[i] = fz_toreal(fz_arrayget(obj, i));		pdf_logrsrc("c1 %d\n", func->n);	}	else	{		if (func->n != 1)			return fz_throw("/C1 must match /C0 length");		func->u.e.c1[0] = 1;	}	pdf_logrsrc("}\n");	return fz_okay;}static fz_error *evalexponentialfunc(pdf_function *func, float in, float *out){	float x = in;	float tmp;	int i;	x = CLAMP(x, func->domain[0][0], func->domain[0][1]);	/* constraint */	if (func->u.e.n != (int)func->u.e.n && x < 0)		return fz_throw("constraint error");	if (func->u.e.n < 0 && x == 0)		return fz_throw("constraint error");	tmp = pow(x, func->u.e.n);	for (i = 0; i < func->n; ++i)	{		out[i] = func->u.e.c0[i] + tmp * (func->u.e.c1[i] - func->u.e.c0[i]);		if (func->hasrange)			out[i] = CLAMP(out[i], func->range[i][0], func->range[i][1]);	}	return fz_okay;}/* * Stitching function */static fz_error *loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict){	pdf_function **funcs = func->u.st.funcs;	fz_error *error;	fz_obj *obj;	fz_obj *sub;	fz_obj *num;	int k;	int i;	pdf_logrsrc("stitching {\n");	func->u.st.k = 0;	if (func->m != 1)		return fz_throw("/Domain must be one dimension (%d)", func->m);	obj = fz_dictgets(dict, "Functions");	{		error = pdf_resolve(&obj, xref);		if (error)			return fz_rethrow(error, "cannot resolve /Functions");		k = fz_arraylen(obj);		func->u.st.k = k;		pdf_logrsrc("k %d\n", func->u.st.k);		if (k >= MAXK)		{			fz_dropobj(obj);			return fz_throw("assert: /K too big (%d)", k);		}		for (i = 0; i < k; ++i)		{			sub = fz_arrayget(obj, i);			error = pdf_loadfunction(funcs + i, xref, sub);			if (error)			{				fz_dropobj(obj);				return fz_rethrow(error, "cannot load sub function %d", i);			}			if (funcs[i]->m != 1 || funcs[i]->n != funcs[0]->n)			{				fz_dropobj(obj);				return fz_rethrow(error, "sub function %d /Domain or /Range mismatch", i);			}		}		if (!func->n)		{			func->n = funcs[0]->n;		}		else if (func->n != funcs[0]->n)		{			fz_dropobj(obj);			return fz_rethrow(error, "sub function /Domain or /Range mismatch");		}		fz_dropobj(obj);	}	obj = fz_dictgets(dict, "Bounds");	{		error = pdf_resolve(&obj, xref);		if (error)			return fz_rethrow(error, "cannot resolve /Bounds");		if (!fz_isarray(obj) || fz_arraylen(obj) != k - 1)		{			fz_dropobj(obj);			return fz_throw("malformed /Bounds (not array or wrong length)");		}		for (i = 0; i < k-1; ++i)		{			num = fz_arrayget(obj, i);			if (!fz_isint(num) && !fz_isreal(num))			{				fz_dropobj(obj);				return fz_throw("malformed /Bounds (item not number)");			}			func->u.st.bounds[i] = fz_toreal(num);			if (i && func->u.st.bounds[i-1] > func->u.st.bounds[i])			{				fz_dropobj(obj);				return fz_throw("malformed /Bounds (item not monotonic)");			}		}		if (k != 1 &&				(func->domain[0][0] > func->u.st.bounds[0] ||				 func->domain[0][1] < func->u.st.bounds[k-2]))			fz_warn("malformed shading function bounds (domain mismatch), proceeding anyway.");		fz_dropobj(obj);	}	obj = fz_dictgets(dict, "Encode");	{		error = pdf_resolve(&obj, xref);		if (error)			return fz_rethrow(error, "cannot resolve /Encode");		if (!fz_isarray(obj) || fz_arraylen(obj) != k * 2)		{			fz_dropobj(obj);			return fz_throw("malformed /Encode");		}		for (i = 0; i < k; ++i)		{			func->u.st.encode[i][0] = fz_toreal(fz_arrayget(obj, i*2+0));			func->u.st.encode[i][1] = fz_toreal(fz_arrayget(obj, i*2+1));		}		fz_dropobj(obj);	}	pdf_logrsrc("}\n");	return fz_okay;}static fz_error*evalstitchingfunc(pdf_function *func, float in, float *out){	fz_error *error;	float low, high;	int k = func->u.st.k;	float *bounds = func->u.st.bounds;	int i;	in = CLAMP(in, func->domain[0][0], func->domain[0][1]);	for (i = 0; i < k - 1; ++i)	{		if (in < bounds[i])			break;	}	if (i == 0 && k == 1)	{		low = func->domain[0][0];		high = func->domain[0][1];	}	else if (i == 0)	{		low = func->domain[0][0];		high = bounds[0];	}	else if (i == k - 1)	{		low = bounds[k-2];		high = func->domain[0][1];	}	else	{		low = bounds[i-1];		high = bounds[i];	}	in = LERP(in, low, high, func->u.st.encode[i][0], func->u.st.encode[i][1]);	error = pdf_evalfunction(func->u.st.funcs[i], &in, 1, out, func->n);	if (error)		return fz_rethrow(error, "cannot evaluate sub function %d", i);	return fz_okay;}/* * Common */pdf_function *pdf_keepfunction(pdf_function *func){	func->refs ++;	return func;}voidpdf_dropfunction(pdf_function *func){	int i;	if (--func->refs == 0)	{		switch(func->type)		{		case SAMPLE:			fz_free(func->u.sa.samples);			break;		case EXPONENTIAL:			break;		case STITCHING:			for (i = 0; i < func->u.st.k; ++i)				pdf_dropfunction(func->u.st.funcs[i]);			break;		case POSTSCRIPT:			fz_free(func->u.p.code);			break;		}		fz_free(func);	}}fz_error *pdf_loadfunction(pdf_function **funcp, pdf_xref *xref, fz_obj *ref){	fz_error *error;	pdf_function *func;	fz_obj *dict;	fz_obj *obj;	int i;	if ((*funcp = pdf_finditem(xref->store, PDF_KFUNCTION, ref)))	{		pdf_keepfunction(*funcp);		return fz_okay;	}	pdf_logrsrc("load function (%d %d R) {\n", fz_tonum(ref), fz_togen(ref));	func = fz_malloc(sizeof(pdf_function));	if (!func)		return fz_throw("outofmem: function struct");	memset(func, 0, sizeof(pdf_function));	func->refs = 1;	dict = ref;	error = pdf_resolve(&dict, xref);	if (error)	{		fz_free(func);		return fz_rethrow(error, "cannot resolve function object");	}	obj = fz_dictgets(dict, "FunctionType");	func->type = fz_toint(obj);	pdf_logrsrc("type %d\n", func->type);	/* required for all */	obj = fz_dictgets(dict, "Domain");	func->m = fz_arraylen(obj) / 2;	for (i = 0; i < func->m; i++)	{		func->domain[i][0] = fz_toreal(fz_arrayget(obj, i * 2 + 0));		func->domain[i][1] = fz_toreal(fz_arrayget(obj, i * 2 + 1));	}	pdf_logrsrc("domain %d\n", func->m);	/* required for type0 and type4, optional otherwise */	obj = fz_dictgets(dict, "Range");	if (fz_isarray(obj))	{		func->hasrange = 1;		func->n = fz_arraylen(obj) / 2;		for (i = 0; i < func->n; i++)		{			func->range[i][0] = fz_toreal(fz_arrayget(obj, i * 2 + 0));			func->range[i][1] = fz_toreal(fz_arrayget(obj, i * 2 + 1));		}		pdf_logrsrc("range %d\n", func->n);	}	else	{		func->hasrange = 0;		func->n = 0;	}	if (func->m >= MAXM || func->n >= MAXN)	{		fz_free(func);		fz_dropobj(dict);		return fz_throw("assert: /Domain or /Range too big");	}	switch(func->type)	{	case SAMPLE:		error = loadsamplefunc(func, xref, dict, fz_tonum(ref), fz_togen(ref));		if (error)		{			pdf_dropfunction(func);			fz_dropobj(dict);			return fz_rethrow(error, "cannot load sampled function (%d %d R)", fz_tonum(ref), fz_togen(ref));		}		break;	case EXPONENTIAL:		error = loadexponentialfunc(func, dict);		if (error)		{			pdf_dropfunction(func);			fz_dropobj(dict);			return fz_rethrow(error, "cannot load exponential function (%d %d R)", fz_tonum(ref), fz_togen(ref));		}		break;	case STITCHING:		error = loadstitchingfunc(func, xref, dict);		if (error)		{			pdf_dropfunction(func);			fz_dropobj(dict);			return fz_rethrow(error, "cannot load stitching function (%d %d R)", fz_tonum(ref), fz_togen(ref));		}		break;	case POSTSCRIPT:		error = loadpostscriptfunc(func, xref, dict, fz_tonum(ref), fz_togen(ref));		if (error)		{			pdf_dropfunction(func);			fz_dropobj(dict);			return fz_rethrow(error, "cannot load calculator function (%d %d R)", fz_tonum(ref), fz_togen(ref));		}		break;	default:		fz_free(func);		fz_dropobj(dict);		return fz_throw("unknown function type %d (%d %d R)", func->type, fz_tonum(ref), fz_togen(ref));	}	fz_dropobj(dict);	pdf_logrsrc("}\n");	error = pdf_storeitem(xref->store, PDF_KFUNCTION, ref, func);	if (error)	{		pdf_dropfunction(func);		fz_dropobj(dict);		return fz_rethrow(error, "cannot store function resource");	}	*funcp = func;	return fz_okay;}fz_error *pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outlen){	fz_error *error;	float r;	int i;	if (func->m != inlen || func->n != outlen)		return fz_throw("function argument count mismatch");	switch(func->type)	{	case SAMPLE:		error = evalsamplefunc(func, in, out);		if (error)			return fz_rethrow(error, "cannot evaluate sampled function");		break;	case EXPONENTIAL:		error = evalexponentialfunc(func, *in, out);		if (error)			return fz_rethrow(error, "cannot evaluate exponential function");		break;	case STITCHING:		error = evalstitchingfunc(func, *in, out);		if (error)			return fz_rethrow(error, "cannot evaluate stitching function");		break;	case POSTSCRIPT:		{			psstack st;			psinitstack(&st);			for (i = 0; i < func->m; ++i)				SAFE_PUSHREAL(&st, in[i]);			error = evalpostscriptfunc(func, &st, 0);			if (error)				return fz_rethrow(error, "cannot evaluate calculator function");			for (i = func->n - 1; i >= 0; --i)			{				SAFE_POPNUM(&st, &r);				out[i] = CLAMP(r, func->range[i][0], func->range[i][1]);			}		}		break;	default:		return fz_throw("assert: unknown function type");	}	return fz_okay;}

⌨️ 快捷键说明

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