Coverage Report

Created: 2026-04-12 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xpdf-4.06/xpdf/Function.cc
Line
Count
Source
1
//========================================================================
2
//
3
// Function.cc
4
//
5
// Copyright 2001-2003 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
#include <aconf.h>
10
11
#include <stdlib.h>
12
#include <string.h>
13
#include <ctype.h>
14
#include <math.h>
15
#include "gmem.h"
16
#include "gmempp.h"
17
#include "GList.h"
18
#include "Object.h"
19
#include "Dict.h"
20
#include "Stream.h"
21
#include "Error.h"
22
#include "Function.h"
23
24
//------------------------------------------------------------------------
25
26
// Max depth of nested functions.  This is used to catch infinite
27
// loops in the function object structure.
28
10.6k
#define recursionLimit 8
29
30
//------------------------------------------------------------------------
31
// Function
32
//------------------------------------------------------------------------
33
34
12.7k
Function::Function() {
35
12.7k
}
36
37
12.6k
Function::~Function() {
38
12.6k
}
39
40
Function *Function::parse(Object *funcObj, int expectedInputs,
41
10.6k
        int expectedOutputs, int recursion) {
42
10.6k
  Function *func;
43
10.6k
  Dict *dict;
44
10.6k
  int funcType;
45
10.6k
  Object obj1;
46
47
10.6k
  if (recursion > recursionLimit) {
48
4
    error(errSyntaxError, -1, "Loop detected in function objects");
49
4
    return NULL;
50
4
  }
51
52
10.6k
  if (funcObj->isStream()) {
53
2.39k
    dict = funcObj->streamGetDict();
54
8.23k
  } else if (funcObj->isDict()) {
55
7.27k
    dict = funcObj->getDict();
56
7.27k
  } else if (funcObj->isName("Identity")) {
57
0
    if (expectedInputs != expectedOutputs) {
58
0
      error(errSyntaxError, -1, "Invalid use of identity function");
59
0
      return NULL;
60
0
    }
61
0
    return new IdentityFunction(expectedInputs);
62
956
  } else {
63
956
    error(errSyntaxError, -1, "Expected function dictionary or stream");
64
956
    return NULL;
65
956
  }
66
67
9.67k
  if (!dict->lookup("FunctionType", &obj1)->isInt()) {
68
312
    error(errSyntaxError, -1, "Function type is missing or wrong type");
69
312
    obj1.free();
70
312
    return NULL;
71
312
  }
72
9.36k
  funcType = obj1.getInt();
73
9.36k
  obj1.free();
74
75
9.36k
  if (funcType == 0) {
76
1.72k
    func = new SampledFunction(funcObj, dict);
77
7.63k
  } else if (funcType == 2) {
78
4.94k
    func = new ExponentialFunction(funcObj, dict);
79
4.94k
  } else if (funcType == 3) {
80
1.00k
    func = new StitchingFunction(funcObj, dict, expectedInputs,
81
1.00k
         expectedOutputs, recursion);
82
1.68k
  } else if (funcType == 4) {
83
1.58k
    func = new PostScriptFunction(funcObj, dict);
84
1.58k
  } else {
85
104
    error(errSyntaxError, -1, "Unimplemented function type ({0:d})", funcType);
86
104
    return NULL;
87
104
  }
88
9.25k
  if (!func->isOk()) {
89
3.07k
    delete func;
90
3.07k
    return NULL;
91
3.07k
  }
92
93
6.18k
  if (func->getInputSize() != expectedInputs ||
94
6.06k
      (expectedOutputs >= 0 && func->getOutputSize() != expectedOutputs)) {
95
250
    error(errSyntaxError, -1,
96
250
    "Incorrect number of function inputs or outputs");
97
250
    delete func;
98
250
    return NULL;
99
250
  }
100
101
5.93k
  return func;
102
6.18k
}
103
104
9.25k
GBool Function::init(Dict *dict) {
105
9.25k
  Object obj1, obj2;
106
9.25k
  int i;
107
108
  //----- Domain
109
9.25k
  if (!dict->lookup("Domain", &obj1)->isArray()) {
110
296
    error(errSyntaxError, -1, "Function is missing domain");
111
296
    goto err2;
112
296
  }
113
8.96k
  m = obj1.arrayGetLength() / 2;
114
8.96k
  if (m > funcMaxInputs) {
115
25
    error(errSyntaxError, -1,
116
25
    "Functions with more than {0:d} inputs are unsupported",
117
25
    funcMaxInputs);
118
25
    goto err2;
119
25
  }
120
17.9k
  for (i = 0; i < m; ++i) {
121
9.54k
    obj1.arrayGet(2*i, &obj2);
122
9.54k
    if (!obj2.isNum()) {
123
90
      error(errSyntaxError, -1, "Illegal value in function domain array");
124
90
      goto err1;
125
90
    }
126
9.45k
    domain[i][0] = obj2.getNum();
127
9.45k
    obj2.free();
128
9.45k
    obj1.arrayGet(2*i+1, &obj2);
129
9.45k
    if (!obj2.isNum()) {
130
409
      error(errSyntaxError, -1, "Illegal value in function domain array");
131
409
      goto err1;
132
409
    }
133
9.04k
    domain[i][1] = obj2.getNum();
134
9.04k
    obj2.free();
135
9.04k
  }
136
8.43k
  obj1.free();
137
138
  //----- Range
139
8.43k
  hasRange = gFalse;
140
8.43k
  n = 0;
141
8.43k
  if (dict->lookup("Range", &obj1)->isArray()) {
142
3.09k
    hasRange = gTrue;
143
3.09k
    n = obj1.arrayGetLength() / 2;
144
3.09k
    if (n > funcMaxOutputs) {
145
35
      error(errSyntaxError, -1,
146
35
      "Functions with more than {0:d} outputs are unsupported",
147
35
      funcMaxOutputs);
148
35
      goto err2;
149
35
    }
150
9.73k
    for (i = 0; i < n; ++i) {
151
6.82k
      obj1.arrayGet(2*i, &obj2);
152
6.82k
      if (!obj2.isNum()) {
153
45
  error(errSyntaxError, -1, "Illegal value in function range array");
154
45
  goto err1;
155
45
      }
156
6.77k
      range[i][0] = obj2.getNum();
157
6.77k
      obj2.free();
158
6.77k
      obj1.arrayGet(2*i+1, &obj2);
159
6.77k
      if (!obj2.isNum()) {
160
102
  error(errSyntaxError, -1, "Illegal value in function range array");
161
102
  goto err1;
162
102
      }
163
6.67k
      range[i][1] = obj2.getNum();
164
6.67k
      obj2.free();
165
6.67k
    }
166
3.06k
  }
167
8.25k
  obj1.free();
168
169
8.25k
  return gTrue;
170
171
646
 err1:
172
646
  obj2.free();
173
1.00k
 err2:
174
1.00k
  obj1.free();
175
1.00k
  return gFalse;
176
646
}
177
178
//------------------------------------------------------------------------
179
// IdentityFunction
180
//------------------------------------------------------------------------
181
182
0
IdentityFunction::IdentityFunction(int nInputs) {
183
0
  int i;
184
185
0
  m = n = nInputs;
186
  // domain info shouldn't be used anywhere
187
0
  for (i = 0; i < nInputs; ++i) {
188
0
    domain[i][0] = 0;
189
0
    domain[i][1] = 1;
190
0
  }
191
0
  hasRange = gFalse;
192
0
}
193
194
IdentityFunction::~IdentityFunction() {
195
}
196
197
0
void IdentityFunction::transform(double *in, double *out) {
198
0
  int i;
199
200
0
  for (i = 0; i < m; ++i) {
201
0
    out[i] = in[i];
202
0
  }
203
0
}
204
205
//------------------------------------------------------------------------
206
// SampledFunction
207
//------------------------------------------------------------------------
208
209
1.72k
SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
210
1.72k
  Stream *str;
