Coverage Report

Created: 2026-07-04 07:11

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