LCOV - code coverage report
Current view: top level - src/base - pdf-fp-func.c (source / functions) Hit Total Coverage
Test: libgnupdf.info Lines: 483 782 61.8 %
Date: 2011-12-09 Functions: 5 16 31.2 %
Branches: 424 707 60.0 %

           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 */

Generated by: LCOV version 1.8