211
1.72k
  int sampleBits;
212
1.72k
  double sampleMul;
213
1.72k
  Object obj1, obj2;
214
1.72k
  Guint buf, bitMask;
215
1.72k
  int bits;
216
1.72k
  Guint s;
217
1.72k
  double in[funcMaxInputs];
218
1.72k
  int i, j, t, bit, idx;
219
220
1.72k
  idxOffset = NULL;
221
1.72k
  samples = NULL;
222
1.72k
  sBuf = NULL;
223
1.72k
  ok = gFalse;
224
225
  //----- initialize the generic stuff
226
1.72k
  if (!init(dict)) {
227
627
    goto err1;
228
627
  }
229
1.10k
  if (!hasRange) {
230
24
    error(errSyntaxError, -1, "Type 0 function is missing range");
231
24
    goto err1;
232
24
  }
233
1.07k
  if (m > sampledFuncMaxInputs) {
234
0
    error(errSyntaxError, -1,
235
0
    "Sampled functions with more than {0:d} inputs are unsupported",
236
0
    sampledFuncMaxInputs);
237
0
    goto err1;
238
0
  }
239
240
  //----- buffer
241
1.07k
  sBuf = (double *)gmallocn(1 << m, sizeof(double));
242
243
  //----- get the stream
244
1.07k
  if (!funcObj->isStream()) {
245
12
    error(errSyntaxError, -1, "Type 0 function isn't a stream");
246
12
    goto err1;
247
12
  }
248
1.06k
  str = funcObj->getStream();
249
250
  //----- Size
251
1.06k
  if (!dict->lookup("Size", &obj1)->isArray() ||
252
1.05k
      obj1.arrayGetLength() != m) {
253
33
    error(errSyntaxError, -1, "Function has missing or invalid size array");
254
33
    goto err2;
255
33
  }
256
2.25k
  for (i = 0; i < m; ++i) {
257
1.25k
    obj1.arrayGet(i, &obj2);
258
1.25k
    if (!obj2.isInt()) {
259
16
      error(errSyntaxError, -1, "Illegal value in function size array");
260
16
      goto err3;
261
16
    }
262
1.23k
    sampleSize[i] = obj2.getInt();
263
1.23k
    if (sampleSize[i] <= 0) {
264
12
      error(errSyntaxError, -1, "Illegal non-positive value in function size array");
265
12
      goto err3;
266
12
    }
267
1.22k
    obj2.free();
268
1.22k
  }
269
1.00k
  obj1.free();
270
1.00k
  idxOffset = (int *)gmallocn(1 << m, sizeof(int));
271
3.64k
  for (i = 0; i < (1<<m); ++i) {
272
2.63k
    idx = 0;
273
4.31k
    for (j = m - 1, t = i; j >= 1; --j, t <<= 1) {
274
1.68k
      if (sampleSize[j] == 1) {
275
136
  bit = 0;
276
1.54k
      } else {
277
1.54k
  bit = (t >> (m - 1)) & 1;
278
1.54k
      }
279
1.68k
      idx = (idx + bit) * sampleSize[j-1];
280
1.68k
    }
281
2.63k
    if (sampleSize[0] == 1) {
282
8
      bit = 0;
283
2.63k
    } else {
284
2.63k
      bit = (t >> (m - 1)) & 1;
285
2.63k
    }
286
2.63k
    idxOffset[i] = (idx + bit) * n;
287
2.63k
  }
288
289
  //----- BitsPerSample
290
1.00k
  if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
291
25
    error(errSyntaxError, -1, "Function has missing or invalid BitsPerSample");
292
25
    goto err2;
293
25
  }
294
979
  sampleBits = obj1.getInt();
295
979
  sampleMul = 1.0 / (pow(2.0, (double)sampleBits) - 1);
296
979
  obj1.free();
297
298
  //----- Encode
299
979
  if (dict->lookup("Encode", &obj1)->isArray() &&
300
812
      obj1.arrayGetLength() == 2*m) {
301
1.55k
    for (i = 0; i < m; ++i) {
302
785
      obj1.arrayGet(2*i, &obj2);
303
785
      if (!obj2.isNum()) {
304
10
  error(errSyntaxError, -1, "Illegal value in function encode array");
305
10
  goto err3;
306
10
      }
307
775
      encode[i][0] = obj2.getNum();
308
775
      obj2.free();
309
775
      obj1.arrayGet(2*i+1, &obj2);
310
775
      if (!obj2.isNum()) {
311
8
  error(errSyntaxError, -1, "Illegal value in function encode array");
312
8
  goto err3;
313
8
      }
314
767
      encode[i][1] = obj2.getNum();
315
767
      obj2.free();
316
767
    }
317
785
  } else {
318
558
    for (i = 0; i < m; ++i) {
319
364
      encode[i][0] = 0;
320
364
      encode[i][1] = sampleSize[i] - 1;
321
364
    }
322
194
  }
323
961
  obj1.free();
324
2.09k
  for (i = 0; i < m; ++i) {
325
1.13k
    inputMul[i] = (encode[i][1] - encode[i][0]) /
326
1.13k
                  (domain[i][1] - domain[i][0]);
327
1.13k
  }
328
329
  //----- Decode
330
961
  if (dict->lookup("Decode", &obj1)->isArray() &&
331
794
      obj1.arrayGetLength() == 2*n) {
332
2.92k
    for (i = 0; i < n; ++i) {
333
2.20k
      obj1.arrayGet(2*i, &obj2);
334
2.20k
      if (!obj2.isNum()) {
335
11
  error(errSyntaxError, -1, "Illegal value in function decode array");
336
11
  goto err3;
337
11
      }
338
2.19k
      decode[i][0] = obj2.getNum();
339
2.19k
      obj2.free();
340
2.19k
      obj1.arrayGet(2*i+1, &obj2);
341
2.19k
      if (!obj2.isNum()) {
342
9
  error(errSyntaxError, -1, "Illegal value in function decode array");
343
9
  goto err3;
344
9
      }
345
2.18k
      decode[i][1] = obj2.getNum();
346
2.18k
      obj2.free();
347
2.18k
    }
348
742
  } else {
349
679
    for (i = 0; i < n; ++i) {
350
460
      decode[i][0] = range[i][0];
351
460
      decode[i][1] = range[i][1];
352
460
    }
353
219
  }
354
941
  obj1.free();
355
356
  //----- samples
357
941
  nSamples = n;
358
2.05k
  for (i = 0; i < m; ++i) {
359
1.11k
    if (nSamples > INT_MAX / sampleSize[i]) {
360
1
      error(errSyntaxError, -1, "Integer overflow in sampled function setup");
361
1
      goto err1;
362
1
    }
363
1.10k
    nSamples *= sampleSize[i];
364
1.10k
  }
365
940
  samples = (double *)gmallocn(nSamples, sizeof(double));
366
940
  buf = 0;
367
940
  bits = 0;
368
940
  bitMask = (sampleBits < 32) ? ((1 << sampleBits) - 1) : 0xffffffffU;
369
940
  str->reset();
370
1.35M
  for (i = 0; i < nSamples; ++i) {
371
1.35M
    if (sampleBits == 8) {
372
1.05M
      s = str->getChar();
373
1.05M
    } else if (sampleBits == 16) {
374
0
      s = str->getChar();
375
0
      s = (s << 8) + str->getChar();
376
302k
    } else if (sampleBits == 32) {
377
0
      s = str->getChar();
378
0
      s = (s << 8) + str->getChar();
379
0
      s = (s << 8) + str->getChar();
380
0
      s = (s << 8) + str->getChar();
381
302k
    } else {
382
3.36M
      while (bits < sampleBits) {
383
3.06M
  buf = (buf << 8) | (str->getChar() & 0xff);
384
3.06M
  bits += 8;
385
3.06M
      }
386
302k
      s = (buf >> (bits - sampleBits)) & bitMask;
387
302k
      bits -= sampleBits;
388
302k
    }
389
1.35M
    samples[i] = (double)s * sampleMul;
390
1.35M
  }
