Coverage Report

Created: 2026-06-30 07:15

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