Coverage Report

Created: 2026-06-10 06:37

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