summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-10-01 19:20:45 +0100
committerRobin Watts <robin.watts@artifex.com>2013-03-26 13:58:59 +0000
commit68660cd89703996ca315b4affcf37582ed660237 (patch)
treee44026bfde0a28f27e136d0fa2bc83130c773eeb /pdf
parent266a1a44d2f6e73878fb742e088ea722873a182e (diff)
downloadmupdf-68660cd89703996ca315b4affcf37582ed660237.tar.xz
Make pdf_functions public as fz_functions.
Implementations remain unexposed, but this means we can safely pass functions in shades without having to 'sample' them (though we may still choose to do this for speed).
Diffstat (limited to 'pdf')
-rw-r--r--pdf/mupdf-internal.h8
-rw-r--r--pdf/pdf_colorspace.c12
-rw-r--r--pdf/pdf_function.c387
-rw-r--r--pdf/pdf_shade.c37
4 files changed, 198 insertions, 246 deletions
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h
index 164b0c81..69f60583 100644
--- a/pdf/mupdf-internal.h
+++ b/pdf/mupdf-internal.h
@@ -225,13 +225,7 @@ void pdf_print_crypt(pdf_crypt *crypt);
* Functions, Colorspaces, Shadings and Images
*/
-typedef struct pdf_function_s pdf_function;
-
-pdf_function *pdf_load_function(pdf_document *doc, pdf_obj *ref, int in, int out);
-void pdf_eval_function(fz_context *ctx, pdf_function *func, float *in, int inlen, float *out, int outlen);
-pdf_function *pdf_keep_function(fz_context *ctx, pdf_function *func);
-void pdf_drop_function(fz_context *ctx, pdf_function *func);
-unsigned int pdf_function_size(pdf_function *func);
+fz_function *pdf_load_function(pdf_document *doc, pdf_obj *ref, int in, int out);
fz_colorspace *pdf_load_colorspace(pdf_document *doc, pdf_obj *obj);
fz_pixmap *pdf_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src);
diff --git a/pdf/pdf_colorspace.c b/pdf/pdf_colorspace.c
index 7b0ba7c3..f6a1c3b3 100644
--- a/pdf/pdf_colorspace.c
+++ b/pdf/pdf_colorspace.c
@@ -69,7 +69,7 @@ static fz_colorspace *fz_device_lab = &k_device_lab;
struct separation
{
fz_colorspace *base;
- pdf_function *tint;
+ fz_function *tint;
};
static void
@@ -77,7 +77,7 @@ separation_to_rgb(fz_context *ctx, fz_colorspace *cs, float *color, float *rgb)
{
struct separation *sep = cs->data;
float alt[FZ_MAX_COLORS];
- pdf_eval_function(ctx, sep->tint, color, cs->n, alt, sep->base->n);
+ fz_eval_function(ctx, sep->tint, color, cs->n, alt, sep->base->n);
sep->base->to_rgb(ctx, sep->base, alt, rgb);
}
@@ -86,7 +86,7 @@ free_separation(fz_context *ctx, fz_colorspace *cs)
{
struct separation *sep = cs->data;
fz_drop_colorspace(ctx, sep->base);
- pdf_drop_function(ctx, sep->tint);
+ fz_drop_function(ctx, sep->tint);
fz_free(ctx, sep);
}
@@ -100,7 +100,7 @@ load_separation(pdf_document *xref, pdf_obj *array)
pdf_obj *baseobj = pdf_array_get(array, 2);
pdf_obj *tintobj = pdf_array_get(array, 3);
fz_colorspace *base;
- pdf_function *tint = NULL;
+ fz_function *tint = NULL;
int n;
fz_var(tint);
@@ -130,12 +130,12 @@ load_separation(pdf_document *xref, pdf_obj *array)
cs->to_rgb = separation_to_rgb;
cs->free_data = free_separation;
cs->data = sep;
- cs->size += sizeof(struct separation) + (base ? base->size : 0) + pdf_function_size(tint);
+ cs->size += sizeof(struct separation) + (base ? base->size : 0) + fz_function_size(tint);
}
fz_catch(ctx)
{
fz_drop_colorspace(ctx, base);
- pdf_drop_function(ctx, tint);
+ fz_drop_function(ctx, tint);
fz_free(ctx, sep);
fz_rethrow(ctx);
}
diff --git a/pdf/pdf_function.c b/pdf/pdf_function.c
index b6b46358..360f619b 100644
--- a/pdf/pdf_function.c
+++ b/pdf/pdf_function.c
@@ -1,12 +1,6 @@
#include "fitz-internal.h"
#include "mupdf-internal.h"
-enum
-{
- MAXN = FZ_MAX_COLORS,
- MAXM = FZ_MAX_COLORS,
-};
-
typedef struct psobj_s psobj;
enum
@@ -17,36 +11,35 @@ enum
POSTSCRIPT = 4
};
+typedef struct pdf_function_s pdf_function;
+
struct pdf_function_s
{
- fz_storable storable;
- unsigned int size;
+ fz_function base;
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 */
+ float domain[FZ_FN_MAXM][2]; /* even index : min value, odd index : max value */
+ float range[FZ_FN_MAXN][2]; /* even index : min value, odd index : max value */
int has_range;
union
{
struct {
unsigned short bps;
- int size[MAXM];
- float encode[MAXM][2];
- float decode[MAXN][2];
+ int size[FZ_FN_MAXM];
+ float encode[FZ_FN_MAXM][2];
+ float decode[FZ_FN_MAXN][2];
float *samples;
} sa;
struct {
float n;
- float c0[MAXN];
- float c1[MAXN];
+ float c0[FZ_FN_MAXN];
+ float c1[FZ_FN_MAXN];
} e;
struct {
int k;
- pdf_function **funcs; /* k */
+ fz_function **funcs; /* k */
float *bounds; /* k - 1 */
float *encode; /* k * 2 */
} st;
@@ -879,7 +872,7 @@ load_postscript_func(pdf_function *func, pdf_document *xref, pdf_obj *dict, int
fz_throw(ctx, "cannot parse calculator function (%d %d R)", num, gen);
}
- func->size += func->u.p.cap * sizeof(psobj);
+ func->base.size += func->u.p.cap * sizeof(psobj);
}
static void
@@ -891,7 +884,7 @@ eval_postscript_func(fz_context *ctx, pdf_function *func, float *in, float *out)
ps_init_stack(&st);
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
{
x = fz_clamp(in[i], func->domain[i][0], func->domain[i][1]);
ps_push_real(&st, x);
@@ -899,7 +892,7 @@ eval_postscript_func(fz_context *ctx, pdf_function *func, float *in, float *out)
ps_run(ctx, func->u.p.code, &st, 0);
- for (i = func->n - 1; i >= 0; i--)
+ for (i = func->base.n - 1; i >= 0; i--)
{
x = ps_pop_real(&st);
out[i] = fz_clamp(x, func->range[i][0], func->range[i][1]);
@@ -925,11 +918,11 @@ load_sample_func(pdf_function *func, pdf_document *xref, pdf_obj *dict, int num,
func->u.sa.samples = NULL;
obj = pdf_dict_gets(dict, "Size");
- if (pdf_array_len(obj) < func->m)
+ if (pdf_array_len(obj) < func->base.m)
fz_throw(ctx, "too few sample function dimension sizes");
- if (pdf_array_len(obj) > func->m)
+ if (pdf_array_len(obj) > func->base.m)
fz_warn(ctx, "too many sample function dimension sizes");
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
{
func->u.sa.size[i] = pdf_to_int(pdf_array_get(obj, i));
if (func->u.sa.size[i] <= 0)
@@ -942,7 +935,7 @@ load_sample_func(pdf_function *func, pdf_document *xref, pdf_obj *dict, int num,
obj = pdf_dict_gets(dict, "BitsPerSample");
func->u.sa.bps = bps = pdf_to_int(obj);
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
{
func->u.sa.encode[i][0] = 0;
func->u.sa.encode[i][1] = func->u.sa.size[i] - 1;
@@ -950,8 +943,8 @@ load_sample_func(pdf_function *func, pdf_document *xref, pdf_obj *dict, int num,
obj = pdf_dict_gets(dict, "Encode");
if (pdf_is_array(obj))
{
- int ranges = fz_mini(func->m, pdf_array_len(obj) / 2);
- if (ranges != func->m)
+ int ranges = fz_mini(func->base.m, pdf_array_len(obj) / 2);
+ if (ranges != func->base.m)
fz_warn(ctx, "wrong number of sample function input mappings");
for (i = 0; i < ranges; i++)
@@ -961,7 +954,7 @@ load_sample_func(pdf_function *func, pdf_document *xref, pdf_obj *dict, int num,
}
}
- for (i = 0; i < func->n; i++)
+ for (i = 0; i < func->base.n; i++)
{
func->u.sa.decode[i][0] = func->range[i][0];
func->u.sa.decode[i][1] = func->range[i][1];
@@ -970,8 +963,8 @@ load_sample_func(pdf_function *func, pdf_document *xref, pdf_obj *dict, int num,
obj = pdf_dict_gets(dict, "Decode");
if (pdf_is_array(obj))
{
- int ranges = fz_mini(func->n, pdf_array_len(obj) / 2);
- if (ranges != func->n)
+ int ranges = fz_mini(func->base.n, pdf_array_len(obj) / 2);
+ if (ranges != func->base.n)
fz_warn(ctx, "wrong number of sample function output mappings");
for (i = 0; i < ranges; i++)
@@ -981,14 +974,14 @@ load_sample_func(pdf_function *func, pdf_document *xref, pdf_obj *dict, int num,
}
}
- for (i = 0, samplecount = func->n; i < func->m; i++)
+ for (i = 0, samplecount = func->base.n; i < func->base.m; i++)
samplecount *= func->u.sa.size[i];
if (samplecount > MAX_SAMPLE_FUNCTION_SIZE)
fz_throw(ctx, "sample function too large");
func->u.sa.samples = fz_malloc_array(ctx, samplecount, sizeof(float));
- func->size += samplecount * sizeof(float);
+ func->base.size += samplecount * sizeof(float);
stream = pdf_open_stream(xref, num, gen);
@@ -1066,13 +1059,13 @@ interpolate_sample(pdf_function *func, int *scale, int *e0, int *e1, float *efra
static void
eval_sample_func(fz_context *ctx, pdf_function *func, float *in, float *out)
{
- int e0[MAXM], e1[MAXM], scale[MAXM];
- float efrac[MAXM];
+ int e0[FZ_FN_MAXM], e1[FZ_FN_MAXM], scale[FZ_FN_MAXM];
+ float efrac[FZ_FN_MAXM];
float x;
int i;
/* encode input coordinates */
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
{
x = fz_clamp(in[i], func->domain[i][0], func->domain[i][1]);
x = lerp(x, func->domain[i][0], func->domain[i][1],
@@ -1083,16 +1076,16 @@ eval_sample_func(fz_context *ctx, pdf_function *func, float *in, float *out)
efrac[i] = x - floorf(x);
}
- scale[0] = func->n;
- for (i = 1; i < func->m; i++)
+ scale[0] = func->base.n;
+ for (i = 1; i < func->base.m; i++)
scale[i] = scale[i - 1] * func->u.sa.size[i];
- for (i = 0; i < func->n; i++)
+ for (i = 0; i < func->base.n; i++)
{
- if (func->m == 1)
+ if (func->base.m == 1)
{
- float a = func->u.sa.samples[e0[0] * func->n + i];
- float b = func->u.sa.samples[e1[0] * func->n + i];
+ float a = func->u.sa.samples[e0[0] * func->base.n + i];
+ float b = func->u.sa.samples[e1[0] * func->base.n + i];
float ab = a + (b - a) * efrac[0];
@@ -1100,9 +1093,9 @@ eval_sample_func(fz_context *ctx, pdf_function *func, float *in, float *out)
out[i] = fz_clamp(out[i], func->range[i][0], func->range[i][1]);
}
- else if (func->m == 2)
+ else if (func->base.m == 2)
{
- int s0 = func->n;
+ int s0 = func->base.n;
int s1 = s0 * func->u.sa.size[0];
float a = func->u.sa.samples[e0[0] * s0 + e0[1] * s1 + i];
@@ -1120,7 +1113,7 @@ eval_sample_func(fz_context *ctx, pdf_function *func, float *in, float *out)
else
{
- x = interpolate_sample(func, scale, e0, e1, efrac, func->m - 1, i);
+ x = interpolate_sample(func, scale, e0, e1, efrac, func->base.m - 1, i);
out[i] = lerp(x, 0, 1, func->u.sa.decode[i][0], func->u.sa.decode[i][1]);
out[i] = fz_clamp(out[i], func->range[i][0], func->range[i][1]);
}
@@ -1137,9 +1130,9 @@ load_exponential_func(fz_context *ctx, pdf_function *func, pdf_obj *dict)
pdf_obj *obj;
int i;
- if (func->m > 1)
+ if (func->base.m > 1)
fz_warn(ctx, "exponential functions have at most one input");
- func->m = 1;
+ func->base.m = 1;
obj = pdf_dict_gets(dict, "N");
func->u.e.n = pdf_to_real(obj);
@@ -1148,20 +1141,20 @@ load_exponential_func(fz_context *ctx, pdf_function *func, pdf_obj *dict)
if (func->u.e.n != (int) func->u.e.n)
{
/* If N is non-integer, input values may never be negative */
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
if (func->domain[i][0] < 0 || func->domain[i][1] < 0)
fz_warn(ctx, "exponential function input domain includes illegal negative input values");
}
else if (func->u.e.n < 0)
{
/* if N is negative, input values may never be zero */
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
if (func->domain[i][0] == 0 || func->domain[i][1] == 0 ||
(func->domain[i][0] < 0 && func->domain[i][1] > 0))
fz_warn(ctx, "exponential function input domain includes illegal input value zero");
}
- for (i = 0; i < func->n; i++)
+ for (i = 0; i < func->base.n; i++)
{
func->u.e.c0[i] = 0;
func->u.e.c1[i] = 1;
@@ -1170,8 +1163,8 @@ load_exponential_func(fz_context *ctx, pdf_function *func, pdf_obj *dict)
obj = pdf_dict_gets(dict, "C0");
if (pdf_is_array(obj))
{
- int ranges = fz_mini(func->n, pdf_array_len(obj));
- if (ranges != func->n)
+ int ranges = fz_mini(func->base.n, pdf_array_len(obj));
+ if (ranges != func->base.n)
fz_warn(ctx, "wrong number of C0 constants for exponential function");
for (i = 0; i < ranges; i++)
@@ -1181,8 +1174,8 @@ load_exponential_func(fz_context *ctx, pdf_function *func, pdf_obj *dict)
obj = pdf_dict_gets(dict, "C1");
if (pdf_is_array(obj))
{
- int ranges = fz_mini(func->n, pdf_array_len(obj));
- if (ranges != func->n)
+ int ranges = fz_mini(func->base.n, pdf_array_len(obj));
+ if (ranges != func->base.n)
fz_warn(ctx, "wrong number of C1 constants for exponential function");
for (i = 0; i < ranges; i++)
@@ -1204,7 +1197,7 @@ eval_exponential_func(fz_context *ctx, pdf_function *func, float in, float *out)
return;
tmp = powf(x, func->u.e.n);
- for (i = 0; i < func->n; i++)
+ for (i = 0; i < func->base.n; i++)
{
out[i] = func->u.e.c0[i] + tmp * (func->u.e.c1[i] - func->u.e.c0[i]);
if (func->has_range)
@@ -1220,7 +1213,7 @@ static void
load_stitching_func(pdf_function *func, pdf_document *xref, pdf_obj *dict)
{
fz_context *ctx = xref->ctx;
- pdf_function **funcs;
+ fz_function **funcs;
pdf_obj *obj;
pdf_obj *sub;
pdf_obj *num;
@@ -1229,9 +1222,9 @@ load_stitching_func(pdf_function *func, pdf_document *xref, pdf_obj *dict)
func->u.st.k = 0;
- if (func->m > 1)
+ if (func->base.m > 1)
fz_warn(ctx, "stitching functions have at most one input");
- func->m = 1;
+ func->base.m = 1;
obj = pdf_dict_gets(dict, "Functions");
if (!pdf_is_array(obj))
@@ -1242,7 +1235,7 @@ load_stitching_func(pdf_function *func, pdf_document *xref, pdf_obj *dict)
pdf_obj_mark(obj);
k = pdf_array_len(obj);
- func->u.st.funcs = fz_malloc_array(ctx, k, sizeof(pdf_function*));
+ func->u.st.funcs = fz_malloc_array(ctx, k, sizeof(fz_function*));
func->u.st.bounds = fz_malloc_array(ctx, k - 1, sizeof(float));
func->u.st.encode = fz_malloc_array(ctx, k * 2, sizeof(float));
funcs = func->u.st.funcs;
@@ -1250,14 +1243,14 @@ load_stitching_func(pdf_function *func, pdf_document *xref, pdf_obj *dict)
for (i = 0; i < k; i++)
{
sub = pdf_array_get(obj, i);
- funcs[i] = pdf_load_function(xref, sub, 1, func->n);
+ funcs[i] = pdf_load_function(xref, sub, 1, func->base.n);
- func->size += pdf_function_size(funcs[i]);
+ func->base.size += fz_function_size(funcs[i]);
func->u.st.k ++;
- if (funcs[i]->m != func->m)
+ if (funcs[i]->m != func->base.m)
fz_warn(ctx, "wrong number of inputs for sub function %d", i);
- if (funcs[i]->n != func->n)
+ if (funcs[i]->n != func->base.n)
fz_warn(ctx, "wrong number of outputs for sub function %d", i);
}
}
@@ -1352,25 +1345,13 @@ eval_stitching_func(fz_context *ctx, pdf_function *func, float in, float *out)
in = lerp(in, low, high, func->u.st.encode[i * 2 + 0], func->u.st.encode[i * 2 + 1]);
- pdf_eval_function(ctx, func->u.st.funcs[i], &in, 1, out, func->n);
+ fz_eval_function(ctx, func->u.st.funcs[i], &in, 1, out, func->u.st.funcs[i]->n);
}
/*
* Common
*/
-pdf_function *
-pdf_keep_function(fz_context *ctx, pdf_function *func)
-{
- return (pdf_function *)fz_keep_storable(ctx, &func->storable);
-}
-
-void
-pdf_drop_function(fz_context *ctx, pdf_function *func)
-{
- fz_drop_storable(ctx, &func->storable);
-}
-
static void
pdf_free_function_imp(fz_context *ctx, fz_storable *func_)
{
@@ -1386,7 +1367,7 @@ pdf_free_function_imp(fz_context *ctx, fz_storable *func_)
break;
case STITCHING:
for (i = 0; i < func->u.st.k; i++)
- pdf_drop_function(ctx, func->u.st.funcs[i]);
+ fz_drop_function(ctx, func->u.st.funcs[i]);
fz_free(ctx, func->u.st.funcs);
fz_free(ctx, func->u.st.bounds);
fz_free(ctx, func->u.st.encode);
@@ -1398,132 +1379,10 @@ pdf_free_function_imp(fz_context *ctx, fz_storable *func_)
fz_free(ctx, func);
}
-unsigned int
-pdf_function_size(pdf_function *func)
-{
- return (func ? func->size : 0);
-}
-
-pdf_function *
-pdf_load_function(pdf_document *xref, pdf_obj *dict, int in, int out)
-{
- fz_context *ctx = xref->ctx;
- pdf_function *func;
- pdf_obj *obj;
- int i;
-
- if (pdf_obj_marked(dict))
- fz_throw(ctx, "Recursion in function definition");
-
- if ((func = pdf_find_item(ctx, pdf_free_function_imp, dict)))
- {
- return func;
- }
-
- func = fz_malloc_struct(ctx, pdf_function);
- FZ_INIT_STORABLE(func, 1, pdf_free_function_imp);
- func->size = sizeof(*func);
-
- obj = pdf_dict_gets(dict, "FunctionType");
- func->type = pdf_to_int(obj);
-
- /* required for all */
- obj = pdf_dict_gets(dict, "Domain");
- func->m = fz_clampi(pdf_array_len(obj) / 2, 1, MAXM);
- for (i = 0; i < func->m; i++)
- {
- func->domain[i][0] = pdf_to_real(pdf_array_get(obj, i * 2 + 0));
- func->domain[i][1] = pdf_to_real(pdf_array_get(obj, i * 2 + 1));
- }
-
- /* required for type0 and type4, optional otherwise */
- obj = pdf_dict_gets(dict, "Range");
- if (pdf_is_array(obj))
- {
- func->has_range = 1;
- func->n = fz_clampi(pdf_array_len(obj) / 2, 1, MAXN);
- for (i = 0; i < func->n; i++)
- {
- func->range[i][0] = pdf_to_real(pdf_array_get(obj, i * 2 + 0));
- func->range[i][1] = pdf_to_real(pdf_array_get(obj, i * 2 + 1));
- }
- }
- else
- {
- func->has_range = 0;
- func->n = out;
- }
-
- if (func->m != in)
- fz_warn(ctx, "wrong number of function inputs");
- if (func->n != out)
- fz_warn(ctx, "wrong number of function outputs");
-
- fz_try(ctx)
- {
- switch(func->type)
- {
- case SAMPLE:
- load_sample_func(func, xref, dict, pdf_to_num(dict), pdf_to_gen(dict));
- break;
-
- case EXPONENTIAL:
- load_exponential_func(ctx, func, dict);
- break;
-
- case STITCHING:
- load_stitching_func(func, xref, dict);
- break;
-
- case POSTSCRIPT:
- load_postscript_func(func, xref, dict, pdf_to_num(dict), pdf_to_gen(dict));
- break;
-
- default:
- fz_free(ctx, func);
- fz_throw(ctx, "unknown function type (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
- }
-
- pdf_store_item(ctx, dict, func, func->size);
- }
- fz_catch(ctx)
- {
- int type = func->type;
- pdf_drop_function(ctx, func);
- fz_throw(ctx, "cannot load %s function (%d %d R)",
- type == SAMPLE ? "sampled" :
- type == EXPONENTIAL ? "exponential" :
- type == STITCHING ? "stitching" :
- type == POSTSCRIPT ? "calculator" :
- "unknown",
- pdf_to_num(dict), pdf_to_gen(dict));
- }
-
- return func;
-}
-
-void
-pdf_eval_function(fz_context *ctx, pdf_function *func, float *in_, int inlen, float *out_, int outlen)
+static void
+pdf_eval_function(fz_context *ctx, fz_function *func_, float *in, float *out)
{
- float fakein[MAXM];
- float fakeout[MAXN];
- float *in = in_;
- float *out = out_;
-
- if (inlen < func->m)
- {
- in = fakein;
- memset(in, 0, sizeof(float) * func->m);
- memcpy(in, in_, sizeof(float) * inlen);
- }
-
- if (outlen < func->n)
- {
- out = fakeout;
- memset(out, 0, sizeof(float) * func->n);
- }
- else
- memset(out, 0, sizeof(float) * outlen);
+ pdf_function *func = (pdf_function *)func_;
switch(func->type)
{
@@ -1532,9 +1391,6 @@ pdf_eval_function(fz_context *ctx, pdf_function *func, float *in_, int inlen, fl
case STITCHING: eval_stitching_func(ctx, func, *in, out); break;
case POSTSCRIPT: eval_postscript_func(ctx, func, in, out); break;
}
-
- if (outlen < func->n)
- memcpy(out_, out, sizeof(float) * outlen);
}
/*
@@ -1642,9 +1498,10 @@ pdf_debug_ps_func_code(psobj *funccode, psobj *code, int level)
}
static void
-pdf_debug_function_imp(pdf_function *func, int level)
+pdf_debug_function_imp(fz_function *func_, int level)
{
int i;
+ pdf_function *func = (pdf_function *)func_;
pdf_debug_indent("", level, "function {\n");
@@ -1666,17 +1523,17 @@ pdf_debug_function_imp(pdf_function *func, int level)
}
pdf_debug_indent("\n", level, "");
- printf("%d input -> %d output\n", func->m, func->n);
+ printf("%d input -> %d output\n", func->base.m, func->base.n);
pdf_debug_indent("", level, "domain ");
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
printf("%g %g ", func->domain[i][0], func->domain[i][1]);
printf("\n");
if (func->has_range)
{
pdf_debug_indent("", level, "range ");
- for (i = 0; i < func->n; i++)
+ for (i = 0; i < func->base.n; i++)
printf("%g %g ", func->range[i][0], func->range[i][1]);
printf("\n");
}
@@ -1689,19 +1546,19 @@ pdf_debug_function_imp(pdf_function *func, int level)
pdf_debug_indent("", level, "");
printf("size: [ ");
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
printf("%d ", func->u.sa.size[i]);
printf("]\n");
pdf_debug_indent("", level, "");
printf("encode: [ ");
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
printf("%g %g ", func->u.sa.encode[i][0], func->u.sa.encode[i][1]);
printf("]\n");
pdf_debug_indent("", level, "");
printf("decode: [ ");
- for (i = 0; i < func->m; i++)
+ for (i = 0; i < func->base.m; i++)
printf("%g %g ", func->u.sa.decode[i][0], func->u.sa.decode[i][1]);
printf("]\n");
break;
@@ -1712,13 +1569,13 @@ pdf_debug_function_imp(pdf_function *func, int level)
pdf_debug_indent("", level, "");
printf("c0: [ ");
- for (i = 0; i < func->n; i++)
+ for (i = 0; i < func->base.n; i++)
printf("%g ", func->u.e.c0[i]);
printf("]\n");
pdf_debug_indent("", level, "");
printf("c1: [ ");
- for (i = 0; i < func->n; i++)
+ for (i = 0; i < func->base.n; i++)
printf("%g ", func->u.e.c1[i]);
printf("]\n");
break;
@@ -1753,8 +1610,110 @@ pdf_debug_function_imp(pdf_function *func, int level)
}
void
-pdf_debug_function(pdf_function *func)
+pdf_debug_function(fz_function *func)
{
pdf_debug_function_imp(func, 0);
}
#endif
+
+fz_function *
+pdf_load_function(pdf_document *xref, pdf_obj *dict, int in, int out)
+{
+ fz_context *ctx = xref->ctx;
+ pdf_function *func;
+ pdf_obj *obj;
+ int i;
+
+ if (pdf_obj_marked(dict))
+ fz_throw(ctx, "Recursion in function definition");
+
+ if ((func = pdf_find_item(ctx, pdf_free_function_imp, dict)))
+ {
+ return (fz_function *)func;
+ }
+
+ func = fz_malloc_struct(ctx, pdf_function);
+ FZ_INIT_STORABLE(&func->base, 1, pdf_free_function_imp);
+ func->base.size = sizeof(*func);
+ func->base.evaluate = pdf_eval_function;
+#ifndef NDEBUG
+ func->base.debug = pdf_debug_function;
+#endif
+
+ obj = pdf_dict_gets(dict, "FunctionType");
+ func->type = pdf_to_int(obj);
+
+ /* required for all */
+ obj = pdf_dict_gets(dict, "Domain");
+ func->base.m = fz_clampi(pdf_array_len(obj) / 2, 1, FZ_FN_MAXM);
+ for (i = 0; i < func->base.m; i++)
+ {
+ func->domain[i][0] = pdf_to_real(pdf_array_get(obj, i * 2 + 0));
+ func->domain[i][1] = pdf_to_real(pdf_array_get(obj, i * 2 + 1));
+ }
+
+ /* required for type0 and type4, optional otherwise */
+ obj = pdf_dict_gets(dict, "Range");
+ if (pdf_is_array(obj))
+ {
+ func->has_range = 1;
+ func->base.n = fz_clampi(pdf_array_len(obj) / 2, 1, FZ_FN_MAXN);
+ for (i = 0; i < func->base.n; i++)
+ {
+ func->range[i][0] = pdf_to_real(pdf_array_get(obj, i * 2 + 0));
+ func->range[i][1] = pdf_to_real(pdf_array_get(obj, i * 2 + 1));
+ }
+ }
+ else
+ {
+ func->has_range = 0;
+ func->base.n = out;
+ }
+
+ if (func->base.m != in)
+ fz_warn(ctx, "wrong number of function inputs");
+ if (func->base.n != out)
+ fz_warn(ctx, "wrong number of function outputs");
+
+ fz_try(ctx)
+ {
+ switch(func->type)
+ {
+ case SAMPLE:
+ load_sample_func(func, xref, dict, pdf_to_num(dict), pdf_to_gen(dict));
+ break;
+
+ case EXPONENTIAL:
+ load_exponential_func(ctx, func, dict);
+ break;
+
+ case STITCHING:
+ load_stitching_func(func, xref, dict);
+ break;
+
+ case POSTSCRIPT:
+ load_postscript_func(func, xref, dict, pdf_to_num(dict), pdf_to_gen(dict));
+ break;
+
+ default:
+ fz_free(ctx, func);
+ fz_throw(ctx, "unknown function type (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
+ }
+
+ pdf_store_item(ctx, dict, func, func->base.size);
+ }
+ fz_catch(ctx)
+ {
+ int type = func->type;
+ fz_drop_function(ctx, (fz_function *)func);
+ fz_throw(ctx, "cannot load %s function (%d %d R)",
+ type == SAMPLE ? "sampled" :
+ type == EXPONENTIAL ? "exponential" :
+ type == STITCHING ? "stitching" :
+ type == POSTSCRIPT ? "calculator" :
+ "unknown",
+ pdf_to_num(dict), pdf_to_gen(dict));
+ }
+
+ return (fz_function *)func;
+}
diff --git a/pdf/pdf_shade.c b/pdf/pdf_shade.c
index 2eee5168..f74910f8 100644
--- a/pdf/pdf_shade.c
+++ b/pdf/pdf_shade.c
@@ -7,7 +7,7 @@
/* Sample various functions into lookup tables */
static void
-pdf_sample_composite_shade_function(fz_context *ctx, fz_shade *shade, pdf_function *func, float t0, float t1)
+pdf_sample_composite_shade_function(fz_context *ctx, fz_shade *shade, fz_function *func, float t0, float t1)
{
int i;
float t;
@@ -15,13 +15,13 @@ pdf_sample_composite_shade_function(fz_context *ctx, fz_shade *shade, pdf_functi
for (i = 0; i < 256; i++)
{
t = t0 + (i / 255.0f) * (t1 - t0);
- pdf_eval_function(ctx, func, &t, 1, shade->function[i], shade->colorspace->n);
+ fz_eval_function(ctx, func, &t, 1, shade->function[i], shade->colorspace->n);
shade->function[i][shade->colorspace->n] = 1;
}
}
static void
-pdf_sample_component_shade_function(fz_context *ctx, fz_shade *shade, int funcs, pdf_function **func, float t0, float t1)
+pdf_sample_component_shade_function(fz_context *ctx, fz_shade *shade, int funcs, fz_function **func, float t0, float t1)
{
int i, k;
float t;
@@ -30,13 +30,13 @@ pdf_sample_component_shade_function(fz_context *ctx, fz_shade *shade, int funcs,
{
t = t0 + (i / 255.0f) * (t1 - t0);
for (k = 0; k < funcs; k++)
- pdf_eval_function(ctx, func[k], &t, 1, &shade->function[i][k], 1);
+ fz_eval_function(ctx, func[k], &t, 1, &shade->function[i][k], 1);
shade->function[i][k] = 1;
}
}
static void
-pdf_sample_shade_function(fz_context *ctx, fz_shade *shade, int funcs, pdf_function **func, float t0, float t1)
+pdf_sample_shade_function(fz_context *ctx, fz_shade *shade, int funcs, fz_function **func, float t0, float t1)
{
shade->use_function = 1;
if (funcs == 1)
@@ -48,7 +48,7 @@ pdf_sample_shade_function(fz_context *ctx, fz_shade *shade, int funcs, pdf_funct
/* Type 1-3 -- Function-based, linear and radial shadings */
static void
-pdf_load_function_based_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, pdf_function *func)
+pdf_load_function_based_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, fz_function *func)
{
pdf_obj *obj;
float x0, y0, x1, y1;
@@ -92,14 +92,14 @@ pdf_load_function_based_shading(fz_shade *shade, pdf_document *xref, pdf_obj *di
{
fv[0] = x0 + (x1 - x0) * xx / FUNSEGS;
- pdf_eval_function(ctx, func, fv, 2, p, shade->colorspace->n);
+ fz_eval_function(ctx, func, fv, 2, p, shade->colorspace->n);
p += shade->colorspace->n;
}
}
}
static void
-pdf_load_linear_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, int funcs, pdf_function **func)
+pdf_load_linear_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, int funcs, fz_function **func)
{
pdf_obj *obj;
float d0, d1;
@@ -136,7 +136,7 @@ pdf_load_linear_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, int
}
static void
-pdf_load_radial_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, int funcs, pdf_function **func)
+pdf_load_radial_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, int funcs, fz_function **func)
{
pdf_obj *obj;
float d0, d1;
@@ -254,7 +254,7 @@ pdf_load_mesh_params(fz_shade *shade, pdf_document *xref, pdf_obj *dict)
static void
pdf_load_type4_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
- int funcs, pdf_function **func)
+ int funcs, fz_function **func)
{
fz_context *ctx = xref->ctx;
@@ -268,7 +268,7 @@ pdf_load_type4_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
static void
pdf_load_type5_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
- int funcs, pdf_function **func)
+ int funcs, fz_function **func)
{
fz_context *ctx = xref->ctx;
@@ -284,7 +284,7 @@ pdf_load_type5_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
static void
pdf_load_type6_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
- int funcs, pdf_function **func)
+ int funcs, fz_function **func)
{
fz_context *ctx = xref->ctx;
@@ -298,7 +298,7 @@ pdf_load_type6_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
static void
pdf_load_type7_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
- int funcs, pdf_function **func)
+ int funcs, fz_function **func)
{
fz_context *ctx = xref->ctx;
@@ -316,7 +316,7 @@ static fz_shade *
pdf_load_shading_dict(pdf_document *xref, pdf_obj *dict, const fz_matrix *transform)
{
fz_shade *shade = NULL;
- pdf_function *func[FZ_MAX_COLORS] = { NULL };
+ fz_function *func[FZ_MAX_COLORS] = { NULL };
pdf_obj *obj;
int funcs = 0;
int type = 0;
@@ -423,16 +423,15 @@ pdf_load_shading_dict(pdf_document *xref, pdf_obj *dict, const fz_matrix *transf
default:
fz_throw(ctx, "unknown shading type: %d", type);
}
-
+ }
+ fz_always(ctx)
+ {
for (i = 0; i < funcs; i++)
if (func[i])
- pdf_drop_function(ctx, func[i]);
+ fz_drop_function(ctx, func[i]);
}
fz_catch(ctx)
{
- for (i = 0; i < funcs; i++)
- if (func[i])
- pdf_drop_function(ctx, func[i]);
fz_drop_shade(ctx, shade);
fz_throw(ctx, "cannot load shading type %d (%d %d R)", type, pdf_to_num(dict), pdf_to_gen(dict));