~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/poppler/poppler/Function.cc

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//========================================================================
 
2
//
 
3
// Function.cc
 
4
//
 
5
// Copyright 2001-2003 Glyph & Cog, LLC
 
6
//
 
7
//========================================================================
 
8
 
 
9
//========================================================================
 
10
//
 
11
// Modified under the Poppler project - http://poppler.freedesktop.org
 
12
//
 
13
// All changes made under the Poppler project to this file are licensed
 
14
// under GPL version 2 or later
 
15
//
 
16
// Copyright (C) 2006, 2008-2010 Albert Astals Cid <aacid@kde.org>
 
17
// Copyright (C) 2006 Jeff Muizelaar <jeff@infidigm.net>
 
18
// Copyright (C) 2010 Christian Feuersļæ½nger <cfeuersaenger@googlemail.com>
 
19
//
 
20
// To see a description of the changes please see the Changelog file that
 
21
// came with your tarball or type make ChangeLog if you are building from git
 
22
//
 
23
//========================================================================
 
24
 
 
25
#include <config.h>
 
26
 
 
27
#ifdef USE_GCC_PRAGMAS
 
28
#pragma implementation
 
29
#endif
 
30
 
 
31
#include <stdlib.h>
 
32
#include <string.h>
 
33
#include <ctype.h>
 
34
#include <math.h>
 
35
#include "goo/gmem.h"
 
36
#include "goo/gstrtod.h"
 
37
#include "Object.h"
 
38
#include "Dict.h"
 
39
#include "Stream.h"
 
40
#include "Error.h"
 
41
#include "Function.h"
 
42
#include "PopplerCache.h"
 
43
 
 
44
#ifndef M_PI
 
45
#define M_PI 3.14159265358979323846
 
46
#endif
 
47
 
 
48
//------------------------------------------------------------------------
 
49
// Function
 
50
//------------------------------------------------------------------------
 
51
 
 
52
Function::Function() {
 
53
}
 
54
 
 
55
Function::~Function() {
 
56
}
 
57
 
 
58
Function *Function::parse(Object *funcObj) {
 
59
  std::set<int> usedParents;
 
60
  return parse(funcObj, &usedParents);
 
61
}
 
62
 
 
63
Function *Function::parse(Object *funcObj, std::set<int> *usedParents) {
 
64
  Function *func;
 
65
  Dict *dict;
 
66
  int funcType;
 
67
  Object obj1;
 
68
 
 
69
  if (funcObj->isStream()) {
 
70
    dict = funcObj->streamGetDict();
 
71
  } else if (funcObj->isDict()) {
 
72
    dict = funcObj->getDict();
 
73
  } else if (funcObj->isName("Identity")) {
 
74
    return new IdentityFunction();
 
75
  } else {
 
76
    error(-1, "Expected function dictionary or stream");
 
77
    return NULL;
 
78
  }
 
79
 
 
80
  if (!dict->lookup("FunctionType", &obj1)->isInt()) {
 
81
    error(-1, "Function type is missing or wrong type");
 
82
    obj1.free();
 
83
    return NULL;
 
84
  }
 
85
  funcType = obj1.getInt();
 
86
  obj1.free();
 
87
 
 
88
  if (funcType == 0) {
 
89
    func = new SampledFunction(funcObj, dict);
 
90
  } else if (funcType == 2) {
 
91
    func = new ExponentialFunction(funcObj, dict);
 
92
  } else if (funcType == 3) {
 
93
    func = new StitchingFunction(funcObj, dict, usedParents);
 
94
  } else if (funcType == 4) {
 
95
    func = new PostScriptFunction(funcObj, dict);
 
96
  } else {
 
97
    error(-1, "Unimplemented function type (%d)", funcType);
 
98
    return NULL;
 
99
  }
 
100
  if (!func->isOk()) {
 
101
    delete func;
 
102
    return NULL;
 
103
  }
 
104
 
 
105
  return func;
 
106
}
 
107
 
 
108
GBool Function::init(Dict *dict) {
 
109
  Object obj1, obj2;
 
110
  int i;
 
111
 
 
112
  //----- Domain
 
113
  if (!dict->lookup("Domain", &obj1)->isArray()) {
 
114
    error(-1, "Function is missing domain");
 
115
    goto err2;
 
116
  }
 
117
  m = obj1.arrayGetLength() / 2;
 
118
  if (m > funcMaxInputs) {
 
119
    error(-1, "Functions with more than %d inputs are unsupported",
 
120
          funcMaxInputs);
 
121
    goto err2;
 
122
  }
 
123
  for (i = 0; i < m; ++i) {
 
124
    obj1.arrayGet(2*i, &obj2);
 
125
    if (!obj2.isNum()) {
 
126
      error(-1, "Illegal value in function domain array");
 
127
      goto err1;
 
128
    }
 
129
    domain[i][0] = obj2.getNum();
 
130
    obj2.free();
 
131
    obj1.arrayGet(2*i+1, &obj2);
 
132
    if (!obj2.isNum()) {
 
133
      error(-1, "Illegal value in function domain array");
 
134
      goto err1;
 
135
    }
 
136
    domain[i][1] = obj2.getNum();
 
137
    obj2.free();
 
138
  }
 
139
  obj1.free();
 
140
 
 
141
  //----- Range
 
142
  hasRange = gFalse;
 
143
  n = 0;
 
144
  if (dict->lookup("Range", &obj1)->isArray()) {
 
145
    hasRange = gTrue;
 
146
    n = obj1.arrayGetLength() / 2;
 
147
    if (n > funcMaxOutputs) {
 
148
      error(-1, "Functions with more than %d outputs are unsupported",
 
149
            funcMaxOutputs);
 
150
      goto err2;
 
151
    }
 
152
    for (i = 0; i < n; ++i) {
 
153
      obj1.arrayGet(2*i, &obj2);
 
154
      if (!obj2.isNum()) {
 
155
        error(-1, "Illegal value in function range array");
 
156
        goto err1;
 
157
      }
 
158
      range[i][0] = obj2.getNum();
 
159
      obj2.free();
 
160
      obj1.arrayGet(2*i+1, &obj2);
 
161
      if (!obj2.isNum()) {
 
162
        error(-1, "Illegal value in function range array");
 
163
        goto err1;
 
164
      }
 
165
      range[i][1] = obj2.getNum();
 
166
      obj2.free();
 
167
    }
 
168
  }
 
169
  obj1.free();
 
170
 
 
171
  return gTrue;
 
172
 
 
173
 err1:
 
174
  obj2.free();
 
175
 err2:
 
176
  obj1.free();
 
177
  return gFalse;
 
178
}
 
179
 
 
180
//------------------------------------------------------------------------
 
181
// IdentityFunction
 
182
//------------------------------------------------------------------------
 
183
 
 
184
IdentityFunction::IdentityFunction() {
 
185
  int i;
 
186
 
 
187
  // fill these in with arbitrary values just in case they get used
 
188
  // somewhere
 
189
  m = funcMaxInputs;
 
190
  n = funcMaxOutputs;
 
191
  for (i = 0; i < funcMaxInputs; ++i) {
 
192
    domain[i][0] = 0;
 
193
    domain[i][1] = 1;
 
194
  }
 
195
  hasRange = gFalse;
 
196
}
 
197
 
 
198
IdentityFunction::~IdentityFunction() {
 
199
}
 
200
 
 
201
void IdentityFunction::transform(double *in, double *out) {
 
202
  int i;
 
203
 
 
204
  for (i = 0; i < funcMaxOutputs; ++i) {
 
205
    out[i] = in[i];
 
206
  }
 
207
}
 
208
 
 
209
//------------------------------------------------------------------------
 
210
// SampledFunction
 
211
//------------------------------------------------------------------------
 
212
 
 
213
SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
 
214
  Stream *str;
 
215
  int sampleBits;
 
216
  double sampleMul;
 
217
  Object obj1, obj2;
 
218
  Guint buf, bitMask;
 
219
  int bits;
 
220
  Guint s;
 
221
  int i;
 
222
 
 
223
  samples = NULL;
 
224
  sBuf = NULL;
 
225
  ok = gFalse;
 