391
940
  str->close();
392
393
  // set up the cache
394
2.04k
  for (i = 0; i < m; ++i) {
395
1.10k
    in[i] = domain[i][0];
396
1.10k
    cacheIn[i] = in[i] - 1;
397
1.10k
  }
398
940
  transform(in, cacheOut);
399
400
940
  ok = gTrue;
401
940
  return;
402
403
66
 err3:
404
66
  obj2.free();
405
124
 err2:
406
124
  obj1.free();
407
788
 err1:
408
788
  return;
409
124
}
410
411
2.28k
SampledFunction::~SampledFunction() {
412
2.28k
  if (idxOffset) {
413
1.56k
    gfree(idxOffset);
414
1.56k
  }
415
2.28k
  if (samples) {
416
1.48k
    gfree(samples);
417
1.48k
  }
418
2.28k
  if (sBuf) {
419
1.63k
    gfree(sBuf);
420
1.63k
  }
421
2.28k
}
422
423
577
SampledFunction::SampledFunction(SampledFunction *func) {
424
577
  memcpy((void *)this, (void *)func, sizeof(SampledFunction));
425
577
  idxOffset = (int *)gmallocn(1 << m, sizeof(int));
426
577
  memcpy(idxOffset, func->idxOffset, (1 << m) * (int)sizeof(int));
427
577
  samples = (double *)gmallocn(nSamples, sizeof(double));
428
577
  memcpy(samples, func->samples, nSamples * sizeof(double));
429
577
  sBuf = (double *)gmallocn(1 << m, sizeof(double));
430
577
}
431
432
23.3k
void SampledFunction::transform(double *in, double *out) {
433
23.3k
  double x;
434
23.3k
  int e[funcMaxInputs];
435
23.3k
  double efrac0[funcMaxInputs];
436
23.3k
  double efrac1[funcMaxInputs];
437
23.3k
  int i, j, k, idx0, t;
438
439
  // check the cache
440
23.9k
  for (i = 0; i < m; ++i) {
441
23.3k
    if (in[i] != cacheIn[i]) {
442
22.8k
      break;
443
22.8k
    }
444
23.3k
  }
445
23.3k
  if (i == m) {
446
2.10k
    for (i = 0; i < n; ++i) {
447
1.55k
      out[i] = cacheOut[i];
448
1.55k
    }
449
543
    return;
450
543
  }
451
452
  // map input values into sample array
453
45.8k
  for (i = 0; i < m; ++i) {
454
23.0k
    x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0];
455
23.0k
    if (x < 0 || x != x) {  // x!=x is a more portable version of isnan(x)
456
78
      x = 0;
457
22.9k
    } else if (x > sampleSize[i] - 1) {
458
3.44k
      x = sampleSize[i] - 1;
459
3.44k
    }
460
23.0k
    e[i] = (int)x;
461
23.0k
    if (e[i] == sampleSize[i] - 1 && sampleSize[i] > 1) {
462
      // this happens if in[i] = domain[i][1]
463
4.36k
      e[i] = sampleSize[i] - 2;
464
4.36k
    }
465
23.0k
    efrac1[i] = x - e[i];
466
23.0k
    efrac0[i] = 1 - efrac1[i];
467
23.0k
  }
468
469
  // compute index for the first sample to be used
470
22.8k
  idx0 = 0;
471
23.0k
  for (k = m - 1; k >= 1; --k) {
472
270
    idx0 = (idx0 + e[k]) * sampleSize[k-1];
473
270
  }
474
22.8k
  idx0 = (idx0 + e[0]) * n;
475
476
  // for each output, do m-linear interpolation
477
72.6k
  for (i = 0; i < n; ++i) {
478
479
    // pull 2^m values out of the sample array
480
151k
    for (j = 0; j < (1<<m); ++j) {
481
102k
      sBuf[j] = samples[idx0 + idxOffset[j] + i];
482
102k
    }
483
484
    // do m sets of interpolations
485
100k
    for (j = 0, t = (1<<m); j < m; ++j, t >>= 1) {
486
102k
      for (k = 0; k < t; k += 2) {
487
52.2k
  sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k+1];
488
52.2k
      }
489
50.6k
    }
490
491
    // map output value to range
492
49.8k
    out[i] = sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
493
49.8k
    if (out[i] < range[i][0]) {
494
852
      out[i] = range[i][0];
495
49.0k
    } else if (out[i] > range[i][1]) {
496
2.06k
      out[i] = range[i][1];
497
2.06k
    }
498
49.8k
  }
499
500
  // save current result in the cache
501
45.8k
  for (i = 0; i < m; ++i) {
502
23.0k
    cacheIn[i] = in[i];
503
23.0k
  }
504
72.6k
  for (i = 0; i < n; ++i) {
505
49.8k
    cacheOut[i] = out[i];
506
49.8k
  }
507
22.8k
}
508
509
//------------------------------------------------------------------------
510
// ExponentialFunction
511
//------------------------------------------------------------------------
512
513
4.94k
ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
514
4.94k
  Object obj1, obj2;
515
4.94k
  int i;
516
517
4.94k
  ok = gFalse;
518
519
  //----- initialize the generic stuff
520
4.94k
  if (!init(dict)) {
521
142
    goto err1;
522
142
  }
523
4.80k
  if (m != 1) {
524
33
    error(errSyntaxError, -1, "Exponential function with more than one input");
525
33
    goto err1;
526
33
  }
527
528
  //----- C0
529
4.77k
  if (dict->lookup("C0", &obj1)->isArray()) {
530
4.57k
    if (hasRange && obj1.arrayGetLength() != n) {
531
77
      error(errSyntaxError, -1, "Function's C0 array is wrong length");
532
77
      goto err2;
533
77
    }
534
4.49k
    n = obj1.arrayGetLength();
535
4.49k
    if (n > funcMaxOutputs) {
536
48
      error(errSyntaxError, -1,
537
48
      "Functions with more than {0:d} outputs are unsupported",
538
48
      funcMaxOutputs);
539
48
      goto err2;
540
48
    }
541
16.5k
    for (i = 0; i < n; ++i) {
542
12.3k
      obj1.arrayGet(i, &obj2);
543
12.3k
      if (!obj2.isNum()) {
544
185
  error(errSyntaxError, -1, "Illegal value in function C0 array");
545
185
  goto err3;
546
185
      }
547
12.1k
      c0[i] = obj2.getNum();
548
12.1k
      obj2.free();
549
12.1k
    }
550
4.45k
  } else {
551
196
    if (hasRange && n != 1) {
552
40
      error(errSyntaxError, -1, "Function's C0 array is wrong length");
553
40
      goto err2;
554
40
    }
555
156
    n = 1;
556
156
    c0[0] = 0;
557
156
  }
558
4.42k
  obj1.free();
559
560
  //----- C1
561
4.42k
  if (dict->lookup("C1", &obj1)->isArray()) {
562
4.18k
    if (obj1.arrayGetLength() != n) {
563
120
      error(errSyntaxError, -1, "Function's C1 array is wrong length");
564
120
      goto err2;
565
120
    }
566
15.3k
    for (i = 0; i < n; ++i) {
567
11.3k
      obj1.arrayGet(i, &obj2);
568
11.3k
      if (!obj2.isNum()) {
569
62
  error(errSyntaxError, -1, "Illegal value in function C1 array");
570
62
  goto err3;
571
62
      }
572
11.2k
      c1[i] = obj2.getNum();
573
11.2k
      obj2.free();
574
11.2k
    }
575
4.06k
  } else {
576
235
    if (n != 1) {
577
116
      error(errSyntaxError, -1, "Function's C1 array is wrong length");
578
116
      goto err2;
579
116
    }
580
119
    c1[0] = 1;
581
119
  }
582
4.12k
  obj1.free();
583
584
  //----- N (exponent)
