Coverage Report

Created: 2026-07-12 06:50

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.1k
#define recursionLimit 8
29
30
//------------------------------------------------------------------------
31
// Function
32
//------------------------------------------------------------------------
33
34
11.4k
Function::Function() {
35
11.4k
}
36
37
11.3k
Function::~Function() {
38
11.3k
}
39
40
Function *Function::parse(Object *funcObj, int expectedInputs,
41
10.1k
        int expectedOutputs, int recursion) {
42
10.1k
  Function *func;
43
10.1k
  Dict *dict;
44
10.1k
  int funcType;
45
10.1k
  Object obj1;
46
47
10.1k
  if (recursion > recursionLimit) {
48
13
    error(errSyntaxError, -1, "Loop detected in function objects");
49
13
    return NULL;
50
13
  }
51
52
10.1k
  if (funcObj->isStream()) {
53
2.06k
    dict = funcObj->streamGetDict();
54
8.04k
  } else if (funcObj->isDict()) {
55
7.00k
    dict = funcObj->getDict();
56
7.00k
  } 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
1.03k
  } else {
63
1.03k
    error(errSyntaxError, -1, "Expected function dictionary or stream");
64
1.03k
    return NULL;
65
1.03k
  }
66
67
9.07k
  if (!dict->lookup("FunctionType", &obj1)->isInt()) {
68
496
    error(errSyntaxError, -1, "Function type is missing or wrong type");
69
496
    obj1.free();
70
496
    return NULL;
71
496
  }
72
8.58k
  funcType = obj1.getInt();
73
8.58k
  obj1.free();
74
75
8.58k
  if (funcType == 0) {
76
879
    func = new SampledFunction(funcObj, dict);
77
7.70k
  } else if (funcType == 2) {
78
5.19k
    func = new ExponentialFunction(funcObj, dict);
79
5.19k
  } else if (funcType == 3) {
80
950
    func = new StitchingFunction(funcObj, dict, expectedInputs,
81
950
         expectedOutputs, recursion);
82
1.55k
  } else if (funcType == 4) {
83
1.50k
    func = new PostScriptFunction(funcObj, dict);
84
1.50k
  } else {
85
45
    error(errSyntaxError, -1, "Unimplemented function type ({0:d})", funcType);
86
45
    return NULL;
87
45
  }
88
8.53k
  if (!func->isOk()) {
89
3.42k
    delete func;
90
3.42k
    return NULL;
91
3.42k
  }
92
93
5.11k
  if (func->getInputSize() != expectedInputs ||
94
5.00k
      (expectedOutputs >= 0 && func->getOutputSize() != expectedOutputs)) {
95
194
    error(errSyntaxError, -1,
96
194
    "Incorrect number of function inputs or outputs");
97
194
    delete func;
98
194
    return NULL;
99
194
  }
100
101
4.91k
  return func;
102
5.11k
}
103
104
8.53k
GBool Function::init(Dict *dict) {
105
8.53k
  Object obj1, obj2;
106
8.53k
  int i;
107
108
  //----- Domain
109
8.53k
  if (!dict->lookup("Domain", &obj1)->isArray()) {
110
123
    error(errSyntaxError, -1, "Function is missing domain");
111
123
    goto err2;
112
123
  }
113
8.41k
  m = obj1.arrayGetLength() / 2;
114
8.41k
  if (m > funcMaxInputs) {
115
16
    error(errSyntaxError, -1,
116
16
    "Functions with more than {0:d} inputs are unsupported",
117
16
    funcMaxInputs);
118
16
    goto err2;
119
16
  }
120
16.6k
  for (i = 0; i < m; ++i) {
121
8.53k
    obj1.arrayGet(2*i, &obj2);
122
8.53k
    if (!obj2.isNum()) {
123
79
      error(errSyntaxError, -1, "Illegal value in function domain array");
124
79
      goto err1;
125
79
    }
126
8.45k
    domain[i][0] = obj2.getNum();
127
8.45k
    obj2.free();
128
8.45k
    obj1.arrayGet(2*i+1, &obj2);
129
8.45k
    if (!obj2.isNum()) {
130
232
      error(errSyntaxError, -1, "Illegal value in function domain array");
131
232
      goto err1;
132
232
    }
133
8.22k
    domain[i][1] = obj2.getNum();
134
8.22k
    obj2.free();
135
8.22k
  }
136
8.08k
  obj1.free();
137
138
  //----- Range
139
8.08k
  hasRange = gFalse;
140
8.08k
  n = 0;
141
8.08k
  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
53
      error(errSyntaxError, -1,
146
53
      "Functions with more than {0:d} outputs are unsupported",
147
53
      funcMaxOutputs);
148
53
      goto err2;
149
53
    }
150
9.17k
    for (i = 0; i < n; ++i) {
151
6.43k
      obj1.arrayGet(2*i, &obj2);
152
6.43k
      if (!obj2.isNum()) {
153
80
  error(errSyntaxError, -1, "Illegal value in function range array");
154
80
  goto err1;
155
80
      }
156
6.35k
      range[i][0] = obj2.getNum();
157
6.35k
      obj2.free();
158
6.35k
      obj1.arrayGet(2*i+1, &obj2);
159
6.35k
      if (!obj2.isNum()) {
160
216
  error(errSyntaxError, -1, "Illegal value in function range array");
161
216
  goto err1;
162
216
      }
163
6.13k
      range[i][1] = obj2.getNum();
164
6.13k
      obj2.free();
165
6.13k
    }
166
3.04k
  }
167
7.73k
  obj1.free();
168
169
7.73k
  return gTrue;
170
171
607
 err1:
172
607
  obj2.free();
173
799
 err2:
174
799
  obj1.free();
175
799
  return gFalse;
176
607
}
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
879
SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
210
879
  Stream *str;
211
879
  int sampleBits;
212
879
  double sampleMul;
213
879
  Object obj1, obj2;
214
879
  Guint buf, bitMask;
215
879
  int bits;
216
879
  Guint s;
217
879
  double in[funcMaxInputs];
218
879
  int i, j, t, bit, idx;
219
220
879
  idxOffset = NULL;
