1#include "mupdf/fitz.h"
2#include "mupdf/pdf.h"
3
4#include <string.h>
5#include <math.h>
6#include <float.h>
7#include <limits.h>
8
9#define DIV_BY_ZERO(a, b, min, max) (((a) < 0) ^ ((b) < 0) ? (min) : (max))
10
11enum
12{
13 MAX_N = FZ_MAX_COLORS,
14 MAX_M = FZ_MAX_COLORS
15};
16
17typedef struct psobj_s psobj;
18
19enum
20{
21 SAMPLE = 0,
22 EXPONENTIAL = 2,
23 STITCHING = 3,
24 POSTSCRIPT = 4
25};
26
27struct pdf_function_s
28{
29 fz_storable storable;
30 size_t size;
31 int m; /* number of input values */
32 int n; /* number of output values */
33
34 int type; /* 0=sample 2=exponential 3=stitching 4=postscript */
35 float domain[MAX_M][2]; /* even index : min value, odd index : max value */
36 float range[MAX_N][2]; /* even index : min value, odd index : max value */
37 int has_range;
38
39 union
40 {
41 struct {
42 unsigned short bps;
43 int size[MAX_M];
44 float encode[MAX_M][2];
45 float decode[MAX_N][2];
46 float *samples;
47 } sa;
48
49 struct {
50 float n;
51 float c0[MAX_N];
52 float c1[MAX_N];
53 } e;
54
55 struct {
56 int k;
57 pdf_function **funcs; /* k */
58 float *bounds; /* k - 1 */
59 float *encode; /* k * 2 */
60 } st;
61
62 struct {
63 psobj *code;
64 int cap;
65 } p;
66 } u;
67};
68
69pdf_function *
70pdf_keep_function(fz_context *ctx, pdf_function *func)
71{
72 return fz_keep_storable(ctx, &func->storable);
73}
74
75void
76pdf_drop_function(fz_context *ctx, pdf_function *func)
77{
78 fz_drop_storable(ctx, &func->storable);
79}
80
81size_t
82pdf_function_size(fz_context *ctx, pdf_function *func)
83{
84 return (func ? func->size : 0);
85}
86
87static inline float lerp(float x, float xmin, float xmax, float ymin, float ymax)
88{
89 if (xmin == xmax)
90 return ymin;
91 if (ymin == ymax)
92 return ymin;
93 return ymin + (x - xmin) * (ymax - ymin) / (xmax - xmin);
94}
95
96/*
97 * PostScript calculator
98 */
99
100enum { PS_BOOL, PS_INT, PS_REAL, PS_OPERATOR, PS_BLOCK };
101
102enum
103{
104 PS_OP_ABS, PS_OP_ADD, PS_OP_AND, PS_OP_ATAN, PS_OP_BITSHIFT,
105 PS_OP_CEILING, PS_OP_COPY, PS_OP_COS, PS_OP_CVI, PS_OP_CVR,
106 PS_OP_DIV, PS_OP_DUP, PS_OP_EQ, PS_OP_EXCH, PS_OP_EXP,
107 PS_OP_FALSE, PS_OP_FLOOR, PS_OP_GE, PS_OP_GT, PS_OP_IDIV, PS_OP_IF,
108 PS_OP_IFELSE, PS_OP_INDEX, PS_OP_LE, PS_OP_LN, PS_OP_LOG, PS_OP_LT,
109 PS_OP_MOD, PS_OP_MUL, PS_OP_NE, PS_OP_NEG, PS_OP_NOT, PS_OP_OR,
110 PS_OP_POP, PS_OP_RETURN, PS_OP_ROLL, PS_OP_ROUND, PS_OP_SIN,
111 PS_OP_SQRT, PS_OP_SUB, PS_OP_TRUE, PS_OP_TRUNCATE, PS_OP_XOR
112};
113
114static char *ps_op_names[] =
115{
116 "abs", "add", "and", "atan", "bitshift", "ceiling", "copy",
117 "cos", "cvi", "cvr", "div", "dup", "eq", "exch", "exp",
118 "false", "floor", "ge", "gt", "idiv", "if", "ifelse", "index", "le", "ln",
119 "log", "lt", "mod", "mul", "ne", "neg", "not", "or", "pop", "return",
120 "roll", "round", "sin", "sqrt", "sub", "true", "truncate", "xor"
121};
122
123struct psobj_s
124{
125 int type;
126 union
127 {
128 int b; /* boolean (stack only) */
129 int i; /* integer (stack and code) */
130 float f; /* real (stack and code) */
131 int op; /* operator (code only) */
132 int block; /* if/ifelse block pointer (code only) */
133 } u;
134};
135
136typedef struct ps_stack_s ps_stack;
137
138struct ps_stack_s
139{
140 psobj stack[100];
141 int sp;
142};
143
144static void
145ps_init_stack(ps_stack *st)
146{
147 memset(st->stack, 0, sizeof(st->stack));
148 st->sp = 0;
149}
150
151static inline int ps_overflow(ps_stack *st, int n)
152{
153 return n < 0 || st->sp + n >= nelem(st->stack);
154}
155
156static inline int ps_underflow(ps_stack *st, int n)
157{
158 return n < 0 || n > st->sp;
159}
160
161static inline int ps_is_type(ps_stack *st, int t)
162{
163 return !ps_underflow(st, 1) && st->stack[st->sp - 1].type == t;
164}
165
166static inline int ps_is_type2(ps_stack *st, int t)
167{
168 return !ps_underflow(st, 2) && st->stack[st->sp - 1].type == t && st->stack[st->sp - 2].type == t;
169}
170
171static void
172ps_push_bool(ps_stack *st, int b)
173{
174 if (!ps_overflow(st, 1))
175 {
176 st->stack[st->sp].type = PS_BOOL;
177 st->stack[st->sp].u.b = b;
178 st->sp++;
179 }
180}
181
182static void
183ps_push_int(ps_stack *st, int n)
184{
185 if (!ps_overflow(st, 1))
186 {
187 st->stack[st->sp].type = PS_INT;
188 st->stack[st->sp].u.i = n;
189 st->sp++;
190 }
191}
192
193static void
194ps_push_real(ps_stack *st, float n)
195{
196 if (!ps_overflow(st, 1))
197 {
198 st->stack[st->sp].type = PS_REAL;
199 if (isnan(n))
200 {
201 /* Push 1.0, as it's a small known value that won't
202 * cause a divide by 0. Same reason as in fz_atof. */
203 n = 1.0f;
204 }
205 st->stack[st->sp].u.f = fz_clamp(n, -FLT_MAX, FLT_MAX);
206 st->sp++;
207 }
208}
209
210static int
211ps_pop_bool(ps_stack *st)
212{
213 if (!ps_underflow(st, 1))
214 {
215 if (ps_is_type(st, PS_BOOL))
216 return st->stack[--st->sp].u.b;
217 }
218 return 0;
219}
220
221static int
222ps_pop_int(ps_stack *st)
223{
224 if (!ps_underflow(st, 1))
225 {
226 if (ps_is_type(st, PS_INT))
227 return st->stack[--st->sp].u.i;
228 if (ps_is_type(st, PS_REAL))
229 return st->stack[--st->sp].u.f;
230 }
231 return 0;
232}
233
234static float
235ps_pop_real(ps_stack *st)
236{
237 if (!ps_underflow(st, 1))
238 {
239 if (ps_is_type(st, PS_INT))
240 return st->stack[--st->sp].u.i;
241 if (ps_is_type(st, PS_REAL))
242 return st->stack[--st->sp].u.f;
243 }
244 return 0;
245}
246
247static void
248ps_copy(ps_stack *st, int n)
249{
250 if (!ps_underflow(st, n) && !ps_overflow(st, n))
251 {
252 memcpy(st->stack + st->sp, st->stack + st->sp - n, n * sizeof(psobj));
253 st->sp += n;
254 }
255}
256
257static void
258ps_roll(ps_stack *st, int n, int j)
259{
260 psobj tmp;
261 int i;
262
263 if (ps_underflow(st, n) || j == 0 || n == 0)
264 return;
265
266 if (j >= 0)
267 {
268 j %= n;
269 }
270 else
271 {
272 j = -j % n;
273 if (j != 0)
274 j = n - j;
275 }
276
277 for (i = 0; i < j; i++)
278 {
279 tmp = st->stack[st->sp - 1];
280 memmove(st->stack + st->sp - n + 1, st->stack + st->sp - n, n * sizeof(psobj));
281 st->stack[st->sp - n] = tmp;
282 }
283}
284
285static void
286ps_index(ps_stack *st, int n)
287{
288 if (!ps_overflow(st, 1) && !ps_underflow(st, n + 1))
289 {
290 st->stack[st->sp] = st->stack[st->sp - n - 1];
291 st->sp++;
292 }
293}
294
295static void
296ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc)
297{
298 int i1, i2;
299 float r1, r2;
300 int b1, b2;
301
302 while (1)
303 {
304 switch (code[pc].type)
305 {
306 case PS_INT:
307 ps_push_int(st, code[pc++].u.i);
308 break;
309
310 case PS_REAL:
311 ps_push_real(st, code[pc++].u.f);
312 break;
313
314 case PS_OPERATOR:
315 switch (code[pc++].u.op)
316 {
317 case PS_OP_ABS:
318 if (ps_is_type(st, PS_INT))
319 ps_push_int(st, fz_absi(ps_pop_int(st)));
320 else
321 ps_push_real(st, fz_abs(ps_pop_real(st)));
322 break;
323
324 case PS_OP_ADD:
325 if (ps_is_type2(st, PS_INT)) {
326 i2 = ps_pop_int(st);
327 i1 = ps_pop_int(st);
328 ps_push_int(st, i1 + i2);
329 }
330 else {
331 r2 = ps_pop_real(st);
332 r1 = ps_pop_real(st);
333 ps_push_real(st, r1 + r2);
334 }
335 break;
336
337 case PS_OP_AND:
338 if (ps_is_type2(st, PS_INT)) {
339 i2 = ps_pop_int(st);
340 i1 = ps_pop_int(st);
341 ps_push_int(st, i1 & i2);
342 }
343 else {
344 b2 = ps_pop_bool(st);
345 b1 = ps_pop_bool(st);
346 ps_push_bool(st, b1 && b2);
347 }
348 break;
349
350 case PS_OP_ATAN:
351 r2 = ps_pop_real(st);
352 r1 = ps_pop_real(st);
353 r1 = atan2f(r1, r2) * FZ_RADIAN;
354 if (r1 < 0)
355 r1 += 360;
356 ps_push_real(st, r1);
357 break;
358
359 case PS_OP_BITSHIFT:
360 i2 = ps_pop_int(st);
361 i1 = ps_pop_int(st);
362 if (i2 > 0 && i2 < 8 * sizeof (i2))
363 ps_push_int(st, i1 << i2);
364 else if (i2 < 0 && i2 > -8 * (int)sizeof (i2))
365 ps_push_int(st, (int)((unsigned int)i1 >> -i2));
366 else
367 ps_push_int(st, i1);
368 break;
369
370 case PS_OP_CEILING:
371 r1 = ps_pop_real(st);
372 ps_push_real(st, ceilf(r1));
373 break;
374
375 case PS_OP_COPY:
376 ps_copy(st, ps_pop_int(st));
377 break;
378
379 case PS_OP_COS:
380 r1 = ps_pop_real(st);
381 ps_push_real(st, cosf(r1/FZ_RADIAN));
382 break;
383
384 case PS_OP_CVI:
385 ps_push_int(st, ps_pop_int(st));
386 break;
387
388 case PS_OP_CVR:
389 ps_push_real(st, ps_pop_real(st));
390 break;
391
392 case PS_OP_DIV:
393 r2 = ps_pop_real(st);
394 r1 = ps_pop_real(st);
395 if (fabsf(r2) >= FLT_EPSILON)
396 ps_push_real(st, r1 / r2);
397 else
398 ps_push_real(st, DIV_BY_ZERO(r1, r2, -FLT_MAX, FLT_MAX));
399 break;
400
401 case PS_OP_DUP:
402 ps_copy(st, 1);
403 break;
404
405 case PS_OP_EQ:
406 if (ps_is_type2(st, PS_BOOL)) {
407 b2 = ps_pop_bool(st);
408 b1 = ps_pop_bool(st);
409 ps_push_bool(st, b1 == b2);
410 }
411 else if (ps_is_type2(st, PS_INT)) {
412 i2 = ps_pop_int(st);
413 i1 = ps_pop_int(st);
414 ps_push_bool(st, i1 == i2);
415 }
416 else {
417 r2 = ps_pop_real(st);
418 r1 = ps_pop_real(st);
419 ps_push_bool(st, r1 == r2);
420 }
421 break;
422
423 case PS_OP_EXCH:
424 ps_roll(st, 2, 1);
425 break;
426
427 case PS_OP_EXP:
428 r2 = ps_pop_real(st);
429 r1 = ps_pop_real(st);
430 ps_push_real(st, powf(r1, r2));
431 break;
432
433 case PS_OP_FALSE:
434 ps_push_bool(st, 0);
435 break;
436
437 case PS_OP_FLOOR:
438 r1 = ps_pop_real(st);
439 ps_push_real(st, floorf(r1));
440 break;
441
442 case PS_OP_GE:
443 if (ps_is_type2(st, PS_INT)) {
444 i2 = ps_pop_int(st);
445 i1 = ps_pop_int(st);
446 ps_push_bool(st, i1 >= i2);
447 }
448 else {
449 r2 = ps_pop_real(st);
450 r1 = ps_pop_real(st);
451 ps_push_bool(st, r1 >= r2);
452 }
453 break;
454
455 case PS_OP_GT:
456 if (ps_is_type2(st, PS_INT)) {
457 i2 = ps_pop_int(st);
458 i1 = ps_pop_int(st);
459 ps_push_bool(st, i1 > i2);
460 }
461 else {
462 r2 = ps_pop_real(st);
463 r1 = ps_pop_real(st);
464 ps_push_bool(st, r1 > r2);
465 }
466 break;
467
468 case PS_OP_IDIV:
469 i2 = ps_pop_int(st);
470 i1 = ps_pop_int(st);
471 if (i2 != 0)
472 ps_push_int(st, i1 / i2);
473 else
474 ps_push_int(st, DIV_BY_ZERO(i1, i2, INT_MIN, INT_MAX));
475 break;
476
477 case PS_OP_INDEX:
478 ps_index(st, ps_pop_int(st));
479 break;
480
481 case PS_OP_LE:
482 if (ps_is_type2(st, PS_INT)) {
483 i2 = ps_pop_int(st);
484 i1 = ps_pop_int(st);
485 ps_push_bool(st, i1 <= i2);
486 }
487 else {
488 r2 = ps_pop_real(st);
489 r1 = ps_pop_real(st);
490 ps_push_bool(st, r1 <= r2);
491 }
492 break;
493
494 case PS_OP_LN:
495 r1 = ps_pop_real(st);
496 /* Bug 692941 - logf as separate statement */
497 r2 = logf(r1);
498 ps_push_real(st, r2);
499 break;
500
501 case PS_OP_LOG:
502 r1 = ps_pop_real(st);
503 ps_push_real(st, log10f(r1));
504 break;
505
506 case PS_OP_LT:
507 if (ps_is_type2(st, PS_INT)) {
508 i2 = ps_pop_int(st);
509 i1 = ps_pop_int(st);
510 ps_push_bool(st, i1 < i2);
511 }
512 else {
513 r2 = ps_pop_real(st);
514 r1 = ps_pop_real(st);
515 ps_push_bool(st, r1 < r2);
516 }
517 break;
518
519 case PS_OP_MOD:
520 i2 = ps_pop_int(st);
521 i1 = ps_pop_int(st);
522 if (i2 != 0)
523 ps_push_int(st, i1 % i2);
524 else
525 ps_push_int(st, DIV_BY_ZERO(i1, i2, INT_MIN, INT_MAX));
526 break;
527
528 case PS_OP_MUL:
529 if (ps_is_type2(st, PS_INT)) {
530 i2 = ps_pop_int(st);
531 i1 = ps_pop_int(st);
532 ps_push_int(st, i1 * i2);
533 }
534 else {
535 r2 = ps_pop_real(st);
536 r1 = ps_pop_real(st);
537 ps_push_real(st, r1 * r2);
538 }
539 break;
540
541 case PS_OP_NE:
542 if (ps_is_type2(st, PS_BOOL)) {
543 b2 = ps_pop_bool(st);
544 b1 = ps_pop_bool(st);
545 ps_push_bool(st, b1 != b2);
546 }
547 else if (ps_is_type2(st, PS_INT)) {
548 i2 = ps_pop_int(st);
549 i1 = ps_pop_int(st);
550 ps_push_bool(st, i1 != i2);
551 }
552 else {
553 r2 = ps_pop_real(st);
554 r1 = ps_pop_real(st);
555 ps_push_bool(st, r1 != r2);
556 }
557 break;
558
559 case PS_OP_NEG:
560 if (ps_is_type(st, PS_INT))
561 ps_push_int(st, -ps_pop_int(st));
562 else
563 ps_push_real(st, -ps_pop_real(st));
564 break;
565
566 case PS_OP_NOT:
567 if (ps_is_type(st, PS_BOOL))
568 ps_push_bool(st, !ps_pop_bool(st));
569 else
570 ps_push_int(st, ~ps_pop_int(st));
571 break;
572
573 case PS_OP_OR:
574 if (ps_is_type2(st, PS_BOOL)) {
575 b2 = ps_pop_bool(st);
576 b1 = ps_pop_bool(st);
577 ps_push_bool(st, b1 || b2);
578 }
579 else {
580 i2 = ps_pop_int(st);
581 i1 = ps_pop_int(st);
582 ps_push_int(st, i1 | i2);
583 }
584 break;
585
586 case PS_OP_POP:
587 if (!ps_underflow(st, 1))
588 st->sp--;
589 break;
590
591 case PS_OP_ROLL:
592 i2 = ps_pop_int(st);
593 i1 = ps_pop_int(st);
594 ps_roll(st, i1, i2);
595 break;
596
597 case PS_OP_ROUND:
598 if (!ps_is_type(st, PS_INT)) {
599 r1 = ps_pop_real(st);
600 ps_push_real(st, (r1 >= 0) ? floorf(r1 + 0.5f) : ceilf(r1 - 0.5f));
601 }
602 break;
603
604 case PS_OP_SIN:
605 r1 = ps_pop_real(st);
606 ps_push_real(st, sinf(r1/FZ_RADIAN));
607 break;
608
609 case PS_OP_SQRT:
610 r1 = ps_pop_real(st);
611 ps_push_real(st, sqrtf(r1));
612 break;
613
614 case PS_OP_SUB:
615 if (ps_is_type2(st, PS_INT)) {
616 i2 = ps_pop_int(st);
617 i1 = ps_pop_int(st);
618 ps_push_int(st, i1 - i2);
619 }
620 else {
621 r2 = ps_pop_real(st);
622 r1 = ps_pop_real(st);
623 ps_push_real(st, r1 - r2);
624 }
625 break;
626
627 case PS_OP_TRUE:
628 ps_push_bool(st, 1);
629 break;
630
631 case PS_OP_TRUNCATE:
632 if (!ps_is_type(st, PS_INT)) {
633 r1 = ps_pop_real(st);
634 ps_push_real(st, (r1 >= 0) ? floorf(r1) : ceilf(r1));
635 }
636 break;
637
638 case PS_OP_XOR:
639 if (ps_is_type2(st, PS_BOOL)) {
640 b2 = ps_pop_bool(st);
641 b1 = ps_pop_bool(st);
642 ps_push_bool(st, b1 ^ b2);
643 }
644 else {
645 i2 = ps_pop_int(st);
646 i1 = ps_pop_int(st);
647 ps_push_int(st, i1 ^ i2);
648 }
649 break;
650
651 case PS_OP_IF:
652 b1 = ps_pop_bool(st);
653 if (b1)
654 ps_run(ctx, code, st, code[pc + 1].u.block);
655 pc = code[pc + 2].u.block;
656 break;
657
658 case PS_OP_IFELSE:
659 b1 = ps_pop_bool(st);
660 if (b1)
661 ps_run(ctx, code, st, code[pc + 1].u.block);
662 else
663 ps_run(ctx, code, st, code[pc + 0].u.block);
664 pc = code[pc + 2].u.block;
665 break;
666
667 case PS_OP_RETURN:
668 return;
669
670 default:
671 fz_warn(ctx, "foreign operator in calculator function");
672 return;
673 }
674 break;
675
676 default:
677 fz_warn(ctx, "foreign object in calculator function");
678 return;
679 }
680 }
681}
682
683static void
684resize_code(fz_context *ctx, pdf_function *func, int newsize)
685{
686 if (newsize >= func->u.p.cap)
687 {
688 int new_cap = func->u.p.cap + 64;
689 func->u.p.code = fz_realloc_array(ctx, func->u.p.code, new_cap, psobj);
690 func->u.p.cap = new_cap;
691 }
692}
693
694static void
695parse_code(fz_context *ctx, pdf_function *func, fz_stream *stream, int *codeptr, pdf_lexbuf *buf)
696{
697 pdf_token tok;
698 int opptr, elseptr, ifptr;
699 int a, b, mid, cmp;
700
701 while (1)
702 {
703 tok = pdf_lex(ctx, stream, buf);
704
705 switch (tok)
706 {
707 case PDF_TOK_EOF:
708 fz_throw(ctx, FZ_ERROR_SYNTAX, "truncated calculator function");
709
710 case PDF_TOK_INT:
711 resize_code(ctx, func, *codeptr);
712 func->u.p.code[*codeptr].type = PS_INT;
713 func->u.p.code[*codeptr].u.i = buf->i;
714 ++*codeptr;
715 break;
716
717 case PDF_TOK_TRUE:
718 resize_code(ctx, func, *codeptr);
719 func->u.p.code[*codeptr].type = PS_BOOL;
720 func->u.p.code[*codeptr].u.b = 1;
721 ++*codeptr;
722 break;
723
724 case PDF_TOK_FALSE:
725 resize_code(ctx, func, *codeptr);
726 func->u.p.code[*codeptr].type = PS_BOOL;
727 func->u.p.code[*codeptr].u.b = 0;
728 ++*codeptr;
729 break;
730
731 case PDF_TOK_REAL:
732 resize_code(ctx, func, *codeptr);
733 func->u.p.code[*codeptr].type = PS_REAL;
734 func->u.p.code[*codeptr].u.f = buf->f;
735 ++*codeptr;
736 break;
737
738 case PDF_TOK_OPEN_BRACE:
739 opptr = *codeptr;
740 *codeptr += 4;
741
742 resize_code(ctx, func, *codeptr);
743
744 ifptr = *codeptr;
745 parse_code(ctx, func, stream, codeptr, buf);
746
747 tok = pdf_lex(ctx, stream, buf);
748
749 if (tok == PDF_TOK_OPEN_BRACE)
750 {
751 elseptr = *codeptr;
752 parse_code(ctx, func, stream, codeptr, buf);
753
754 tok = pdf_lex(ctx, stream, buf);
755 }
756 else
757 {
758 elseptr = -1;
759 }
760
761 if (tok != PDF_TOK_KEYWORD)
762 fz_throw(ctx, FZ_ERROR_SYNTAX, "missing keyword in 'if-else' context");
763
764 if (!strcmp(buf->scratch, "if"))
765 {
766 if (elseptr >= 0)
767 fz_throw(ctx, FZ_ERROR_SYNTAX, "too many branches for 'if'");
768 func->u.p.code[opptr].type = PS_OPERATOR;
769 func->u.p.code[opptr].u.op = PS_OP_IF;
770 func->u.p.code[opptr+2].type = PS_BLOCK;
771 func->u.p.code[opptr+2].u.block = ifptr;
772 func->u.p.code[opptr+3].type = PS_BLOCK;
773 func->u.p.code[opptr+3].u.block = *codeptr;
774 }
775 else if (!strcmp(buf->scratch, "ifelse"))
776 {
777 if (elseptr < 0)
778 fz_throw(ctx, FZ_ERROR_SYNTAX, "not enough branches for 'ifelse'");
779 func->u.p.code[opptr].type = PS_OPERATOR;
780 func->u.p.code[opptr].u.op = PS_OP_IFELSE;
781 func->u.p.code[opptr+1].type = PS_BLOCK;
782 func->u.p.code[opptr+1].u.block = elseptr;
783 func->u.p.code[opptr+2].type = PS_BLOCK;
784 func->u.p.code[opptr+2].u.block = ifptr;
785 func->u.p.code[opptr+3].type = PS_BLOCK;
786 func->u.p.code[opptr+3].u.block = *codeptr;
787 }
788 else
789 {
790 fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown keyword in 'if-else' context: '%s'", buf->scratch);
791 }
792 break;
793
794 case PDF_TOK_CLOSE_BRACE:
795 resize_code(ctx, func, *codeptr);
796 func->u.p.code[*codeptr].type = PS_OPERATOR;
797 func->u.p.code[*codeptr].u.op = PS_OP_RETURN;
798 ++*codeptr;
799 return;
800
801 case PDF_TOK_KEYWORD:
802 cmp = -1;
803 a = -1;
804 b = nelem(ps_op_names);
805 while (b - a > 1)
806 {
807 mid = (a + b) / 2;
808 cmp = strcmp(buf->scratch, ps_op_names[mid]);
809 if (cmp > 0)
810 a = mid;
811 else if (cmp < 0)
812 b = mid;
813 else
814 a = b = mid;
815 }
816 if (cmp != 0)
817 fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown operator: '%s'", buf->scratch);
818 if (a == PS_OP_IFELSE)
819 fz_throw(ctx, FZ_ERROR_SYNTAX, "illegally positioned ifelse operator in function");
820 if (a == PS_OP_IF)
821 fz_throw(ctx, FZ_ERROR_SYNTAX, "illegally positioned if operator in function");
822
823 resize_code(ctx, func, *codeptr);
824 func->u.p.code[*codeptr].type = PS_OPERATOR;
825 func->u.p.code[*codeptr].u.op = a;
826 ++*codeptr;
827 break;
828
829 default:
830 fz_throw(ctx, FZ_ERROR_SYNTAX, "calculator function syntax error");
831 }
832 }
833}
834
835static void
836load_postscript_func(fz_context *ctx, pdf_function *func, pdf_obj *dict)
837{
838 fz_stream *stream = NULL;
839 int codeptr;
840 pdf_lexbuf buf;
841 pdf_token tok;
842
843 pdf_lexbuf_init(ctx, &buf, PDF_LEXBUF_SMALL);
844
845 fz_var(stream);
846
847 fz_try(ctx)
848 {
849 stream = pdf_open_stream(ctx, dict);
850
851 tok = pdf_lex(ctx, stream, &buf);
852 if (tok != PDF_TOK_OPEN_BRACE)
853 {
854 fz_throw(ctx, FZ_ERROR_SYNTAX, "stream is not a calculator function");
855 }
856
857 func->u.p.code = NULL;
858 func->u.p.cap = 0;
859
860 codeptr = 0;
861 parse_code(ctx, func, stream, &codeptr, &buf);
862 }
863 fz_always(ctx)
864 {
865 fz_drop_stream(ctx, stream);
866 pdf_lexbuf_fin(ctx, &buf);
867 }
868 fz_catch(ctx)
869 {
870 fz_rethrow(ctx);
871 }
872
873 func->size += func->u.p.cap * sizeof(psobj);
874}
875
876static void
877eval_postscript_func(fz_context *ctx, pdf_function *func, const float *in, float *out)
878{
879 ps_stack st;
880 float x;
881 int i;
882
883 ps_init_stack(&st);
884
885 for (i = 0; i < func->m; i++)
886 {
887 x = fz_clamp(in[i], func->domain[i][0], func->domain[i][1]);
888 ps_push_real(&st, x);
889 }
890
891 ps_run(ctx, func->u.p.code, &st, 0);
892
893 for (i = func->n - 1; i >= 0; i--)
894 {
895 x = ps_pop_real(&st);
896 out[i] = fz_clamp(x, func->range[i][0], func->range[i][1]);
897 }
898}
899
900/*
901 * Sample function
902 */
903
904#define MAX_SAMPLE_FUNCTION_SIZE (100 << 20)
905
906static void
907load_sample_func(fz_context *ctx, pdf_function *func, pdf_obj *dict)
908{
909 fz_stream *stream;
910 pdf_obj *obj;
911 int samplecount;
912 int bps;
913 int i;
914
915 func->u.sa.samples = NULL;
916
917 obj = pdf_dict_get(ctx, dict, PDF_NAME(Size));
918 if (pdf_array_len(ctx, obj) < func->m)
919 fz_throw(ctx, FZ_ERROR_SYNTAX, "too few sample function dimension sizes");
920 if (pdf_array_len(ctx, obj) > func->m)
921 fz_warn(ctx, "too many sample function dimension sizes");
922 for (i = 0; i < func->m; i++)
923 {
924 func->u.sa.size[i] = pdf_array_get_int(ctx, obj, i);
925 if (func->u.sa.size[i] <= 0)
926 {
927 fz_warn(ctx, "non-positive sample function dimension size");
928 func->u.sa.size[i] = 1;
929 }
930 }
931
932 obj = pdf_dict_get(ctx, dict, PDF_NAME(BitsPerSample));
933 func->u.sa.bps = bps = pdf_to_int(ctx, obj);
934
935 for (i = 0; i < func->m; i++)
936 {
937 func->u.sa.encode[i][0] = 0;
938 func->u.sa.encode[i][1] = func->u.sa.size[i] - 1;
939 }
940 obj = pdf_dict_get(ctx, dict, PDF_NAME(Encode));
941 if (pdf_is_array(ctx, obj))
942 {
943 int ranges = fz_mini(func->m, pdf_array_len(ctx, obj) / 2);
944 if (ranges != func->m)
945 fz_warn(ctx, "wrong number of sample function input mappings");
946
947 for (i = 0; i < ranges; i++)
948 {
949 func->u.sa.encode[i][0] = pdf_array_get_real(ctx, obj, i * 2 + 0);
950 func->u.sa.encode[i][1] = pdf_array_get_real(ctx, obj, i * 2 + 1);
951 }
952 }
953
954 for (i = 0; i < func->n; i++)
955 {
956 func->u.sa.decode[i][0] = func->range[i][0];
957 func->u.sa.decode[i][1] = func->range[i][1];
958 }
959
960 obj = pdf_dict_get(ctx, dict, PDF_NAME(Decode));
961 if (pdf_is_array(ctx, obj))
962 {
963 int ranges = fz_mini(func->n, pdf_array_len(ctx, obj) / 2);
964 if (ranges != func->n)
965 fz_warn(ctx, "wrong number of sample function output mappings");
966
967 for (i = 0; i < ranges; i++)
968 {
969 func->u.sa.decode[i][0] = pdf_array_get_real(ctx, obj, i * 2 + 0);
970 func->u.sa.decode[i][1] = pdf_array_get_real(ctx, obj, i * 2 + 1);
971 }
972 }
973
974 for (i = 0, samplecount = func->n; i < func->m; i++)
975 samplecount *= func->u.sa.size[i];
976
977 if (samplecount > MAX_SAMPLE_FUNCTION_SIZE)
978 fz_throw(ctx, FZ_ERROR_SYNTAX, "sample function too large");
979
980 func->u.sa.samples = fz_malloc_array(ctx, samplecount, float);
981 func->size += samplecount * sizeof(float);
982
983 stream = pdf_open_stream(ctx, dict);
984
985 fz_try(ctx)
986 {
987 /* read samples */
988 for (i = 0; i < samplecount; i++)
989 {
990 float s;
991
992 if (fz_is_eof_bits(ctx, stream))
993 fz_throw(ctx, FZ_ERROR_SYNTAX, "truncated sample function stream");
994
995 switch (bps)
996 {
997 case 1: s = fz_read_bits(ctx, stream, 1); break;
998 case 2: s = fz_read_bits(ctx, stream, 2) / 3.0f; break;
999 case 4: s = fz_read_bits(ctx, stream, 4) / 15.0f; break;
1000 case 8: s = fz_read_byte(ctx, stream) / 255.0f; break;
1001 case 12: s = fz_read_bits(ctx, stream, 12) / 4095.0f; break;
1002 case 16: s = fz_read_uint16(ctx, stream) / 65535.0f; break;
1003 case 24: s = fz_read_uint24(ctx, stream) / 16777215.0f; break;
1004 case 32: s = fz_read_uint32(ctx, stream) / 4294967295.0f; break;
1005 default: fz_throw(ctx, FZ_ERROR_SYNTAX, "sample stream bit depth %d unsupported", bps);
1006 }
1007
1008 func->u.sa.samples[i] = s;
1009 }
1010 }
1011 fz_always(ctx)
1012 {
1013 fz_drop_stream(ctx, stream);
1014 }
1015 fz_catch(ctx)
1016 {
1017 fz_rethrow(ctx);
1018 }
1019}
1020
1021static float
1022interpolate_sample(pdf_function *func, int *scale, int *e0, int *e1, float *efrac, int dim, int idx)
1023{
1024 float a, b;
1025 int idx0, idx1;
1026
1027 idx0 = e0[dim] * scale[dim] + idx;
1028 idx1 = e1[dim] * scale[dim] + idx;
1029
1030 if (dim == 0)
1031 {
1032 a = func->u.sa.samples[idx0];
1033 b = func->u.sa.samples[idx1];
1034 }
1035 else
1036 {
1037 a = interpolate_sample(func, scale, e0, e1, efrac, dim - 1, idx0);
1038 b = interpolate_sample(func, scale, e0, e1, efrac, dim - 1, idx1);
1039 }
1040
1041 return a + (b - a) * efrac[dim];
1042}
1043
1044static void
1045eval_sample_func(fz_context *ctx, pdf_function *func, const float *in, float *out)
1046{
1047 int e0[MAX_M], e1[MAX_M], scale[MAX_M];
1048 float efrac[MAX_M];
1049 float x;
1050 int i;
1051
1052 /* encode input coordinates */
1053 for (i = 0; i < func->m; i++)
1054 {
1055 x = fz_clamp(in[i], func->domain[i][0], func->domain[i][1]);
1056 x = lerp(x, func->domain[i][0], func->domain[i][1],
1057 func->u.sa.encode[i][0], func->u.sa.encode[i][1]);
1058 x = fz_clamp(x, 0, func->u.sa.size[i] - 1);
1059 e0[i] = floorf(x);
1060 e1[i] = ceilf(x);
1061 efrac[i] = x - e0[i];
1062 }
1063
1064 scale[0] = func->n;
1065 for (i = 1; i < func->m; i++)
1066 scale[i] = scale[i - 1] * func->u.sa.size[i-1];
1067
1068 for (i = 0; i < func->n; i++)
1069 {
1070 if (func->m == 1)
1071 {
1072 float a = func->u.sa.samples[e0[0] * func->n + i];
1073 float b = func->u.sa.samples[e1[0] * func->n + i];
1074
1075 float ab = a + (b - a) * efrac[0];
1076
1077 out[i] = lerp(ab, 0, 1, func->u.sa.decode[i][0], func->u.sa.decode[i][1]);
1078 out[i] = fz_clamp(out[i], func->range[i][0], func->range[i][1]);
1079 }
1080
1081 else if (func->m == 2)
1082 {
1083 int s0 = func->n;
1084 int s1 = s0 * func->u.sa.size[0];
1085
1086 float a = func->u.sa.samples[e0[0] * s0 + e0[1] * s1 + i];
1087 float b = func->u.sa.samples[e1[0] * s0 + e0[1] * s1 + i];
1088 float c = func->u.sa.samples[e0[0] * s0 + e1[1] * s1 + i];
1089 float d = func->u.sa.samples[e1[0] * s0 + e1[1] * s1 + i];
1090
1091 float ab = a + (b - a) * efrac[0];
1092 float cd = c + (d - c) * efrac[0];
1093 float abcd = ab + (cd - ab) * efrac[1];
1094
1095 out[i] = lerp(abcd, 0, 1, func->u.sa.decode[i][0], func->u.sa.decode[i][1]);
1096 out[i] = fz_clamp(out[i], func->range[i][0], func->range[i][1]);
1097 }
1098
1099 else
1100 {
1101 x = interpolate_sample(func, scale, e0, e1, efrac, func->m - 1, i);
1102 out[i] = lerp(x, 0, 1, func->u.sa.decode[i][0], func->u.sa.decode[i][1]);
1103 out[i] = fz_clamp(out[i], func->range[i][0], func->range[i][1]);
1104 }
1105 }
1106}
1107
1108/*
1109 * Exponential function
1110 */
1111
1112static void
1113load_exponential_func(fz_context *ctx, pdf_function *func, pdf_obj *dict)
1114{
1115 pdf_obj *obj;
1116 int i;
1117
1118 if (func->m > 1)
1119 fz_warn(ctx, "exponential functions have at most one input");
1120 func->m = 1;
1121
1122 obj = pdf_dict_get(ctx, dict, PDF_NAME(N));
1123 func->u.e.n = pdf_to_real(ctx, obj);
1124
1125 /* See exponential functions (PDF 1.7 section 3.9.2) */
1126 if (func->u.e.n != (int) func->u.e.n)
1127 {
1128 /* If N is non-integer, input values may never be negative */
1129 for (i = 0; i < func->m; i++)
1130 if (func->domain[i][0] < 0 || func->domain[i][1] < 0)
1131 fz_warn(ctx, "exponential function input domain includes illegal negative input values");
1132 }
1133 else if (func->u.e.n < 0)
1134 {
1135 /* if N is negative, input values may never be zero */
1136 for (i = 0; i < func->m; i++)
1137 if (func->domain[i][0] == 0 || func->domain[i][1] == 0 ||
1138 (func->domain[i][0] < 0 && func->domain[i][1] > 0))
1139 fz_warn(ctx, "exponential function input domain includes illegal input value zero");
1140 }
1141
1142 for (i = 0; i < func->n; i++)
1143 {
1144 func->u.e.c0[i] = 0;
1145 func->u.e.c1[i] = 1;
1146 }
1147
1148 obj = pdf_dict_get(ctx, dict, PDF_NAME(C0));
1149 if (pdf_is_array(ctx, obj))
1150 {
1151 int ranges = fz_mini(func->n, pdf_array_len(ctx, obj));
1152 if (ranges != func->n)
1153 fz_warn(ctx, "wrong number of C0 constants for exponential function");
1154
1155 for (i = 0; i < ranges; i++)
1156 func->u.e.c0[i] = pdf_array_get_real(ctx, obj, i);
1157 }
1158
1159 obj = pdf_dict_get(ctx, dict, PDF_NAME(C1));
1160 if (pdf_is_array(ctx, obj))
1161 {
1162 int ranges = fz_mini(func->n, pdf_array_len(ctx, obj));
1163 if (ranges != func->n)
1164 fz_warn(ctx, "wrong number of C1 constants for exponential function");
1165
1166 for (i = 0; i < ranges; i++)
1167 func->u.e.c1[i] = pdf_array_get_real(ctx, obj, i);
1168 }
1169}
1170
1171static void
1172eval_exponential_func(fz_context *ctx, pdf_function *func, float in, float *out)
1173{
1174 float x = in;
1175 float tmp;
1176 int i;
1177
1178 x = fz_clamp(x, func->domain[0][0], func->domain[0][1]);
1179
1180 /* Default output is zero, which is suitable for violated constraints */
1181 if ((func->u.e.n != (int)func->u.e.n && x < 0) || (func->u.e.n < 0 && x == 0))
1182 return;
1183
1184 tmp = powf(x, func->u.e.n);
1185 for (i = 0; i < func->n; i++)
1186 {
1187 out[i] = func->u.e.c0[i] + tmp * (func->u.e.c1[i] - func->u.e.c0[i]);
1188 if (func->has_range)
1189 out[i] = fz_clamp(out[i], func->range[i][0], func->range[i][1]);
1190 }
1191}
1192
1193/*
1194 * Stitching function
1195 */
1196
1197static void
1198load_stitching_func(fz_context *ctx, pdf_function *func, pdf_obj *dict)
1199{
1200 pdf_function **funcs;
1201 pdf_obj *obj;
1202 pdf_obj *sub;
1203 pdf_obj *num;
1204 int k;
1205 int i;
1206
1207 func->u.st.k = 0;
1208
1209 if (func->m > 1)
1210 fz_warn(ctx, "stitching functions have at most one input");
1211 func->m = 1;
1212
1213 obj = pdf_dict_get(ctx, dict, PDF_NAME(Functions));
1214 if (!pdf_is_array(ctx, obj))
1215 fz_throw(ctx, FZ_ERROR_SYNTAX, "stitching function has no input functions");
1216
1217 fz_try(ctx)
1218 {
1219 if (pdf_mark_obj(ctx, obj))
1220 fz_throw(ctx, FZ_ERROR_SYNTAX, "recursive function");
1221 k = pdf_array_len(ctx, obj);
1222
1223 func->u.st.funcs = fz_malloc_array(ctx, k, pdf_function*);
1224 func->u.st.bounds = fz_malloc_array(ctx, k - 1, float);
1225 func->u.st.encode = fz_malloc_array(ctx, k * 2, float);
1226 funcs = func->u.st.funcs;
1227
1228 for (i = 0; i < k; i++)
1229 {
1230 sub = pdf_array_get(ctx, obj, i);
1231 funcs[i] = pdf_load_function(ctx, sub, 1, func->n);
1232
1233 func->size += pdf_function_size(ctx, funcs[i]);
1234 func->u.st.k ++;
1235
1236 if (funcs[i]->m != func->m)
1237 fz_warn(ctx, "wrong number of inputs for sub function %d", i);
1238 if (funcs[i]->n != func->n)
1239 fz_warn(ctx, "wrong number of outputs for sub function %d", i);
1240 }
1241 }
1242 fz_always(ctx)
1243 {
1244 pdf_unmark_obj(ctx, obj);
1245 }
1246 fz_catch(ctx)
1247 {
1248 fz_rethrow(ctx);
1249 }
1250
1251 obj = pdf_dict_get(ctx, dict, PDF_NAME(Bounds));
1252 if (!pdf_is_array(ctx, obj))
1253 fz_throw(ctx, FZ_ERROR_SYNTAX, "stitching function has no bounds");
1254 {
1255 if (pdf_array_len(ctx, obj) < k - 1)
1256 fz_throw(ctx, FZ_ERROR_SYNTAX, "too few subfunction boundaries");
1257 if (pdf_array_len(ctx, obj) > k)
1258 fz_warn(ctx, "too many subfunction boundaries");
1259
1260 for (i = 0; i < k - 1; i++)
1261 {
1262 num = pdf_array_get(ctx, obj, i);
1263 func->u.st.bounds[i] = pdf_to_real(ctx, num);
1264 if (i && func->u.st.bounds[i - 1] > func->u.st.bounds[i])
1265 fz_throw(ctx, FZ_ERROR_SYNTAX, "subfunction %d boundary out of range", i);
1266 }
1267
1268 if (k > 1 && (func->domain[0][0] > func->u.st.bounds[0] ||
1269 func->domain[0][1] < func->u.st.bounds[k - 2]))
1270 fz_warn(ctx, "subfunction boundaries outside of input mapping");
1271 }
1272
1273 for (i = 0; i < k; i++)
1274 {
1275 func->u.st.encode[i * 2 + 0] = 0;
1276 func->u.st.encode[i * 2 + 1] = 0;
1277 }
1278
1279 obj = pdf_dict_get(ctx, dict, PDF_NAME(Encode));
1280 if (pdf_is_array(ctx, obj))
1281 {
1282 int ranges = fz_mini(k, pdf_array_len(ctx, obj) / 2);
1283 if (ranges != k)
1284 fz_warn(ctx, "wrong number of stitching function input mappings");
1285
1286 for (i = 0; i < ranges; i++)
1287 {
1288 func->u.st.encode[i * 2 + 0] = pdf_array_get_real(ctx, obj, i * 2 + 0);
1289 func->u.st.encode[i * 2 + 1] = pdf_array_get_real(ctx, obj, i * 2 + 1);
1290 }
1291 }
1292}
1293
1294static void
1295eval_stitching_func(fz_context *ctx, pdf_function *func, float in, float *out)
1296{
1297 float low, high;
1298 int k = func->u.st.k;
1299 float *bounds = func->u.st.bounds;
1300 int i;
1301
1302 in = fz_clamp(in, func->domain[0][0], func->domain[0][1]);
1303
1304 for (i = 0; i < k - 1; i++)
1305 {
1306 if (in < bounds[i])
1307 break;
1308 }
1309
1310 if (i == 0 && k == 1)
1311 {
1312 low = func->domain[0][0];
1313 high = func->domain[0][1];
1314 }
1315 else if (i == 0)
1316 {
1317 low = func->domain[0][0];
1318 high = bounds[0];
1319 }
1320 else if (i == k - 1)
1321 {
1322 low = bounds[k - 2];
1323 high = func->domain[0][1];
1324 }
1325 else
1326 {
1327 low = bounds[i - 1];
1328 high = bounds[i];
1329 }
1330
1331 in = lerp(in, low, high, func->u.st.encode[i * 2 + 0], func->u.st.encode[i * 2 + 1]);
1332
1333 pdf_eval_function(ctx, func->u.st.funcs[i], &in, 1, out, func->n);
1334}
1335
1336/*
1337 * Common
1338 */
1339
1340static void
1341pdf_drop_function_imp(fz_context *ctx, fz_storable *func_)
1342{
1343 pdf_function *func = (pdf_function *)func_;
1344 int i;
1345
1346 switch (func->type)
1347 {
1348 case SAMPLE:
1349 fz_free(ctx, func->u.sa.samples);
1350 break;
1351 case EXPONENTIAL:
1352 break;
1353 case STITCHING:
1354 for (i = 0; i < func->u.st.k; i++)
1355 pdf_drop_function(ctx, func->u.st.funcs[i]);
1356 fz_free(ctx, func->u.st.funcs);
1357 fz_free(ctx, func->u.st.bounds);
1358 fz_free(ctx, func->u.st.encode);
1359 break;
1360 case POSTSCRIPT:
1361 fz_free(ctx, func->u.p.code);
1362 break;
1363 }
1364 fz_free(ctx, func);
1365}
1366
1367static void
1368pdf_eval_function_imp(fz_context *ctx, pdf_function *func, const float *in, float *out)
1369{
1370 switch (func->type)
1371 {
1372 case SAMPLE: eval_sample_func(ctx, func, in, out); break;
1373 case EXPONENTIAL: eval_exponential_func(ctx, func, *in, out); break;
1374 case STITCHING: eval_stitching_func(ctx, func, *in, out); break;
1375 case POSTSCRIPT: eval_postscript_func(ctx, func, in, out); break;
1376 }
1377}
1378
1379void
1380pdf_eval_function(fz_context *ctx, pdf_function *func, const float *in, int inlen, float *out, int outlen)
1381{
1382 float fakein[MAX_M];
1383 float fakeout[MAX_N];
1384 int i;
1385
1386 if (inlen < func->m)
1387 {
1388 for (i = 0; i < inlen; ++i)
1389 fakein[i] = in[i];
1390 for (; i < func->m; ++i)
1391 fakein[i] = 0;
1392 in = fakein;
1393 }
1394
1395 if (outlen < func->n)
1396 {
1397 pdf_eval_function_imp(ctx, func, in, fakeout);
1398 for (i = 0; i < outlen; ++i)
1399 out[i] = fakeout[i];
1400 }
1401 else
1402 {
1403 pdf_eval_function_imp(ctx, func, in, out);
1404 for (i = func->n; i < outlen; ++i)
1405 out[i] = 0;
1406 }
1407}
1408
1409pdf_function *
1410pdf_load_function(fz_context *ctx, pdf_obj *dict, int in, int out)
1411{
1412 pdf_function *func;
1413 pdf_obj *obj;
1414 int i;
1415
1416 if (pdf_obj_marked(ctx, dict))
1417 fz_throw(ctx, FZ_ERROR_SYNTAX, "Recursion in function definition");
1418
1419 if ((func = pdf_find_item(ctx, pdf_drop_function_imp, dict)) != NULL)
1420 return func;
1421
1422 func = fz_malloc_struct(ctx, pdf_function);
1423 FZ_INIT_STORABLE(func, 1, pdf_drop_function_imp);
1424 func->size = sizeof(*func);
1425
1426 obj = pdf_dict_get(ctx, dict, PDF_NAME(FunctionType));
1427 func->type = pdf_to_int(ctx, obj);
1428
1429 /* required for all */
1430 obj = pdf_dict_get(ctx, dict, PDF_NAME(Domain));
1431 func->m = fz_clampi(pdf_array_len(ctx, obj) / 2, 1, MAX_M);
1432 for (i = 0; i < func->m; i++)
1433 {
1434 func->domain[i][0] = pdf_array_get_real(ctx, obj, i * 2 + 0);
1435 func->domain[i][1] = pdf_array_get_real(ctx, obj, i * 2 + 1);
1436 }
1437
1438 /* required for type0 and type4, optional otherwise */
1439 obj = pdf_dict_get(ctx, dict, PDF_NAME(Range));
1440 if (pdf_is_array(ctx, obj))
1441 {
1442 func->has_range = 1;
1443 func->n = fz_clampi(pdf_array_len(ctx, obj) / 2, 1, MAX_N);
1444 for (i = 0; i < func->n; i++)
1445 {
1446 func->range[i][0] = pdf_array_get_real(ctx, obj, i * 2 + 0);
1447 func->range[i][1] = pdf_array_get_real(ctx, obj, i * 2 + 1);
1448 }
1449 }
1450 else
1451 {
1452 func->has_range = 0;
1453 func->n = out;
1454 }
1455
1456 if (func->m != in)
1457 fz_warn(ctx, "wrong number of function inputs");
1458 if (func->n != out)
1459 fz_warn(ctx, "wrong number of function outputs");
1460
1461 fz_try(ctx)
1462 {
1463 switch (func->type)
1464 {
1465 case SAMPLE:
1466 load_sample_func(ctx, func, dict);
1467 break;
1468
1469 case EXPONENTIAL:
1470 load_exponential_func(ctx, func, dict);
1471 break;
1472
1473 case STITCHING:
1474 load_stitching_func(ctx, func, dict);
1475 break;
1476
1477 case POSTSCRIPT:
1478 load_postscript_func(ctx, func, dict);
1479 break;
1480
1481 default:
1482 fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown function type (%d 0 R)", pdf_to_num(ctx, dict));
1483 }
1484
1485 pdf_store_item(ctx, dict, func, func->size);
1486 }
1487 fz_catch(ctx)
1488 {
1489 pdf_drop_function(ctx, func);
1490 fz_rethrow(ctx);
1491 }
1492
1493 return func;
1494}
1495