585
4.12k
  if (!dict->lookup("N", &obj1)->isNum()) {
586
82
    error(errSyntaxError, -1, "Function has missing or invalid N");
587
82
    goto err2;
588
82
  }
589
4.04k
  e = obj1.getNum();
590
4.04k
  obj1.free();
591
592
4.04k
  ok = gTrue;
593
4.04k
  return;
594
595
247
 err3:
596
247
  obj2.free();
597
730
 err2:
598
730
  obj1.free();
599
905
 err1:
600
905
  return;
601
730
}
602
603
ExponentialFunction::~ExponentialFunction() {
604
}
605
606
2.02k
ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
607
2.02k
  memcpy((void *)this, (void *)func, sizeof(ExponentialFunction));
608
2.02k
}
609
610
94.3k
void ExponentialFunction::transform(double *in, double *out) {
611
94.3k
  double x;
612
94.3k
  int i;
613
614
94.3k
  if (in[0] < domain[0][0]) {
615
1.38k
    x = domain[0][0];
616
92.9k
  } else if (in[0] > domain[0][1]) {
617
1.02k
    x = domain[0][1];
618
91.9k
  } else {
619
91.9k
    x = in[0];
620
91.9k
  }
621
376k
  for (i = 0; i < n; ++i) {
622
281k
    out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
623
281k
    if (hasRange) {
624
1.36k
      if (out[i] < range[i][0]) {
625
68
  out[i] = range[i][0];
626
1.30k
      } else if (out[i] > range[i][1]) {
627
102
  out[i] = range[i][1];
628
102
      }
629
1.36k
    }
630
281k
  }
631
94.3k
  return;
632
94.3k
}
633
634
//------------------------------------------------------------------------
635
// StitchingFunction
636
//------------------------------------------------------------------------
637
638
StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict,
639
             int expectedInputs, int expectedOutputs,
640
1.00k
             int recursion) {
641
1.00k
  Object obj1, obj2;
642
1.00k
  int i;
643
644
1.00k
  ok = gFalse;
645
1.00k
  funcs = NULL;
646
1.00k
  bounds = NULL;
647
1.00k
  encode = NULL;
648
1.00k
  scale = NULL;
649
650
  //----- initialize the generic stuff
651
1.00k
  if (!init(dict)) {
652
21
    goto err1;
653
21
  }
654
983
  if (m != 1) {
655
10
    error(errSyntaxError, -1, "Stitching function with more than one input");
656
10
    goto err1;
657
10
  }
658
659
  //----- Functions
660
973
  if (!dict->lookup("Functions", &obj1)->isArray() ||
661
926
      obj1.arrayGetLength() < 1) {
662
83
    error(errSyntaxError, -1,
663
83
    "Missing 'Functions' entry in stitching function");
664
83
    goto err1;
665
83
  }
666
890
  k = obj1.arrayGetLength();
667
890
  funcs = (Function **)gmallocn(k, sizeof(Function *));
668
890
  bounds = (double *)gmallocn(k + 1, sizeof(double));
669
890
  encode = (double *)gmallocn(2 * k, sizeof(double));
670
890
  scale = (double *)gmallocn(k, sizeof(double));
671
3.97k
  for (i = 0; i < k; ++i) {
672
3.08k
    funcs[i] = NULL;
673
3.08k
  }
674
2.46k
  for (i = 0; i < k; ++i) {
675
1.81k
    if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2),
676
1.81k
             expectedInputs, expectedOutputs,
677
1.81k
             recursion + 1))) {
678
232
      goto err2;
679
232
    }
680
1.58k
    if (i == 0) {
681
743
      n = funcs[0]->getOutputSize();
682
743
    }
683
1.58k
    if (funcs[i]->getInputSize() != 1 || funcs[i]->getOutputSize() != n) {
684
6
      error(errSyntaxError, -1,
685
6
      "Incompatible subfunctions in stitching function");
686
6
      goto err2;
687
6
    }
688
1.57k
    obj2.free();
689
1.57k
  }
690
652
  obj1.free();
691
692
  //----- Bounds
693
652
  if (!dict->lookup("Bounds", &obj1)->isArray() ||
694
631
      obj1.arrayGetLength() != k - 1) {
695
40
    error(errSyntaxError, -1,
696
40
    "Missing or invalid 'Bounds' entry in stitching function");
697
40
    goto err1;
698
40
  }
699
612
  bounds[0] = domain[0][0];
700
1.38k
  for (i = 1; i < k; ++i) {
701
785
    if (!obj1.arrayGet(i - 1, &obj2)->isNum()) {
702
11
      error(errSyntaxError, -1,
703
11
      "Invalid type in 'Bounds' array in stitching function");
704
11
      goto err2;
705
11
    }
706
774
    bounds[i] = obj2.getNum();
707
774
    obj2.free();
708
774
  }
709
601
  bounds[k] = domain[0][1];
710
601
  obj1.free();
711
712
  //----- Encode
713
601
  if (!dict->lookup("Encode", &obj1)->isArray() ||
714
580
      obj1.arrayGetLength() != 2 * k) {
715
42
    error(errSyntaxError, -1,
716
42
    "Missing or invalid 'Encode' entry in stitching function");
717
42
    goto err1;
718
42
  }
719
3.14k
  for (i = 0; i < 2 * k; ++i) {
720
2.61k
    if (!obj1.arrayGet(i, &obj2)->isNum()) {
721
22
      error(errSyntaxError, -1,
722
22
      "Invalid type in 'Encode' array in stitching function");
723
22
      goto err2;
724
22
    }
725
2.58k
    encode[i] = obj2.getNum();
726
2.58k
    obj2.free();
727
2.58k
  }
728
537
  obj1.free();
729
730
  //----- pre-compute the scale factors
731
1.81k
  for (i = 0; i < k; ++i) {
732
1.28k
    if (bounds[i] == bounds[i+1]) {
733
      // avoid a divide-by-zero -- in this situation, function i will
734
      // never be used anyway
735
11
      scale[i] = 0;
736
1.27k
    } else {
737
1.27k
      scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]);
738
1.27k
    }
739
1.28k
  }
740
741
537
  ok = gTrue;
742
537
  return;
743
744
271
 err2:
745
271
  obj2.free();
746
467
 err1:
747
467
  obj1.free();