221
879
  samples = NULL;
222
879
  sBuf = NULL;
223
879
  ok = gFalse;
224
225
  //----- initialize the generic stuff
226
879
  if (!init(dict)) {
227
36
    goto err1;
228
36
  }
229
843
  if (!hasRange) {
230
90
    error(errSyntaxError, -1, "Type 0 function is missing range");
231
90
    goto err1;
232
90
  }
233
753
  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
753
  sBuf = (double *)gmallocn(1 << m, sizeof(double));
242
243
  //----- get the stream
244
753
  if (!funcObj->isStream()) {
245
19
    error(errSyntaxError, -1, "Type 0 function isn't a stream");
246
19
    goto err1;
247
19
  }
248
734
  str = funcObj->getStream();
249
250
  //----- Size
251
734
  if (!dict->lookup("Size", &obj1)->isArray() ||
252
710
      obj1.arrayGetLength() != m) {
253
46
    error(errSyntaxError, -1, "Function has missing or invalid size array");
254
46
    goto err2;
255
46
  }
256
1.40k
  for (i = 0; i < m; ++i) {
257
735
    obj1.arrayGet(i, &obj2);
258
735
    if (!obj2.isInt()) {
259
16
      error(errSyntaxError, -1, "Illegal value in function size array");
260
16
      goto err3;
261
16
    }
262
719
    sampleSize[i] = obj2.getInt();
263
719
    if (sampleSize[i] <= 0) {
264
7
      error(errSyntaxError, -1, "Illegal non-positive value in function size array");
265
7
      goto err3;
266
7
    }
267
712
    obj2.free();
268
712
  }
269
665
  obj1.free();
270
665
  idxOffset = (int *)gmallocn(1 << m, sizeof(int));
271
2.14k
  for (i = 0; i < (1<<m); ++i) {
272
1.48k
    idx = 0;
273
1.90k
    for (j = m - 1, t = i; j >= 1; --j, t <<= 1) {
274
420
      if (sampleSize[j] == 1) {
275
64
  bit = 0;
276
356
      } else {
277
356
  bit = (t >> (m - 1)) & 1;
278
356
      }
279
420
      idx = (idx + bit) * sampleSize[j-1];
280
420
    }
281
1.48k
    if (sampleSize[0] == 1) {
282
14
      bit = 0;
283
1.46k
    } else {
284
1.46k
      bit = (t >> (m - 1)) & 1;
285
1.46k
    }
286
1.48k
    idxOffset[i] = (idx + bit) * n;
287
1.48k
  }
288
289
  //----- BitsPerSample
290
665
  if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
291
13
    error(errSyntaxError, -1, "Function has missing or invalid BitsPerSample");
292
13
    goto err2;
293
13
  }
294
652
  sampleBits = obj1.getInt();
295
652
  sampleMul = 1.0 / (pow(2.0, (double)sampleBits) - 1);
296
652
  obj1.free();
297
298
  //----- Encode
299
652
  if (dict->lookup("Encode", &obj1)->isArray() &&
300
541
      obj1.arrayGetLength() == 2*m) {
301
1.00k
    for (i = 0; i < m; ++i) {
302
508
      obj1.arrayGet(2*i, &obj2);
303
508
      if (!obj2.isNum()) {
304
5
  error(errSyntaxError, -1, "Illegal value in function encode array");
305
5
  goto err3;
306
5
      }
307
503
      encode[i][0] = obj2.getNum();
308
503
      obj2.free();
309
503
      obj1.arrayGet(2*i+1, &obj2);
310
503
      if (!obj2.isNum()) {
311
3
  error(errSyntaxError, -1, "Illegal value in function encode array");
312
3
  goto err3;
313
3
      }
314
500
      encode[i][1] = obj2.getNum();
315
500
      obj2.free();
316
500
    }
317
508
  } else {
318
322
    for (i = 0; i < m; ++i) {
319
178
      encode[i][0] = 0;
320
178
      encode[i][1] = sampleSize[i] - 1;
321
178
    }
322
144
  }
323
644
  obj1.free();
324
1.32k
  for (i = 0; i < m; ++i) {
325
678
    inputMul[i] = (encode[i][1] - encode[i][0]) /
326
678
                  (domain[i][1] - domain[i][0]);
327
678
  }
328
329
  //----- Decode
330
644
  if (dict->lookup("Decode", &obj1)->isArray() &&
331
525
      obj1.arrayGetLength() == 2*n) {
332
1.87k
    for (i = 0; i < n; ++i) {
333
1.41k
      obj1.arrayGet(2*i, &obj2);
334
1.41k
      if (!obj2.isNum()) {
335
12
  error(errSyntaxError, -1, "Illegal value in function decode array");
336
12
  goto err3;
337
12
      }
338
1.40k
      decode[i][0] = obj2.getNum();
339
1.40k
      obj2.free();
340
1.40k
      obj1.arrayGet(2*i+1, &obj2);
341
1.40k
      if (!obj2.isNum()) {
342
7
  error(errSyntaxError, -1, "Illegal value in function decode array");
343
7
  goto err3;
344
7
      }
345
1.39k
      decode[i][1] = obj2.getNum();
346
1.39k
      obj2.free();
347
1.39k
    }
348
476
  } else {
349
413
    for (i = 0; i < n; ++i) {
350
245
      decode[i][0] = range[i][0];
351
245
      decode[i][1] = range[i][1];
352
245
    }
353
168
  }
354
625
  obj1.free();
355
356
  //----- samples
357
625
  nSamples = n;
358
1.27k
  for (i = 0; i < m; ++i) {
359
656
    if (nSamples > INT_MAX / sampleSize[i]) {
360
3
      error(errSyntaxError, -1, "Integer overflow in sampled function setup");
361
3
      goto err1;
362
3
    }
363
653
    nSamples *= sampleSize[i];
364
653
  }
365
622
  samples = (double *)gmallocn(nSamples, sizeof(double));
366
622
  buf = 0;
367
622
  bits = 0;
368
622
  bitMask = (sampleBits < 32) ? ((1 << sampleBits) - 1) : 0xffffffffU;