226
 
 
227
  //----- initialize the generic stuff
 
228
  if (!init(dict)) {
 
229
    goto err1;
 
230
  }
 
231
  if (!hasRange) {
 
232
    error(-1, "Type 0 function is missing range");
 
233
    goto err1;
 
234
  }
 
235
  if (m > sampledFuncMaxInputs) {
 
236
    error(-1, "Sampled functions with more than %d inputs are unsupported",
 
237
          sampledFuncMaxInputs);
 
238
    goto err1;
 
239
  }
 
240
 
 
241
  //----- buffer
 
242
  sBuf = (double *)gmallocn(1 << m, sizeof(double));
 
243
 
 
244
  //----- get the stream
 
245
  if (!funcObj->isStream()) {
 
246
    error(-1, "Type 0 function isn't a stream");
 
247
    goto err1;
 
248
  }
 
249
  str = funcObj->getStream();
 
250
 
 
251
  //----- Size
 
252
  if (!dict->lookup("Size", &obj1)->isArray() ||
 
253
      obj1.arrayGetLength() != m) {
 
254
    error(-1, "Function has missing or invalid size array");
 
255
    goto err2;
 
256
  }
 
257
  for (i = 0; i < m; ++i) {
 
258
    obj1.arrayGet(i, &obj2);
 
259
    if (!obj2.isInt()) {
 
260
      error(-1, "Illegal value in function size array");
 
261
      goto err3;
 
262
    }
 
263
    sampleSize[i] = obj2.getInt();
 
264
    obj2.free();
 
265
  }
 
266
  obj1.free();
 
267
  idxMul[0] = n;
 
268
  for (i = 1; i < m; ++i) {
 
269
    idxMul[i] = idxMul[i-1] * sampleSize[i-1];
 
270
  }
 
271
 
 
272
  //----- BitsPerSample
 
273
  if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
 
274
    error(-1, "Function has missing or invalid BitsPerSample");
 
275
    goto err2;
 
276
  }
 
277
  sampleBits = obj1.getInt();
 
278
  sampleMul = 1.0 / (pow(2.0, (double)sampleBits) - 1);
 
279
  obj1.free();
 
280
 
 
281
  //----- Encode
 
282
  if (dict->lookup("Encode", &obj1)->isArray() &&
 
283
      obj1.arrayGetLength() == 2*m) {
 
284
    for (i = 0; i < m; ++i) {
 
285
      obj1.arrayGet(2*i, &obj2);
 
286
      if (!obj2.isNum()) {
 
287
        error(-1, "Illegal value in function encode array");
 
288
        goto err3;
 
289
      }
 
290
      encode[i][0] = obj2.getNum();
 
291
      obj2.free();
 
292
      obj1.arrayGet(2*i+1, &obj2);
 
293
      if (!obj2.isNum()) {
 
294
        error(-1, "Illegal value in function encode array");
 
295
        goto err3;
 
296
      }
 
297
      encode[i][1] = obj2.getNum();
 
298
      obj2.free();
 
299
    }
 
300
  } else {
 
301
    for (i = 0; i < m; ++i) {
 
302
      encode[i][0] = 0;
 
303
      encode[i][1] = sampleSize[i] - 1;
 
304
    }
 
305
  }
 
306
  obj1.free();
 
307
  for (i = 0; i < m; ++i) {
 
308
    inputMul[i] = (encode[i][1] - encode[i][0]) /
 
309
                  (domain[i][1] - domain[i][0]);
 
310
  }
 
311
 
 
312
  //----- Decode
 
313
  if (dict->lookup("Decode", &obj1)->isArray() &&
 
314
      obj1.arrayGetLength() == 2*n) {
 
315
    for (i = 0; i < n; ++i) {
 
316
      obj1.arrayGet(2*i, &obj2);
 
317
      if (!obj2.isNum()) {
 
318
        error(-1, "Illegal value in function decode array");
 
319
        goto err3;
 
320
      }
 
321
      decode[i][0] = obj2.getNum();
 
322
      obj2.free();
 
323
      obj1.arrayGet(2*i+1, &obj2);
 
324
      if (!obj2.isNum()) {
 
325
        error(-1, "Illegal value in function decode array");
 
326
        goto err3;
 
327
      }
 
328
      decode[i][1] = obj2.getNum();
 
329
      obj2.free();
 
330
    }
 
331
  } else {
 
332
    for (i = 0; i < n; ++i) {
 
333
      decode[i][0] = range[i][0];
 
334
      decode[i][1] = range[i][1];
 
335
    }
 
336
  }
 
337
  obj1.free();
 
338
 
 
339
  //----- samples
 
340
  nSamples = n;
 
341
  for (i = 0; i < m; ++i)
 
342
    nSamples *= sampleSize[i];
 
343
  samples = (double *)gmallocn(nSamples, sizeof(double));
 
344
  buf = 0;
 
345
  bits = 0;
 
346
  bitMask = (1 << sampleBits) - 1;
 
347
  str->reset();
 
348
  for (i = 0; i < nSamples; ++i) {
 
349
    if (sampleBits == 8) {
 
350
      s = str->getChar();
 
351
    } else if (sampleBits == 16) {
 
352
      s = str->getChar();
 
353
      s = (s << 8) + str->getChar();
 
354
    } else if (sampleBits == 32) {
 
355
      s = str->getChar();
 
356
      s = (s << 8) + str->getChar();
 
357
      s = (s << 8) + str->getChar();
 
358
      s = (s << 8) + str->getChar();
 
359
    } else {
 
360
      while (bits < sampleBits) {
 
361
        buf = (buf << 8) | (str->getChar() & 0xff);
 
362
        bits += 8;
 
363
      }
 
364
      s = (buf >> (bits - sampleBits)) & bitMask;
 
365
      bits -= sampleBits;
 
366
    }
 
367
    samples[i] = (double)s * sampleMul;
 
368
  }
 
369
  str->close();
 
370
 
 
371
  ok = gTrue;
 
372
  return;
 
373
 
 
374
 err3:
 
375
  obj2.free();
 
376
 err2:
 
377
  obj1.free();
 
378
 err1:
 
379
  return;
 
380
}
 
381
 
 
382
SampledFunction::~SampledFunction() {
 
383
  if (samples) {
 
384
    gfree(samples);
 
385
  }
 
386
  if (sBuf) {
 
387
    gfree(sBuf);
 
388
  }
 
389
}
 
390
 
 
391
SampledFunction::SampledFunction(SampledFunction *func) {
 
392
  memcpy(this, func, sizeof(SampledFunction));
 
393
  samples = (double *)gmallocn(nSamples, sizeof(double));
 
394
  memcpy(samples, func->samples, nSamples * sizeof(double));
 
395
  sBuf = (double *)gmallocn(1 << m, sizeof(double));
 
396
}
 
397
 
 
398
void SampledFunction::transform(double *in, double *out) {
 
399
  double x;
 
400
  int e[funcMaxInputs][2];
 
401
  double efrac0[funcMaxInputs];
 
402
  double efrac1[funcMaxInputs];
 
403
  int i, j, k, idx, t;
 
404
 
 
405
  // map input values into sample array
 
406
  for (i = 0; i < m; ++i) {
 
407
    x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0];
 
408
    if (x < 0) {
 
409
      x = 0;
 
410
    } else if (x > sampleSize[i] - 1) {
 
411
      x = sampleSize[i] - 1;
 
412
    }
 
413
    e[i][0] = (int)x;
 
414
    if ((e[i][1] = e[i][0] + 1) >= sampleSize[i]) {
 
415
      // this happens if in[i] = domain[i][1]
 
416
      e[i][1] = e[i][0];
 
417
    }
 
418
    efrac1[i] = x - e[i][0];
 
419
    efrac0[i] = 1 - efrac1[i];
 
420
  }
 
421
 
 
422
  // for each output, do m-linear interpolation
 