748
467
}
749
750
289
StitchingFunction::StitchingFunction(StitchingFunction *func) {
751
289
  int i;
752
753
289
  memcpy((void *)this, (void *)func, sizeof(StitchingFunction));
754
289
  funcs = (Function **)gmallocn(k, sizeof(Function *));
755
1.05k
  for (i = 0; i < k; ++i) {
756
767
    funcs[i] = func->funcs[i]->copy();
757
767
  }
758
289
  bounds = (double *)gmallocn(k + 1, sizeof(double));
759
289
  memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
760
289
  encode = (double *)gmallocn(2 * k, sizeof(double));
761
289
  memcpy(encode, func->encode, 2 * k * sizeof(double));
762
289
  scale = (double *)gmallocn(k, sizeof(double));
763
289
  memcpy(scale, func->scale, k * sizeof(double));
764
289
  ok = gTrue;
765
289
}
766
767
1.28k
StitchingFunction::~StitchingFunction() {
768
1.28k
  int i;
769
770
1.28k
  if (funcs) {
771
4.97k
    for (i = 0; i < k; ++i) {
772
3.80k
      if (funcs[i]) {
773
2.31k
  delete funcs[i];
774
2.31k
      }
775
3.80k
    }
776
1.16k
  }
777
1.28k
  gfree(funcs);
778
1.28k
  gfree(bounds);
779
1.28k
  gfree(encode);
780
1.28k
  gfree(scale);
781
1.28k
}
782
783
86.7k
void StitchingFunction::transform(double *in, double *out) {
784
86.7k
  double x;
785
86.7k
  int i;
786
787
86.7k
  if (in[0] < domain[0][0]) {
788
0
    x = domain[0][0];
789
86.7k
  } else if (in[0] > domain[0][1]) {
790
40.4k
    x = domain[0][1];
791
46.2k
  } else {
792
46.2k
    x = in[0];
793
46.2k
  }
794
202k
  for (i = 0; i < k - 1; ++i) {
795
150k
    if (x < bounds[i+1]) {
796
34.8k
      break;
797
34.8k
    }
798
150k
  }
799
86.7k
  x = encode[2*i] + (x - bounds[i]) * scale[i];
800
86.7k
  funcs[i]->transform(&x, out);
801
86.7k
}
802
803
//------------------------------------------------------------------------
804
// PostScriptFunction
805
//------------------------------------------------------------------------
806
807
// This is not an enum, because we can't foreward-declare the enum
808
// type in Function.h
809
//
810
// NB: This must be kept in sync with psOpNames[] below.
811
51
#define psOpAbs       0
812
39
#define psOpAdd       1
813
0
#define psOpAnd       2
814
0
#define psOpAtan      3
815
0
#define psOpBitshift  4
816
0
#define psOpCeiling   5
817
0
#define psOpCopy      6
818
0
#define psOpCos       7
819
0
#define psOpCvi       8
820
4.09k
#define psOpCvr       9
821
0
#define psOpDiv      10
822
307
#define psOpDup      11
823
0
#define psOpEq       12
824
21.5k
#define psOpExch     13
825
0
#define psOpExp      14
826
0
#define psOpFalse    15
827
0
#define psOpFloor    16
828
178
#define psOpGe       17
829
128
#define psOpGt       18
830
0
#define psOpIdiv     19
831
969
#define psOpIndex    20
832
0
#define psOpLe       21
833
0
#define psOpLn       22
834
0
#define psOpLog      23
835
60
#define psOpLt       24
836
0
#define psOpMod      25
837
0
#define psOpMul      26
838
0
#define psOpNe       27
839
0
#define psOpNeg      28
840
0
#define psOpNot      29
841
0
#define psOpOr       30
842
994
#define psOpPop      31
843
9.91k
#define psOpRoll     32
844
0
#define psOpRound    33
845
0
#define psOpSin      34
846
0
#define psOpSqrt     35
847
21.6k
#define psOpSub      36
848
0
#define psOpTrue     37
849
0
#define psOpTruncate 38
850
0
#define psOpXor      39
851
// the push/j/jz ops are used internally (and are not listed in psOpNames[])
852
53.5k
#define psOpPush     40
853
37
#define psOpJ        41
854
2.48k
#define psOpJz       42
855
856
7.28k
#define nPSOps (sizeof(psOpNames) / sizeof(const char *))
857
858
// Note: 'if' and 'ifelse' are parsed separately.
859
// The rest are listed here in alphabetical order.
860
//
861
// NB: This must be kept in sync with the psOpXXX defines above.
862
static const char *psOpNames[] = {
863
  "abs",
864
  "add",
865
  "and",
866
  "atan",
867
  "bitshift",
868
  "ceiling",
869
  "copy",
870
  "cos",
871
  "cvi",
872
  "cvr",
873
  "div",
874
  "dup",
875
  "eq",
876
  "exch",
877
  "exp",
878
  "false",
879
  "floor",
880
  "ge",
881
  "gt",
882
  "idiv",
883
  "index",
884
  "le",
885
  "ln",
886
  "log",
887
  "lt",
888
  "mod",
889
  "mul",
890
  "ne",
891
  "neg",
892
  "not",
893
  "or",
894
  "pop",
895
  "roll",
896
  "round",
897
  "sin",
898
  "sqrt",
899
  "sub",
900
  "true",
901
  "truncate",
902
  "xor"
903
};
904
905
struct PSCode {
906
  int op;
907
  union {
908
    double d;
909
    int i;
910
  } val;
911
};
912
913
177k
#define psStackSize 100
914
915
1.58k
PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
916
1.58k
  Stream *str;
917
1.58k
  GList *tokens;
918
1.58k
  GString *tok;
919
1.58k
  double in[funcMaxInputs];
920
1.58k
  int tokPtr, codePtr, i;
921
922
1.58k
  codeString = NULL;
923
1.58k
  code = NULL;
924
1.58k
  codeSize = 0;
925
1.58k
  ok = gFalse;
926
927
  //----- initialize the generic stuff
928
1.58k
  if (!init(dict)) {
929
212
    goto err1;
930
212
  }
931
1.36k
  if (!hasRange) {
932
69
    error(errSyntaxError, -1, "Type 4 function is missing range");
933
69
    goto err1;
934
69
  }
935
936
  //----- get the stream
937
1.29k
  if (!funcObj->isStream()) {
938
89
    error(errSyntaxError, -1, "Type 4 function isn't a stream");
939
89
    goto err1;
940
89
  }
941
1.21k
  str = funcObj->getStream();
942
943
  //----- tokenize the function
944
1.21k
  codeString = new GString();
945
1.21k
  tokens = new GList();
946
1.21k
  str->reset();
947
176k
  while ((tok = getToken(str))) {
948
175k
    tokens->append(tok);
949
175k
  }
950
1.21k
  str->close();
951
952
  //----- parse the function
953
1.21k
  if (tokens->getLength() < 1 ||
954
1.17k
      ((GString *)tokens->get(0))->cmp("{")) {
955
154
    error(errSyntaxError, -1, "Expected '{{' at start of PostScript function");
956
154
    goto err2;
957
154
  }
958
1.05k
  tokPtr = 1;
959
1.05k
  codePtr = 0;
960
1.05k
  if (!parseCode(tokens, &tokPtr, &codePtr)) {
961
393
    goto err2;
962
393
  }
963
663
  codeLen = codePtr;
964
965
  //----- set up the cache
966
1.38k
  for (i = 0; i < m; ++i) {
967
723
    in[i] = domain[i][0];
968
723
    cacheIn[i] = in[i] - 1;
969
723
  }
970
663
  transform(in, cacheOut);
971
972
663
  ok = gTrue;
973
974
1.21k
 err2:
975
1.21k
  deleteGList(tokens, GString);
976
1.58k
 err1:
977
1.58k
  return;