369
622
  str->reset();
370
703k
  for (i = 0; i < nSamples; ++i) {
371
703k
    if (sampleBits == 8) {
372
674k
      s = str->getChar();
373
674k
    } else if (sampleBits == 16) {
374
0
      s = str->getChar();
375
0
      s = (s << 8) + str->getChar();
376
29.0k
    } 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
29.0k
    } else {
382
250k
      while (bits < sampleBits) {
383
221k
  buf = (buf << 8) | (str->getChar() & 0xff);
384
221k
  bits += 8;
385
221k
      }
386
29.0k
      s = (buf >> (bits - sampleBits)) & bitMask;
387
29.0k
      bits -= sampleBits;
388
29.0k
    }
389
703k
    samples[i] = (double)s * sampleMul;
390
703k
  }
391
622
  str->close();
392
393
  // set up the cache
394
1.27k
  for (i = 0; i < m; ++i) {
395
649
    in[i] = domain[i][0];
396
649
    cacheIn[i] = in[i] - 1;
397
649
  }
398
622
  transform(in, cacheOut);
399
400
622
  ok = gTrue;
401
622
  return;
402
403
50
 err3:
404
50
  obj2.free();
405
109
 err2:
406
109
  obj1.free();
407
257
 err1:
408
257
  return;
409
109
}
410
411
1.17k
SampledFunction::~SampledFunction() {
412
1.17k
  if (idxOffset) {
413
960
    gfree(idxOffset);
414
960
  }
415
1.17k
  if (samples) {
416
895
    gfree(samples);
417
895
  }
418
1.17k
  if (sBuf) {
419
1.04k
    gfree(sBuf);
420
1.04k
  }
421
1.17k
}
422
423
319
SampledFunction::SampledFunction(SampledFunction *func) {
424
319
  memcpy((void *)this, (void *)func, sizeof(SampledFunction));
425
319
  idxOffset = (int *)gmallocn(1 << m, sizeof(int));
426
319
  memcpy(idxOffset, func->idxOffset, (1 << m) * (int)sizeof(int));
427
319
  samples = (double *)gmallocn(nSamples, sizeof(double));
428
319
  memcpy(samples, func->samples, nSamples * sizeof(double));
429
319
  sBuf = (double *)gmallocn(1 << m, sizeof(double));
430
319
}
431
432
18.1k
void SampledFunction::transform(double *in, double *out) {
433
18.1k
  double x;
434
18.1k
  int e[funcMaxInputs];
435
18.1k
  double efrac0[funcMaxInputs];
436
18.1k
  double efrac1[funcMaxInputs];
437
18.1k
  int i, j, k, idx0, t;
438
439
  // check the cache
440
18.5k
  for (i = 0; i < m; ++i) {
441
18.1k
    if (in[i] != cacheIn[i]) {
442
17.8k
      break;
443
17.8k
    }
444
18.1k
  }
445
18.1k
  if (i == m) {
446
1.24k
    for (i = 0; i < n; ++i) {
447
910
      out[i] = cacheOut[i];
448
910
    }
449
336
    return;
450
336
  }
451
452
  // map input values into sample array
453
35.7k
  for (i = 0; i < m; ++i) {
454
17.9k
    x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0];
455
17.9k
    if (x < 0 || x != x) {  // x!=x is a more portable version of isnan(x)
456
20
      x = 0;
457
17.9k
    } else if (x > sampleSize[i] - 1) {
458
1.02k
      x = sampleSize[i] - 1;
459
1.02k
    }
460
17.9k
    e[i] = (int)x;
461
17.9k
    if (e[i] == sampleSize[i] - 1 && sampleSize[i] > 1) {
462
      // this happens if in[i] = domain[i][1]
463
1.56k
      e[i] = sampleSize[i] - 2;
464
1.56k
    }
465
17.9k
    efrac1[i] = x - e[i];
466
17.9k
    efrac0[i] = 1 - efrac1[i];
467
17.9k
  }
468
469
  // compute index for the first sample to be used
470
17.8k
  idx0 = 0;
471
17.9k
  for (k = m - 1; k >= 1; --k) {
472
106
    idx0 = (idx0 + e[k]) * sampleSize[k-1];
473
106
  }
474
17.8k
  idx0 = (idx0 + e[0]) * n;
475
476
  // for each output, do m-linear interpolation
477
50.7k
  for (i = 0; i < n; ++i) {
478
479
    // pull 2^m values out of the sample array
480
99.5k
    for (j = 0; j < (1<<m); ++j) {
481
66.6k
      sBuf[j] = samples[idx0 + idxOffset[j] + i];
482
66.6k
    }
483
484
    // do m sets of interpolations
485
66.0k
    for (j = 0, t = (1<<m); j < m; ++j, t >>= 1) {
486
67.0k
      for (k = 0; k < t; k += 2) {
487
33.8k
  sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k+1];
488
33.8k
      }
489
33.1k
    }
490
491
    // map output value to range
492
32.8k
    out[i] = sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
493
32.8k
    if (out[i] < range[i][0]) {
494
950
      out[i] = range[i][0];
495
31.9k
    } else if (out[i] > range[i][1]) {
496
3.04k
      out[i] = range[i][1];
497
3.04k
    }
498
32.8k
  }
499
500
  // save current result in the cache
501
35.7k
  for (i = 0; i < m; ++i) {
502
17.9k
    cacheIn[i] = in[i];
503
17.9k
  }
504
50.7k
  for (i = 0; i < n; ++i) {
505
32.8k
    cacheOut[i] = out[i];
506
32.8k
  }
507
17.8k
}
508
509
//------------------------------------------------------------------------
510
// ExponentialFunction
511
//------------------------------------------------------------------------
512
513
5.19k
ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
514
5.19k
  Object obj1, obj2;
515
5.19k
  int i;
516
517
5.19k
  ok = gFalse;
518
519
  //----- initialize the generic stuff
520
5.19k
  if (!init(dict)) {
521
541
    goto err1;
522
541
  }
523
4.65k
  if (m != 1) {
524
36
    error(errSyntaxError, -1, "Exponential function with more than one input");
525
36
    goto err1;
526
36
  }