423
  for (i = 0; i < n; ++i) {
 
424
 
 
425
    // pull 2^m values out of the sample array
 
426
    for (j = 0; j < (1<<m); ++j) {
 
427
      idx = i;
 
428
      for (k = 0, t = j; k < m; ++k, t >>= 1) {
 
429
        idx += idxMul[k] * (e[k][t & 1]);
 
430
      }
 
431
      if (likely(idx >= 0 && idx < nSamples)) {
 
432
        sBuf[j] = samples[idx];
 
433
      } else {
 
434
        sBuf[j] = 0; // TODO Investigate if this is what Adobe does
 
435
      }
 
436
    }
 
437
 
 
438
    // do m sets of interpolations
 
439
    for (j = 0, t = (1<<m); j < m; ++j, t >>= 1) {
 
440
      for (k = 0; k < t; k += 2) {
 
441
        sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k+1];
 
442
      }
 
443
    }
 
444
 
 
445
    // map output value to range
 
446
    out[i] = sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
 
447
    if (out[i] < range[i][0]) {
 
448
      out[i] = range[i][0];
 
449
    } else if (out[i] > range[i][1]) {
 
450
      out[i] = range[i][1];
 
451
    }
 
452
  }
 
453
}
 
454
 
 
455
//------------------------------------------------------------------------
 
456
// ExponentialFunction
 
457
//------------------------------------------------------------------------
 
458
 
 
459
ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
 
460
  Object obj1, obj2;
 
461
  int i;
 
462
 
 
463
  ok = gFalse;
 
464
 
 
465
  //----- initialize the generic stuff
 
466
  if (!init(dict)) {
 
467
    goto err1;
 
468
  }
 
469
  if (m != 1) {
 
470
    error(-1, "Exponential function with more than one input");
 
471
    goto err1;
 
472
  }
 
473
 
 
474
  //----- C0
 
475
  if (dict->lookup("C0", &obj1)->isArray()) {
 
476
    if (hasRange && obj1.arrayGetLength() != n) {
 
477
      error(-1, "Function's C0 array is wrong length");
 
478
      goto err2;
 
479
    }
 
480
    n = obj1.arrayGetLength();
 
481
    for (i = 0; i < n; ++i) {
 
482
      obj1.arrayGet(i, &obj2);
 
483
      if (!obj2.isNum()) {
 
484
        error(-1, "Illegal value in function C0 array");
 
485
        goto err3;
 
486
      }
 
487
      c0[i] = obj2.getNum();
 
488
      obj2.free();
 
489
    }
 
490
  } else {
 
491
    if (hasRange && n != 1) {
 
492
      error(-1, "Function's C0 array is wrong length");
 
493
      goto err2;
 
494
    }
 
495
    n = 1;
 
496
    c0[0] = 0;
 
497
  }
 
498
  obj1.free();
 
499
 
 
500
  //----- C1
 
501
  if (dict->lookup("C1", &obj1)->isArray()) {
 
502
    if (obj1.arrayGetLength() != n) {
 
503
      error(-1, "Function's C1 array is wrong length");
 
504
      goto err2;
 
505
    }
 
506
    for (i = 0; i < n; ++i) {
 
507
      obj1.arrayGet(i, &obj2);
 
508
      if (!obj2.isNum()) {
 
509
        error(-1, "Illegal value in function C1 array");
 
510
        goto err3;
 
511
      }
 
512
      c1[i] = obj2.getNum();
 
513
      obj2.free();
 
514
    }
 
515
  } else {
 
516
    if (n != 1) {
 
517
      error(-1, "Function's C1 array is wrong length");
 
518
      goto err2;
 
519
    }
 
520
    c1[0] = 1;
 
521
  }
 
522
  obj1.free();
 
523
 
 
524
  //----- N (exponent)
 
525
  if (!dict->lookup("N", &obj1)->isNum()) {
 
526
    error(-1, "Function has missing or invalid N");
 
527
    goto err2;
 
528
  }
 
529
  e = obj1.getNum();
 
530
  obj1.free();
 
531
 
 
532
  isLinear = fabs(e-1.) < 1e-10;
 
533
  ok = gTrue;
 
534
  return;
 
535
 
 
536
 err3:
 
537
  obj2.free();
 
538
 err2:
 
539
  obj1.free();
 
540
 err1:
 
541
  return;
 
542
}
 
543
 
 
544
ExponentialFunction::~ExponentialFunction() {
 
545
}
 
546
 
 
547
ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
 
548
  memcpy(this, func, sizeof(ExponentialFunction));
 
549
}
 
550
 
 
551
void ExponentialFunction::transform(double *in, double *out) {
 
552
  double x;
 
553
  int i;
 
554
 
 
555
  if (in[0] < domain[0][0]) {
 
556
    x = domain[0][0];
 
557
  } else if (in[0] > domain[0][1]) {
 
558
    x = domain[0][1];
 
559
  } else {
 
560
    x = in[0];
 
561
  }
 
562
  for (i = 0; i < n; ++i) {
 
563
    out[i] = c0[i] + (isLinear ? x : pow(x, e)) * (c1[i] - c0[i]);
 
564
    if (hasRange) {
 
565
      if (out[i] < range[i][0]) {
 
566
        out[i] = range[i][0];
 
567
      } else if (out[i] > range[i][1]) {
 
568
        out[i] = range[i][1];
 
569
      }
 
570
    }
 
571
  }
 
572
  return;
 
573
}
 
574
 
 
575
//------------------------------------------------------------------------
 
576
// StitchingFunction
 
577
//------------------------------------------------------------------------
 
578
 
 
579
StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict, std::set<int> *usedParents) {
 
580
  Object obj1, obj2;
 
581
  int i;
 
582
 
 
583
  ok = gFalse;
 
584
  funcs = NULL;
 
585
  bounds = NULL;
 
586
  encode = NULL;
 
587
  scale = NULL;
 
588
 
 
589
  //----- initialize the generic stuff
 
590
  if (!init(dict)) {
 
591
    goto err1;
 
592
  }
 
593
  if (m != 1) {
 
594
    error(-1, "Stitching function with more than one input");
 
595
    goto err1;
 
596
  }
 
597
 
 
598
  //----- Functions
 
599
  if (!dict->lookup("Functions", &obj1)->isArray()) {
 
600
    error(-1, "Missing 'Functions' entry in stitching function");
 
601
    goto err1;
 
602
  }
 
603
  k = obj1.arrayGetLength();
 
604
  funcs = (Function **)gmallocn(k, sizeof(Function *));
 
605
  bounds = (double *)gmallocn(k + 1, sizeof(double));
 
606
  encode = (double *)gmallocn(2 * k, sizeof(double));
 
607
  scale = (double *)gmallocn(k, sizeof(double));
 
608
  for (i = 0; i < k; ++i) {
 
609
    funcs[i] = NULL;
 
610
  }
 
611
  for (i = 0; i < k; ++i) {
 
612
    std::set<int> usedParentsAux = *usedParents;
 
613
    obj1.arrayGetNF(i, &obj2);
 
614
    if (obj2.isRef()) {
 
615
      const Ref ref = obj2.getRef();
 
616
      if (usedParentsAux.find(ref.num) == usedParentsAux.end()) {
 
617
        usedParentsAux.insert(ref.num);
 
618
        obj2.free();
 
619
        obj1.arrayGet(i, &obj2);
 
620
      } else {
 
621
        goto err2;
 
622
      }
 
623
    }
 
624
    if (!(funcs[i] = Function::parse(&obj2, &usedParentsAux))) {
 
625
      goto err2;
 
626
    }
 
627
    if (i > 0 && (funcs[i]->getInputSize() != 1 ||
 
628
                  funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
 
629
      error(-1, "Incompatible subfunctions in stitching function");
 
630
      goto err2;
 
631
    }
 
632
    obj2.free();
 
633
  }
 
634
  obj1.free();
 
635
 
 
636
  //----- Bounds
 
637
  if (!dict->lookup("Bounds", &obj1)->isArray() ||
 
638
      obj1.arrayGetLength() != k - 1) {
 
639
    error(-1, "Missing or invalid 'Bounds' entry in stitching function");
 
640
    goto err1;
 
641
  }
 
642
  bounds[0] = domain[0][0];
 
643
  for (i = 1; i < k; ++i) {
 
644
    if (!obj1.arrayGet(i - 1, &obj2)->isNum()) {
 
645
      error(-1, "Invalid type in 'Bounds' array in stitching function");
 
646
      goto err2;
 
647
    }
 
648
    bounds[i] = obj2.getNum();
 
649
    obj2.free();
 
650
  }
 
651
  bounds[k] = domain[0][1];
 
652
  obj1.free();
 
653
 
 
654
  //----- Encode
 
655
  if (!dict->lookup("Encode", &obj1)->isArray() ||
 
656
      obj1.arrayGetLength() != 2 * k) {
 
657
    error(-1, "Missing or invalid 'Encode' entry in stitching function");
 
658
    goto err1;
 
659
  }
 
660
  for (i = 0; i < 2 * k; ++i) {
 
661
    if (!obj1.arrayGet(i, &obj2)->isNum()) {
 
662
      error(-1, "Invalid type in 'Encode' array in stitching function");
 
663
      goto err2;
 
664
    }
 
665
    encode[i] = obj2.getNum();
 
666
    obj2.free();
 
667
  }
 
668
  obj1.free();
 
669
 
 
670
  //----- pre-compute the scale factors
 
671
  for (i = 0; i < k; ++i) {
 
672
    if (bounds[i] == bounds[i+1]) {
 
673
      // avoid a divide-by-zero -- in this situation, function i will
 
674
      // never be used anyway
 
675
      scale[i] = 0;
 
676
    } else {
 
677
      scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]);
 
678
    }
 
679
  }
 