978
1.21k
}
979
980
596
PostScriptFunction::PostScriptFunction(PostScriptFunction *func) {
981
596
  memcpy((void *)this, (void *)func, sizeof(PostScriptFunction));
982
596
  codeString = func->codeString->copy();
983
596
  code = (PSCode *)gmallocn(codeSize, sizeof(PSCode));
984
596
  memcpy(code, func->code, codeSize * sizeof(PSCode));
985
596
}
986
987
2.17k
PostScriptFunction::~PostScriptFunction() {
988
2.17k
  gfree(code);
989
2.17k
  if (codeString) {
990
1.80k
    delete codeString;
991
1.80k
  }
992
2.17k
}
993
994
19.0k
void PostScriptFunction::transform(double *in, double *out) {
995
19.0k
  double stack[psStackSize];
996
19.0k
  double x;
997
19.0k
  int sp, i;
998
999
  // check the cache
1000
19.5k
  for (i = 0; i < m; ++i) {
1001
18.9k
    if (in[i] != cacheIn[i]) {
1002
18.5k
      break;
1003
18.5k
    }
1004
18.9k
  }
1005
19.0k
  if (i == m) {
1006
1.46k
    for (i = 0; i < n; ++i) {
1007
949
      out[i] = cacheOut[i];
1008
949
    }
1009
519
    return;
1010
519
  }
1011
1012
37.0k
  for (i = 0; i < m; ++i) {
1013
18.5k
    stack[psStackSize - 1 - i] = in[i];
1014
18.5k
  }
1015
18.5k
  sp = exec(stack, psStackSize - m);
1016
  // if (sp < psStackSize - n) {
1017
  //   error(errSyntaxWarning, -1,
1018
  //    "Extra values on stack at end of PostScript function");
1019
  // }
1020
18.5k
  if (sp > psStackSize - n) {
1021
107
    error(errSyntaxError, -1, "Stack underflow in PostScript function");
1022
107
    sp = psStackSize - n;
1023
107
  }
1024
39.8k
  for (i = 0; i < n; ++i) {
1025
21.3k
    x = stack[sp + n - 1 - i];
1026
21.3k
    if (x < range[i][0]) {
1027
49
      out[i] = range[i][0];
1028
21.2k
    } else if (x > range[i][1]) {
1029
130
      out[i] = range[i][1];
1030
21.1k
    } else {
1031
21.1k
      out[i] = x;
1032
21.1k
    }
1033
21.3k
  }
1034
1035
  // save current result in the cache
1036
37.0k
  for (i = 0; i < m; ++i) {
1037
18.5k
    cacheIn[i] = in[i];
1038
18.5k
  }
1039
39.8k
  for (i = 0; i < n; ++i) {
1040
21.3k
    cacheOut[i] = out[i];
1041
21.3k
  }
1042
18.5k
}
1043
1044
3.15k
GBool PostScriptFunction::parseCode(GList *tokens, int *tokPtr, int *codePtr) {
1045
3.15k
  GString *tok;
1046
3.15k
  char *p;
1047
3.15k
  int a, b, mid, cmp;
1048
3.15k
  int codePtr0, codePtr1;
1049
1050
18.5k
  while (1) {
1051
18.5k
    if (*tokPtr >= tokens->getLength()) {
1052
205
      error(errSyntaxError, -1,
1053
205
      "Unexpected end of PostScript function stream");
1054
205
      return gFalse;
1055
205
    }
1056
18.3k
    tok = (GString *)tokens->get((*tokPtr)++);
1057
18.3k
    p = tok->getCString();
1058
18.3k
    if (isdigit(*p) || *p == '.' || *p == '-') {
1059
7.78k
      addCodeD(codePtr, psOpPush, atof(tok->getCString()));
1060
10.6k
    } else if (!tok->cmp("{")) {
1061
2.06k
      codePtr0 = *codePtr;
1062
2.06k
      addCodeI(codePtr, psOpJz, 0);
1063
2.06k
      if (!parseCode(tokens, tokPtr, codePtr)) {
1064
1.49k
  return gFalse;
1065
1.49k
      }
1066
569
      if (*tokPtr >= tokens->getLength()) {
1067
3
  error(errSyntaxError, -1,
1068
3
        "Unexpected end of PostScript function stream");
1069
3
  return gFalse;
1070
3
      }
1071
566
      tok = (GString *)tokens->get((*tokPtr)++);
1072
566
      if (!tok->cmp("if")) {
1073
503
  code[codePtr0].val.i = *codePtr;
1074
503
      } else if (!tok->cmp("{")) {
1075
37
  codePtr1 = *codePtr;
1076
37
  addCodeI(codePtr, psOpJ, 0);
1077
37
  code[codePtr0].val.i = *codePtr;
1078
37
  if (!parseCode(tokens, tokPtr, codePtr)) {
1079
27
    return gFalse;
1080
27
  }
1081
10
  if (*tokPtr >= tokens->getLength()) {
1082
0
    error(errSyntaxError, -1,
1083
0
    "Unexpected end of PostScript function stream");
1084
0
    return gFalse;
1085
0
  }
1086
10
  tok = (GString *)tokens->get((*tokPtr)++);
1087
10
  if (!tok->cmp("ifelse")) {
1088
0
    code[codePtr1].val.i = *codePtr;
1089
10
  } else {
1090
10
    error(errSyntaxError, -1,
1091
10
    "Expected 'ifelse' in PostScript function stream");
1092
10
    return gFalse;
1093
10
  }
1094
26
      } else {
1095
26
  error(errSyntaxError, -1,
1096
26
        "Expected 'if' in PostScript function stream");
1097
26
  return gFalse;
1098
26
      }
1099
8.54k
    } else if (!tok->cmp("}")) {
1100
1.24k
      break;
1101
7.30k
    } else if (!tok->cmp("if")) {
1102
17
      error(errSyntaxError, -1,
1103
17
      "Unexpected 'if' in PostScript function stream");
1104
17
      return gFalse;
1105
7.28k
    } else if (!tok->cmp("ifelse")) {
1106
0
      error(errSyntaxError, -1,
1107
0
      "Unexpected 'ifelse' in PostScript function stream");
1108
0
      return gFalse;
1109
7.28k
    } else {
1110
7.28k
      a = -1;
1111
7.28k
      b = nPSOps;
1112
7.28k
      cmp = 0; // make gcc happy
1113
      // invariant: psOpNames[a] < tok < psOpNames[b]
1114
42.9k
      while (b - a > 1) {
1115
35.7k
  mid = (a + b) / 2;
1116
35.7k
  cmp = tok->cmp(psOpNames[mid]);
1117
35.7k
  if (cmp > 0) {
1118
18.5k
    a = mid;
1119
18.5k
  } else if (cmp < 0) {
1120
9.97k
    b = mid;
1121
9.97k
  } else {
1122
7.15k
    a = b = mid;
1123
7.15k
  }
1124
35.7k
      }
1125
7.28k
      if (cmp != 0) {
1126
132
  error(errSyntaxError, -1,
1127
132
        "Unknown operator '{0:t}' in PostScript function",
1128
132
        tok);
1129
132
  return gFalse;
1130
132
      }
1131
7.15k
      addCode(codePtr, a);
1132
7.15k
    }
1133
18.3k
  }
1134
1.24k
  return gTrue;
1135
3.15k
}
1136
1137
7.15k
void PostScriptFunction::addCode(int *codePtr, int op) {
1138
7.15k
  if (*codePtr >= codeSize) {
1139
384
    if (codeSize) {
1140
284
      codeSize *= 2;
1141
284
    } else {
1142
100
      codeSize = 16;
1143
100
    }
1144
384
    code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode));
1145
384
  }
1146
7.15k
  code[*codePtr].op = op;
1147
7.15k
  ++(*codePtr);
1148
7.15k
}
1149
1150
2.09k
void PostScriptFunction::addCodeI(int *codePtr, int op, int x) {
1151
2.09k
  if (*codePtr >= codeSize) {
1152
173
    if (codeSize) {
1153
103
      codeSize *= 2;
1154
103
    } else {
1155
70
      codeSize = 16;
1156
70
    }
1157
173
    code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode));
1158
173
  }
1159
2.09k
  code[*codePtr].op = op;
1160
2.09k
  code[*codePtr].val.i = x;
1161
2.09k
  ++(*codePtr);
1162
2.09k
}
1163
1164
7.78k
void PostScriptFunction::addCodeD(int *codePtr, int op, double x) {
1165
7.78k
  if (*codePtr >= codeSize) {
1166
1.00k
    if (codeSize) {
1167
220
      codeSize *= 2;
1168
783
    } else {
1169
783
      codeSize = 16;
1170
783
    }
1171
1.00k
    code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode));
1172
1.00k
  }
1173
7.78k
  code[*codePtr].op = op;
1174
7.78k
  code[*codePtr].val.d = x;
1175
7.78k
  ++(*codePtr);
