LTP GCOV extension - code coverage report
Current view: directory - src/base - pdf-fp-func.c
Test: libgnupdf.info
Date: 2010-07-31 Instrumented lines: 767
Code covered: 62.1 % Executed lines: 476

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

Generated by: LTP GCOV extension version 1.6