680
 
 
681
  ok = gTrue;
 
682
  return;
 
683
 
 
684
 err2:
 
685
  obj2.free();
 
686
 err1:
 
687
  obj1.free();
 
688
}
 
689
 
 
690
StitchingFunction::StitchingFunction(StitchingFunction *func) {
 
691
  int i;
 
692
 
 
693
  memcpy(this, func, sizeof(StitchingFunction));
 
694
 
 
695
  k = func->k;
 
696
  funcs = (Function **)gmallocn(k, sizeof(Function *));
 
697
  for (i = 0; i < k; ++i) {
 
698
    funcs[i] = func->funcs[i]->copy();
 
699
  }
 
700
  bounds = (double *)gmallocn(k + 1, sizeof(double));
 
701
  memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
 
702
  encode = (double *)gmallocn(2 * k, sizeof(double));
 
703
  memcpy(encode, func->encode, 2 * k * sizeof(double));
 
704
  scale = (double *)gmallocn(k, sizeof(double));
 
705
  memcpy(scale, func->scale, k * sizeof(double));
 
706
  ok = gTrue;
 
707
}
 
708
 
 
709
StitchingFunction::~StitchingFunction() {
 
710
  int i;
 
711
 
 
712
  if (funcs) {
 
713
    for (i = 0; i < k; ++i) {
 
714
      if (funcs[i]) {
 
715
        delete funcs[i];
 
716
      }
 
717
    }
 
718
  }
 
719
  gfree(funcs);
 
720
  gfree(bounds);
 
721
  gfree(encode);
 
722
  gfree(scale);
 
723
}
 
724
 
 
725
void StitchingFunction::transform(double *in, double *out) {
 
726
  double x;
 
727
  int i;
 
728
 
 
729
  if (in[0] < domain[0][0]) {
 
730
    x = domain[0][0];
 
731
  } else if (in[0] > domain[0][1]) {
 
732
    x = domain[0][1];
 
733
  } else {
 
734
    x = in[0];
 
735
  }
 
736
  for (i = 0; i < k - 1; ++i) {
 
737
    if (x < bounds[i+1]) {
 
738
      break;
 
739
    }
 
740
  }
 
741
  x = encode[2*i] + (x - bounds[i]) * scale[i];
 
742
  funcs[i]->transform(&x, out);
 
743
}
 
744
 
 
745
//------------------------------------------------------------------------
 
746
// PostScriptFunction
 
747
//------------------------------------------------------------------------
 
748
 
 
749
enum PSOp {
 
750
  psOpAbs,
 
751
  psOpAdd,
 
752
  psOpAnd,
 
753
  psOpAtan,
 
754
  psOpBitshift,
 
755
  psOpCeiling,
 
756
  psOpCopy,
 
757
  psOpCos,
 
758
  psOpCvi,
 
759
  psOpCvr,
 
760
  psOpDiv,
 
761
  psOpDup,
 
762
  psOpEq,
 
763
  psOpExch,
 
764
  psOpExp,
 
765
  psOpFalse,
 
766
  psOpFloor,
 
767
  psOpGe,
 
768
  psOpGt,
 
769
  psOpIdiv,
 
770
  psOpIndex,
 
771
  psOpLe,
 
772
  psOpLn,
 
773
  psOpLog,
 
774
  psOpLt,
 
775
  psOpMod,
 
776
  psOpMul,
 
777
  psOpNe,
 
778
  psOpNeg,
 
779
  psOpNot,
 
780
  psOpOr,
 
781
  psOpPop,
 
782
  psOpRoll,
 
783
  psOpRound,
 
784
  psOpSin,
 
785
  psOpSqrt,
 
786
  psOpSub,
 
787
  psOpTrue,
 
788
  psOpTruncate,
 
789
  psOpXor,
 
790
  psOpIf,
 
791
  psOpIfelse,
 
792
  psOpReturn
 
793
};
 
794
 
 
795
// Note: 'if' and 'ifelse' are parsed separately.
 
796
// The rest are listed here in alphabetical order.
 
797
// The index in this table is equivalent to the entry in PSOp.
 
798
static const char *psOpNames[] = {
 
799
  "abs",
 
800
  "add",
 
801
  "and",
 
802
  "atan",
 
803
  "bitshift",
 
804
  "ceiling",
 
805
  "copy",
 
806
  "cos",
 
807
  "cvi",
 
808
  "cvr",
 
809
  "div",
 
810
  "dup",
 
811
  "eq",
 
812
  "exch",
 
813
  "exp",
 
814
  "false",
 
815
  "floor",
 
816
  "ge",
 
817
  "gt",
 
818
  "idiv",
 
819
  "index",
 
820
  "le",
 
821
  "ln",
 
822
  "log",
 
823
  "lt",
 
824
  "mod",
 
825
  "mul",
 
826
  "ne",
 
827
  "neg",
 
828
  "not",
 
829
  "or",
 
830
  "pop",
 
831
  "roll",
 
832
  "round",
 
833
  "sin",
 
834
  "sqrt",
 
835
  "sub",
 
836
  "true",
 
837
  "truncate",
 
838
  "xor"
 
839
};
 
840
 
 
841
#define nPSOps (sizeof(psOpNames) / sizeof(char *))
 
842
 
 
843
enum PSObjectType {
 
844
  psBool,
 
845
  psInt,
 
846
  psReal,
 
847
  psOperator,
 
848
  psBlock
 
849
};
 
850
 
 
851
// In the code array, 'if'/'ifelse' operators take up three slots
 
852
// plus space for the code in the subclause(s).
 
853
//
 
854
//         +---------------------------------+
 
855
//         | psOperator: psOpIf / psOpIfelse |
 
856
//         +---------------------------------+
 
857
//         | psBlock: ptr=<A>                |
 
858
//         +---------------------------------+
 
859
//         | psBlock: ptr=<B>                |
 
860
//         +---------------------------------+
 
861
//         | if clause                       |
 
862
//         | ...                             |
 
863
//         | psOperator: psOpReturn          |
 
864
//         +---------------------------------+
 
865
//     <A> | else clause                     |
 
866
//         | ...                             |
 
867
//         | psOperator: psOpReturn          |
 
868
//         +---------------------------------+
 
869
//     <B> | ...                             |
 
870
//
 
871
// For 'if', pointer <A> is present in the code stream but unused.
 
872
 
 
873
struct PSObject {
 
874
  PSObjectType type;
 
875
  union {
 
876
    GBool booln;                // boolean (stack only)
 
877
    int intg;                   // integer (stack and code)
 
878
    double real;                // real (stack and code)
 
879
    PSOp op;                    // operator (code only)
 
880
    int blk;                    // if/ifelse block pointer (code only)
 
881
  };
 
882
};
 