1176
7.78k
}
1177
1178
176k
GString *PostScriptFunction::getToken(Stream *str) {
1179
176k
  GString *s;
1180
176k
  int c;
1181
176k
  GBool comment;
1182
1183
176k
  s = new GString();
1184
176k
  comment = gFalse;
1185
220k
  while (1) {
1186
220k
    if ((c = str->getChar()) == EOF) {
1187
1.21k
      delete s;
1188
1.21k
      return NULL;
1189
1.21k
    }
1190
219k
    codeString->append((char)c);
1191
219k
    if (comment) {
1192
11.1k
      if (c == '\x0a' || c == '\x0d') {
1193
334
  comment = gFalse;
1194
334
      }
1195
208k
    } else if (c == '%') {
1196
337
      comment = gTrue;
1197
207k
    } else if (!isspace(c)) {
1198
175k
      break;
1199
175k
    }
1200
219k
  }
1201
175k
  if (c == '{' || c == '}') {
1202
5.59k
    s->append((char)c);
1203
169k
  } else if (isdigit(c) || c == '.' || c == '-') {
1204
29.9k
    while (1) {
1205
29.9k
      s->append((char)c);
1206
29.9k
      c = str->lookChar();
1207
29.9k
      if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
1208
12.8k
  break;
1209
12.8k
      }
1210
17.1k
      str->getChar();
1211
17.1k
      codeString->append((char)c);
1212
17.1k
    }
1213
156k
  } else {
1214
210k
    while (1) {
1215
210k
      s->append((char)c);
1216
210k
      c = str->lookChar();
1217
210k
      if (c == EOF || !isalnum(c)) {
1218
156k
  break;
1219
156k
      }
1220
53.5k
      str->getChar();
1221
53.5k
      codeString->append((char)c);
1222
53.5k
    }
1223
156k
  }
1224
175k
  return s;
