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