883
 
 
884
#define psStackSize 100
 
885
 
 
886
class PSStack {
 
887
public:
 
888
 
 
889
  PSStack() {sp = psStackSize; }
 
890
  void clear() { sp = psStackSize; }
 
891
  void pushBool(GBool booln)
 
892
  {
 
893
    if (checkOverflow()) {
 
894
      stack[--sp].type = psBool;
 
895
      stack[sp].booln = booln;
 
896
    }
 
897
  }
 
898
  void pushInt(int intg)
 
899
  {
 
900
    if (checkOverflow()) {
 
901
      stack[--sp].type = psInt;
 
902
      stack[sp].intg = intg;
 
903
    }
 
904
  }
 
905
  void pushReal(double real)
 
906
  {
 
907
    if (checkOverflow()) {
 
908
      stack[--sp].type = psReal;
 
909
      stack[sp].real = real;
 
910
    }
 
911
  }
 
912
  GBool popBool()
 
913
  {
 
914
    if (checkUnderflow() && checkType(psBool, psBool)) {
 
915
      return stack[sp++].booln;
 
916
    }
 
917
    return gFalse;
 
918
  }
 
919
  int popInt()
 
920
  {
 
921
    if (checkUnderflow() && checkType(psInt, psInt)) {
 
922
      return stack[sp++].intg;
 
923
    }
 
924
    return 0;
 
925
  }
 
926
  double popNum()
 
927
  {
 
928
    double ret;
 
929
 
 
930
    if (checkUnderflow() && checkType(psInt, psReal)) {
 
931
      ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real;
 
932
      ++sp;
 
933
      return ret;
 
934
    }
 
935
    return 0;
 
936
  }
 
937
  GBool empty() { return sp == psStackSize; }
 
938
  GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; }
 
939
  GBool topTwoAreInts()
 
940
    { return sp < psStackSize - 1 &&
 
941
             stack[sp].type == psInt &&
 
942
             stack[sp+1].type == psInt; }
 
943
  GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; }
 
944
  GBool topTwoAreNums()
 
945
    { return sp < psStackSize - 1 &&
 
946
             (stack[sp].type == psInt || stack[sp].type == psReal) &&
 
947
             (stack[sp+1].type == psInt || stack[sp+1].type == psReal); }
 
948
  void copy(int n);
 
949
  void roll(int n, int j);
 
950
  void index(int i)
 
951
  {
 
952
    if (!checkOverflow()) {
 
953
      return;
 
954
    }
 
955
    --sp;
 
956
    stack[sp] = stack[sp + 1 + i];
 
957
  }
 
958
  void pop()
 
959
  {
 
960
    if (!checkUnderflow()) {
 
961
      return;
 
962
    }
 
963
    ++sp;
 
964
  }
 
965
 
 
966
private:
 
967
 
 
968
  GBool checkOverflow(int n = 1)
 
969
  {
 
970
    if (sp - n < 0) {
 
971
      error(-1, "Stack overflow in PostScript function");
 
972
      return gFalse;
 
973
    }
 
974
    return gTrue;
 
975
  }
 
976
  GBool checkUnderflow()
 
977
  {
 
978
    if (sp == psStackSize) {
 
979
      error(-1, "Stack underflow in PostScript function");
 
980
      return gFalse;
 
981
    }
 
982
    return gTrue;
 
983
  }
 
984
  GBool checkType(PSObjectType t1, PSObjectType t2)
 
985
  {
 
986
    if (stack[sp].type != t1 && stack[sp].type != t2) {
 
987
      error(-1, "Type mismatch in PostScript function");
 
988
      return gFalse;
 
989
    }
 
990
    return gTrue;
 
991
  }
 
992
  PSObject stack[psStackSize];
 
993
  int sp;
 
994
};
 
995
 
 
996
 
 
997
void PSStack::copy(int n) {
 
998
  int i;
 
999
 
 
1000
  if (sp + n > psStackSize) {
 
1001
    error(-1, "Stack underflow in PostScript function");
 
1002
    return;
 
1003
  }
 
1004
  if (!checkOverflow(n)) {
 
1005
    return;
 
1006
  }
 
1007
  for (i = sp + n - 1; i >= sp; --i) {
 
1008
    stack[i - n] = stack[i];
 
1009
  }
 
1010
  sp -= n;
 
1011
}
 
1012
 
 
1013
void PSStack::roll(int n, int j) {
 
1014
  PSObject obj;
 
1015
  int i, k;
 
1016
 
 
1017
  if (unlikely(n == 0)) {
 
1018
    return;
 
1019
  }
 
1020
  if (j >= 0) {
 
1021
    j %= n;
 
1022
  } else {
 
1023
    j = -j % n;
 
1024
    if (j != 0) {
 
1025
      j = n - j;
 
1026
    }
 
1027
  }
 
1028
  if (n <= 0 || j == 0) {
 
1029
    return;
 
1030
  }
 
1031
  if (j <= n / 2) {
 
1032
    for (i = 0; i < j; ++i) {
 
1033
      obj = stack[sp];
 
1034
      for (k = sp; k < sp + n - 1; ++k) {
 
1035
        stack[k] = stack[k+1];
 
1036
      }
 
1037
      stack[sp + n - 1] = obj;
 
1038
    }
 
1039
  } else {
 
1040
    j = n - j;
 
1041
    for (i = 0; i < j; ++i) {
 
1042
      obj = stack[sp + n - 1];
 
1043
      for (k = sp + n - 1; k > sp; --k) {
 
1044
        stack[k] = stack[k-1];
 
1045
      }
 
1046
      stack[sp] = obj;
 
1047
    }
 
1048
  }
 
1049
}
 
1050
 
 
1051
class PostScriptFunctionKey : public PopplerCacheKey
 
1052
{
 
1053
  public:
 
1054
    PostScriptFunctionKey(int sizeA, double *inA, bool copyA)
 
1055
    {
 
1056
      init(sizeA, inA, copyA);
 
1057
    }
 
1058
    
 
1059
    PostScriptFunctionKey(const PostScriptFunctionKey &key)
 
1060
    {
 
1061
      init(key.size, key.in, key.copied);
 
1062
    }
 
1063
    
 
1064
    void init(int sizeA, double *inA, bool copyA)
 
1065
    {
 
1066
      copied = copyA;
 
1067
      size = sizeA;
 
1068
      if (copied) {
 
1069
        in = new double[size];
 
1070
        for (int i = 0; i < size; ++i) in[i] = inA[i];
 
1071
      } else {
 
1072
        in = inA;
 
1073
      }
 
1074
    }
 
1075
    
 
1076
    ~PostScriptFunctionKey()
 
1077
    {
 
1078
      if (copied) delete[] in;
 
1079
    }
 
1080
       
 
1081
    bool operator==(const PopplerCacheKey &key) const
 
1082
    {
 
1083
      const PostScriptFunctionKey *k = static_cast<const PostScriptFunctionKey*>(&key);
 
1084
      if (size == k->size) {
 
1085
        bool equal = true;
 
1086
        for (int i = 0; equal && i < size; ++i) {
 
1087
          equal = in[i] == k->in[i];
 
1088
        }
 
1089
        return equal;
 
1090
      } else {
 
1091
        return false;
 
1092
      }
 
1093
    }
 
1094
  
 
1095
    bool copied;
 
1096
    int size;
 
1097
    double *in;
 
1098
};
 
1099
 
 
1100
class PostScriptFunctionItem : public PopplerCacheItem
 
1101
{
 
1102
  public:
 
1103
    PostScriptFunctionItem(int sizeA, double *outA)
 
1104
    {
 
1105
      init(sizeA, outA);
 
1106
    }
 
1107
    
 
1108
    PostScriptFunctionItem(const PostScriptFunctionItem &item)
 
1109
    {
 
1110
      init(item.size, item.out);
 
1111
    }
 
1112
    
 
1113
    void init(int sizeA, double *outA)
 
1114
    {
 
1115
      size = sizeA;
 
1116
      out = new double[size];
 
1117
      for (int i = 0; i < size; ++i) out[i] = outA[i];
 
1118
    }
 
1119
    
 
1120
    ~PostScriptFunctionItem()
 
1121
    {
 
1122
      delete[] out;
 
1123
    }
 
1124
    
 
1125
    int size;
 
1126
    double *out;
 
1127
};
 