1225
176k
}
1226
1227
18.5k
int PostScriptFunction::exec(double *stack, int sp0) {
1228
18.5k
  PSCode *c;
1229
18.5k
  double tmp[psStackSize];
1230
18.5k
  double t;
1231
18.5k
  int sp, ip, nn, k, i;
1232
1233
18.5k
  sp = sp0;
1234
18.5k
  ip = 0;
1235
124k
  while (ip < codeLen) {
1236
106k
    c = &code[ip++];
1237
106k
    switch(c->op) {
1238
51
    case psOpAbs:
1239
51
      if (sp >= psStackSize) {
1240
0
  goto underflow;
1241
0
      }
1242
51
      stack[sp] = fabs(stack[sp]);
1243
51
      break;
1244
39
    case psOpAdd:
1245
39
      if (sp + 1 >= psStackSize) {
1246
0
  goto underflow;
1247
0
      }
1248
39
      stack[sp + 1] = stack[sp + 1] + stack[sp];
1249
39
      ++sp;
1250
39
      break;
1251
0
    case psOpAnd:
1252
0
      if (sp + 1 >= psStackSize) {
1253
0
  goto underflow;
1254
0
      }
1255
0
      stack[sp + 1] = (int)stack[sp + 1] & (int)stack[sp];
1256
0
      ++sp;
1257
0
      break;
1258
0
    case psOpAtan:
1259
0
      if (sp + 1 >= psStackSize) {
1260
0
  goto underflow;
1261
0
      }
1262
0
      stack[sp + 1] = atan2(stack[sp + 1], stack[sp]);
1263
0
      ++sp;
1264
0
      break;
1265
0
    case psOpBitshift:
1266
0
      if (sp + 1 >= psStackSize) {
1267
0
  goto underflow;
1268
0
      }
1269
0
      k = (int)stack[sp + 1];
1270
0
      nn = (int)stack[sp];
1271
0
      if (nn > 0) {
1272
0
  stack[sp + 1] = k << nn;
1273
0
      } else if (nn < 0) {
1274
0
  stack[sp + 1] = k >> -nn;
1275
0
      } else {
1276
0
  stack[sp + 1] = k;
1277
0
      }
1278
0
      ++sp;
1279
0
      break;
1280
0
    case psOpCeiling:
1281
0
      if (sp >= psStackSize) {
1282
0
  goto underflow;
1283
0
      }
1284
0
      stack[sp] = ceil(stack[sp]);
1285
0
      break;
1286
0
    case psOpCopy:
1287
0
      if (sp >= psStackSize) {
1288
0
  goto underflow;
1289
0
      }
1290
0
      nn = (int)stack[sp++];
1291
0
      if (nn < 0 || nn > psStackSize) {
1292
0
  goto invalidArg;
1293
0
      }
1294
0
      if (sp + nn > psStackSize) {
1295
0
  goto underflow;
1296
0
      }
1297
0
      if (sp - nn < 0) {
1298
0
  goto overflow;
1299
0
      }
1300
0
      for (i = 0; i < nn; ++i) {
1301
0
  stack[sp - nn + i] = stack[sp + i];
1302
0
      }
1303
0
      sp -= nn;
1304
0
      break;
1305
0
    case psOpCos:
1306
0
      if (sp >= psStackSize) {
1307
0
  goto underflow;
1308
0
      }
1309
0
      stack[sp] = cos(stack[sp]);
1310
0
      break;
1311
0
    case psOpCvi:
1312
0
      if (sp >= psStackSize) {
1313
0
  goto underflow;
1314
0
      }
1315
0
      stack[sp] = (int)stack[sp];
1316
0
      break;
1317
4.09k
    case psOpCvr:
1318
4.09k
      if (sp >= psStackSize) {
1319
0
  goto underflow;
1320
0
      }
1321
4.09k
      break;
1322
4.09k
    case psOpDiv:
1323
0
      if (sp + 1 >= psStackSize) {
1324
0
  goto underflow;
1325
0
      }
1326
0
      if (stack[sp] == 0) {
1327
0
  goto invalidArg;
1328
0
      }
1329
0
      stack[sp + 1] = stack[sp + 1] / stack[sp];
1330
0
      ++sp;
1331
0
      break;
1332
307
    case psOpDup:
1333
307
      if (sp >= psStackSize) {
1334
27
  goto underflow;
1335
27
      }
1336
280
      if (sp < 1) {
1337
0
  goto overflow;
1338
0
      }
1339
280
      stack[sp - 1] = stack[sp];
1340
280
      --sp;
1341
280
      break;
1342
0
    case psOpEq:
1343
0
      if (sp + 1 >= psStackSize) {
1344
0
  goto underflow;
1345
0
      }
1346
0
      stack[sp + 1] = stack[sp + 1] == stack[sp] ? 1 : 0;
1347
0
      ++sp;
1348
0
      break;
1349
21.5k
    case psOpExch:
1350
21.5k
      if (sp + 1 >= psStackSize) {
1351
0
  goto underflow;
1352
0
      }
1353
21.5k
      t = stack[sp];
1354
21.5k
      stack[sp] = stack[sp + 1];
1355
21.5k
      stack[sp + 1] = t;
1356
21.5k
      break;
1357
0
    case psOpExp:
1358
0
      if (sp + 1 >= psStackSize) {
1359
0
  goto underflow;
1360
0
      }
1361
0
      stack[sp + 1] = pow(stack[sp + 1], stack[sp]);
1362
0
      ++sp;
1363
0
      break;
1364
0
    case psOpFalse:
1365
0
      if (sp < 1) {
1366
0
  goto overflow;
1367
0
      }
1368
0
      stack[sp - 1] = 0;
1369
0
      --sp;
1370
0
      break;
1371
0
    case psOpFloor:
1372
0
      if (sp >= psStackSize) {
1373
0
  goto underflow;
1374
0
      }
1375
0
      stack[sp] = floor(stack[sp]);
1376
0
      break;
1377
178
    case psOpGe:
1378
178
      if (sp + 1 >= psStackSize) {
1379
12
  goto underflow;
1380
12
      }
1381
166
      stack[sp + 1] = stack[sp + 1] >= stack[sp] ? 1 : 0;
1382
166
      ++sp;
1383
166
      break;
1384
128
    case psOpGt:
1385
128
      if (sp + 1 >= psStackSize) {
1386
0
  goto underflow;
1387
0
      }
1388
128
      stack[sp + 1] = stack[sp + 1] > stack[sp] ? 1 : 0;
1389
128
      ++sp;
1390
128
      break;
1391
0
    case psOpIdiv:
1392
0
      if (sp + 1 >= psStackSize) {
1393
0
  goto underflow;
1394
0
      }
1395
0
      k = (int)stack[sp];
1396
0
      if (k == 0) {
1397
0
  goto invalidArg;
1398
0
      }
1399
0
      stack[sp + 1] = (int)stack[sp + 1] / k;
1400
0
      ++sp;
1401
0
      break;
1402
969
    case psOpIndex:
1403
969
      if (sp >= psStackSize) {
1404
10
  goto underflow;
1405
10
      }
1406
959
      k = (int)stack[sp];
1407
959
      if (k < 0 || k > psStackSize) {
1408
0
        goto invalidArg;
1409
0
      }
1410
959
      if (sp + 1 + k >= psStackSize) {
1411
12
  goto underflow;
1412
12
      }
1413
947
      stack[sp] = stack[sp + 1 + k];
1414
947
      break;
1415
0
    case psOpLe:
1416
0
      if (sp + 1 >= psStackSize) {
1417
0
  goto underflow;
1418
0
      }
1419
0
      stack[sp + 1] = stack[sp + 1] <= stack[sp] ? 1 : 0;
1420
0
      ++sp;
1421
0
      break;
1422
0
    case psOpLn:
1423
0
      if (sp >= psStackSize) {
1424
0
  goto underflow;
1425
0
      }
1426
0
      stack[sp] = log(stack[sp]);
1427
0
      break;
1428
0
    case psOpLog:
1429
0
      if (sp >= psStackSize) {
1430
0
  goto underflow;
1431
0
      }
1432
0
      stack[sp] = log10(stack[sp]);
1433
0
      break;
1434
60
    case psOpLt:
1435
60
      if (sp + 1 >= psStackSize) {
1436
0
  goto underflow;
1437
0
      }
1438
60
      stack[sp + 1] = stack[sp + 1] < stack[sp] ? 1 : 0;
1439
60
      ++sp;
1440
60
      break;
1441
0
    case psOpMod:
1442
0
      if (sp + 1 >= psStackSize) {
1443
0
  goto underflow;
1444
0
      }
1445
0
      k = (int)stack[sp];
1446
0
      if (k == 0) {
1447
0
  goto invalidArg;
1448
0
      }
1449
0
      stack[sp + 1] = (int)stack[sp + 1] % k;
1450
0
      ++sp;
1451
0
      break;
1452
0
    case psOpMul:
1453
0
      if (sp + 1 >= psStackSize) {
1454
0
  goto underflow;
1455
0
      }
1456
0
      stack[sp + 1] = stack[sp + 1] * stack[sp];
1457
0
      ++sp;
1458
0
      break;
1459
0
    case psOpNe:
1460
0
      if (sp + 1 >= psStackSize) {
1461
0
  goto underflow;
1462
0
      }
1463
0
      stack[sp + 1] = stack[sp + 1] != stack[sp] ? 1 : 0;
1464
0
      ++sp;
1465
0
      break;
1466
0
    case psOpNeg:
1467
0
      if (sp >= psStackSize) {
1468
0
  goto underflow;
1469
0
      }
1470
0
      stack[sp] = -stack[sp];
1471
0
      break;
1472
0
    case psOpNot:
1473
0
      if (sp >= psStackSize) {
1474
0
  goto underflow;
1475
0
      }
1476
0
      stack[sp] = stack[sp] == 0 ? 1 : 0;
1477
0
      break;
1478
0
    case psOpOr:
1479
0
      if (sp + 1 >= psStackSize) {
1480
0
  goto underflow;
1481
0
      }
1482
0
      stack[sp + 1] = (int)stack[sp + 1] | (int)stack[sp];
1483
0
      ++sp;
1484
0
      break;
1485
994
    case psOpPop:
1486
994
      if (sp >= psStackSize) {
1487
3
  goto underflow;
1488
3
      }
1489
991
      ++sp;
1490
991
      break;
1491
9.91k
    case psOpRoll:
1492
9.91k
      if (sp + 1 >= psStackSize) {
1493
6
  goto underflow;
1494
6
      }
1495
9.91k
      k = (int)stack[sp++];
1496
9.91k
      nn = (int)stack[sp++];
1497
9.91k
      if (k < -psStackSize || k > psStackSize || nn < 0 || nn > psStackSize) {
1498
0
        goto invalidArg;
1499
0
      }
1500
9.91k
      if (nn > 0) {
1501
9.86k
  if (sp + nn > psStackSize) {
1502
10
    goto underflow;
1503
10
  }
1504
9.85k
  if (k >= 0) {
1505
6.59k
    k %= nn;
1506
6.59k
  } else {
1507
3.26k
    k = -k % nn;
1508
3.26k
    if (k) {
1509
3.25k
      k = nn - k;
1510
3.25k
    }
1511
3.26k
  }
1512
40.6k
  for (i = 0; i < nn; ++i) {
1513
30.8k
    tmp[i] = stack[sp + i];
1514
30.8k
  }
1515
40.6k
  for (i = 0; i < nn; ++i) {
1516
30.8k
    stack[sp + i] = tmp[(i + k) % nn];
1517
30.8k
  }
1518
9.85k
      }
1519
9.90k
      break;
1520
9.90k
    case psOpRound:
1521
0
      if (sp >= psStackSize) {
1522
0
  goto underflow;
1523
0
      }
1524
0
      t = stack[sp];
1525
0
      stack[sp] = (t >= 0) ? floor(t + 0.5) : ceil(t - 0.5);
1526
0
      break;
1527
0
    case psOpSin:
1528
0
      if (sp >= psStackSize) {
1529
0
  goto underflow;
1530
0
      }
1531
0
      stack[sp] = sin(stack[sp]);
1532
0
      break;
1533
0
    case psOpSqrt:
1534
0
      if (sp >= psStackSize) {
1535
0
  goto underflow;
1536
0
      }
1537
0
      stack[sp] = sqrt(stack[sp]);
1538
0
      break;
1539
21.6k
    case psOpSub:
1540
21.6k
      if (sp + 1 >= psStackSize) {
1541
7
  goto underflow;
1542
7
      }
1543
21.6k
      stack[sp + 1] = stack[sp + 1] - stack[sp];
1544
21.6k
      ++sp;
1545
21.6k
      break;
1546
0
    case psOpTrue:
1547
0
      if (sp < 1) {
1548
0
  goto overflow;
1549
0
      }
1550
0
      stack[sp - 1] = 1;
1551
0
      --sp;
1552
0
      break;
1553
0
    case psOpTruncate:
1554
0
      if (sp >= psStackSize) {
1555
0
  goto underflow;
1556
0
      }
1557
0
      t = stack[sp];
1558
0
      stack[sp] = (t >= 0) ? floor(t) : ceil(t);
1559
0
      break;
1560
0
    case psOpXor:
1561
0
      if (sp + 1 >= psStackSize) {
1562
0
  goto underflow;
1563
0
      }
1564
0
      stack[sp + 1] = (int)stack[sp + 1] ^ (int)stack[sp];
1565
0
      ++sp;
1566
0
      break;
1567
45.7k
    case psOpPush:
1568
45.7k
      if (sp < 1) {
1569
0
  goto overflow;
1570
0
      }
1571
45.7k
      stack[--sp] = c->val.d;
1572
45.7k
      break;
1573
0
    case psOpJ:
1574
0
      ip = c->val.i;
1575
0
      break;
1576
420
    case psOpJz:
1577
420
      if (sp >= psStackSize) {
1578
0
  goto underflow;
1579
0
      }
1580
420
      k = (int)stack[sp++];
1581
420
      if (k == 0) {
1582
222
  ip = c->val.i;
1583
222
      }
1584
420
      break;
1585
106k
    }
1586
106k
  }
1587
18.4k
  return sp;
1588
1589
87
 underflow:
1590
87
  error(errSyntaxError, -1, "Stack underflow in PostScript function");
1591
87
  return sp;
1592
0
 overflow:
1593
0
  error(errSyntaxError, -1, "Stack overflow in PostScript function");
1594
0
  return sp;
1595
0
 invalidArg:
1596
0
  error(errSyntaxError, -1, "Invalid arg in PostScript function");
1597
0
  return sp;
1598
18.5k
}