527
528
  //----- C0
529
4.62k
  if (dict->lookup("C0", &obj1)->isArray()) {
530
4.29k
    if (hasRange && obj1.arrayGetLength() != n) {
531
233
      error(errSyntaxError, -1, "Function's C0 array is wrong length");
532
233
      goto err2;
533
233
    }
534
4.06k
    n = obj1.arrayGetLength();
535
4.06k
    if (n > funcMaxOutputs) {
536
42
      error(errSyntaxError, -1,
537
42
      "Functions with more than {0:d} outputs are unsupported",
538
42
      funcMaxOutputs);
539
42
      goto err2;
540
42
    }
541
14.8k
    for (i = 0; i < n; ++i) {
542
11.1k
      obj1.arrayGet(i, &obj2);
543
11.1k
      if (!obj2.isNum()) {
544
355
  error(errSyntaxError, -1, "Illegal value in function C0 array");
545
355
  goto err3;
546
355
      }
547
10.8k
      c0[i] = obj2.getNum();
548
10.8k
      obj2.free();
549
10.8k
    }
550
4.02k
  } else {
551
326
    if (hasRange && n != 1) {
552
72
      error(errSyntaxError, -1, "Function's C0 array is wrong length");
553
72
      goto err2;
554
72
    }
555
254
    n = 1;
556
254
    c0[0] = 0;
557
254
  }
558
3.92k
  obj1.free();
559
560
  //----- C1
561
3.92k
  if (dict->lookup("C1", &obj1)->isArray()) {
562
3.49k
    if (obj1.arrayGetLength() != n) {
563
66
      error(errSyntaxError, -1, "Function's C1 array is wrong length");
564
66
      goto err2;
565
66
    }
566
12.9k
    for (i = 0; i < n; ++i) {
567
9.53k
      obj1.arrayGet(i, &obj2);
568
9.53k
      if (!obj2.isNum()) {
569
52
  error(errSyntaxError, -1, "Illegal value in function C1 array");
570
52
  goto err3;
571
52
      }
572
9.48k
      c1[i] = obj2.getNum();
573
9.48k
      obj2.free();
574
9.48k
    }
575
3.42k
  } else {
576
426
    if (n != 1) {
577
189
      error(errSyntaxError, -1, "Function's C1 array is wrong length");
578
189
      goto err2;
579
189
    }
580
237
    c1[0] = 1;
581
237
  }
582
3.61k
  obj1.free();
583
584
  //----- N (exponent)
585
3.61k
  if (!dict->lookup("N", &obj1)->isNum()) {
586
76
    error(errSyntaxError, -1, "Function has missing or invalid N");
587
76
    goto err2;
588
76
  }
589
3.53k
  e = obj1.getNum();
590
3.53k
  obj1.free();
591
592
3.53k
  ok = gTrue;
593
3.53k
  return;
594
595
407
 err3:
596
407
  obj2.free();
597
1.08k
 err2:
598
1.08k
  obj1.free();
599
1.66k
 err1:
600
1.66k
  return;
601
1.08k
}
602
603
ExponentialFunction::~ExponentialFunction() {
604
}
605
606
1.95k
ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
607
1.95k
  memcpy((void *)this, (void *)func, sizeof(ExponentialFunction));
608
1.95k
}
609
610
45.0k
void ExponentialFunction::transform(double *in, double *out) {
611
45.0k
  double x;
612
45.0k
  int i;
613
614
45.0k
  if (in[0] < domain[0][0]) {
615
654
    x = domain[0][0];
616
44.4k
  } else if (in[0] > domain[0][1]) {
617
2.38k
    x = domain[0][1];
618
42.0k
  } else {
619
42.0k
    x = in[0];
620
42.0k
  }
621
178k
  for (i = 0; i < n; ++i) {
622
133k
    out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
623
133k
    if (hasRange) {
624
1.04k
      if (out[i] < range[i][0]) {
625
41
  out[i] = range[i][0];
626
1.00k
      } else if (out[i] > range[i][1]) {
627
51
  out[i] = range[i][1];
628
51
      }
629
1.04k
    }
630
133k
  }
631
45.0k
  return;
632
45.0k
}
633
634
//------------------------------------------------------------------------
635
// StitchingFunction
636
//------------------------------------------------------------------------
637
638
StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict,
639
             int expectedInputs, int expectedOutputs,
640
950
             int recursion) {
641
950
  Object obj1, obj2;
642
950
  int i;
643
644
950
  ok = gFalse;
645
950
  funcs = NULL;
646
950
  bounds = NULL;
647
950
  encode = NULL;
648
950
  scale = NULL;
649
650
  //----- initialize the generic stuff
651
950
  if (!init(dict)) {
652
46
    goto err1;
653
46
  }
654
904
  if (m != 1) {
655
18
    error(errSyntaxError, -1, "Stitching function with more than one input");
656
18
    goto err1;
657
18
  }
658
659
  //----- Functions
660
886
  if (!dict->lookup("Functions", &obj1)->isArray() ||
661
846
      obj1.arrayGetLength() < 1) {
662
80
    error(errSyntaxError, -1,
663
80
    "Missing 'Functions' entry in stitching function");
664
80
    goto err1;
665
80
  }
666
806
  k = obj1.arrayGetLength();
667
806
  funcs = (Function **)gmallocn(k, sizeof(Function *));
668
806
  bounds = (double *)gmallocn(k + 1, sizeof(double));
669
806
  encode = (double *)gmallocn(2 * k, sizeof(double));
670
806
  scale = (double *)gmallocn(k, sizeof(double));
671
2.76k
  for (i = 0; i < k; ++i) {
672
1.95k
    funcs[i] = NULL;
673
1.95k
  }
674
2.04k
  for (i = 0; i < k; ++i) {
675
1.56k
    if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2),
676
1.56k
             expectedInputs, expectedOutputs,
677
1.56k
             recursion + 1))) {
678
320
      goto err2;
679
320
    }
680
1.24k
    if (i == 0) {
681
556
      n = funcs[0]->getOutputSize();
682
556
    }