1128
 
 
1129
PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
 
1130
  Stream *str;
 
1131
  int codePtr;
 
1132
  GooString *tok;
 
1133
 
 
1134
  code = NULL;
 
1135
  codeString = NULL;
 
1136
  codeSize = 0;
 
1137
  stack = NULL;
 
1138
  ok = gFalse;
 
1139
  cache = new PopplerCache(5);
 
1140
 
 
1141
  //----- initialize the generic stuff
 
1142
  if (!init(dict)) {
 
1143
    goto err1;
 
1144
  }
 
1145
  if (!hasRange) {
 
1146
    error(-1, "Type 4 function is missing range");
 
1147
    goto err1;
 
1148
  }
 
1149
 
 
1150
  //----- get the stream
 
1151
  if (!funcObj->isStream()) {
 
1152
    error(-1, "Type 4 function isn't a stream");
 
1153
    goto err1;
 
1154
  }
 
1155
  str = funcObj->getStream();
 
1156
 
 
1157
  //----- parse the function
 
1158
  codeString = new GooString();
 
1159
  str->reset();
 
1160
  if (!(tok = getToken(str)) || tok->cmp("{")) {
 
1161
    error(-1, "Expected '{' at start of PostScript function");
 
1162
    if (tok) {
 
1163
      delete tok;
 
1164
    }
 
1165
    goto err1;
 
1166
  }
 
1167
  delete tok;
 
1168
  codePtr = 0;
 
1169
  if (!parseCode(str, &codePtr)) {
 
1170
    goto err2;
 
1171
  }
 
1172
  str->close();
 
1173
 
 
1174
  ok = gTrue;
 
1175
  
 
1176
  stack = new PSStack();
 
1177
 
 
1178
 err2:
 
1179
  str->close();
 
1180
 err1:
 
1181
  return;
 
1182
}
 
1183
 
 
1184
PostScriptFunction::PostScriptFunction(PostScriptFunction *func) {
 
1185
  memcpy(this, func, sizeof(PostScriptFunction));
 
1186
  code = (PSObject *)gmallocn(codeSize, sizeof(PSObject));
 
1187
  memcpy(code, func->code, codeSize * sizeof(PSObject));
 
1188
  codeString = func->codeString->copy();
 
1189
  stack = new PSStack();
 
1190
  memcpy(stack, func->stack, sizeof(PSStack));
 
1191
  
 
1192
  cache = new PopplerCache(func->cache->size());
 
1193
  for (int i = 0; i < func->cache->numberOfItems(); ++i)
 
1194
  {
 
1195
    PostScriptFunctionKey *key = new PostScriptFunctionKey(*(PostScriptFunctionKey*)func->cache->key(i));
 
1196
    PostScriptFunctionItem *item = new PostScriptFunctionItem(*(PostScriptFunctionItem*)func->cache->item(i));
 
1197
    cache->put(key, item);
 
1198
  }
 
1199
}
 
1200
 
 
1201
PostScriptFunction::~PostScriptFunction() {
 
1202
  gfree(code);
 
1203
  delete codeString;
 
1204
  delete stack;
 
1205
  delete cache;
 
1206
}
 
1207
 
 
1208
void PostScriptFunction::transform(double *in, double *out) {
 
1209
  int i;
 
1210
  
 
1211
  PostScriptFunctionKey key(m, in, false);
 
1212
  PopplerCacheItem *item = cache->lookup(key);
 
1213
  if (item) {
 
1214
    PostScriptFunctionItem *it = static_cast<PostScriptFunctionItem *>(item);
 
1215
    for (int i = 0; i < n; ++i) {
 
1216
      out[i] = it->out[i];
 
1217
    }
 
1218
    return;
 
1219
  }
 
1220
 
 
1221
  stack->clear();
 
1222
  for (i = 0; i < m; ++i) {
 
1223
    //~ may need to check for integers here
 
1224
    stack->pushReal(in[i]);
 
1225
  }
 
1226
  exec(stack, 0);
 
1227
  for (i = n - 1; i >= 0; --i) {
 
1228
    out[i] = stack->popNum();
 
1229
    if (out[i] < range[i][0]) {
 
1230
      out[i] = range[i][0];
 
1231
    } else if (out[i] > range[i][1]) {
 
1232
      out[i] = range[i][1];
 
1233
    }
 
1234
  }
 
1235
 
 
1236
  PostScriptFunctionKey *newKey = new PostScriptFunctionKey(m, in, true);
 
1237
  PostScriptFunctionItem *newItem = new PostScriptFunctionItem(n, out);
 
1238
  cache->put(newKey, newItem);
 
1239
  
 
1240
  // if (!stack->empty()) {
 
1241
  //   error(-1, "Extra values on stack at end of PostScript function");
 
1242
  // }
 
1243
}
 
1244
 
 
1245
GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
 
1246
  GooString *tok;
 
1247
  char *p;
 
1248
  GBool isReal;
 
1249
  int opPtr, elsePtr;
 
1250
  int a, b, mid, cmp;
 
1251
 
 
1252
  while (1) {
 
1253
    if (!(tok = getToken(str))) {
 
1254
      error(-1, "Unexpected end of PostScript function stream");
 
1255
      return gFalse;
 
1256
    }
 
1257
    p = tok->getCString();
 
1258
    if (isdigit(*p) || *p == '.' || *p == '-') {
 
1259
      isReal = gFalse;
 
1260
      for (++p; *p; ++p) {
 
1261
        if (*p == '.') {
 
1262
          isReal = gTrue;
 
1263
          break;
 
1264
        }
 
1265
      }
 
1266
      resizeCode(*codePtr);
 
1267
      if (isReal) {
 
1268
        code[*codePtr].type = psReal;
 
1269
          code[*codePtr].real = gatof(tok->getCString());
 
1270
      } else {
 
1271
        code[*codePtr].type = psInt;
 
1272
        code[*codePtr].intg = atoi(tok->getCString());
 
1273
      }
 
1274
      ++*codePtr;
 
1275
      delete tok;
 
1276
    } else if (!tok->cmp("{")) {
 
1277
      delete tok;
 
1278
      opPtr = *codePtr;
 
1279
      *codePtr += 3;
 
1280
      resizeCode(opPtr + 2);
 
1281
      if (!parseCode(str, codePtr)) {
 
1282
        return gFalse;
 
1283
      }
 
1284
      if (!(tok = getToken(str))) {
 
1285
        error(-1, "Unexpected end of PostScript function stream");
 
1286
        return gFalse;
 
1287
      }
 
1288
      if (!tok->cmp("{")) {
 
1289
        elsePtr = *codePtr;
 
1290
        if (!parseCode(str, codePtr)) {
 
1291
          return gFalse;
 
1292
        }
 
1293
        delete tok;
 
1294
        if (!(tok = getToken(str))) {
 
1295
          error(-1, "Unexpected end of PostScript function stream");
 
1296
          return gFalse;
 
1297
        }
 
1298
      } else {
 
1299
        elsePtr = -1;
 
1300
      }
 
1301
      if (!tok->cmp("if")) {
 
1302
        if (elsePtr >= 0) {
 
1303
          error(-1, "Got 'if' operator with two blocks in PostScript function");
 
1304
          return gFalse;
 
1305
        }
 
1306
        code[opPtr].type = psOperator;
 
1307
        code[opPtr].op = psOpIf;
 
1308
        code[opPtr+2].type = psBlock;
 
1309
        code[opPtr+2].blk = *codePtr;
 
1310
      } else if (!tok->cmp("ifelse")) {
 
1311
        if (elsePtr < 0) {
 
1312
          error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
 
1313
          return gFalse;
 
1314
        }
 
1315
        code[opPtr].type = psOperator;
 
1316
        code[opPtr].op = psOpIfelse;
 
1317
        code[opPtr+1].type = psBlock;
 
1318
        code[opPtr+1].blk = elsePtr;
 
1319
        code[opPtr+2].type = psBlock;
 
1320
        code[opPtr+2].blk = *codePtr;
 
1321
      } else {
 
1322
        error(-1, "Expected if/ifelse operator in PostScript function");
 
1323
        delete tok;
 
1324
        return gFalse;
 
1325
      }
 
1326
      delete tok;
 
1327
    } else if (!tok->cmp("}")) {
 
1328
      delete tok;
 
1329
      resizeCode(*codePtr);
 
1330
      code[*codePtr].type = psOperator;
 
1331
      code[*codePtr].op = psOpReturn;
 
1332
      ++*codePtr;
 
1333
      break;
 
1334
    } else {
 
1335
      a = -1;
 
1336
      b = nPSOps;
 
1337
      // invariant: psOpNames[a] < tok < psOpNames[b]
 
1338
      while (b - a > 1) {
 
1339
        mid = (a + b) / 2;
 
1340
        cmp = tok->cmp(psOpNames[mid]);
 
1341
        if (cmp > 0) {
 
1342
          a = mid;
 
1343
        } else if (cmp < 0) {
 
1344
          b = mid;
 
1345
        } else {
 
1346
          a = b = mid;
 
1347
        }
 
1348
      }
 
1349
      if (cmp != 0) {
 
1350
        error(-1, "Unknown operator '%s' in PostScript function",
 
1351
              tok->getCString());
 
1352
        delete tok;
 
1353
        return gFalse;
 
1354
      }
 
1355
      delete tok;
 
1356
      resizeCode(*codePtr);
 
1357
      code[*codePtr].type = psOperator;
 
1358
      code[*codePtr].op = (PSOp)a;
 
1359
      ++*codePtr;
 
1360
    }
 
1361
  }
 
