summaryrefslogtreecommitdiff
path: root/pdf/pdf_function.c
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_function.c')
-rw-r--r--pdf/pdf_function.c208
1 files changed, 112 insertions, 96 deletions
diff --git a/pdf/pdf_function.c b/pdf/pdf_function.c
index 23acc4db..e1c53beb 100644
--- a/pdf/pdf_function.c
+++ b/pdf/pdf_function.c
@@ -1,5 +1,5 @@
-#include "fitz.h"
-#include "mupdf.h"
+#include "fitz-internal.h"
+#include "mupdf-internal.h"
enum
{
@@ -203,7 +203,13 @@ ps_push_real(ps_stack *st, float n)
if (!ps_overflow(st, 1))
{
st->stack[st->sp].type = PS_REAL;
- st->stack[st->sp].u.f = n;
+ if (isnan(n))
+ {
+ /* Push 1.0, as it's a small known value that won't
+ cause a divide by 0. Same reason as in fz_atof. */
+ n = 1.0;
+ }
+ st->stack[st->sp].u.f = CLAMP(n, -FLT_MAX, FLT_MAX);
st->sp++;
}
}
@@ -360,10 +366,10 @@ ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc)
case PS_OP_BITSHIFT:
i2 = ps_pop_int(st);
i1 = ps_pop_int(st);
- if (i2 > 0)
+ if (i2 > 0 && i2 < 8 * sizeof (i2))
ps_push_int(st, i1 << i2);
- else if (i2 < 0)
- ps_push_int(st, (int)((unsigned int)i1 >> i2));
+ else if (i2 < 0 && i2 > -8 * (int)sizeof (i2))
+ ps_push_int(st, (int)((unsigned int)i1 >> -i2));
else
ps_push_int(st, i1);
break;
@@ -393,7 +399,10 @@ ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc)
case PS_OP_DIV:
r2 = ps_pop_real(st);
r1 = ps_pop_real(st);
- ps_push_real(st, r1 / r2);
+ if (fabsf(r2) < FLT_EPSILON)
+ ps_push_real(st, r1 / r2);
+ else
+ ps_push_real(st, DIV_BY_ZERO(r1, r2, -FLT_MAX, FLT_MAX));
break;
case PS_OP_DUP:
@@ -466,7 +475,10 @@ ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc)
case PS_OP_IDIV:
i2 = ps_pop_int(st);
i1 = ps_pop_int(st);
- ps_push_int(st, i1 / i2);
+ if (i2 != 0)
+ ps_push_int(st, i1 / i2);
+ else
+ ps_push_int(st, DIV_BY_ZERO(i1, i2, INT_MIN, INT_MAX));
break;
case PS_OP_INDEX:
@@ -512,7 +524,10 @@ ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc)
case PS_OP_MOD:
i2 = ps_pop_int(st);
i1 = ps_pop_int(st);
- ps_push_int(st, i1 % i2);
+ if (i2 != 0)
+ ps_push_int(st, i1 % i2);
+ else
+ ps_push_int(st, DIV_BY_ZERO(i1, i2, INT_MIN, INT_MAX));
break;
case PS_OP_MUL:
@@ -683,18 +698,18 @@ resize_code(fz_context *ctx, pdf_function *func, int newsize)
static void
parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
{
- char buf[64];
- int len;
+ pdf_lexbuf buf;
int tok;
int opptr, elseptr, ifptr;
int a, b, mid, cmp;
fz_context *ctx = stream->ctx;
- memset(buf, 0, sizeof(buf));
+ buf.size = PDF_LEXBUF_SMALL;
+ memset(buf.scratch, 0, sizeof(buf.scratch));
while (1)
{
- tok = pdf_lex(stream, buf, sizeof buf, &len);
+ tok = pdf_lex(stream, &buf);
/* RJW: "calculator function lexical error" */
switch(tok)
@@ -705,7 +720,7 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
case PDF_TOK_INT:
resize_code(ctx, func, *codeptr);
func->u.p.code[*codeptr].type = PS_INT;
- func->u.p.code[*codeptr].u.i = atoi(buf);
+ func->u.p.code[*codeptr].u.i = buf.i;
++*codeptr;
break;
@@ -726,7 +741,7 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
case PDF_TOK_REAL:
resize_code(ctx, func, *codeptr);
func->u.p.code[*codeptr].type = PS_REAL;
- func->u.p.code[*codeptr].u.f = fz_atof(buf);
+ func->u.p.code[*codeptr].u.f = buf.f;
++*codeptr;
break;
@@ -740,7 +755,7 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
parse_code(func, stream, codeptr);
/* RJW: "error in 'if' branch" */
- tok = pdf_lex(stream, buf, sizeof buf, &len);
+ tok = pdf_lex(stream, &buf);
/* RJW: "calculator function syntax error" */
if (tok == PDF_TOK_OPEN_BRACE)
@@ -749,7 +764,7 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
parse_code(func, stream, codeptr);
/* RJW: "error in 'else' branch" */
- tok = pdf_lex(stream, buf, sizeof buf, &len);
+ tok = pdf_lex(stream, &buf);
/* RJW: "calculator function syntax error" */
}
else
@@ -760,7 +775,7 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
if (tok != PDF_TOK_KEYWORD)
fz_throw(ctx, "missing keyword in 'if-else' context");
- if (!strcmp(buf, "if"))
+ if (!strcmp(buf.scratch, "if"))
{
if (elseptr >= 0)
fz_throw(ctx, "too many branches for 'if'");
@@ -771,7 +786,7 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
func->u.p.code[opptr+3].type = PS_BLOCK;
func->u.p.code[opptr+3].u.block = *codeptr;
}
- else if (!strcmp(buf, "ifelse"))
+ else if (!strcmp(buf.scratch, "ifelse"))
{
if (elseptr < 0)
fz_throw(ctx, "not enough branches for 'ifelse'");
@@ -786,7 +801,7 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
}
else
{
- fz_throw(ctx, "unknown keyword in 'if-else' context: '%s'", buf);
+ fz_throw(ctx, "unknown keyword in 'if-else' context: '%s'", buf.scratch);
}
break;
@@ -804,7 +819,7 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
while (b - a > 1)
{
mid = (a + b) / 2;
- cmp = strcmp(buf, ps_op_names[mid]);
+ cmp = strcmp(buf.scratch, ps_op_names[mid]);
if (cmp > 0)
a = mid;
else if (cmp < 0)
@@ -813,7 +828,7 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
a = b = mid;
}
if (cmp != 0)
- fz_throw(ctx, "unknown operator: '%s'", buf);
+ fz_throw(ctx, "unknown operator: '%s'", buf.scratch);
resize_code(ctx, func, *codeptr);
func->u.p.code[*codeptr].type = PS_OPERATOR;
@@ -828,16 +843,17 @@ parse_code(pdf_function *func, fz_stream *stream, int *codeptr)
}
static void
-load_postscript_func(pdf_function *func, pdf_document *xref, fz_obj *dict, int num, int gen)
+load_postscript_func(pdf_function *func, pdf_document *xref, pdf_obj *dict, int num, int gen)
{
fz_stream *stream = NULL;
int codeptr;
- char buf[64];
+ pdf_lexbuf buf;
int tok;
- int len;
fz_context *ctx = xref->ctx;
int locked = 0;
+ buf.size = PDF_LEXBUF_SMALL;
+
fz_var(stream);
fz_var(locked);
@@ -846,7 +862,7 @@ load_postscript_func(pdf_function *func, pdf_document *xref, fz_obj *dict, int n
stream = pdf_open_stream(xref, num, gen);
/* RJW: "cannot open calculator function stream" */
- tok = pdf_lex(stream, buf, sizeof buf, &len);
+ tok = pdf_lex(stream, &buf);
if (tok != PDF_TOK_OPEN_BRACE)
{
fz_throw(ctx, "stream is not a calculator function");
@@ -899,37 +915,37 @@ eval_postscript_func(fz_context *ctx, pdf_function *func, float *in, float *out)
*/
static void
-load_sample_func(pdf_function *func, pdf_document *xref, fz_obj *dict, int num, int gen)
+load_sample_func(pdf_function *func, pdf_document *xref, pdf_obj *dict, int num, int gen)
{
fz_context *ctx = xref->ctx;
fz_stream *stream;
- fz_obj *obj;
+ pdf_obj *obj;
int samplecount;
int bps;
int i;
func->u.sa.samples = NULL;
- obj = fz_dict_gets(dict, "Size");
- if (!fz_is_array(obj) || fz_array_len(obj) != func->m)
+ obj = pdf_dict_gets(dict, "Size");
+ if (!pdf_is_array(obj) || pdf_array_len(obj) != func->m)
fz_throw(ctx, "malformed /Size");
for (i = 0; i < func->m; i++)
- func->u.sa.size[i] = fz_to_int(fz_array_get(obj, i));
+ func->u.sa.size[i] = pdf_to_int(pdf_array_get(obj, i));
- obj = fz_dict_gets(dict, "BitsPerSample");
- if (!fz_is_int(obj))
+ obj = pdf_dict_gets(dict, "BitsPerSample");
+ if (!pdf_is_int(obj))
fz_throw(ctx, "malformed /BitsPerSample");
- func->u.sa.bps = bps = fz_to_int(obj);
+ func->u.sa.bps = bps = pdf_to_int(obj);
- obj = fz_dict_gets(dict, "Encode");
- if (fz_is_array(obj))
+ obj = pdf_dict_gets(dict, "Encode");
+ if (pdf_is_array(obj))
{
- if (fz_array_len(obj) != func->m * 2)
+ if (pdf_array_len(obj) != func->m * 2)
fz_throw(ctx, "malformed /Encode");
for (i = 0; i < func->m; i++)
{
- func->u.sa.encode[i][0] = fz_to_real(fz_array_get(obj, i*2+0));
- func->u.sa.encode[i][1] = fz_to_real(fz_array_get(obj, i*2+1));
+ func->u.sa.encode[i][0] = pdf_to_real(pdf_array_get(obj, i*2+0));
+ func->u.sa.encode[i][1] = pdf_to_real(pdf_array_get(obj, i*2+1));
}
}
else
@@ -941,15 +957,15 @@ load_sample_func(pdf_function *func, pdf_document *xref, fz_obj *dict, int num,
}
}
- obj = fz_dict_gets(dict, "Decode");
- if (fz_is_array(obj))
+ obj = pdf_dict_gets(dict, "Decode");
+ if (pdf_is_array(obj))
{
- if (fz_array_len(obj) != func->n * 2)
+ if (pdf_array_len(obj) != func->n * 2)
fz_throw(ctx, "malformed /Decode");
for (i = 0; i < func->n; i++)
{
- func->u.sa.decode[i][0] = fz_to_real(fz_array_get(obj, i*2+0));
- func->u.sa.decode[i][1] = fz_to_real(fz_array_get(obj, i*2+1));
+ func->u.sa.decode[i][0] = pdf_to_real(pdf_array_get(obj, i*2+0));
+ func->u.sa.decode[i][1] = pdf_to_real(pdf_array_get(obj, i*2+1));
}
}
else
@@ -1110,27 +1126,27 @@ eval_sample_func(fz_context *ctx, pdf_function *func, float *in, float *out)
*/
static void
-load_exponential_func(fz_context *ctx, pdf_function *func, fz_obj *dict)
+load_exponential_func(fz_context *ctx, pdf_function *func, pdf_obj *dict)
{
- fz_obj *obj;
+ pdf_obj *obj;
int i;
if (func->m != 1)
fz_throw(ctx, "/Domain must be one dimension (%d)", func->m);
- obj = fz_dict_gets(dict, "N");
- if (!fz_is_int(obj) && !fz_is_real(obj))
+ obj = pdf_dict_gets(dict, "N");
+ if (!pdf_is_int(obj) && !pdf_is_real(obj))
fz_throw(ctx, "malformed /N");
- func->u.e.n = fz_to_real(obj);
+ func->u.e.n = pdf_to_real(obj);
- obj = fz_dict_gets(dict, "C0");
- if (fz_is_array(obj))
+ obj = pdf_dict_gets(dict, "C0");
+ if (pdf_is_array(obj))
{
- func->n = fz_array_len(obj);
+ func->n = pdf_array_len(obj);
if (func->n >= MAXN)
fz_throw(ctx, "exponential function result array out of range");
for (i = 0; i < func->n; i++)
- func->u.e.c0[i] = fz_to_real(fz_array_get(obj, i));
+ func->u.e.c0[i] = pdf_to_real(pdf_array_get(obj, i));
}
else
{
@@ -1138,13 +1154,13 @@ load_exponential_func(fz_context *ctx, pdf_function *func, fz_obj *dict)
func->u.e.c0[0] = 0;
}
- obj = fz_dict_gets(dict, "C1");
- if (fz_is_array(obj))
+ obj = pdf_dict_gets(dict, "C1");
+ if (pdf_is_array(obj))
{
- if (fz_array_len(obj) != func->n)
+ if (pdf_array_len(obj) != func->n)
fz_throw(ctx, "/C1 must match /C0 length");
for (i = 0; i < func->n; i++)
- func->u.e.c1[i] = fz_to_real(fz_array_get(obj, i));
+ func->u.e.c1[i] = pdf_to_real(pdf_array_get(obj, i));
}
else
{
@@ -1184,13 +1200,13 @@ eval_exponential_func(fz_context *ctx, pdf_function *func, float in, float *out)
*/
static void
-load_stitching_func(pdf_function *func, pdf_document *xref, fz_obj *dict)
+load_stitching_func(pdf_function *func, pdf_document *xref, pdf_obj *dict)
{
fz_context *ctx = xref->ctx;
pdf_function **funcs;
- fz_obj *obj;
- fz_obj *sub;
- fz_obj *num;
+ pdf_obj *obj;
+ pdf_obj *sub;
+ pdf_obj *num;
int k;
int i;
@@ -1199,11 +1215,11 @@ load_stitching_func(pdf_function *func, pdf_document *xref, fz_obj *dict)
if (func->m != 1)
fz_throw(ctx, "/Domain must be one dimension (%d)", func->m);
- obj = fz_dict_gets(dict, "Functions");
- if (!fz_is_array(obj))
+ obj = pdf_dict_gets(dict, "Functions");
+ if (!pdf_is_array(obj))
fz_throw(ctx, "stitching function has no input functions");
{
- k = fz_array_len(obj);
+ k = pdf_array_len(obj);
func->u.st.funcs = fz_malloc_array(ctx, k, sizeof(pdf_function*));
func->u.st.bounds = fz_malloc_array(ctx, k - 1, sizeof(float));
@@ -1212,9 +1228,9 @@ load_stitching_func(pdf_function *func, pdf_document *xref, fz_obj *dict)
for (i = 0; i < k; i++)
{
- sub = fz_array_get(obj, i);
+ sub = pdf_array_get(obj, i);
funcs[i] = pdf_load_function(xref, sub);
- /* RJW: "cannot load sub function %d (%d %d R)", i, fz_to_num(sub), fz_to_gen(sub) */
+ /* RJW: "cannot load sub function %d (%d %d R)", i, pdf_to_num(sub), pdf_to_gen(sub) */
if (funcs[i]->m != 1 || funcs[i]->n != funcs[0]->n)
fz_throw(ctx, "sub function %d /Domain or /Range mismatch", i);
func->size += pdf_function_size(funcs[i]);
@@ -1227,19 +1243,19 @@ load_stitching_func(pdf_function *func, pdf_document *xref, fz_obj *dict)
fz_throw(ctx, "sub function /Domain or /Range mismatch");
}
- obj = fz_dict_gets(dict, "Bounds");
- if (!fz_is_array(obj))
+ obj = pdf_dict_gets(dict, "Bounds");
+ if (!pdf_is_array(obj))
fz_throw(ctx, "stitching function has no bounds");
{
- if (fz_array_len(obj) != k - 1)
+ if (pdf_array_len(obj) != k - 1)
fz_throw(ctx, "malformed /Bounds (wrong length)");
for (i = 0; i < k-1; i++)
{
- num = fz_array_get(obj, i);
- if (!fz_is_int(num) && !fz_is_real(num))
+ num = pdf_array_get(obj, i);
+ if (!pdf_is_int(num) && !pdf_is_real(num))
fz_throw(ctx, "malformed /Bounds (item not real)");
- func->u.st.bounds[i] = fz_to_real(num);
+ func->u.st.bounds[i] = pdf_to_real(num);
if (i && func->u.st.bounds[i-1] > func->u.st.bounds[i])
fz_throw(ctx, "malformed /Bounds (item not monotonic)");
}
@@ -1249,16 +1265,16 @@ load_stitching_func(pdf_function *func, pdf_document *xref, fz_obj *dict)
fz_warn(ctx, "malformed shading function bounds (domain mismatch), proceeding anyway.");
}
- obj = fz_dict_gets(dict, "Encode");
- if (!fz_is_array(obj))
+ obj = pdf_dict_gets(dict, "Encode");
+ if (!pdf_is_array(obj))
fz_throw(ctx, "stitching function is missing encoding");
{
- if (fz_array_len(obj) != k * 2)
+ if (pdf_array_len(obj) != k * 2)
fz_throw(ctx, "malformed /Encode");
for (i = 0; i < k; i++)
{
- func->u.st.encode[i*2+0] = fz_to_real(fz_array_get(obj, i*2+0));
- func->u.st.encode[i*2+1] = fz_to_real(fz_array_get(obj, i*2+1));
+ func->u.st.encode[i*2+0] = pdf_to_real(pdf_array_get(obj, i*2+0));
+ func->u.st.encode[i*2+1] = pdf_to_real(pdf_array_get(obj, i*2+1));
}
}
}
@@ -1355,14 +1371,14 @@ pdf_function_size(pdf_function *func)
}
pdf_function *
-pdf_load_function(pdf_document *xref, fz_obj *dict)
+pdf_load_function(pdf_document *xref, pdf_obj *dict)
{
fz_context *ctx = xref->ctx;
pdf_function *func;
- fz_obj *obj;
+ pdf_obj *obj;
int i;
- if ((func = fz_find_item(ctx, pdf_free_function_imp, dict)))
+ if ((func = pdf_find_item(ctx, pdf_free_function_imp, dict)))
{
return func;
}
@@ -1371,28 +1387,28 @@ pdf_load_function(pdf_document *xref, fz_obj *dict)
FZ_INIT_STORABLE(func, 1, pdf_free_function_imp);
func->size = sizeof(*func);
- obj = fz_dict_gets(dict, "FunctionType");
- func->type = fz_to_int(obj);
+ obj = pdf_dict_gets(dict, "FunctionType");
+ func->type = pdf_to_int(obj);
/* required for all */
- obj = fz_dict_gets(dict, "Domain");
- func->m = fz_array_len(obj) / 2;
+ obj = pdf_dict_gets(dict, "Domain");
+ func->m = pdf_array_len(obj) / 2;
for (i = 0; i < func->m; i++)
{
- func->domain[i][0] = fz_to_real(fz_array_get(obj, i * 2 + 0));
- func->domain[i][1] = fz_to_real(fz_array_get(obj, i * 2 + 1));
+ 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 = fz_dict_gets(dict, "Range");
- if (fz_is_array(obj))
+ obj = pdf_dict_gets(dict, "Range");
+ if (pdf_is_array(obj))
{
func->has_range = 1;
- func->n = fz_array_len(obj) / 2;
+ func->n = pdf_array_len(obj) / 2;
for (i = 0; i < func->n; i++)
{
- func->range[i][0] = fz_to_real(fz_array_get(obj, i * 2 + 0));
- func->range[i][1] = fz_to_real(fz_array_get(obj, i * 2 + 1));
+ 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
@@ -1412,7 +1428,7 @@ pdf_load_function(pdf_document *xref, fz_obj *dict)
switch(func->type)
{
case SAMPLE:
- load_sample_func(func, xref, dict, fz_to_num(dict), fz_to_gen(dict));
+ load_sample_func(func, xref, dict, pdf_to_num(dict), pdf_to_gen(dict));
break;
case EXPONENTIAL:
@@ -1424,15 +1440,15 @@ pdf_load_function(pdf_document *xref, fz_obj *dict)
break;
case POSTSCRIPT:
- load_postscript_func(func, xref, dict, fz_to_num(dict), fz_to_gen(dict));
+ 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)", fz_to_num(dict), fz_to_gen(dict));
+ fz_throw(ctx, "unknown function type (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
}
- fz_store_item(ctx, dict, func, func->size);
+ pdf_store_item(ctx, dict, func, func->size);
}
fz_catch(ctx)
{
@@ -1444,7 +1460,7 @@ pdf_load_function(pdf_document *xref, fz_obj *dict)
type == STITCHING ? "stitching" :
type == POSTSCRIPT ? "calculator" :
"unknown",
- fz_to_num(dict), fz_to_gen(dict));
+ pdf_to_num(dict), pdf_to_gen(dict));
}
return func;