683
1.24k
    if (funcs[i]->getInputSize() != 1 || funcs[i]->getOutputSize() != n) {
684
9
      error(errSyntaxError, -1,
685
9
      "Incompatible subfunctions in stitching function");
686
9
      goto err2;
687
9
    }
688
1.23k
    obj2.free();
689
1.23k
  }
690
477
  obj1.free();
691
692
  //----- Bounds
693
477
  if (!dict->lookup("Bounds", &obj1)->isArray() ||
694
463
      obj1.arrayGetLength() != k - 1) {
695
28
    error(errSyntaxError, -1,
696
28
    "Missing or invalid 'Bounds' entry in stitching function");
697
28
    goto err1;
698
28
  }
699
449
  bounds[0] = domain[0][0];
700
1.10k
  for (i = 1; i < k; ++i) {
701
662
    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
651
    bounds[i] = obj2.getNum();
707
651
    obj2.free();
708
651
  }
709
438
  bounds[k] = domain[0][1];
710
438
  obj1.free();
711
712
  //----- Encode
713
438
  if (!dict->lookup("Encode", &obj1)->isArray() ||
714
426
      obj1.arrayGetLength() != 2 * k) {
715
18
    error(errSyntaxError, -1,
716
18
    "Missing or invalid 'Encode' entry in stitching function");
717
18
    goto err1;
718
18
  }
719
2.47k
  for (i = 0; i < 2 * k; ++i) {
720
2.08k
    if (!obj1.arrayGet(i, &obj2)->isNum()) {
721
25
      error(errSyntaxError, -1,
722
25
      "Invalid type in 'Encode' array in stitching function");
723
25
      goto err2;
724
25
    }
725
2.05k
    encode[i] = obj2.getNum();
726
2.05k
    obj2.free();
727
2.05k
  }
728
395
  obj1.free();
729
730
  //----- pre-compute the scale factors
731
1.41k
  for (i = 0; i < k; ++i) {
732
1.01k
    if (bounds[i] == bounds[i+1]) {
733
      // avoid a divide-by-zero -- in this situation, function i will
734
      // never be used anyway
735
6
      scale[i] = 0;
736
1.00k
    } else {
737
1.00k
      scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]);
738
1.00k
    }
739
1.01k
  }
740
741
395
  ok = gTrue;
742
395
  return;
743
744
365
 err2:
745
365
  obj2.free();
746
555
 err1:
747
555
  obj1.free();
748
555
}
749
750
185
StitchingFunction::StitchingFunction(StitchingFunction *func) {
751
185
  int i;
752
753
185
  memcpy((void *)this, (void *)func, sizeof(StitchingFunction));
754
185
  funcs = (Function **)gmallocn(k, sizeof(Function *));
755
739
  for (i = 0; i < k; ++i) {
756
554
    funcs[i] = func->funcs[i]->copy();
757
554
  }
758
185
  bounds = (double *)gmallocn(k + 1, sizeof(double));
759
185
  memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
760
185
  encode = (double *)gmallocn(2 * k, sizeof(double));
761
185
  memcpy(encode, func->encode, 2 * k * sizeof(double));
762
185
  scale = (double *)gmallocn(k, sizeof(double));
763
185
  memcpy(scale, func->scale, k * sizeof(double));
764
185
  ok = gTrue;
765
185
}
766
767
1.11k
StitchingFunction::~StitchingFunction() {
768
1.11k
  int i;
769
770
1.11k
  if (funcs) {
771
3.40k
    for (i = 0; i < k; ++i) {
772
2.43k
      if (funcs[i]) {
773
1.72k
  delete funcs[i];
774
1.72k
      }
775
2.43k
    }
776
969
  }
777
1.11k
  gfree(funcs);
778
1.11k
  gfree(bounds);
779
1.11k
  gfree(encode);
780
1.11k
  gfree(scale);
781
1.11k
}
782
783
37.8k
void StitchingFunction::transform(double *in, double *out) {
784
37.8k
  double x;
785
37.8k
  int i;
786
787
37.8k
  if (in[0] < domain[0][0]) {
788
14.7k
    x = domain[0][0];
789
23.0k
  } else if (in[0] > domain[0][1]) {
790
21.2k
    x = domain[0][1];
791
21.2k
  } else {
792
1.74k
    x = in[0];
793
1.74k
  }
794
81.5k
  for (i = 0; i < k - 1; ++i) {
795
59.9k
    if (x < bounds[i+1]) {
796
16.1k
      break;
797
16.1k
    }
798
59.9k
  }
799
37.8k
  x = encode[2*i] + (x - bounds[i]) * scale[i];
800
37.8k
  funcs[i]->transform(&x, out);
801
37.8k
}
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
45
#define psOpAbs       0
812
16
#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
3.53k
#define psOpCvr       9
821
0
#define psOpDiv      10
822
152
#define psOpDup      11
823
0
#define psOpEq       12
824
51.3k
#define psOpExch     13
825
0
#define psOpExp      14
826
0
#define psOpFalse    15
827
0
#define psOpFloor    16
828
82
#define psOpGe       17
829
34
#define psOpGt       18
830
0
#define psOpIdiv     19
831
754
#define psOpIndex    20
832
0
#define psOpLe       21
833
1
#define psOpLn       22
834
0
#define psOpLog      23
835
53
#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
771
#define psOpPop      31
843
8.63k
#define psOpRoll     32
844
0
#define psOpRound    33
845
0
#define psOpSin      34
846
0
#define psOpSqrt     35
847
51.3k
#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
76.4k
#define psOpPush     40
853
53
#define psOpJ        41
854
1.67k
#define psOpJz       42
855
856
3.64k
#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
316k
#define psStackSize 100
914
915
1.50k
PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
916
1.50k
  Stream *str;
917
1.50k
  GList *tokens;
918
1.50k
  GString *tok;
919
1.50k
  double in[funcMaxInputs];
920
1.50k
  int tokPtr, codePtr, i;
921
922
1.50k
  codeString = NULL;
923
1.50k
  code = NULL;
924
1.50k
  codeSize = 0;
925
1.50k
  ok = gFalse;