1362
  return gTrue;
 
1363
}
 
1364
 
 
1365
GooString *PostScriptFunction::getToken(Stream *str) {
 
1366
  GooString *s;
 
1367
  int c;
 
1368
  GBool comment;
 
1369
 
 
1370
  s = new GooString();
 
1371
  comment = gFalse;
 
1372
  while (1) {
 
1373
    if ((c = str->getChar()) == EOF) {
 
1374
      break;
 
1375
    }
 
1376
    codeString->append(c);
 
1377
    if (comment) {
 
1378
      if (c == '\x0a' || c == '\x0d') {
 
1379
        comment = gFalse;
 
1380
      }
 
1381
    } else if (c == '%') {
 
1382
      comment = gTrue;
 
1383
    } else if (!isspace(c)) {
 
1384
      break;
 
1385
    }
 
1386
  }
 
1387
  if (c == '{' || c == '}') {
 
1388
    s->append((char)c);
 
1389
  } else if (isdigit(c) || c == '.' || c == '-') {
 
1390
    while (1) {
 
1391
      s->append((char)c);
 
1392
      c = str->lookChar();
 
1393
      if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
 
1394
        break;
 
1395
      }
 
1396
      str->getChar();
 
1397
      codeString->append(c);
 
1398
    }
 
1399
  } else {
 
1400
    while (1) {
 
1401
      s->append((char)c);
 
1402
      c = str->lookChar();
 
1403
      if (c == EOF || !isalnum(c)) {
 
1404
        break;
 
1405
      }
 
1406
      str->getChar();
 
1407
      codeString->append(c);
 
1408
    }
 
1409
  }
 
1410
  return s;
 
1411
}
 
1412
 
 
1413
void PostScriptFunction::resizeCode(int newSize) {
 
1414
  if (newSize >= codeSize) {
 
1415
    codeSize += 64;
 
1416
    code = (PSObject *)greallocn(code, codeSize, sizeof(PSObject));
 
1417
  }
 
1418
}
 
