Coverage Report

Created: 2025-11-07 06:58

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