926
927
  //----- initialize the generic stuff
928
1.50k
  if (!init(dict)) {
929
176
    goto err1;
930
176
  }
931
1.33k
  if (!hasRange) {
932
60
    error(errSyntaxError, -1, "Type 4 function is missing range");
933
60
    goto err1;
934
60
  }
935
936
  //----- get the stream
937
1.27k
  if (!funcObj->isStream()) {
938
97
    error(errSyntaxError, -1, "Type 4 function isn't a stream");
939
97
    goto err1;
940
97
  }
941
1.17k
  str = funcObj->getStream();
942
943
  //----- tokenize the function
944
1.17k
  codeString = new GString();
945
1.17k
  tokens = new GList();
946
1.17k
  str->reset();
947
754k
  while ((tok = getToken(str))) {
948
753k
    tokens->append(tok);
949
753k
  }
950
1.17k
  str->close();
951
952
  //----- parse the function
953
1.17k
  if (tokens->getLength() < 1 ||
954
1.11k
      ((GString *)tokens->get(0))->cmp("{")) {
955
221
    error(errSyntaxError, -1, "Expected '{{' at start of PostScript function");
956
221
    goto err2;
957
221
  }
958
955
  tokPtr = 1;
959
955
  codePtr = 0;
960
955
  if (!parseCode(tokens, &tokPtr, &codePtr)) {
961
396
    goto err2;
962
396
  }
963
559
  codeLen = codePtr;
964
965
  //----- set up the cache
966
1.04k
  for (i = 0; i < m; ++i) {
967
484
    in[i] = domain[i][0];
968
484
    cacheIn[i] = in[i] - 1;
969
484
  }
970
559
  transform(in, cacheOut);
971
972
559
  ok = gTrue;
973
974
1.17k
 err2:
975
1.17k
  deleteGList(tokens, GString);
976
1.50k
 err1:
977
1.50k
  return;
978
1.17k
}
979
980
464
PostScriptFunction::PostScriptFunction(PostScriptFunction *func) {
981
464
  memcpy((void *)this, (void *)func, sizeof(PostScriptFunction));
982
464
  codeString = func->codeString->copy();
983
464
  code = (PSCode *)gmallocn(codeSize, sizeof(PSCode));
984
464
  memcpy(code, func->code, codeSize * sizeof(PSCode));
985
464
}
986
987
1.96k
PostScriptFunction::~PostScriptFunction() {
988
1.96k
  gfree(code);
989
1.96k
  if (codeString) {
990
1.63k
    delete codeString;
991
1.63k
  }
992
1.96k
}
993
994
49.2k
void PostScriptFunction::transform(double *in, double *out) {
995
49.2k
  double stack[psStackSize];
996
49.2k
  double x;
997
49.2k
  int sp, i;
998
999
  // check the cache
1000
49.7k
  for (i = 0; i < m; ++i) {
1001
49.1k
    if (in[i] != cacheIn[i]) {
1002
48.6k
      break;
1003
48.6k
    }
1004
49.1k
  }
1005
49.2k
  if (i == m) {
1006
1.55k
    for (i = 0; i < n; ++i) {
1007
956
      out[i] = cacheOut[i];
1008
956
    }
1009
595
    return;
1010
595
  }
1011
1012
97.2k
  for (i = 0; i < m; ++i) {
1013
48.6k
    stack[psStackSize - 1 - i] = in[i];
1014
48.6k
  }
1015
48.6k
  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
48.6k
  if (sp > psStackSize - n) {
1021
65
    error(errSyntaxError, -1, "Stack underflow in PostScript function");
1022
65
    sp = psStackSize - n;
1023
65
  }
1024
99.5k
  for (i = 0; i < n; ++i) {
1025
50.9k
    x = stack[sp + n - 1 - i];
1026
50.9k
    if (x < range[i][0]) {
1027
54
      out[i] = range[i][0];
1028
50.9k
    } else if (x > range[i][1]) {
1029
9.00k
      out[i] = range[i][1];
1030
41.9k
    } else {
1031
41.9k
      out[i] = x;
1032
41.9k
    }
1033
50.9k
  }
1034
1035
  // save current result in the cache
1036
97.2k
  for (i = 0; i < m; ++i) {
1037
48.6k
    cacheIn[i] = in[i];
1038
48.6k
  }
1039
99.5k
  for (i = 0; i < n; ++i) {
1040
50.9k
    cacheOut[i] = out[i];
1041
50.9k
  }
1042
48.6k
}
1043
1044
2.49k
GBool PostScriptFunction::parseCode(GList *tokens, int *tokPtr, int *codePtr) {
1045
2.49k
  GString *tok;
1046
2.49k
  char *p;
1047
2.49k
  int a, b, mid, cmp;
1048
2.49k
  int codePtr0, codePtr1;
1049
1050
10.8k
  while (1) {
1051
10.8k
    if (*tokPtr >= tokens->getLength()) {
1052
265
      error(errSyntaxError, -1,
1053
265
      "Unexpected end of PostScript function stream");
1054
265
      return gFalse;
1055
265
    }
1056
10.5k
    tok = (GString *)tokens->get((*tokPtr)++);
1057
10.5k
    p = tok->getCString();
1058
10.5k
    if (isdigit(*p) || *p == '.' || *p == '-') {
1059
4.39k
      addCodeD(codePtr, psOpPush, atof(tok->getCString()));
1060
6.17k
    } else if (!tok->cmp("{")) {
1061
1.48k
      codePtr0 = *codePtr;
1062
1.48k
      addCodeI(codePtr, psOpJz, 0);
1063
1.48k
      if (!parseCode(tokens, tokPtr, codePtr)) {
1064
1.00k
  return gFalse;
1065
1.00k
      }
1066
474
      if (*tokPtr >= tokens->getLength()) {
1067
1
  error(errSyntaxError, -1,
1068
1
        "Unexpected end of PostScript function stream");
1069
1
  return gFalse;
1070
1
      }
1071
473
      tok = (GString *)tokens->get((*tokPtr)++);
1072
473
      if (!tok->cmp("if")) {
1073
409
  code[codePtr0].val.i = *codePtr;
1074
409
      } else if (!tok->cmp("{")) {
1075
53
  codePtr1 = *codePtr;
1076
53
  addCodeI(codePtr, psOpJ, 0);
1077
53
  code[codePtr0].val.i = *codePtr;
1078
53
  if (!parseCode(tokens, tokPtr, codePtr)) {
1079
43
    return gFalse;
1080
43
  }
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
11
      } else {
1095
11
  error(errSyntaxError, -1,
1096
11
        "Expected 'if' in PostScript function stream");
1097
11
  return gFalse;
1098
11
      }
1099
4.69k
    } else if (!tok->cmp("}")) {
1100
1.04k
      break;
1101
3.65k
    } else if (!tok->cmp("if")) {
1102
10
      error(errSyntaxError, -1,
1103
10
      "Unexpected 'if' in PostScript function stream");
1104
10
      return gFalse;
1105
3.64k
    } else if (!tok->cmp("ifelse")) {
1106
0
      error(errSyntaxError, -1,
1107
0
      "Unexpected 'ifelse' in PostScript function stream");
1108
0
      return gFalse;
1109
3.64k
    } else {
1110
3.64k
      a = -1;
1111
3.64k
      b = nPSOps;
1112
3.64k
      cmp = 0; // make gcc happy
1113
      // invariant: psOpNames[a] < tok < psOpNames[b]
1114
21.8k
      while (b - a > 1) {
1115
18.2k
  mid = (a + b) / 2;
1116
18.2k
  cmp = tok->cmp(psOpNames[mid]);
1117
18.2k
  if (cmp > 0) {
1118
9.40k
    a = mid;
1119
9.40k
  } else if (cmp < 0) {
1120
5.30k
    b = mid;
1121
5.30k
  } else {
1122
3.54k
    a = b = mid;
1123
3.54k
  }
1124
18.2k
      }
1125
3.64k
      if (cmp != 0) {
1126
99
  error(errSyntaxError, -1,
1127
99
        "Unknown operator '{0:t}' in PostScript function",
1128
99
        tok);
1129
99
  return gFalse;
1130
99
      }
1131
3.54k
      addCode(codePtr, a);
1132
3.54k
    }
1133
10.5k
  }
1134
1.04k
  return gTrue;
1135
2.49k
}
1136
1137
3.54k
void PostScriptFunction::addCode(int *codePtr, int op) {
1138
3.54k
  if (*codePtr >= codeSize) {
1139
185
    if (codeSize) {
1140
83
      codeSize *= 2;
1141
102
    } else {
1142
102
      codeSize = 16;
1143
102
    }
1144
185
    code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode));