1419
 
 
1420
void PostScriptFunction::exec(PSStack *stack, int codePtr) {
 
1421
  int i1, i2;
 
1422
  double r1, r2, result;
 
1423
  GBool b1, b2;
 
1424
 
 
1425
  while (1) {
 
1426
    switch (code[codePtr].type) {
 
1427
    case psInt:
 
1428
      stack->pushInt(code[codePtr++].intg);
 
1429
      break;
 
1430
    case psReal:
 
1431
      stack->pushReal(code[codePtr++].real);
 
1432
      break;
 
1433
    case psOperator:
 
1434
      switch (code[codePtr++].op) {
 
1435
      case psOpAbs:
 
1436
        if (stack->topIsInt()) {
 
1437
          stack->pushInt(abs(stack->popInt()));
 
1438
        } else {
 
1439
          stack->pushReal(fabs(stack->popNum()));
 
1440
        }
 
1441
        break;
 
1442
      case psOpAdd:
 
1443
        if (stack->topTwoAreInts()) {
 
1444
          i2 = stack->popInt();
 
1445
          i1 = stack->popInt();
 
1446
          stack->pushInt(i1 + i2);
 
1447
        } else {
 
1448
          r2 = stack->popNum();
 
1449
          r1 = stack->popNum();
 
1450
          stack->pushReal(r1 + r2);
 
1451
        }
 
1452
        break;
 
1453
      case psOpAnd:
 
1454
        if (stack->topTwoAreInts()) {
 
1455
          i2 = stack->popInt();
 
1456
          i1 = stack->popInt();
 
1457
          stack->pushInt(i1 & i2);
 
1458
        } else {
 
1459
          b2 = stack->popBool();
 
1460
          b1 = stack->popBool();
 
1461
          stack->pushBool(b1 && b2);
 
1462
        }
 
1463
        break;
 
1464
      case psOpAtan:
 
1465
        r2 = stack->popNum();
 
1466
        r1 = stack->popNum();
 
1467
        result = atan2(r1, r2) * 180.0 / M_PI;
 
1468
        if (result < 0) result += 360.0;
 
1469
        stack->pushReal(result);
 
1470
        break;
 
1471
      case psOpBitshift:
 
1472
        i2 = stack->popInt();
 
1473
        i1 = stack->popInt();
 
1474
        if (i2 > 0) {
 
1475
          stack->pushInt(i1 << i2);
 
1476
        } else if (i2 < 0) {
 
1477
          stack->pushInt((int)((Guint)i1 >> i2));
 
1478
        } else {
 
1479
          stack->pushInt(i1);
 
1480
        }
 
1481
        break;
 
1482
      case psOpCeiling:
 
1483
        if (!stack->topIsInt()) {
 
1484
          stack->pushReal(ceil(stack->popNum()));
 
1485
        }
 
1486
        break;
 
1487
      case psOpCopy:
 
1488
        stack->copy(stack->popInt());
 
1489
        break;
 
1490
      case psOpCos:
 
1491
        stack->pushReal(cos(stack->popNum() * M_PI / 180.0));
 
1492
        break;
 
1493
      case psOpCvi:
 
1494
        if (!stack->topIsInt()) {
 
1495
          stack->pushInt((int)stack->popNum());
 
1496
        }
 
1497
        break;
 
1498
      case psOpCvr:
 
1499
        if (!stack->topIsReal()) {
 
1500
          stack->pushReal(stack->popNum());
 
1501
        }
 
1502
        break;
 
1503
      case psOpDiv:
 
1504
        r2 = stack->popNum();
 
1505
        r1 = stack->popNum();
 
1506
        stack->pushReal(r1 / r2);
 
1507
        break;
 
1508
      case psOpDup:
 
1509
        stack->copy(1);
 
1510
        break;
 
1511
      case psOpEq:
 
1512
        if (stack->topTwoAreInts()) {
 
1513
          i2 = stack->popInt();
 
1514
          i1 = stack->popInt();
 
1515
          stack->pushBool(i1 == i2);
 
1516
        } else if (stack->topTwoAreNums()) {
 
1517
          r2 = stack->popNum();
 
1518
          r1 = stack->popNum();
 
1519
          stack->pushBool(r1 == r2);
 
1520
        } else {
 
1521
          b2 = stack->popBool();
 
1522
          b1 = stack->popBool();
 
1523
          stack->pushBool(b1 == b2);
 
1524
        }
 
1525
        break;
 
1526
      case psOpExch:
 
1527
        stack->roll(2, 1);
 
1528
        break;
 
1529
      case psOpExp:
 
1530
        r2 = stack->popNum();
 
1531
        r1 = stack->popNum();
 
1532
        stack->pushReal(pow(r1, r2));
 
1533
        break;
 
1534
      case psOpFalse:
 
1535
        stack->pushBool(gFalse);
 
1536
        break;
 
1537
      case psOpFloor:
 
1538
        if (!stack->topIsInt()) {
 
1539
          stack->pushReal(floor(stack->popNum()));
 
1540
        }
 
1541
        break;
 
1542
      case psOpGe:
 
1543
        if (stack->topTwoAreInts()) {
 
1544
          i2 = stack->popInt();
 
1545
          i1 = stack->popInt();
 
1546
          stack->pushBool(i1 >= i2);
 
1547
        } else {
 
1548
          r2 = stack->popNum();
 
1549
          r1 = stack->popNum();
 
1550
          stack->pushBool(r1 >= r2);
 
1551
        }
 
1552
        break;
 
1553
      case psOpGt:
 
1554
        if (stack->topTwoAreInts()) {
 
1555
          i2 = stack->popInt();
 
1556
          i1 = stack->popInt();
 
1557
          stack->pushBool(i1 > i2);
 
1558
        } else {
 
1559
          r2 = stack->popNum();
 
1560
          r1 = stack->popNum();
 
1561
          stack->pushBool(r1 > r2);
 
1562
        }
 
1563
        break;
 
1564
      case psOpIdiv:
 
1565
        i2 = stack->popInt();
 
1566
        i1 = stack->popInt();
 
1567
        stack->pushInt(i1 / i2);
 
1568
        break;
 
1569
      case psOpIndex:
 
1570
        stack->index(stack->popInt());
 
1571
        break;
 
1572
      case psOpLe:
 
1573
        if (stack->topTwoAreInts()) {
 
1574
          i2 = stack->popInt();
 
1575
          i1 = stack->popInt();
 
1576
          stack->pushBool(i1 <= i2);
 
1577
        } else {
 
1578
          r2 = stack->popNum();
 
1579
          r1 = stack->popNum();
 
1580
          stack->pushBool(r1 <= r2);
 
1581
        }
 
1582
        break;
 
1583
      case psOpLn:
 
1584
        stack->pushReal(log(stack->popNum()));
 
1585
        break;
 
1586
      case psOpLog:
 
1587
        stack->pushReal(log10(stack->popNum()));
 
1588
        break;
 
1589
      case psOpLt:
 
1590
        if (stack->topTwoAreInts()) {
 
1591
          i2 = stack->popInt();
 
1592
          i1 = stack->popInt();
 
1593
          stack->pushBool(i1 < i2);
 
1594
        } else {
 
1595
          r2 = stack->popNum();
 
1596
          r1 = stack->popNum();
 
1597
          stack->pushBool(r1 < r2);
 
1598
        }
 
1599
        break;
 
1600
      case psOpMod:
 
1601
        i2 = stack->popInt();
 
1602
        i1 = stack->popInt();
 
1603
        stack->pushInt(i1 % i2);
 
1604
        break;
 
1605
      case psOpMul:
 
1606
        if (stack->topTwoAreInts()) {
 
1607
          i2 = stack->popInt();
 
1608
          i1 = stack->popInt();
 
1609
          //~ should check for out-of-range, and push a real instead
 
1610
          stack->pushInt(i1 * i2);
 
1611
        } else {
 
1612
          r2 = stack->popNum();
 
1613
          r1 = stack->popNum();
 
1614
          stack->pushReal(r1 * r2);
 
1615
        }
 
1616
        break;
 
1617
      case psOpNe:
 
1618
        if (stack->topTwoAreInts()) {
 
1619
          i2 = stack->popInt();
 
1620
          i1 = stack->popInt();
 
1621
          stack->pushBool(i1 != i2);
 
1622
        } else if (stack->topTwoAreNums()) {
 
1623
          r2 = stack->popNum();
 
1624
          r1 = stack->popNum();
 
1625
          stack->pushBool(r1 != r2);
 
1626
        } else {
 
1627
          b2 = stack->popBool();
 
1628
          b1 = stack->popBool();
 
1629
          stack->pushBool(b1 != b2);
 
1630
        }
 
1631
        break;
 
1632
      case psOpNeg:
 
1633
        if (stack->topIsInt()) {
 
1634
          stack->pushInt(-stack->popInt());
 
1635
        } else {
 
1636
          stack->pushReal(-stack->popNum());
 
1637
        }
 
1638
        break;
 
1639
      case psOpNot:
 
1640
        if (stack->topIsInt()) {
 
1641
          stack->pushInt(~stack->popInt());
 
1642
        } else {
 
1643
          stack->pushBool(!stack->popBool());
 
1644
        }
 
1645
        break;
 
1646
      case psOpOr:
 
1647
        if (stack->topTwoAreInts()) {
 
1648
          i2 = stack->popInt();
 
1649
          i1 = stack->popInt();
 
1650
          stack->pushInt(i1 | i2);
 
1651
        } else {
 
1652
          b2 = stack->popBool();
 
1653
          b1 = stack->popBool();
 
1654
          stack->pushBool(b1 || b2);
 
1655
        }
 
1656
        break;
 
1657
      case psOpPop:
 
1658
        stack->pop();
 
1659
        break;
 
1660
      case psOpRoll:
 
1661
        i2 = stack->popInt();
 
1662
        i1 = stack->popInt();
 
1663
        stack->roll(i1, i2);
 
1664
        break;
 
1665
      case psOpRound:
 
1666
        if (!stack->topIsInt()) {
 
1667
          r1 = stack->popNum();
 
1668
          stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5));
 
1669
        }
 
1670
        break;
 
1671
      case psOpSin:
 
1672
        stack->pushReal(sin(stack->popNum() * M_PI / 180.0));
 
1673
        break;
 
1674
      case psOpSqrt:
 
1675
        stack->pushReal(sqrt(stack->popNum()));
 
1676
        break;
 
1677
      case psOpSub:
 
1678
        if (stack->topTwoAreInts()) {
 
1679
          i2 = stack->popInt();
 
1680
          i1 = stack->popInt();
 
1681
          stack->pushInt(i1 - i2);
 
1682
        } else {
 
1683
          r2 = stack->popNum();
 
1684
          r1 = stack->popNum();
 
1685
          stack->pushReal(r1 - r2);
 
1686
        }
 
1687
        break;
 
1688
      case psOpTrue:
 
1689
        stack->pushBool(gTrue);
 
1690
        break;
 
1691
      case psOpTruncate:
 
1692
        if (!stack->topIsInt()) {
 
1693
          r1 = stack->popNum();
 
1694
          stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1));
 
1695
        }
 
1696
        break;
 
1697
      case psOpXor:
 
1698
        if (stack->topTwoAreInts()) {
 
1699
          i2 = stack->popInt();
 
1700
          i1 = stack->popInt();
 
1701
          stack->pushInt(i1 ^ i2);
 
1702
        } else {
 
1703
          b2 = stack->popBool();
 
1704
          b1 = stack->popBool();
 
1705
          stack->pushBool(b1 ^ b2);
 
1706
        }
 
1707
        break;
 
1708
      case psOpIf:
 
1709
        b1 = stack->popBool();
 
1710
        if (b1) {
 
1711
          exec(stack, codePtr + 2);
 
1712
        }
 
1713
        codePtr = code[codePtr + 1].blk;
 
1714
        break;
 
1715
      case psOpIfelse:
 
1716
        b1 = stack->popBool();
 
1717
        if (b1) {
 
1718
          exec(stack, codePtr + 2);
 
1719
        } else {
 
1720
          exec(stack, code[codePtr].blk);
 
1721
        }
 
1722
        codePtr = code[codePtr + 1].blk;
 
1723
        break;
 
1724
      case psOpReturn:
 
1725
        return;
 
1726
      }
 
1727
      break;
 
1728
    default:
 
1729
      error(-1, "Internal: bad object in PostScript function code");
 
1730
      break;
 
1731
    }
 
1732
  }
 
1733
}