1 : /* -*- mode: C -*- Time-stamp: "2010-06-29 13:39:12 jemarch"
2 : *
3 : * File: pdf-fp-func.c
4 : * Date: Sun Nov 30 18:46:06 2008
5 : *
6 : * GNU PDF Library - Functions
7 : *
8 : */
9 :
10 : /* Copyright (C) 2008 Free Software Foundation, Inc. */
11 :
12 : /* This program is free software: you can redistribute it and/or modify
13 : * it under the terms of the GNU General Public License as published by
14 : * the Free Software Foundation, either version 3 of the License, or
15 : * (at your option) any later version.
16 : *
17 : * This program is distributed in the hope that it will be useful,
18 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : * GNU General Public License for more details.
21 : *
22 : * You should have received a copy of the GNU General Public License
23 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include <config.h>
27 :
28 : #include <stdlib.h>
29 : #include <math.h>
30 : #include <limits.h>
31 : #include <ctype.h>
32 : #include <string.h>
33 :
34 : #include <pdf-error.h>
35 : #include <pdf-alloc.h>
36 : #include <pdf-stm.h>
37 : #include <pdf-token-reader.h>
38 : #include <pdf-fp-func.h>
39 :
40 : static pdf_real_t *
41 : read_type0_sample_table (pdf_char_t *buf, pdf_size_t buf_size,
42 : pdf_u32_t bps, pdf_u32_t nsamples , pdf_u32_t n);
43 :
44 : static pdf_i32_t get_token (pdf_token_reader_t reader,
45 : double *literal,
46 : pdf_size_t *token_begin);
47 : static inline void setmap (double map[2],
48 : const pdf_real_t to[2],
49 : const pdf_real_t from[2]);
50 :
51 : static pdf_status_t pdf_eval_spline (pdf_fp_func_t fun,
52 : const pdf_real_t t[],
53 : pdf_real_t out[],
54 : pdf_fp_func_debug_t * debug);
55 :
56 : static pdf_status_t pdf_eval_linear (pdf_fp_func_t fun,
57 : const pdf_real_t t[],
58 : pdf_real_t out[],
59 : pdf_fp_func_debug_t * debug);
60 :
61 : static pdf_status_t pdf_eval_exponential (pdf_fp_func_t t,
62 : const pdf_real_t in[],
63 : pdf_real_t out[],
64 : pdf_fp_func_debug_t * debug);
65 :
66 : static pdf_status_t pdf_eval_stitch (pdf_fp_func_t t,
67 : const pdf_real_t in[],
68 : pdf_real_t out[],
69 : pdf_fp_func_debug_t * debug);
70 :
71 : static pdf_status_t pdf_eval_type4(pdf_fp_func_t t,
72 : const pdf_real_t in[],
73 : pdf_real_t out[],
74 : pdf_fp_func_debug_t * debug);
75 :
76 : typedef enum
77 : {
78 : OPC_ret, /* end of function, return result */
79 : OPC_jnt, /* jump if not true , offset follows */
80 : OPC_jmp, /* jump always, offset follows */
81 : OPC_lit_i, /* integer literal follows. */
82 : OPC_lit_r, /* real literal follows. */
83 : OPC_begin, /* token opening brace */
84 : OPC_end, /* token closing brace */
85 : OPC_if, /* token */
86 : OPC_ifelse,/* token */
87 : OPC_bad, /* bad token */
88 :
89 : OPC_floor,
90 : OPC_ceiling,
91 : OPC_truncate,
92 : OPC_round,
93 :
94 : OPC_abs,
95 : OPC_sqrt,
96 : OPC_atan,
97 : OPC_sin,
98 : OPC_cos,
99 : OPC_exp,
100 : OPC_log,
101 : OPC_ln,
102 : OPC_neg,
103 : OPC_cvi,
104 : OPC_cvr,
105 :
106 : OPC_mod,
107 : OPC_div,
108 : OPC_add,
109 : OPC_idiv,
110 : OPC_bitshift,
111 : OPC_mul,
112 : OPC_sub,
113 :
114 : OPC_true,
115 : OPC_false,
116 : OPC_not,
117 : OPC_and,
118 : OPC_or,
119 : OPC_xor,
120 :
121 : OPC_eq,
122 : OPC_le,
123 : OPC_ge,
124 : OPC_lt,
125 : OPC_gt,
126 : OPC_ne,
127 :
128 :
129 : OPC_copy,
130 : OPC_exch,
131 : OPC_pop,
132 : OPC_dup,
133 : OPC_index,
134 : OPC_roll
135 : } PDF_TYPE4_OPC;
136 :
137 :
138 : /*
139 : * Public functions
140 : */
141 :
142 : pdf_status_t
143 : pdf_fp_func_0_new (pdf_u32_t m,
144 : pdf_u32_t n,
145 : const pdf_real_t domain[],
146 : const pdf_real_t range[],
147 : pdf_u32_t size[],
148 : pdf_u32_t bps,
149 : pdf_u32_t order,
150 : const pdf_real_t encode[],
151 : const pdf_real_t decode[],
152 : pdf_char_t *samples,
153 : pdf_size_t samples_size,
154 : pdf_fp_func_t *function)
155 0 : {
156 : pdf_status_t ret;
157 : pdf_fp_func_t f;
158 : pdf_u32_t i, j, k;
159 : pdf_u32_t nsamples;
160 : pdf_u32_t nsamples_limit;
161 :
162 0 : ret = PDF_OK;
163 :
164 : /* Common data */
165 0 : f = pdf_alloc (sizeof(struct pdf_fp_func_s));
166 0 : f->m = m;
167 0 : f->n = n;
168 0 : f->type = 0;
169 :
170 : /* Specific data */
171 0 : f->u.t0.size = size;
172 :
173 : /* Get the number of samples */
174 0 : nsamples = 1;
175 0 : nsamples_limit = 1U<<28/f->n; /* insane values */
176 0 : for (i = 0; i < m; i++)
177 : {
178 0 : if (f->u.t0.size[i] > nsamples_limit/nsamples) /* avoid overflow */
179 : {
180 0 : return PDF_EOVERFLOW;
181 : }
182 0 : nsamples *= f->u.t0.size[i];
183 : }
184 0 : f->u.t0.nsamples = nsamples;
185 :
186 : /* Manage the bits per sample value */
187 0 : switch (bps)
188 : {
189 : case 1:
190 : case 2:
191 : case 4:
192 : case 8:
193 : case 12:
194 : case 16:
195 : case 24:
196 : case 32: /* possible loss of precision in conversion to pdf_real_t */
197 : {
198 : break;
199 : }
200 : default:
201 : {
202 : /* ths implementation allows any value between 1 and 32 */
203 : /* the spec does not */
204 0 : return PDF_EBADDATA;
205 : }
206 : }
207 :
208 0 : f->u.t0.m = f->m;
209 0 : f->u.t0.n = f->n;
210 :
211 0 : if (f->u.t0.m > 12 ) /* sanity check */
212 : {
213 0 : return PDF_EMTOOBIG;
214 : }
215 :
216 0 : f->u.t0.y = read_type0_sample_table (samples,
217 : samples_size,
218 : bps,
219 : nsamples,
220 : f->n);
221 0 : if (!f->u.t0.y)
222 : {
223 0 : return PDF_EBADSAMPLES;
224 : }
225 :
226 0 : if (encode != NULL)
227 : {
228 0 : f->u.t0.encode = pdf_alloc (2 * f->m * sizeof(f->u.t0.encode[0]));
229 0 : for (k = 0; k < f->m; k++)
230 : {
231 0 : setmap(f->u.t0.encode + (2 * k),
232 : encode + (2 * k),
233 : f->domain + (2 * k));
234 : }
235 : }
236 : else
237 : {
238 : /* Use the default encoding array */
239 : pdf_real_t enc[2];
240 :
241 0 : enc[0] = 0;
242 0 : for (k = 0; k < f->m; k++)
243 : {
244 0 : enc[1] = f->u.t0.size[k] - 1;
245 0 : setmap(f->u.t0.encode + 2*k, enc, f->domain+2*k);
246 : }
247 : }
248 :
249 0 : if (decode != NULL)
250 : {
251 0 : f->u.t0.decode = pdf_alloc (2 * f->n * sizeof(f->u.t0.decode[0]));
252 0 : for (j = 0; j < f->n; j++)
253 : {
254 0 : setmap (f->u.t0.decode + (2 * j),
255 : f->range + (2 * j),
256 : decode + (2 * j));
257 : }
258 : }
259 : else
260 : {
261 : /* Use the default decoding array */
262 : pdf_real_t dec[2];
263 :
264 0 : dec[0] = 0;
265 0 : dec[1] = (bps < 32) ? ((1U<<bps)-1U) : 0xFFFFFFFFU;
266 0 : for (j = 0; j < f->n; j++)
267 : {
268 0 : setmap (f->u.t0.decode + (2 * j),
269 : f->range + (2 * j),
270 : dec);
271 : }
272 : }
273 :
274 0 : f->u.t0.k = pdf_alloc (m * sizeof(f->u.t0.k[0]));
275 0 : f->u.t0.w0 = pdf_alloc (m * sizeof(f->u.t0.w0[0]));
276 0 : f->u.t0.w1 = pdf_alloc (m * sizeof(f->u.t0.w1[0]));
277 :
278 :
279 0 : if (order == 3)
280 : {
281 0 : f->u.t0.wm = pdf_alloc (m * sizeof(f->u.t0.wm[0]));
282 0 : f->u.t0.w2 = pdf_alloc (m * sizeof(f->u.t0.w2[0]));
283 0 : f->eval = pdf_eval_spline;
284 : }
285 : else
286 : {
287 0 : f->eval = pdf_eval_linear;
288 : }
289 :
290 0 : *function = f;
291 0 : return ret;
292 : }
293 :
294 : pdf_status_t
295 : pdf_fp_func_2_new (pdf_u32_t m,
296 : pdf_u32_t n,
297 : const pdf_real_t domain[],
298 : const pdf_real_t range[],
299 : pdf_real_t N,
300 : pdf_real_t c0[],
301 : pdf_real_t c1[],
302 : pdf_fp_func_t *function)
303 0 : {
304 : pdf_status_t ret;
305 : pdf_fp_func_t f;
306 :
307 0 : ret = PDF_OK;
308 :
309 : /* Common data */
310 0 : f = pdf_alloc (sizeof(struct pdf_fp_func_s));
311 0 : f->m = m;
312 0 : f->n = n;
313 0 : f->type = 2;
314 :
315 : /* Specific data */
316 0 : f->u.t2.N = N;
317 0 : f->u.t2.c0 = c0;
318 0 : f->u.t2.c1 = c1;
319 :
320 0 : f->eval = pdf_eval_exponential;
321 :
322 0 : *function = f;
323 0 : return ret;
324 : }
325 :
326 : pdf_status_t
327 : pdf_fp_func_3_new (pdf_u32_t m,
328 : pdf_u32_t n,
329 : const pdf_real_t domain[],
330 : const pdf_real_t range[],
331 : pdf_u32_t k,
332 : pdf_fp_func_t *functions,
333 : pdf_real_t bounds[],
334 : const pdf_u32_t encode[],
335 : pdf_fp_func_t *function)
336 0 : {
337 : pdf_status_t ret;
338 : pdf_fp_func_t f;
339 : pdf_u32_t i;
340 :
341 0 : ret = PDF_OK;
342 :
343 : /* Common data */
344 0 : f = pdf_alloc (sizeof(struct pdf_fp_func_s));
345 0 : f->m = m;
346 0 : f->n = n;
347 0 : f->type = 3;
348 :
349 : /* Specific data */
350 0 : f->u.t3.k = k;
351 0 : f->u.t3.functions = functions;
352 0 : f->u.t3.bounds = bounds;
353 :
354 0 : f->u.t3.bounds = pdf_alloc ((1+k) * sizeof(f->u.t3.bounds[0]));
355 0 : f->u.t3.bounds[0] = f->domain[0];
356 0 : for (i = 1; i < k; i++)
357 : {
358 0 : f->u.t3.bounds[i] = bounds[i - 1];
359 : }
360 0 : f->u.t3.bounds[i] = f->domain[1];
361 :
362 0 : f->u.t3.encode = pdf_alloc (2 * k * sizeof(f->u.t3.encode[0]));
363 0 : for (i = 0; i < k; i++)
364 : {
365 : pdf_real_t enc[2];
366 :
367 0 : enc[0] = encode[2 * i];
368 0 : enc[1] = encode[2 * i + 1];
369 0 : setmap(f->u.t3.encode + 2 * i,
370 : enc,
371 : f->u.t3.bounds + i);
372 : }
373 :
374 0 : f->eval = pdf_eval_stitch;
375 :
376 0 : *function = f;
377 0 : return ret;
378 : }
379 :
380 : #define BRACES_MAX_LEVEL 32
381 :
382 : pdf_status_t
383 : pdf_fp_func_4_new (pdf_u32_t m,
384 : pdf_u32_t n,
385 : pdf_real_t domain[],
386 : pdf_real_t range[],
387 : pdf_char_t *code,
388 : pdf_size_t code_size,
389 : pdf_size_t *error_at,
390 : pdf_fp_func_t *function)
391 181 : {
392 : pdf_fp_func_t f;
393 : pdf_u32_t off[BRACES_MAX_LEVEL];
394 : pdf_u32_t braces_pos[BRACES_MAX_LEVEL];
395 : pdf_char_t *op;
396 : pdf_i32_t at;
397 : pdf_i32_t to;
398 : pdf_i32_t alloc;
399 : pdf_i32_t bsp;
400 : pdf_i32_t blevel; /* braces level depth */
401 : double lit;
402 : pdf_i32_t opc;
403 : pdf_size_t beg_pos; /* beginning of current token */
404 : pdf_status_t ret;
405 : pdf_u32_t (*debug_off)[2];
406 : pdf_size_t debug_size;
407 : pdf_size_t debug_alloc;
408 181 : size_t s_domain = sizeof(pdf_real_t)*m*2;
409 181 : size_t s_range = sizeof(pdf_real_t)*n*2;
410 :
411 : pdf_stm_t reader_stm;
412 : pdf_token_reader_t reader;
413 :
414 : /* Common data */
415 181 : f = pdf_alloc (sizeof(struct pdf_fp_func_s));
416 181 : f->m = m;
417 181 : f->n = n;
418 181 : f->type = 4;
419 181 : f->domain = pdf_alloc (s_domain);
420 181 : f->range = pdf_alloc (s_range);
421 181 : memcpy (f->domain, domain, s_domain);
422 181 : memcpy (f->range, range, s_range);
423 :
424 : /* Specific data */
425 181 : beg_pos = 0;
426 181 : alloc = 64;
427 181 : op = pdf_alloc (alloc);
428 181 : debug_alloc = 64;
429 181 : debug_size = 0;
430 181 : debug_off = pdf_alloc (sizeof(*debug_off) * debug_alloc);
431 :
432 : /* Initialize the token reader */
433 181 : if (pdf_stm_mem_new (code,
434 : code_size,
435 : code_size, /* Use the default cache size */
436 : PDF_STM_READ,
437 : &reader_stm) != PDF_OK)
438 : {
439 : /* FIXME: REFINE */
440 0 : ret = PDF_ERROR;
441 0 : goto fail;
442 : }
443 :
444 181 : if (pdf_token_reader_new (reader_stm, &reader) != PDF_OK)
445 : {
446 : /* FIXME: REFINE */
447 0 : ret = PDF_ERROR;
448 0 : goto fail;
449 : }
450 :
451 181 : opc = get_token (reader, &lit, &beg_pos);
452 181 : if (opc != OPC_begin)
453 : {
454 1 : ret = PDF_ENOWRAP;
455 1 : goto fail;
456 : }
457 :
458 180 : blevel = 1;
459 180 : bsp = 0;
460 180 : at = 0;
461 : for(;;)
462 : {
463 1062 : if (bsp >= BRACES_MAX_LEVEL)
464 : {
465 0 : ret = PDF_ETOODEPTH;
466 0 : goto fail;
467 : }
468 :
469 1062 : if (at+1+sizeof(lit) >= alloc)
470 : {
471 6 : alloc *= 2;
472 6 : op = pdf_realloc (op,alloc);
473 : }
474 :
475 1062 : if (debug_size >= debug_alloc)
476 : {
477 1 : debug_alloc *= 2;
478 1 : debug_off = pdf_realloc (debug_off, sizeof(*debug_off) * debug_alloc);
479 : }
480 :
481 1062 : opc = get_token (reader, &lit, &beg_pos);
482 1062 : if (opc < 0)
483 : {
484 0 : ret = PDF_EEOF;
485 0 : goto fail;
486 : }
487 1062 : switch ((PDF_TYPE4_OPC)opc)
488 : {
489 : case OPC_lit_i:
490 : case OPC_lit_r:
491 : {
492 179 : debug_off[debug_size][0] = at;
493 179 : debug_off[debug_size][1] = beg_pos;
494 179 : debug_size++;
495 :
496 179 : op[at++] = opc;
497 179 : memcpy (op+at, &lit, sizeof(lit));
498 179 : at += sizeof (lit);
499 179 : break;
500 : }
501 : case OPC_begin:
502 : {
503 34 : blevel++;
504 34 : off[bsp] = at; /* backpatched by if/ifelse */
505 34 : braces_pos[bsp] = beg_pos;
506 34 : bsp++;
507 :
508 34 : debug_off[debug_size][0] = at;
509 34 : debug_off[debug_size][1] = beg_pos;
510 34 : debug_size++;
511 :
512 34 : op[at] = OPC_begin; /* OPC_error */
513 34 : at += 1+sizeof(at);
514 :
515 34 : break;
516 : }
517 : case OPC_end:
518 : {
519 213 : blevel--;
520 :
521 213 : if (blevel)
522 : {
523 34 : off[bsp] = at;
524 34 : braces_pos[bsp] = beg_pos;
525 34 : bsp++;
526 : }
527 : else
528 : {
529 : void *r;
530 :
531 179 : debug_off[debug_size][0] = at;
532 179 : debug_off[debug_size][1] = beg_pos;
533 179 : debug_size++;
534 :
535 179 : op[at++] = OPC_ret;
536 :
537 179 : if (get_token (reader, &lit, &beg_pos) >= 0)
538 : {
539 2 : ret = PDF_ENOWRAP;
540 2 : goto fail;
541 : }
542 :
543 177 : if (bsp)
544 : {
545 1 : beg_pos = braces_pos[--bsp]; /* reporting error offset */
546 1 : ret = PDF_EMISSIF;
547 1 : goto fail;
548 : }
549 :
550 : /* memory is transferred to f, not freed here */
551 176 : debug_off = pdf_realloc (debug_off, sizeof(*debug_off) * debug_alloc);
552 :
553 176 : r = pdf_realloc (op,at);
554 176 : if (r)
555 : {
556 176 : op = r;
557 : }
558 :
559 176 : f->u.t4.opcodes = op;
560 176 : f->u.t4.n_opcodes = at;
561 176 : f->u.t4.debug_off = debug_off;
562 176 : f->u.t4.debug_size = debug_size;
563 :
564 176 : f->eval = pdf_eval_type4;
565 :
566 176 : goto success;
567 : }
568 34 : break;
569 : }
570 : case OPC_if:
571 : {
572 3 : if (bsp < 2 || at != off[--bsp])
573 : {
574 1 : ret = PDF_EMISSBODY;
575 1 : goto fail;
576 : }
577 :
578 2 : debug_off[debug_size][0] = --bsp;
579 2 : debug_off[debug_size][1] = beg_pos;
580 2 : debug_size++;
581 :
582 2 : op[off[bsp]] = OPC_jnt;
583 2 : to = at - 1;
584 2 : memcpy(op+1+off[bsp],&to,sizeof(to));
585 2 : break;
586 : }
587 : case OPC_ifelse:
588 : {
589 15 : if (bsp < 4 || at != off[--bsp])
590 : {
591 0 : ret = PDF_EMISSBODY;
592 0 : goto fail;
593 : }
594 :
595 15 : debug_off[debug_size][0] = --bsp;
596 15 : debug_off[debug_size][1] = beg_pos;
597 15 : debug_size++;
598 :
599 15 : op[off[bsp]] = OPC_jmp;
600 15 : to = at-1;
601 15 : memcpy(op+off[bsp]+1,&to,sizeof(to));
602 :
603 15 : to = off[bsp--];
604 15 : if (to != off[bsp--])
605 : {
606 0 : ret = PDF_EMISSBODY;
607 0 : goto fail;
608 : }
609 15 : to += sizeof(to);
610 15 : op[off[bsp]] = OPC_jnt;
611 15 : memcpy(op+off[bsp]+1,&to,sizeof(to));
612 15 : break;
613 : }
614 : case OPC_bad:
615 : {
616 0 : ret = PDF_EBADOP;
617 0 : goto fail;
618 : break;
619 : }
620 : default:
621 : {
622 618 : debug_off[debug_size][0] = at;
623 618 : debug_off[debug_size][1] = beg_pos;
624 618 : debug_size++;
625 :
626 618 : op[at++] = opc;
627 : break;
628 : }
629 : }
630 : }
631 : /* not reached */
632 :
633 5 : fail:
634 5 : pdf_dealloc (op);
635 5 : pdf_dealloc (debug_off);
636 :
637 5 : if (error_at != NULL)
638 : {
639 5 : *error_at = beg_pos;
640 : }
641 :
642 5 : *function = NULL;
643 5 : return ret;
644 :
645 176 : success:
646 176 : *function = f;
647 176 : return PDF_OK;
648 : }
649 :
650 : pdf_status_t
651 : pdf_fp_func_eval (pdf_fp_func_t function,
652 : const pdf_real_t in[],
653 : pdf_real_t out[],
654 : pdf_fp_func_debug_t * result)
655 399 : {
656 399 : return function->eval(function, in, out, result);
657 : }
658 :
659 : pdf_status_t
660 : pdf_fp_func_get_bounds (const pdf_fp_func_t function,
661 : pdf_i32_t *in_dimensions,
662 : pdf_i32_t *out_dimensions)
663 0 : {
664 0 : *in_dimensions = function->m;
665 0 : *out_dimensions = function->n;
666 :
667 0 : return PDF_OK;
668 : }
669 :
670 : pdf_status_t
671 : pdf_fp_func_destroy (pdf_fp_func_t t)
672 176 : {
673 : pdf_u32_t i;
674 :
675 176 : if (!t)
676 : {
677 : /* pdf_destroy_func(0) is valid. */
678 : /* this simplifies cleanup after a 'goto fail' */
679 0 : return PDF_OK;
680 : }
681 :
682 176 : pdf_dealloc (t->domain);
683 176 : pdf_dealloc (t->range);
684 :
685 176 : switch(t->type)
686 : {
687 : case 0:
688 0 : pdf_dealloc (t->u.t0.size);
689 0 : pdf_dealloc (t->u.t0.y);
690 0 : pdf_dealloc (t->u.t0.y1);
691 0 : pdf_dealloc (t->u.t0.r);
692 :
693 0 : pdf_dealloc (t->u.t0.wm);
694 0 : pdf_dealloc (t->u.t0.w0);
695 0 : pdf_dealloc (t->u.t0.w1);
696 0 : pdf_dealloc (t->u.t0.w2);
697 :
698 0 : pdf_dealloc (t->u.t0.b);
699 0 : pdf_dealloc (t->u.t0.d);
700 0 : pdf_dealloc (t->u.t0.encode);
701 0 : pdf_dealloc (t->u.t0.decode);
702 0 : break;
703 :
704 : case 2:
705 0 : pdf_dealloc (t->u.t2.c0);
706 0 : pdf_dealloc (t->u.t2.c1);
707 0 : break;
708 :
709 : case 3:
710 0 : for (i = 0; i < t->u.t3.k; i++)
711 : {
712 0 : pdf_fp_func_destroy (t->u.t3.functions[i]);
713 : }
714 0 : pdf_dealloc (t->u.t3.functions);
715 0 : pdf_dealloc (t->u.t3.bounds);
716 0 : pdf_dealloc (t->u.t3.encode);
717 0 : break;
718 : case 4:
719 176 : pdf_dealloc (t->u.t4.opcodes);
720 176 : pdf_dealloc (t->u.t4.debug_off);
721 : break;
722 : }
723 :
724 176 : pdf_dealloc (t);
725 :
726 176 : return PDF_OK;
727 : }
728 :
729 : /*
730 : * Private functions
731 : */
732 :
733 : /* On type 0 functions.
734 : * Linear interpolation works the obvious way in 1D,
735 : * and there is a simple,recursive generalization to multilinear interpolation.
736 : * any performance penalty would show up only for large m (# of inputs).
737 : *
738 : * True splines have C2 continuity, at least in the one-dimensional case.
739 : * Solving the linear equations is easy (see below), and the results may be cached.
740 : * There is, however, no straightforward generalization to m > 1.
741 : * An iterative solution would require to solve many systems of linear equations.
742 : * Only the outermost results would be cacheable.
743 : * It does not feel right.
744 : *
745 : * If we use Catmull-Rom splines, which are common in computer graphics,
746 : * these difficulties vanish.
747 : * They depend on four surrounding samples instead of two,
748 : * but the algorithm is almost the same for order 1 and order 3.
749 : *
750 : */
751 :
752 : static inline double
753 : clip(double x, const pdf_real_t r[2])
754 : /* HF: clip() will pass NaNs */
755 : {
756 1225 : if (x < r[0])
757 45 : x = r[0];
758 1180 : else if (x > r[1])
759 21 : x = r[1];
760 1225 : return x;
761 : }
762 :
763 : static inline void
764 : setmap(double map[2], const pdf_real_t to[2] , const pdf_real_t from[2])
765 0 : {
766 0 : map[0] = (to[1] - to[0]) / (from[1] - from[0]);
767 0 : map[1] = to[0] - map[0] * from[0];
768 0 : }
769 :
770 : #if 0
771 : /* True Splines, see comments above */
772 : /* build two and expect to throw away one of them */
773 : /* the eqn sover is not used anymore */
774 :
775 :
776 : static pdf_real_t
777 : eval_spline(
778 : pdf_real_t x,
779 : pdf_u32_t nsamples,
780 : const pdf_real_t y[],
781 : const pdf_real_t y1[])
782 : {
783 : pdf_real_t t;
784 : pdf_real_t c,d;
785 : pdf_u32_t i;
786 :
787 : if (x <= 0)
788 : return y[0];
789 : else if (x >= nsamples-1)
790 : return y[nsamples-1];
791 :
792 : t = pdf_fp_floor (x);
793 : i = (pdf_u32_t)t;
794 : t = x-t;
795 :
796 : PDF_ASSERT_BASE (i < nsamples);
797 :
798 : if (nsamples < 4)
799 : {
800 : return y[i] + y1[i]*t;
801 : }
802 :
803 : /* From the spec:
804 : * The /Size for an input dimension can be 1, in which case all input values in
805 : * that dimension will be mapped to the single allowed value. If Size is less than 4,
806 : * cubic spline interpolation is not possible and Order 3 will be ignored if specified.
807 : * This seems to exclude the use of quadratic interpolation if nsamples = 3
808 : * what happens in mixed cases ?
809 : * */
810 :
811 : c = 3*(y[i+1]-y[i]) - (2*y1[i] + y1[i+1]);
812 : d = -2*(y[i+1]-y[i]) + ( y1[i] + y1[i+1]);
813 :
814 : return ((d*t + c) *t + y1[i]) *t + y[i];
815 : }
816 :
817 : static void
818 : solve_spline(
819 : pdf_u32_t nsamples,
820 : const pdf_real_t y[],
821 : pdf_real_t y1[],
822 : pdf_real_t d[],
823 : pdf_real_t b[])
824 : /* calculate the vector y1[] of derivatives for a not-a-knot spline
825 : * by solving a tridiagonal system.
826 : * d[] and b[] are buffers for diagonal and right side, respectively
827 : */
828 : {
829 : pdf_u32_t i;
830 : if (nsamples < 4)
831 : {
832 : for (i = 0; i < nsamples-1; i++)
833 : y1[i] = y[i+1] - y[i];
834 : /* y1[nsamples-1] is not used in this case */
835 : }
836 : else
837 : {
838 : b[0] = (-5*y[0] + 4*y[1] + y[2])/4;
839 : d[0] = 0.5;
840 : for (i = 1; i < nsamples-1; i++)
841 : {
842 : b[i] = 3*(y[i+1] - y[i-1]);
843 : d[i] = 4;
844 : }
845 : b[i] = (5*y[i] - 4*y[i-1] - y[i-2])/4;
846 : d[i] = 0.5;
847 :
848 : /* forward */
849 : for (i = 0; i < nsamples-1; i++)
850 : {
851 : b[i+1] -= b[i]/d[i];
852 : d[i+1] -= 1/d[i];
853 : }
854 :
855 : /* backward */
856 : for (i = nsamples-1; i > 0; --i)
857 : {
858 : y1[i] = b[i]/d[i];
859 : b[i-1] -= y1[i];
860 : }
861 : y1[0] = b[0]/d[0];
862 : }
863 : }
864 :
865 :
866 : static void pdf_spline_init(struct pdf_func0_s *p)
867 : /* precalculate spline coefficients, final initialization steps */
868 : {
869 : pdf_u32_t i,j,k,l;
870 : pdf_u32_t max;
871 :
872 : max = 0;
873 : for (k = 0; k < p->m; k++)
874 : {
875 : if (max < p->size[k])
876 : max = p->size[k];
877 : }
878 :
879 : p->b = pdf_alloc (max * sizeof(p->b[0]));
880 : p->d = pdf_alloc (max * sizeof(p->d[0]));
881 :
882 : p->y1 = pdf_alloc (sizeof(p->y1[0]) * p->n * p->nsamples);
883 :
884 : l = p->nsamples/p->size[0];
885 :
886 : p->r = pdf_alloc (2*sizeof(p->r[0]) * l);
887 :
888 : for (j = 0; j < p->n; j++)
889 : {
890 : for (i = 0; i < l; i++)
891 : {
892 : solve_spline(p->size[0],
893 : p->y + j*p->nsamples + i*p->size[0],
894 : p->y1 + j*p->nsamples + i*p->size[0], p->b , p->d);
895 : }
896 : }
897 : }
898 :
899 : static pdf_status_t
900 : pdf_eval_spline (pdf_fp_func_t fun,
901 : const pdf_real_t t[],
902 : pdf_real_t out[])
903 : {
904 : struct pdf_func0_s *p;
905 : pdf_u32_t i,j,l,k;
906 : pdf_real_t *r,*r1;
907 : pdf_real_t x,y;
908 :
909 : p = &fun->u.t0;
910 :
911 :
912 : l = p->nsamples/p->size[0];
913 :
914 : r = p->r;
915 : r1 = p->r + l;
916 :
917 : for (j = 0; j < p->n; j++)
918 : {
919 : k = 0;
920 : x = p->encode[0] * t[0] + p->encode[1];
921 : for (i = 0; i < l; i++)
922 : {
923 : r[i] = eval_spline(x , p->size[k],
924 : p->y + (j * p->nsamples + i*p->size[k]) ,
925 : p->y1+ (j * p->nsamples + i*p->size[k]) );
926 : }
927 :
928 : for (k = 1; k < p->m; k++)
929 : {
930 : l /= p->size[k];
931 :
932 : for (i = 0; i < l; i++)
933 : solve_spline(p->size[k], r+i*p->size[k],r1+i*p->size[k],p->b,p->d);
934 :
935 : x = p->encode[2*k] * t[k] + p->encode[2*k+1];
936 : for (i = 0; i < l; i++)
937 : {
938 : r[i] = eval_spline(x , p->size[k], r+i*p->size[k],r1+i*p->size[k]);
939 : }
940 : /* this reuse of r works! */
941 : }
942 :
943 :
944 : y = r[0];
945 : y = fun->u.t0.decode[2*j] * y + fun->u.t0.decode[2*j+1];
946 :
947 : if (fun->range)
948 : y = clip(y,fun->range+2*j);
949 : out[j] = y;
950 : }
951 :
952 : return PDF_OK;
953 : }
954 :
955 :
956 :
957 : static void
958 : pdf_linear_init(struct pdf_func0_s *p)
959 : {
960 : p->r = pdf_alloc (sizeof(p->r[0]) * (1U << p->m));
961 : }
962 :
963 :
964 : static pdf_status_t
965 : pdf_eval_linear (pdf_fp_func_t fun,
966 : const pdf_real_t t[],
967 : pdf_real_t out[])
968 : /* the original code (postscript) was almost certainly more stack oriented */
969 : {
970 : pdf_u32_t xcp;
971 : double x,y;
972 : struct pdf_func0_s *p;
973 : pdf_u32_t m;
974 : pdf_u32_t i,j,s,k,i0;
975 : pdf_u32_t cc;
976 : double t0[TYPE0_MAX_DIM];
977 : double t1[TYPE0_MAX_DIM];
978 :
979 : p = &fun->u.t0;
980 : m = fun->m;
981 :
982 : PDF_ASSERT_BASE (m <= TYPE0_MAX_DIM);
983 :
984 : xcp = 0;
985 : i0 = 0;
986 : cc = 1;
987 : for (k = 0; k < m; k++)
988 : {
989 : x = t[k] * p->encode[2*k] + p->encode[2*k+1];
990 :
991 : if (!(x < p->size[k]-1)) /* catch NaN, and size [k] == 1, too */
992 : {
993 : i = p->size[k]-1;
994 : xcp |= (1U<<k); /* exceptional cases */
995 : t1[k] = 0;
996 : t0[k] = 1;
997 : }
998 : else if (x <= 0) /* else !!! */
999 : {
1000 : i = 0;
1001 : t1[k] = 0;
1002 : t0[k] = 1;
1003 : }
1004 : else
1005 : {
1006 : i = (pdf_u32_t) pdf_fp_floor (x);
1007 : t1[k] = x - pdf_fp_floor (x);
1008 : t0[k] = (1 - t1[k]);
1009 : }
1010 : i0 += cc * i;
1011 : cc *= p->size[k];
1012 : }
1013 : j = 0;
1014 :
1015 : for (j = 0; j < p->n; j++)
1016 : {
1017 : for (i = 0; i < (1U<<m); i++)
1018 : /* smells like recursion */
1019 : {
1020 : s = i0;
1021 : cc = 1;
1022 : for (k = 0; k < m; k++)
1023 : {
1024 : if (i & (~xcp) & (1U<<k))
1025 : s += cc;
1026 : cc *= p->size[k];
1027 : }
1028 : p->r[i] = p->y[s];
1029 : printf("\n\tsample[%u] = [%u]",i,s);
1030 : }
1031 : printf("\n");
1032 :
1033 : for (k = 0; k < m; k++) /* reduction steps */
1034 : {
1035 : /* i is dominant loop index. */
1036 : for (i = 0; i < 1U<<(m-k-1); i++)
1037 : {
1038 : p->r[i] = t0[k]*p->r[2*i] + t1[k] * p->r[2*i+1];
1039 : }
1040 : }
1041 :
1042 : y = p->r[0];
1043 : y = fun->u.t0.decode[2*j] * y + fun->u.t0.decode[2*j+1];
1044 :
1045 : if (fun->range)
1046 : y = clip(y,fun->range+2*j);
1047 :
1048 : out[j] = y;
1049 : }
1050 :
1051 : return PDF_OK;
1052 : }
1053 :
1054 : #endif
1055 : /* TRUE_C2_NOT_A_KNOT_SPLINES */
1056 :
1057 :
1058 :
1059 :
1060 : static double
1061 : linear_interpolation(pdf_u32_t i,
1062 : const double w0[], const double w1[],
1063 : const pdf_u32_t k[],
1064 : const pdf_real_t y[],
1065 : pdf_u32_t stride,
1066 : const pdf_u32_t size[])
1067 : /* w0[i] and w1[i] are weights for samples surrounding samples k[i] and k[i+1] in the ith dimension */
1068 : /* cubic interpolation will need four weights */
1069 : /* Samples with weight 0 may have an index out of range */
1070 0 : {
1071 : pdf_u32_t j;
1072 0 : j = k[i];
1073 0 : stride /= size[i];
1074 :
1075 0 : if (w1[i]) /* zero indicates a possibly invalid array index */
1076 : {
1077 0 : PDF_ASSERT_BASE (j+1 < size[i]);
1078 0 : if (i == 0)
1079 0 : return w0[i] * y[j] + w1[i] * y[j+1];
1080 : else
1081 0 : return w0[i] * linear_interpolation(i-1,w0,w1,k,y+j*stride,stride,size)
1082 : + w1[i] * linear_interpolation(i-1,w0,w1,k,y+(j+1)*stride,stride,size);
1083 : }
1084 : else
1085 : {
1086 0 : if (i == 0)
1087 0 : return y[j];
1088 : else
1089 0 : return linear_interpolation(i-1,w0,w1,k,y+j*stride,stride,size);
1090 : }
1091 : }
1092 :
1093 : static pdf_status_t
1094 : pdf_eval_linear (pdf_fp_func_t fun,
1095 : const pdf_real_t in[],
1096 : pdf_real_t out[],
1097 : pdf_fp_func_debug_t * debug)
1098 0 : {
1099 : pdf_u32_t i,j;
1100 : double t;
1101 : double y;
1102 0 : for (i = 0; i < fun->m; i++)
1103 : {
1104 0 : t = in[i] * fun->u.t0.encode[2*i] + fun->u.t0.encode[2*i+1];
1105 0 : if (isnan(t))
1106 : {
1107 0 : return -1;
1108 : }
1109 0 : if (t >= fun->u.t0.size[i]-1)
1110 : {
1111 0 : fun->u.t0.k[i] = fun->u.t0.size[i]-1;
1112 0 : fun->u.t0.w0[i] = 1;
1113 0 : fun->u.t0.w1[i] = 0;
1114 : }
1115 0 : else if (t <= 0)
1116 : {
1117 0 : fun->u.t0.k[i] = 0;
1118 0 : fun->u.t0.w0[i] = 1;
1119 0 : fun->u.t0.w1[i] = 0;
1120 : }
1121 : else
1122 : {
1123 0 : fun->u.t0.k[i] = (pdf_u32_t) pdf_fp_floor (t);
1124 0 : t = t - pdf_fp_floor (t);
1125 0 : fun->u.t0.w0[i] = 1-t;
1126 0 : fun->u.t0.w1[i] = t;
1127 : }
1128 : }
1129 :
1130 :
1131 0 : for (j = 0; j < fun->n; j++)
1132 : {
1133 0 : y = linear_interpolation(fun->m-1,fun->u.t0.w0,fun->u.t0.w1,fun->u.t0.k,
1134 : &fun->u.t0.y[j*fun->u.t0.nsamples], fun->u.t0.nsamples, fun->u.t0.size);
1135 :
1136 0 : y = fun->u.t0.decode[2*j] * y + fun->u.t0.decode[2*j+1];
1137 0 : if (fun->range)
1138 0 : y = clip(y,fun->range+2*j);
1139 0 : if (isnan(y))
1140 : {
1141 0 : return -1;
1142 : }
1143 0 : out[j] = y;
1144 : }
1145 :
1146 0 : return PDF_OK;
1147 : }
1148 :
1149 :
1150 :
1151 : static double
1152 : spline_interpolation(pdf_u32_t i,
1153 : const double wm[], const double w0[], const double w1[], const double w2[],
1154 : const pdf_u32_t k[], const pdf_real_t y[], pdf_u32_t stride, const pdf_u32_t size[])
1155 : /* Catmull-Rom splines, cf wikipedia or almost any texbook on CG */
1156 0 : {
1157 : pdf_u32_t j;
1158 : double sum;
1159 0 : stride /= size[i];
1160 :
1161 0 : j = k[i];
1162 0 : sum = 0;
1163 0 : if (wm[i])
1164 0 : sum += wm[i] * ((i) ? spline_interpolation(i-1,wm,w0,w1,w2,k,y+(j-1)*stride,stride,size) : y[j-1]);
1165 0 : if (w0[i])
1166 0 : sum += w0[i] * ((i) ? spline_interpolation(i-1,wm,w0,w1,w2,k,y+(j)*stride,stride,size) : y[j]);
1167 0 : if (w1[i])
1168 0 : sum += w1[i] * ((i) ? spline_interpolation(i-1,wm,w0,w1,w2,k,y+(j+1)*stride,stride,size) : y[j+1]);
1169 0 : if (w2[i])
1170 0 : sum += w2[i] * ((i) ? spline_interpolation(i-1,wm,w0,w1,w2,k,y+(j+2)*stride,stride,size) : y[j+2]);
1171 : /* the caller ensures that w[*] is zero if y[j+*] does not exist */
1172 : /* if this seems ugly, try doing it with ... if (j >= 1 && j < size[i]-2 && ... */
1173 0 : return sum;
1174 : }
1175 :
1176 :
1177 : static pdf_status_t
1178 : pdf_eval_spline (pdf_fp_func_t fun,
1179 : const pdf_real_t in[],
1180 : pdf_real_t out[],
1181 : pdf_fp_func_debug_t * debug)
1182 0 : {
1183 : pdf_u32_t i,j;
1184 : double t,v;
1185 :
1186 0 : for (i = 0; i < fun->m; i++)
1187 : {
1188 0 : t = in[i] * fun->u.t0.encode[2*i] + fun->u.t0.encode[2*i+1];
1189 0 : if (isnan(t))
1190 : {
1191 0 : return PDF_ERROR;
1192 : }
1193 :
1194 0 : v = t - pdf_fp_floor (t);
1195 0 : fun->u.t0.k[i] = (pdf_u32_t) pdf_fp_floor (t);
1196 0 : if (t >= fun->u.t0.size[i]-1)
1197 : {
1198 0 : fun->u.t0.k[i] = fun->u.t0.size[i]-1;
1199 0 : fun->u.t0.wm[i] = 0;
1200 0 : fun->u.t0.w0[i] = 1;
1201 0 : fun->u.t0.w1[i] = 0;
1202 0 : fun->u.t0.w2[i] = 0;
1203 : }
1204 0 : else if (t+1 >= fun->u.t0.size[i]-1)
1205 : {
1206 0 : if (t-1 >= 0)
1207 : {
1208 0 : fun->u.t0.wm[i] = -0.5*v*(1-v);
1209 0 : fun->u.t0.w0[i] = 1-v*v;
1210 0 : fun->u.t0.w1[i] = 0.5*v*(1+v);
1211 : }
1212 : else /* linear */
1213 : {
1214 0 : fun->u.t0.wm[i] = 0;
1215 0 : fun->u.t0.w0[i] = 1-v;
1216 0 : fun->u.t0.w1[i] = v;
1217 : }
1218 0 : fun->u.t0.w2[i] = 0;
1219 : }
1220 : else
1221 : {
1222 0 : if (t >= 1)
1223 : {
1224 0 : fun->u.t0.wm[i] = ((-0.5 * v + 1)*v-0.5)*v;
1225 0 : fun->u.t0.w0[i] = (1.5* v -2.5)*v*v+1;
1226 0 : fun->u.t0.w1[i] = ((-1.5*v+2)*v+0.5)*v;
1227 0 : fun->u.t0.w2[i] = (0.5*v-0.5)*v*v;
1228 : }
1229 0 : else if (t > 0)
1230 : {
1231 0 : PDF_ASSERT_BASE (fun->u.t0.k[i] == 0);
1232 0 : fun->u.t0.wm[i] = 0;
1233 0 : fun->u.t0.w0[i] = (0.5*v-1.5)*v +1;
1234 0 : fun->u.t0.w1[i] = (2-v)*v;
1235 0 : fun->u.t0.w2[i] = 0.5*(v-1)*v;
1236 : }
1237 : else /* no samples */
1238 : {
1239 0 : fun->u.t0.k[i] = 0;
1240 0 : fun->u.t0.wm[i] = 0;
1241 0 : fun->u.t0.w0[i] = 1;
1242 0 : fun->u.t0.w1[i] = 0;
1243 0 : fun->u.t0.w2[i] = 0;
1244 : }
1245 : }
1246 : }
1247 :
1248 :
1249 0 : for (j = 0; j < fun->n; j++)
1250 : {
1251 : double y;
1252 0 : y = spline_interpolation(fun->m-1,
1253 : fun->u.t0.wm,fun->u.t0.w0,fun->u.t0.w1,fun->u.t0.w2,
1254 : fun->u.t0.k,&fun->u.t0.y[j*fun->u.t0.nsamples], fun->u.t0.nsamples, fun->u.t0.size);
1255 :
1256 0 : y = y * fun->u.t0.decode[2*j] + fun->u.t0.decode[2*j+1];
1257 0 : if (fun->range)
1258 0 : y = clip(y,fun->range+2*j);
1259 0 : if (isnan(y))
1260 : {
1261 0 : return PDF_ERROR;
1262 : }
1263 0 : out[j] = y;
1264 : }
1265 :
1266 0 : return PDF_OK;
1267 : }
1268 :
1269 :
1270 : static pdf_status_t
1271 : pdf_eval_exponential (pdf_fp_func_t t,
1272 : const pdf_real_t in[],
1273 : pdf_real_t out[],
1274 : pdf_fp_func_debug_t * debug)
1275 0 : {
1276 : pdf_u32_t j;
1277 : pdf_real_t x,y;
1278 : pdf_real_t c1,c0;
1279 :
1280 0 : x = clip(in[0],t->domain);
1281 0 : for (j = 0; j < t->n; j++)
1282 : {
1283 0 : c0 = (t->u.t2.c0) ? t->u.t2.c0[j] : 0.0;
1284 0 : c1 = (t->u.t2.c1) ? t->u.t2.c1[j] : 1.0;
1285 0 : y = c0 + pow(x,t->u.t2.N)*(c1-c0);
1286 0 : if (t->range)
1287 0 : y = clip(y, t->range+2*j);
1288 0 : out[j] = y;
1289 0 : if (isnan(y))
1290 : {
1291 0 : return PDF_ERROR;
1292 : }
1293 : }
1294 :
1295 0 : return PDF_OK;
1296 : }
1297 :
1298 : static pdf_status_t
1299 : pdf_eval_stitch (pdf_fp_func_t t,
1300 : const pdf_real_t in[],
1301 : pdf_real_t out[],
1302 : pdf_fp_func_debug_t * debug)
1303 0 : {
1304 : pdf_fp_func_t f;
1305 : pdf_real_t x;
1306 : pdf_u32_t lo,hi;
1307 : pdf_u32_t i;
1308 :
1309 0 : PDF_ASSERT_BASE (t->domain[0] == t->u.t3.bounds[0]);
1310 0 : PDF_ASSERT_BASE (t->domain[1] == t->u.t3.bounds[t->u.t3.k]);
1311 :
1312 0 : x = in[0];
1313 :
1314 0 : if (isnan(x))
1315 : {
1316 0 : return PDF_ERROR;
1317 : }
1318 :
1319 0 : if (! (x >= t->domain[0])) /* NaN */
1320 : {
1321 0 : i = 0;
1322 : }
1323 0 : else if (x >= t->domain[1])
1324 : {
1325 0 : i = t->u.t3.k - 1;
1326 0 : x = t->domain[1];
1327 : }
1328 : else
1329 : {
1330 0 : lo = 0;
1331 0 : hi = t->u.t3.k - 1;
1332 : /* k is at least 1 , one constituent function */
1333 0 : while (lo <= hi)
1334 : {
1335 0 : i = lo + (hi-lo)/2;
1336 0 : if (x < t->u.t3.bounds[i])
1337 0 : hi = i-1;
1338 0 : else if (x >= t->u.t3.bounds[i+1])
1339 0 : lo = i+1;
1340 : else
1341 : {
1342 0 : break;
1343 : }
1344 : }
1345 0 : if (lo > hi)
1346 : {
1347 0 : return PDF_ERROR;
1348 : }
1349 : }
1350 :
1351 0 : x = x * t->u.t3.encode[2*i] + t->u.t3.encode[2*i+1];
1352 :
1353 0 : f = t->u.t3.functions[i];
1354 :
1355 0 : return f->eval(f,&x,out, debug);
1356 : }
1357 :
1358 : /* ------- decoder utilities ------ */
1359 :
1360 : static pdf_real_t *
1361 : read_type0_sample_table (pdf_char_t *buf,
1362 : pdf_size_t buf_size,
1363 : pdf_u32_t bps,
1364 : pdf_u32_t nsamples,
1365 : pdf_u32_t n)
1366 : {
1367 : pdf_real_t *y;
1368 : pdf_u32_t data,mask;
1369 : pdf_u32_t avail;
1370 : pdf_u32_t i;
1371 : pdf_i32_t c;
1372 : pdf_size_t buf_index;
1373 :
1374 0 : if (!n || nsamples > UINT_MAX/n)
1375 : {
1376 0 : return NULL;
1377 : }
1378 :
1379 0 : buf_index = 0;
1380 0 : n = n * nsamples;
1381 :
1382 : /* single precision pdf_float_t loses precision with bps 32 */
1383 : /* this should never be visible with pdf_float_t in[] and out[] */
1384 0 : y = pdf_alloc (nsamples * sizeof(*y));
1385 :
1386 0 : avail = 0;
1387 0 : data = 0;
1388 0 : mask = (bps >= 32) ? 0xFFFFFFFFU : ((1U<<bps)-1U);
1389 0 : for (i = 0; i < nsamples; i++)
1390 : {
1391 0 : while (avail < bps)
1392 : {
1393 0 : if (buf_index >= buf_size)
1394 : {
1395 : goto fail;
1396 : }
1397 :
1398 0 : c = buf[buf_index++];
1399 :
1400 0 : if (c < 0)
1401 : {
1402 : goto fail;
1403 : }
1404 :
1405 0 : data = (data << 8) | (pdf_char_t)c;
1406 0 : avail += 8;
1407 : }
1408 0 : y[i] = (data >> (avail - bps)) & mask;
1409 0 : avail -= bps;
1410 : }
1411 0 : return y;
1412 :
1413 0 : fail:
1414 0 : pdf_dealloc (y);
1415 0 : return NULL;
1416 : }
1417 :
1418 : /* --- ------------------------------- --- */
1419 : /* --- type 4 (postscript) functions --- */
1420 : /* --- ------------------------------- --- */
1421 :
1422 :
1423 : #define NSTACK PDF_FP_FUNC_TYPE4_STACK_SIZE
1424 : #define REP_TRUE PDF_FP_FUNC_TYPE4_TRUE
1425 : #define REP_FALSE PDF_FP_FUNC_TYPE4_FALSE
1426 : #define TRUNC(x) ((x) < 0 ? pdf_fp_ceil(x) : pdf_fp_floor(x))
1427 : #define INT(x) ((int) TRUNC(x))
1428 : #define BOOL(x) ((x) \
1429 : ? PDF_FP_FUNC_TYPE4_TRUE \
1430 : : PDF_FP_FUNC_TYPE4_FALSE)
1431 : #define P_INT(x) ((x).t == INT)
1432 : #define P_BOOL(x) ((x).t == BOOL)
1433 : #define P_NUM(x) ((x).t != BOOL)
1434 : #define P_TRUE(x) ((x).v == REP_TRUE)
1435 : #define P_FALSE(x) ((x).v == REP_FALSE)
1436 : #define NUM_TYPE(x, y) ((P_INT(x) && P_INT(y)) ? INT : REAL)
1437 :
1438 :
1439 : static pdf_status_t
1440 : pdf_eval_type4 (pdf_fp_func_t t,
1441 : const pdf_real_t in[],
1442 : pdf_real_t out[],
1443 : pdf_fp_func_debug_t * debug)
1444 399 : {
1445 : struct t_stack {
1446 : double v;
1447 : enum { BOOL, INT, REAL } t;
1448 : } stack[NSTACK+2];
1449 :
1450 : pdf_char_t *op;
1451 : pdf_u32_t n;
1452 : double tmp;
1453 : struct t_stack tmp_s;
1454 : pdf_i32_t sp;
1455 : pdf_i32_t pc;
1456 : pdf_fp_func_debug_t debug_info;
1457 : pdf_i32_t aux;
1458 :
1459 399 : op = t->u.t4.opcodes;
1460 399 : n = t->u.t4.n_opcodes;
1461 :
1462 1209 : for (sp = 0; sp < t->m; sp++)
1463 : {
1464 1620 : stack[sp].v = clip(in[sp], t->domain + 2*sp);
1465 810 : stack[sp].t = REAL;
1466 : }
1467 399 : sp--;
1468 2382 : for (pc = 0; pc < n; pc++)
1469 : {
1470 2382 : switch ((PDF_TYPE4_OPC) op[pc])
1471 : {
1472 : case OPC_ret:
1473 302 : if (sp+1 < t->n) goto stack_underflow;
1474 301 : if (sp+1 > t->n) goto stack_error;
1475 715 : for (sp = 0; sp < t->n; sp++)
1476 : {
1477 416 : if (!P_NUM(stack[sp])) goto type_error;
1478 830 : out[sp] = clip(stack[sp].v, t->range + 2*sp);
1479 : }
1480 299 : return PDF_OK;
1481 : break;
1482 : case OPC_lit_i:
1483 389 : if (sp >= NSTACK) goto stack_overflow;
1484 389 : sp++;
1485 389 : memcpy(&stack[sp].v, op+pc+1, sizeof(stack[0].v));
1486 389 : stack[sp].t = INT;
1487 389 : pc += sizeof(stack[0].v);
1488 389 : break;
1489 : case OPC_lit_r:
1490 40 : if (sp >= NSTACK) goto stack_overflow;
1491 40 : sp++;
1492 40 : memcpy(&stack[sp].v, op+pc+1, sizeof(stack[0].v));
1493 40 : stack[sp].t = REAL;
1494 40 : pc += sizeof(stack[0].v);
1495 40 : break;
1496 : case OPC_jmp:
1497 33 : memcpy(&pc,op+pc+1,sizeof(pc));
1498 33 : break;
1499 : case OPC_jnt:
1500 78 : if (sp < 0) goto stack_underflow;
1501 78 : if (!P_BOOL(stack[sp])) goto type_error;
1502 78 : if (P_TRUE(stack[sp]))
1503 37 : pc += sizeof(pc);
1504 41 : else if (P_FALSE(stack[sp]))
1505 41 : memcpy(&pc,op+pc+1,sizeof(pc));
1506 0 : else goto type_error;
1507 78 : sp--;
1508 78 : break;
1509 : case OPC_dup:
1510 98 : if (sp < 0) goto stack_underflow;
1511 98 : if (sp >= NSTACK) goto stack_overflow;
1512 98 : stack[sp+1] = stack[sp];
1513 98 : sp++;
1514 98 : break;
1515 : case OPC_pop:
1516 56 : if (sp < 0) goto stack_underflow;
1517 56 : sp--;
1518 56 : break;
1519 : case OPC_exch:
1520 272 : if (sp < 1) goto stack_underflow;
1521 272 : tmp_s = stack[sp-1];
1522 272 : stack[sp-1] = stack[sp];
1523 272 : stack[sp] = tmp_s;
1524 272 : break;
1525 : case OPC_sin:
1526 39 : if (sp < 0) goto stack_underflow;
1527 39 : if (!P_NUM(stack[sp])) goto type_error;
1528 38 : stack[sp].v = pdf_fp_sin ((180/PDF_PI)*stack[sp].v);
1529 38 : stack[sp].t = REAL;
1530 38 : break;
1531 : case OPC_cos:
1532 15 : if (sp < 0) goto stack_underflow;
1533 15 : if (!P_NUM(stack[sp])) goto type_error;
1534 14 : stack[sp].v = pdf_fp_cos ((180/PDF_PI)*stack[sp].v);
1535 14 : stack[sp].t = REAL;
1536 14 : break;
1537 : case OPC_neg:
1538 30 : if (sp < 0) goto stack_underflow;
1539 30 : if (!P_NUM(stack[sp])) goto type_error;
1540 29 : stack[sp].v = - stack[sp].v;
1541 29 : break;
1542 : case OPC_abs:
1543 72 : if (sp < 0) goto stack_underflow;
1544 72 : if (!P_NUM(stack[sp])) goto type_error;
1545 71 : stack[sp].v = pdf_fp_abs (stack[sp].v);
1546 71 : break;
1547 : case OPC_exp:
1548 9 : if (sp < 1) goto stack_underflow;
1549 9 : if (!P_NUM(stack[sp-1]) || !P_NUM(stack[sp])) goto type_error;
1550 7 : tmp = pdf_fp_pow (stack[sp-1].v, stack[sp].v);
1551 7 : if (isinf(tmp) || tmp == HUGE_VAL) goto math_error;
1552 7 : stack[sp-1].v = tmp;
1553 7 : sp--;
1554 7 : break;
1555 : case OPC_log:
1556 7 : if (sp < 0) goto stack_underflow;
1557 7 : if (!P_NUM(stack[sp])) goto type_error;
1558 6 : if (stack[sp].v <= 0) goto range_error;
1559 4 : stack[sp].v = pdf_fp_log10 (stack[sp].v);
1560 4 : stack[sp].t = REAL;
1561 4 : break;
1562 : case OPC_ln:
1563 7 : if (sp < 0) goto stack_underflow;
1564 7 : if (!P_NUM(stack[sp])) goto type_error;
1565 6 : if (stack[sp].v <= 0) goto range_error;
1566 4 : stack[sp].v = pdf_fp_log (stack[sp].v);
1567 4 : stack[sp].t = REAL;
1568 4 : break;
1569 : case OPC_sqrt:
1570 11 : if (sp < 0) goto stack_underflow;
1571 11 : if (!P_NUM(stack[sp])) goto type_error;
1572 10 : if (stack[sp].v < 0) goto range_error;
1573 9 : stack[sp].v = pdf_fp_sqrt (stack[sp].v);
1574 9 : stack[sp].t = REAL;
1575 9 : break;
1576 : case OPC_floor:
1577 8 : if (sp < 0) goto stack_underflow;
1578 8 : if (!P_NUM(stack[sp])) goto type_error;
1579 7 : tmp = pdf_fp_floor (stack[sp].v);
1580 7 : if (isnan(tmp)) goto limit_error;
1581 7 : stack[sp].v = tmp;
1582 7 : break;
1583 : case OPC_ceiling:
1584 8 : if (sp < 0) goto stack_underflow;
1585 8 : if (!P_NUM(stack[sp])) goto type_error;
1586 7 : tmp = pdf_fp_ceil (stack[sp].v);
1587 7 : if (isnan(tmp)) goto limit_error;
1588 7 : stack[sp].v = tmp;
1589 7 : break;
1590 : case OPC_truncate:
1591 8 : if (sp < 0) goto stack_underflow;
1592 8 : if (!P_NUM(stack[sp])) goto type_error;
1593 : /* C99 stack[sp] = trunc(stack[sp]); */
1594 7 : stack[sp].v = TRUNC(stack[sp].v);
1595 7 : break;
1596 : case OPC_round:
1597 8 : if (sp < 0) goto stack_underflow;
1598 8 : if (!P_NUM(stack[sp])) goto type_error;
1599 7 : stack[sp].v = pdf_fp_floor (0.5 + stack[sp].v);
1600 7 : break;
1601 : case OPC_cvi:
1602 67 : if (sp < 0) goto stack_underflow;
1603 67 : if (!P_NUM(stack[sp])) goto type_error;
1604 66 : stack[sp].v = INT(stack[sp].v);
1605 66 : stack[sp].t = INT;
1606 66 : break;
1607 : case OPC_index:
1608 1 : if (sp < 0) goto stack_underflow;
1609 1 : if (!P_INT(stack[sp])) goto type_error;
1610 1 : if (stack[sp].v < 0 || stack[sp].v > sp-1) goto range_error;
1611 : /* copy complete stack element with type info */
1612 1 : stack[sp] = stack[sp-1-INT(stack[sp].v)];
1613 1 : break;
1614 : case OPC_copy:
1615 : {
1616 : pdf_i32_t n,i;
1617 30 : if (sp < 0) goto stack_underflow;
1618 30 : if (!P_INT(stack[sp])) goto type_error;
1619 30 : n = INT(stack[sp].v);
1620 30 : if (n < 0 || n > sp) goto range_error;
1621 30 : if (sp + n >= NSTACK) goto stack_overflow;
1622 29 : sp = sp - n;
1623 87 : for (i = 0; i < n; i++, sp++)
1624 : {
1625 : /* copy complete stack element with type info */
1626 58 : stack[sp+n] = stack[sp];
1627 : }
1628 29 : if (n > 0)
1629 : {
1630 29 : sp++;
1631 : }
1632 : break;
1633 : }
1634 : case OPC_roll:
1635 : {
1636 : pdf_i32_t n,s,j;
1637 4 : if (sp < 2) goto stack_underflow;
1638 4 : if (!P_INT(stack[sp]) || !P_INT(stack[sp-1])) goto type_error;
1639 4 : n = INT(stack[sp-1].v);
1640 4 : j = INT(stack[sp].v);
1641 4 : sp -= 2;
1642 4 : if (n < 0 || n > sp) goto range_error;
1643 2 : if (n >= 2)
1644 : {
1645 : struct t_stack pp[NSTACK];
1646 : int pos;
1647 2 : s = (j-1) % n;
1648 10 : for (pos = 0; pos < n; pos++)
1649 : {
1650 8 : if (s < 0)
1651 2 : s = n - 1;
1652 8 : pp[pos] = stack[sp-s];
1653 8 : s--;
1654 : }
1655 2 : memcpy(&stack[sp-n+1],pp,n*sizeof(stack[0]));
1656 : }
1657 : break;
1658 : }
1659 : case OPC_cvr:
1660 2 : if (sp < 0) goto stack_underflow;
1661 2 : if (!P_NUM(stack[sp])) goto type_error;
1662 1 : stack[sp].t = REAL;
1663 1 : break;
1664 : case OPC_add:
1665 100 : if (sp < 1) goto stack_underflow;
1666 100 : if (!P_NUM(stack[sp-1]) || !P_NUM(stack[sp])) goto type_error;
1667 98 : if (isinf(tmp = pdf_fp_add(stack[sp-1].v, stack[sp].v)))
1668 0 : goto limit_error;
1669 98 : stack[sp-1].v = tmp;
1670 98 : stack[sp-1].t = NUM_TYPE(stack[sp-1], stack[sp]);
1671 98 : sp--;
1672 98 : break;
1673 : case OPC_sub:
1674 68 : if (sp < 1) goto stack_underflow;
1675 68 : if (!P_NUM(stack[sp-1]) || !P_NUM(stack[sp])) goto type_error;
1676 66 : if (isinf(tmp = pdf_fp_sub(stack[sp-1].v, stack[sp].v)))
1677 0 : goto limit_error;
1678 66 : stack[sp-1].v = tmp;
1679 66 : stack[sp-1].t = NUM_TYPE(stack[sp-1], stack[sp]);
1680 66 : sp--;
1681 66 : break;
1682 : case OPC_mul:
1683 180 : if (sp < 1) goto stack_underflow;
1684 180 : if (!P_NUM(stack[sp-1]) || !P_NUM(stack[sp])) goto type_error;
1685 178 : if (isinf(tmp = pdf_fp_mul(stack[sp-1].v, stack[sp].v)))
1686 1 : goto limit_error;
1687 177 : stack[sp-1].v = tmp;
1688 177 : stack[sp-1].t = NUM_TYPE(stack[sp-1], stack[sp]);
1689 177 : sp--;
1690 177 : break;
1691 : case OPC_div:
1692 69 : if (sp < 1) goto stack_underflow;
1693 69 : if (!P_NUM(stack[sp-1]) || !P_NUM(stack[sp])) goto type_error;
1694 67 : if (stack[sp].v == 0) goto math_error;
1695 66 : if (isinf(tmp = pdf_fp_div(stack[sp-1].v, stack[sp].v)))
1696 0 : goto limit_error;
1697 66 : stack[sp-1].v = tmp;
1698 66 : stack[sp-1].t = NUM_TYPE(stack[sp-1], stack[sp]);
1699 66 : sp--;
1700 66 : break;
1701 : case OPC_atan:
1702 9 : if (sp < 1) goto stack_underflow;
1703 9 : if (!P_NUM(stack[sp-1]) || !P_NUM(stack[sp])) goto type_error;
1704 7 : stack[sp-1].v = (180/PDF_PI) *
1705 : pdf_fp_atan2 (stack[sp-1].v, stack[sp].v);
1706 7 : stack[sp-1].t = REAL;
1707 : /* check against Ghostscript */
1708 7 : sp--;
1709 7 : break;
1710 : case OPC_idiv:
1711 13 : if (sp < 1) goto stack_underflow;
1712 13 : if (!P_INT(stack[sp-1]) || !P_INT(stack[sp])) goto type_error;
1713 7 : if (stack[sp].v == 0) goto math_error;
1714 6 : stack[sp-1].v = INT(pdf_fp_div(INT(stack[sp-1].v), INT(stack[sp].v)));
1715 6 : sp--;
1716 6 : break;
1717 : case OPC_mod:
1718 29 : if (sp < 1) goto stack_underflow;
1719 29 : if (!P_INT(stack[sp-1]) || !P_INT(stack[sp])) goto type_error;
1720 23 : if (stack[sp].v == 0) goto math_error;
1721 22 : stack[sp-1].v = pdf_fp_mod(stack[sp-1].v, stack[sp].v);
1722 22 : sp--;
1723 22 : break;
1724 : case OPC_and:
1725 58 : if (sp < 1) goto stack_underflow;
1726 63 : if (P_INT(stack[sp-1]) && P_INT(stack[sp]))
1727 5 : stack[sp-1].v = INT(stack[sp-1].v) & INT(stack[sp].v);
1728 53 : else if (P_BOOL(stack[sp-1]) && P_BOOL(stack[sp]))
1729 28 : stack[sp-1].v = BOOL(P_TRUE(stack[sp-1]) && P_TRUE(stack[sp]));
1730 : else
1731 : goto type_error;
1732 33 : sp--;
1733 33 : break;
1734 : case OPC_bitshift:
1735 11 : if (sp < 1) goto stack_underflow;
1736 11 : if (!P_INT(stack[sp-1]) || !P_INT(stack[sp]))
1737 : goto type_error;
1738 : {
1739 : pdf_i32_t x;
1740 5 : pdf_i32_t i = INT(stack[sp].v);
1741 5 : if ((stack[sp].v > PDF_I32_MAX) ||
1742 : (stack[sp].v < PDF_I32_MIN))
1743 : goto limit_error;
1744 5 : x = INT(stack[sp-1].v);
1745 5 : if (i >= 0)
1746 3 : x = (i < 32) ? (x<<i) : 0;
1747 2 : else if (i < 0)
1748 2 : x = (i > -32) ? (x>>-i) : 0;
1749 5 : stack[sp-1].v = x;
1750 : }
1751 5 : sp--;
1752 5 : break;
1753 : case OPC_or:
1754 15 : if (sp < 1) goto stack_underflow;
1755 20 : if (P_INT(stack[sp-1]) && P_INT(stack[sp]))
1756 5 : stack[sp-1].v = INT(stack[sp-1].v) | INT(stack[sp].v);
1757 10 : else if (P_BOOL(stack[sp-1]) && P_BOOL(stack[sp]))
1758 6 : stack[sp-1].v = BOOL(P_TRUE(stack[sp-1]) || P_TRUE(stack[sp]));
1759 : else
1760 : goto type_error;
1761 11 : sp--;
1762 11 : break;
1763 : case OPC_xor:
1764 15 : if (sp < 1) goto stack_underflow;
1765 20 : if (P_INT(stack[sp-1]) && P_INT(stack[sp]))
1766 5 : stack[sp-1].v = INT(stack[sp-1].v) ^ INT(stack[sp].v);
1767 10 : else if (P_BOOL(stack[sp-1]) && P_BOOL(stack[sp]))
1768 6 : stack[sp-1].v = BOOL((P_TRUE(stack[sp-1]) || P_TRUE(stack[sp])) &&
1769 : (stack[sp-1].v != stack[sp].v));
1770 : else
1771 : goto type_error;
1772 11 : sp--;
1773 11 : break;
1774 : case OPC_not:
1775 8 : if (sp < 0) goto stack_underflow;
1776 8 : if (P_INT(stack[sp]))
1777 4 : stack[sp].v = ~INT(stack[sp].v);
1778 4 : else if (P_BOOL(stack[sp]))
1779 3 : stack[sp].v = BOOL(!P_TRUE(stack[sp]));
1780 : else
1781 1 : goto type_error;
1782 : break;
1783 : case OPC_eq:
1784 40 : if (sp < 1) goto stack_underflow;
1785 40 : if (isnan(stack[sp-1].v) || isnan(stack[sp].v))
1786 : goto math_error;
1787 : /* any comparison involving NaN is false. */
1788 : /* this should not go unnoticed */
1789 40 : if ((P_NUM(stack[sp-1]) && P_NUM(stack[sp])) ||
1790 : (P_BOOL(stack[sp-1]) && P_BOOL(stack[sp])))
1791 40 : stack[sp-1].v = BOOL(stack[sp-1].v == stack[sp].v);
1792 : else
1793 : goto type_error;
1794 40 : stack[sp-1].t = BOOL;
1795 40 : sp--;
1796 40 : break;
1797 : case OPC_ne:
1798 8 : if (sp < 1) goto stack_underflow;
1799 8 : if (isnan(stack[sp-1].v) || isnan(stack[sp].v))
1800 : goto math_error;
1801 8 : if ((P_NUM(stack[sp-1]) && P_NUM(stack[sp])) ||
1802 : (P_BOOL(stack[sp-1]) && P_BOOL(stack[sp])))
1803 8 : stack[sp-1].v = BOOL(stack[sp-1].v != stack[sp].v);
1804 : else
1805 : goto type_error;
1806 8 : stack[sp-1].t = BOOL;
1807 8 : sp--;
1808 8 : break;
1809 : case OPC_lt:
1810 20 : if (sp < 1) goto stack_underflow;
1811 20 : if (isnan(stack[sp-1].v) || isnan(stack[sp].v))
1812 : goto math_error;
1813 20 : if ((P_NUM(stack[sp-1]) && P_NUM(stack[sp])) ||
1814 : (P_BOOL(stack[sp-1]) && P_BOOL(stack[sp])))
1815 18 : stack[sp-1].v = BOOL(stack[sp-1].v < stack[sp].v);
1816 : else
1817 : goto type_error;
1818 18 : stack[sp-1].t = BOOL;
1819 18 : sp--;
1820 18 : break;
1821 : case OPC_le:
1822 23 : if (sp < 1) goto stack_underflow;
1823 23 : if (isnan(stack[sp-1].v) || isnan(stack[sp].v))
1824 : goto math_error;
1825 23 : if ((P_NUM(stack[sp-1]) && P_NUM(stack[sp])) ||
1826 : (P_BOOL(stack[sp-1]) && P_BOOL(stack[sp])))
1827 21 : stack[sp-1].v = BOOL(stack[sp-1].v <= stack[sp].v);
1828 : else
1829 : goto type_error;
1830 21 : stack[sp-1].t = BOOL;
1831 21 : sp--;
1832 21 : break;
1833 : case OPC_ge:
1834 10 : if (sp < 1) goto stack_underflow;
1835 10 : if (isnan(stack[sp-1].v) || isnan(stack[sp].v))
1836 : goto math_error;
1837 10 : if ((P_NUM(stack[sp-1]) && P_NUM(stack[sp])) ||
1838 : (P_BOOL(stack[sp-1]) && P_BOOL(stack[sp])))
1839 8 : stack[sp-1].v = BOOL(stack[sp-1].v >= stack[sp].v);
1840 : else
1841 : goto type_error;
1842 8 : stack[sp-1].t = BOOL;
1843 8 : sp--;
1844 8 : break;
1845 : case OPC_gt:
1846 18 : if (sp < 1) goto stack_underflow;
1847 18 : if (isnan(stack[sp-1].v) || isnan(stack[sp].v))
1848 : goto math_error;
1849 18 : if ((P_NUM(stack[sp-1]) && P_NUM(stack[sp])) ||
1850 : (P_BOOL(stack[sp-1]) && P_BOOL(stack[sp])))
1851 16 : stack[sp-1].v = BOOL(stack[sp-1].v > stack[sp].v);
1852 : else
1853 : goto type_error;
1854 16 : stack[sp-1].t = BOOL;
1855 16 : sp--;
1856 16 : break;
1857 : case OPC_true:
1858 91 : if (sp >= NSTACK) goto stack_overflow;
1859 91 : sp++;
1860 91 : stack[sp].v = REP_TRUE;
1861 91 : stack[sp].t = BOOL;
1862 91 : break;
1863 : case OPC_false:
1864 3 : if (sp >= NSTACK) goto stack_overflow;
1865 3 : sp++;
1866 3 : stack[sp].v = REP_FALSE;
1867 3 : stack[sp].t = BOOL;
1868 3 : break;
1869 : default:
1870 : goto block_error;
1871 : }
1872 : }
1873 :
1874 :
1875 0 : block_error: debug_info.type4.status = PDF_ERROR; goto end;
1876 1 : stack_error: debug_info.type4.status = PDF_EINVRANGE; goto end;
1877 1 : stack_underflow: debug_info.type4.status = PDF_EUNDERFLOW; goto end;
1878 1 : stack_overflow: debug_info.type4.status = PDF_EOVERFLOW; goto end;
1879 7 : range_error: debug_info.type4.status = PDF_EINVRANGE; goto end;
1880 86 : type_error: debug_info.type4.status = PDF_EBADTYPE; goto end;
1881 3 : math_error: debug_info.type4.status = PDF_EMATH; goto end;
1882 1 : limit_error: debug_info.type4.status = PDF_EIMPLLIMIT; goto end;
1883 100 : end:
1884 :
1885 : /* Found that code was compiled to the opcode for debugging. */
1886 100 : debug_info.type4.op = -1;
1887 263 : for (aux = 0; aux < t->u.t4.debug_size; aux++)
1888 : {
1889 263 : if (t->u.t4.debug_off[aux][0] == pc)
1890 : {
1891 100 : debug_info.type4.op = t->u.t4.debug_off[aux][1];
1892 100 : break;
1893 : }
1894 : }
1895 :
1896 : /* Copy some elements from the stack for debugging */
1897 383 : for (aux = 0; aux <= sp; aux++)
1898 : {
1899 283 : debug_info.type4.stack[aux] = stack[sp - aux].v;
1900 : }
1901 100 : debug_info.type4.stack_size = sp + 1;
1902 :
1903 100 : if (debug != NULL)
1904 100 : *debug = debug_info;
1905 :
1906 100 : return PDF_ETYPE4;
1907 : }
1908 : /* ANSI-C code produced by gperf version 3.0.1 */
1909 : /* Command-line: gperf -t -m 100 pdf_function_type4.gperf */
1910 : /* Computed positions: -k'1-3' */
1911 : /* Caution : 7 bit only */
1912 :
1913 : struct toklut { const char *name; pdf_i32_t ret; };
1914 :
1915 : #define TOTAL_KEYWORDS 44
1916 : #define MIN_WORD_LENGTH 1
1917 : #define MAX_WORD_LENGTH 8
1918 : #define MIN_HASH_VALUE 2
1919 : #define MAX_HASH_VALUE 50
1920 : /* maximum key range = 49, duplicates = 0 */
1921 : static inline pdf_i32_t
1922 : hash (register const char *str, register pdf_i32_t len)
1923 : {
1924 : static pdf_char_t asso_values[] =
1925 : {
1926 : 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
1927 : 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
1928 : 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
1929 : 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
1930 : 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
1931 : 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
1932 : 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
1933 : 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
1934 : 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
1935 : 51, 51, 51, 51, 51, 51, 51, 3, 30, 10,
1936 : 4, 4, 12, 2, 51, 5, 51, 51, 1, 27,
1937 : 3, 16, 13, 33, 7, 4, 1, 4, 18, 51,
1938 : 11, 51, 51, 2, 51, 1, 51, 51
1939 : };
1940 637 : register pdf_i32_t hval = len;
1941 :
1942 637 : switch (hval)
1943 : {
1944 : default:
1945 587 : hval += asso_values[(pdf_char_t)str[2]];
1946 : /*FALLTHROUGH*/
1947 : case 2:
1948 637 : hval += asso_values[(pdf_char_t)str[1]];
1949 : /*FALLTHROUGH*/
1950 : case 1:
1951 637 : hval += asso_values[(pdf_char_t)str[0]];
1952 : break;
1953 : }
1954 637 : return hval;
1955 : }
1956 :
1957 : static inline struct toklut *
1958 : in_word_set (register const char *str, register pdf_i32_t len)
1959 : {
1960 : static struct toklut wordlist[] =
1961 : {
1962 : {""}, {""},
1963 : {"}", OPC_end},
1964 : {"{", OPC_begin},
1965 : {"lt", OPC_lt},
1966 : {"gt", OPC_gt},
1967 : {"ln", OPC_ln},
1968 : {"le", OPC_le},
1969 : {"ge", OPC_ge},
1970 : {"ne", OPC_ne},
1971 : {""},
1972 : {"atan", OPC_atan},
1973 : {"neg", OPC_neg},
1974 : {"and", OPC_and},
1975 : {"add", OPC_add},
1976 : {"sin", OPC_sin},
1977 : {"true", OPC_true},
1978 : {"index", OPC_index},
1979 : {"idiv", OPC_idiv},
1980 : {"if", OPC_if},
1981 : {"truncate", OPC_truncate},
1982 : {"false", OPC_false},
1983 : {"log", OPC_log},
1984 : {"not", OPC_not},
1985 : {"dup", OPC_dup},
1986 : {"or", OPC_or},
1987 : {"ceiling", OPC_ceiling},
1988 : {"ifelse", OPC_ifelse},
1989 : {"roll", OPC_roll},
1990 : {"exch", OPC_exch},
1991 : {"div", OPC_div},
1992 : {"exp", OPC_exp},
1993 : {"round", OPC_round},
1994 : {"cos", OPC_cos},
1995 : {"floor", OPC_floor},
1996 : {"mul", OPC_mul},
1997 : {"cvi", OPC_cvi},
1998 : {"xor", OPC_xor},
1999 : {"cvr", OPC_cvr},
2000 : {"eq", OPC_eq},
2001 : {"abs", OPC_abs},
2002 : {"sub", OPC_sub},
2003 : {""},
2004 : {"copy", OPC_copy},
2005 : {"bitshift", OPC_bitshift},
2006 : {"pop", OPC_pop},
2007 : {""}, {""},
2008 : {"sqrt", OPC_sqrt},
2009 : {""},
2010 : {"mod", OPC_mod}
2011 : };
2012 :
2013 637 : if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
2014 : {
2015 637 : register pdf_i32_t key = hash (str, len);
2016 :
2017 637 : if (key <= MAX_HASH_VALUE && key >= 0)
2018 : {
2019 637 : register const char *s = wordlist[key].name;
2020 :
2021 637 : if (*str == *s && !strcmp (str + 1, s + 1))
2022 637 : return &wordlist[key];
2023 : }
2024 : }
2025 0 : return 0;
2026 : }
2027 :
2028 : static pdf_i32_t get_token (pdf_token_reader_t reader,
2029 : double *literal,
2030 : pdf_size_t *token_begin)
2031 1422 : {
2032 : pdf_token_t token;
2033 1422 : pdf_i32_t ret = OPC_bad;
2034 : pdf_status_t token_ret;
2035 :
2036 : /* Invoke the tokeniser */
2037 1422 : token_ret = pdf_token_read (reader,
2038 : PDF_TOKEN_NO_NAME_ESCAPES,
2039 : &token);
2040 1422 : *token_begin = pdf_token_reader_begin_pos (reader);
2041 1422 : switch (token_ret)
2042 : {
2043 : case PDF_OK:
2044 : {
2045 : /* The token should be:
2046 : * - A real literal or
2047 : * - An identifier or
2048 : * - An open brace { (OPC_begin) or
2049 : * - A close brace } (OPC_end)
2050 : */
2051 :
2052 1245 : switch (pdf_token_get_type (token))
2053 : {
2054 : case PDF_TOKEN_INTEGER:
2055 : {
2056 170 : *literal = pdf_token_get_integer_value (token);
2057 170 : ret = OPC_lit_i;
2058 170 : break;
2059 : }
2060 : case PDF_TOKEN_REAL:
2061 : {
2062 11 : *literal = pdf_token_get_real_value (token);
2063 11 : ret = OPC_lit_r;
2064 11 : break;
2065 : }
2066 : case PDF_TOKEN_KEYWORD:
2067 : {
2068 : struct toklut *tk;
2069 :
2070 1274 : tk = in_word_set ((char *) pdf_token_get_keyword_data (token),
2071 : pdf_token_get_keyword_size (token));
2072 637 : ret = (tk) ? tk->ret : OPC_bad;
2073 637 : break;
2074 : }
2075 : case PDF_TOKEN_PROC_START:
2076 : {
2077 214 : ret = OPC_begin;
2078 214 : break;
2079 : }
2080 : case PDF_TOKEN_PROC_END:
2081 : {
2082 213 : ret = OPC_end;
2083 213 : break;
2084 : }
2085 : default:
2086 : {
2087 : /* Wrong token type */
2088 0 : ret = OPC_bad;
2089 : break;
2090 : }
2091 : }
2092 :
2093 : break;
2094 : }
2095 : case PDF_EEOF:
2096 : {
2097 : /* In EOF returns -1 */
2098 177 : return -1;
2099 : }
2100 : default:
2101 : {
2102 : /* Error */
2103 0 : ret = OPC_bad;
2104 : }
2105 : }
2106 :
2107 1245 : pdf_token_destroy (token);
2108 1245 : return ret;
2109 : }
2110 :
2111 : /* End of pdf-fp-func.c */
|