1145
185
  }
1146
3.54k
  code[*codePtr].op = op;
1147
3.54k
  ++(*codePtr);
1148
3.54k
}
1149
1150
1.53k
void PostScriptFunction::addCodeI(int *codePtr, int op, int x) {
1151
1.53k
  if (*codePtr >= codeSize) {
1152
136
    if (codeSize) {
1153
85
      codeSize *= 2;
1154
85
    } else {
1155
51
      codeSize = 16;
1156
51
    }
1157
136
    code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode));
1158
136
  }
1159
1.53k
  code[*codePtr].op = op;
1160
1.53k
  code[*codePtr].val.i = x;
1161
1.53k
  ++(*codePtr);
1162
1.53k
}
1163
1164
4.39k
void PostScriptFunction::addCodeD(int *codePtr, int op, double x) {
1165
4.39k
  if (*codePtr >= codeSize) {
1166
877
    if (codeSize) {
1167
113
      codeSize *= 2;
1168
764
    } else {
1169
764
      codeSize = 16;
1170
764
    }
1171
877
    code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode));
1172
877
  }
1173
4.39k
  code[*codePtr].op = op;
1174
4.39k
  code[*codePtr].val.d = x;
1175
4.39k
  ++(*codePtr);
1176
4.39k
}
1177
1178
754k
GString *PostScriptFunction::getToken(Stream *str) {
1179
754k
  GString *s;
1180
754k
  int c;
1181
754k
  GBool comment;
1182
1183
754k
  s = new GString();
1184
754k
  comment = gFalse;
1185
782k
  while (1) {
1186
782k
    if ((c = str->getChar()) == EOF) {
1187
1.17k
      delete s;
1188
1.17k
      return NULL;
1189
1.17k
    }
1190
780k
    codeString->append((char)c);
1191
780k
    if (comment) {
1192
4.29k
      if (c == '\x0a' || c == '\x0d') {
1193
155
  comment = gFalse;
1194
155
      }
1195
776k
    } else if (c == '%') {
1196
159
      comment = gTrue;
1197
776k
    } else if (!isspace(c)) {
1198
753k
      break;
1199
753k
    }
1200
780k
  }
1201
753k
  if (c == '{' || c == '}') {
1202
4.77k
    s->append((char)c);
1203
748k
  } else if (isdigit(c) || c == '.' || c == '-') {
1204
22.0k
    while (1) {
1205
22.0k
      s->append((char)c);
1206
22.0k
      c = str->lookChar();
1207
22.0k
      if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
1208
9.60k
  break;
1209
9.60k
      }
1210
12.4k
      str->getChar();
1211
12.4k
      codeString->append((char)c);
1212
12.4k
    }
1213
738k
  } else {
1214
885k
    while (1) {
1215
885k
      s->append((char)c);
1216
885k
      c = str->lookChar();
1217
885k
      if (c == EOF || !isalnum(c)) {
1218
738k
  break;
1219
738k
      }
1220
146k
      str->getChar();
1221
146k
      codeString->append((char)c);
1222
146k
    }
1223
738k
  }
1224
753k
  return s;
