comparison mupdf-source/source/pdf/pdf-function.c @ 2:b50eed0cc0ef upstream

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