1225
754k
}
1226
1227
48.6k
int PostScriptFunction::exec(double *stack, int sp0) {
1228
48.6k
  PSCode *c;
1229
48.6k
  double tmp[psStackSize];
1230
48.6k
  double t;
1231
48.6k
  int sp, ip, nn, k, i;
1232
1233
48.6k
  sp = sp0;
1234
48.6k
  ip = 0;
1235
237k
  while (ip < codeLen) {
1236
189k
    c = &code[ip++];
1237
189k
    switch(c->op) {
1238
45
    case psOpAbs:
1239
45
      if (sp >= psStackSize) {
1240
0
  goto underflow;
1241
0
      }
1242
45
      stack[sp] = fabs(stack[sp]);
1243
45
      break;
1244
16
    case psOpAdd:
1245
16
      if (sp + 1 >= psStackSize) {
1246
0
  goto underflow;
1247
0
      }
1248
16
      stack[sp + 1] = stack[sp + 1] + stack[sp];
1249
16
      ++sp;
1250
16
      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
3.53k
    case psOpCvr:
1318
3.53k
      if (sp >= psStackSize) {
1319
0
  goto underflow;
1320
0
      }
1321
3.53k
      break;
1322
3.53k
    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
152
    case psOpDup:
1333
152
      if (sp >= psStackSize) {
1334
16
  goto underflow;
1335
16
      }
1336
136
      if (sp < 1) {
1337
0
  goto overflow;
1338
0
      }
1339
136
      stack[sp - 1] = stack[sp];
1340
136
      --sp;
1341
136
      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
51.3k
    case psOpExch:
1350
51.3k
      if (sp + 1 >= psStackSize) {
1351
0
  goto underflow;
1352
0
      }
1353
51.3k
      t = stack[sp];
1354
51.3k
      stack[sp] = stack[sp + 1];
1355
51.3k
      stack[sp + 1] = t;
1356
51.3k
      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
82
    case psOpGe:
1378
82
      if (sp + 1 >= psStackSize) {
1379
4
  goto underflow;
1380
4
      }
1381
78
      stack[sp + 1] = stack[sp + 1] >= stack[sp] ? 1 : 0;
1382
78
      ++sp;
1383
78
      break;
1384
34
    case psOpGt:
1385
34
      if (sp + 1 >= psStackSize) {
1386
0
  goto underflow;
1387
0
      }
1388
34
      stack[sp + 1] = stack[sp + 1] > stack[sp] ? 1 : 0;
1389
34
      ++sp;
1390
34
      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
754
    case psOpIndex:
1403
754
      if (sp >= psStackSize) {
1404
0
  goto underflow;
1405
0
      }
1406
754
      k = (int)stack[sp];
1407
754
      if (k < 0 || k > psStackSize) {
1408
1
        goto invalidArg;
1409
1
      }
1410
753
      if (sp + 1 + k >= psStackSize) {
1411
12
  goto underflow;
1412
12
      }
1413
741
      stack[sp] = stack[sp + 1 + k];
1414
741
      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
1
    case psOpLn:
1423
1
      if (sp >= psStackSize) {
1424
0
  goto underflow;
1425
0
      }
1426
1
      stack[sp] = log(stack[sp]);
1427
1
      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
53
    case psOpLt:
1435
53
      if (sp + 1 >= psStackSize) {
1436
0
  goto underflow;
1437
0
      }
1438
53
      stack[sp + 1] = stack[sp + 1] < stack[sp] ? 1 : 0;
1439
53
      ++sp;
1440
53
      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
771
    case psOpPop:
1486
771
      if (sp >= psStackSize) {
1487
4
  goto underflow;
1488
4
      }
1489
767
      ++sp;
1490
767
      break;
1491
8.63k
    case psOpRoll:
1492
8.63k
      if (sp + 1 >= psStackSize) {
1493
6
  goto underflow;
1494
6
      }
1495
8.63k
      k = (int)stack[sp++];
1496
8.63k
      nn = (int)stack[sp++];
1497
8.63k
      if (k < -psStackSize || k > psStackSize || nn < 0 || nn > psStackSize) {
1498
0
        goto invalidArg;
1499
0
      }
1500
8.63k
      if (nn > 0) {
1501
8.61k
  if (sp + nn > psStackSize) {
1502
13
    goto underflow;
1503
13
  }
1504
8.60k
  if (k >= 0) {
1505
5.73k
    k %= nn;
1506
5.73k
  } else {
1507
2.86k
    k = -k % nn;
1508
2.86k
    if (k) {
1509
2.85k
      k = nn - k;
1510
2.85k
    }
1511
2.86k
  }
1512
34.5k
  for (i = 0; i < nn; ++i) {
1513
25.9k
    tmp[i] = stack[sp + i];
1514
25.9k
  }
1515
34.5k
  for (i = 0; i < nn; ++i) {
1516
25.9k
    stack[sp + i] = tmp[(i + k) % nn];
1517
25.9k
  }
1518
8.60k
      }
1519
8.61k
      break;
1520
8.61k
    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
51.3k
    case psOpSub:
1540
51.3k
      if (sp + 1 >= psStackSize) {
1541
6
  goto underflow;
1542
6
      }
1543
51.3k
      stack[sp + 1] = stack[sp + 1] - stack[sp];
1544
51.3k
      ++sp;
1545
51.3k
      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
72.0k
    case psOpPush:
1568
72.0k
      if (sp < 1) {
1569
1
  goto overflow;
1570
1
      }
1571
72.0k
      stack[--sp] = c->val.d;
1572
72.0k
      break;
1573
0
    case psOpJ:
1574
0
      ip = c->val.i;
1575
0
      break;
1576
190
    case psOpJz:
1577
190
      if (sp >= psStackSize) {
1578
5
  goto underflow;
1579
5
      }
1580
185
      k = (int)stack[sp++];
1581
185
      if (k == 0) {
1582
77
  ip = c->val.i;
1583
77
      }
1584
185
      break;
1585
189k
    }
1586
189k
  }
1587
48.5k
  return sp;
1588
1589
66
 underflow:
1590
66
  error(errSyntaxError, -1, "Stack underflow in PostScript function");
1591
66
  return sp;
1592
1
 overflow:
1593
1
  error(errSyntaxError, -1, "Stack overflow in PostScript function");
1594
1
  return sp;
1595
1
 invalidArg:
1596
1
  error(errSyntaxError, -1, "Invalid arg in PostScript function");
1597
1
  return sp;
1598
48.6k
}