1
//========================================================================
5
// Copyright 2001-2003 Glyph & Cog, LLC
7
//========================================================================
9
//========================================================================
11
// Modified under the Poppler project - http://poppler.freedesktop.org
13
// All changes made under the Poppler project to this file are licensed
14
// under GPL version 2 or later
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>
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
23
//========================================================================
27
#ifdef USE_GCC_PRAGMAS
28
#pragma implementation
36
#include "goo/gstrtod.h"
42
#include "PopplerCache.h"
45
#define M_PI 3.14159265358979323846
48
//------------------------------------------------------------------------
50
//------------------------------------------------------------------------
52
Function::Function() {
55
Function::~Function() {
58
Function *Function::parse(Object *funcObj) {
59
std::set<int> usedParents;
60
return parse(funcObj, &usedParents);
63
Function *Function::parse(Object *funcObj, std::set<int> *usedParents) {
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();
76
error(-1, "Expected function dictionary or stream");
80
if (!dict->lookup("FunctionType", &obj1)->isInt()) {
81
error(-1, "Function type is missing or wrong type");
85
funcType = obj1.getInt();
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);
97
error(-1, "Unimplemented function type (%d)", funcType);
108
GBool Function::init(Dict *dict) {
113
if (!dict->lookup("Domain", &obj1)->isArray()) {
114
error(-1, "Function is missing domain");
117
m = obj1.arrayGetLength() / 2;
118
if (m > funcMaxInputs) {
119
error(-1, "Functions with more than %d inputs are unsupported",
123
for (i = 0; i < m; ++i) {
124
obj1.arrayGet(2*i, &obj2);
126
error(-1, "Illegal value in function domain array");
129
domain[i][0] = obj2.getNum();
131
obj1.arrayGet(2*i+1, &obj2);
133
error(-1, "Illegal value in function domain array");
136
domain[i][1] = obj2.getNum();
144
if (dict->lookup("Range", &obj1)->isArray()) {
146
n = obj1.arrayGetLength() / 2;
147
if (n > funcMaxOutputs) {
148
error(-1, "Functions with more than %d outputs are unsupported",
152
for (i = 0; i < n; ++i) {
153
obj1.arrayGet(2*i, &obj2);
155
error(-1, "Illegal value in function range array");
158
range[i][0] = obj2.getNum();
160
obj1.arrayGet(2*i+1, &obj2);
162
error(-1, "Illegal value in function range array");
165
range[i][1] = obj2.getNum();
180
//------------------------------------------------------------------------
182
//------------------------------------------------------------------------
184
IdentityFunction::IdentityFunction() {
187
// fill these in with arbitrary values just in case they get used
191
for (i = 0; i < funcMaxInputs; ++i) {
198
IdentityFunction::~IdentityFunction() {
201
void IdentityFunction::transform(double *in, double *out) {
204
for (i = 0; i < funcMaxOutputs; ++i) {
209
//------------------------------------------------------------------------
211
//------------------------------------------------------------------------
213
SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
227
//----- initialize the generic stuff
232
error(-1, "Type 0 function is missing range");
235
if (m > sampledFuncMaxInputs) {
236
error(-1, "Sampled functions with more than %d inputs are unsupported",
237
sampledFuncMaxInputs);
242
sBuf = (double *)gmallocn(1 << m, sizeof(double));
244
//----- get the stream
245
if (!funcObj->isStream()) {
246
error(-1, "Type 0 function isn't a stream");
249
str = funcObj->getStream();
252
if (!dict->lookup("Size", &obj1)->isArray() ||
253
obj1.arrayGetLength() != m) {
254
error(-1, "Function has missing or invalid size array");
257
for (i = 0; i < m; ++i) {
258
obj1.arrayGet(i, &obj2);
260
error(-1, "Illegal value in function size array");
263
sampleSize[i] = obj2.getInt();
268
for (i = 1; i < m; ++i) {
269
idxMul[i] = idxMul[i-1] * sampleSize[i-1];
272
//----- BitsPerSample
273
if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
274
error(-1, "Function has missing or invalid BitsPerSample");
277
sampleBits = obj1.getInt();
278
sampleMul = 1.0 / (pow(2.0, (double)sampleBits) - 1);
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);
287
error(-1, "Illegal value in function encode array");
290
encode[i][0] = obj2.getNum();
292
obj1.arrayGet(2*i+1, &obj2);
294
error(-1, "Illegal value in function encode array");
297
encode[i][1] = obj2.getNum();
301
for (i = 0; i < m; ++i) {
303
encode[i][1] = sampleSize[i] - 1;
307
for (i = 0; i < m; ++i) {
308
inputMul[i] = (encode[i][1] - encode[i][0]) /
309
(domain[i][1] - domain[i][0]);
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);
318
error(-1, "Illegal value in function decode array");
321
decode[i][0] = obj2.getNum();
323
obj1.arrayGet(2*i+1, &obj2);
325
error(-1, "Illegal value in function decode array");
328
decode[i][1] = obj2.getNum();
332
for (i = 0; i < n; ++i) {
333
decode[i][0] = range[i][0];
334
decode[i][1] = range[i][1];
341
for (i = 0; i < m; ++i)
342
nSamples *= sampleSize[i];
343
samples = (double *)gmallocn(nSamples, sizeof(double));
346
bitMask = (1 << sampleBits) - 1;
348
for (i = 0; i < nSamples; ++i) {
349
if (sampleBits == 8) {
351
} else if (sampleBits == 16) {
353
s = (s << 8) + str->getChar();
354
} else if (sampleBits == 32) {
356
s = (s << 8) + str->getChar();
357
s = (s << 8) + str->getChar();
358
s = (s << 8) + str->getChar();
360
while (bits < sampleBits) {
361
buf = (buf << 8) | (str->getChar() & 0xff);
364
s = (buf >> (bits - sampleBits)) & bitMask;
367
samples[i] = (double)s * sampleMul;
382
SampledFunction::~SampledFunction() {
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));
398
void SampledFunction::transform(double *in, double *out) {
400
int e[funcMaxInputs][2];
401
double efrac0[funcMaxInputs];
402
double efrac1[funcMaxInputs];
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];
410
} else if (x > sampleSize[i] - 1) {
411
x = sampleSize[i] - 1;
414
if ((e[i][1] = e[i][0] + 1) >= sampleSize[i]) {
415
// this happens if in[i] = domain[i][1]
418
efrac1[i] = x - e[i][0];
419
efrac0[i] = 1 - efrac1[i];
422
// for each output, do m-linear interpolation
423
for (i = 0; i < n; ++i) {
425
// pull 2^m values out of the sample array
426
for (j = 0; j < (1<<m); ++j) {
428
for (k = 0, t = j; k < m; ++k, t >>= 1) {
429
idx += idxMul[k] * (e[k][t & 1]);
431
if (likely(idx >= 0 && idx < nSamples)) {
432
sBuf[j] = samples[idx];
434
sBuf[j] = 0; // TODO Investigate if this is what Adobe does
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];
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];
455
//------------------------------------------------------------------------
456
// ExponentialFunction
457
//------------------------------------------------------------------------
459
ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
465
//----- initialize the generic stuff
470
error(-1, "Exponential function with more than one input");
475
if (dict->lookup("C0", &obj1)->isArray()) {
476
if (hasRange && obj1.arrayGetLength() != n) {
477
error(-1, "Function's C0 array is wrong length");
480
n = obj1.arrayGetLength();
481
for (i = 0; i < n; ++i) {
482
obj1.arrayGet(i, &obj2);
484
error(-1, "Illegal value in function C0 array");
487
c0[i] = obj2.getNum();
491
if (hasRange && n != 1) {
492
error(-1, "Function's C0 array is wrong length");
501
if (dict->lookup("C1", &obj1)->isArray()) {
502
if (obj1.arrayGetLength() != n) {
503
error(-1, "Function's C1 array is wrong length");
506
for (i = 0; i < n; ++i) {
507
obj1.arrayGet(i, &obj2);
509
error(-1, "Illegal value in function C1 array");
512
c1[i] = obj2.getNum();
517
error(-1, "Function's C1 array is wrong length");
525
if (!dict->lookup("N", &obj1)->isNum()) {
526
error(-1, "Function has missing or invalid N");
532
isLinear = fabs(e-1.) < 1e-10;
544
ExponentialFunction::~ExponentialFunction() {
547
ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
548
memcpy(this, func, sizeof(ExponentialFunction));
551
void ExponentialFunction::transform(double *in, double *out) {
555
if (in[0] < domain[0][0]) {
557
} else if (in[0] > domain[0][1]) {
562
for (i = 0; i < n; ++i) {
563
out[i] = c0[i] + (isLinear ? x : pow(x, e)) * (c1[i] - c0[i]);
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];
575
//------------------------------------------------------------------------
577
//------------------------------------------------------------------------
579
StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict, std::set<int> *usedParents) {
589
//----- initialize the generic stuff
594
error(-1, "Stitching function with more than one input");
599
if (!dict->lookup("Functions", &obj1)->isArray()) {
600
error(-1, "Missing 'Functions' entry in stitching function");
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) {
611
for (i = 0; i < k; ++i) {
612
std::set<int> usedParentsAux = *usedParents;
613
obj1.arrayGetNF(i, &obj2);
615
const Ref ref = obj2.getRef();
616
if (usedParentsAux.find(ref.num) == usedParentsAux.end()) {
617
usedParentsAux.insert(ref.num);
619
obj1.arrayGet(i, &obj2);
624
if (!(funcs[i] = Function::parse(&obj2, &usedParentsAux))) {
627
if (i > 0 && (funcs[i]->getInputSize() != 1 ||
628
funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
629
error(-1, "Incompatible subfunctions in stitching function");
637
if (!dict->lookup("Bounds", &obj1)->isArray() ||
638
obj1.arrayGetLength() != k - 1) {
639
error(-1, "Missing or invalid 'Bounds' entry in stitching function");
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");
648
bounds[i] = obj2.getNum();
651
bounds[k] = domain[0][1];
655
if (!dict->lookup("Encode", &obj1)->isArray() ||
656
obj1.arrayGetLength() != 2 * k) {
657
error(-1, "Missing or invalid 'Encode' entry in stitching function");
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");
665
encode[i] = obj2.getNum();
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
677
scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]);
690
StitchingFunction::StitchingFunction(StitchingFunction *func) {
693
memcpy(this, func, sizeof(StitchingFunction));
696
funcs = (Function **)gmallocn(k, sizeof(Function *));
697
for (i = 0; i < k; ++i) {
698
funcs[i] = func->funcs[i]->copy();
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));
709
StitchingFunction::~StitchingFunction() {
713
for (i = 0; i < k; ++i) {
725
void StitchingFunction::transform(double *in, double *out) {
729
if (in[0] < domain[0][0]) {
731
} else if (in[0] > domain[0][1]) {
736
for (i = 0; i < k - 1; ++i) {
737
if (x < bounds[i+1]) {
741
x = encode[2*i] + (x - bounds[i]) * scale[i];
742
funcs[i]->transform(&x, out);
745
//------------------------------------------------------------------------
746
// PostScriptFunction
747
//------------------------------------------------------------------------
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[] = {
841
#define nPSOps (sizeof(psOpNames) / sizeof(char *))
851
// In the code array, 'if'/'ifelse' operators take up three slots
852
// plus space for the code in the subclause(s).
854
// +---------------------------------+
855
// | psOperator: psOpIf / psOpIfelse |
856
// +---------------------------------+
857
// | psBlock: ptr=<A> |
858
// +---------------------------------+
859
// | psBlock: ptr=<B> |
860
// +---------------------------------+
863
// | psOperator: psOpReturn |
864
// +---------------------------------+
865
// <A> | else clause |
867
// | psOperator: psOpReturn |
868
// +---------------------------------+
871
// For 'if', pointer <A> is present in the code stream but unused.
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)
884
#define psStackSize 100
889
PSStack() {sp = psStackSize; }
890
void clear() { sp = psStackSize; }
891
void pushBool(GBool booln)
893
if (checkOverflow()) {
894
stack[--sp].type = psBool;
895
stack[sp].booln = booln;
898
void pushInt(int intg)
900
if (checkOverflow()) {
901
stack[--sp].type = psInt;
902
stack[sp].intg = intg;
905
void pushReal(double real)
907
if (checkOverflow()) {
908
stack[--sp].type = psReal;
909
stack[sp].real = real;
914
if (checkUnderflow() && checkType(psBool, psBool)) {
915
return stack[sp++].booln;
921
if (checkUnderflow() && checkType(psInt, psInt)) {
922
return stack[sp++].intg;
930
if (checkUnderflow() && checkType(psInt, psReal)) {
931
ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real;
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); }
949
void roll(int n, int j);
952
if (!checkOverflow()) {
956
stack[sp] = stack[sp + 1 + i];
960
if (!checkUnderflow()) {
968
GBool checkOverflow(int n = 1)
971
error(-1, "Stack overflow in PostScript function");
976
GBool checkUnderflow()
978
if (sp == psStackSize) {
979
error(-1, "Stack underflow in PostScript function");
984
GBool checkType(PSObjectType t1, PSObjectType t2)
986
if (stack[sp].type != t1 && stack[sp].type != t2) {
987
error(-1, "Type mismatch in PostScript function");
992
PSObject stack[psStackSize];
997
void PSStack::copy(int n) {
1000
if (sp + n > psStackSize) {
1001
error(-1, "Stack underflow in PostScript function");
1004
if (!checkOverflow(n)) {
1007
for (i = sp + n - 1; i >= sp; --i) {
1008
stack[i - n] = stack[i];
1013
void PSStack::roll(int n, int j) {
1017
if (unlikely(n == 0)) {
1028
if (n <= 0 || j == 0) {
1032
for (i = 0; i < j; ++i) {
1034
for (k = sp; k < sp + n - 1; ++k) {
1035
stack[k] = stack[k+1];
1037
stack[sp + n - 1] = obj;
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];
1051
class PostScriptFunctionKey : public PopplerCacheKey
1054
PostScriptFunctionKey(int sizeA, double *inA, bool copyA)
1056
init(sizeA, inA, copyA);
1059
PostScriptFunctionKey(const PostScriptFunctionKey &key)
1061
init(key.size, key.in, key.copied);
1064
void init(int sizeA, double *inA, bool copyA)
1069
in = new double[size];
1070
for (int i = 0; i < size; ++i) in[i] = inA[i];
1076
~PostScriptFunctionKey()
1078
if (copied) delete[] in;
1081
bool operator==(const PopplerCacheKey &key) const
1083
const PostScriptFunctionKey *k = static_cast<const PostScriptFunctionKey*>(&key);
1084
if (size == k->size) {
1086
for (int i = 0; equal && i < size; ++i) {
1087
equal = in[i] == k->in[i];
1100
class PostScriptFunctionItem : public PopplerCacheItem
1103
PostScriptFunctionItem(int sizeA, double *outA)
1108
PostScriptFunctionItem(const PostScriptFunctionItem &item)
1110
init(item.size, item.out);
1113
void init(int sizeA, double *outA)
1116
out = new double[size];
1117
for (int i = 0; i < size; ++i) out[i] = outA[i];
1120
~PostScriptFunctionItem()
1129
PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
1139
cache = new PopplerCache(5);
1141
//----- initialize the generic stuff
1146
error(-1, "Type 4 function is missing range");
1150
//----- get the stream
1151
if (!funcObj->isStream()) {
1152
error(-1, "Type 4 function isn't a stream");
1155
str = funcObj->getStream();
1157
//----- parse the function
1158
codeString = new GooString();
1160
if (!(tok = getToken(str)) || tok->cmp("{")) {
1161
error(-1, "Expected '{' at start of PostScript function");
1169
if (!parseCode(str, &codePtr)) {
1176
stack = new PSStack();
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));
1192
cache = new PopplerCache(func->cache->size());
1193
for (int i = 0; i < func->cache->numberOfItems(); ++i)
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);
1201
PostScriptFunction::~PostScriptFunction() {
1208
void PostScriptFunction::transform(double *in, double *out) {
1211
PostScriptFunctionKey key(m, in, false);
1212
PopplerCacheItem *item = cache->lookup(key);
1214
PostScriptFunctionItem *it = static_cast<PostScriptFunctionItem *>(item);
1215
for (int i = 0; i < n; ++i) {
1216
out[i] = it->out[i];
1222
for (i = 0; i < m; ++i) {
1223
//~ may need to check for integers here
1224
stack->pushReal(in[i]);
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];
1236
PostScriptFunctionKey *newKey = new PostScriptFunctionKey(m, in, true);
1237
PostScriptFunctionItem *newItem = new PostScriptFunctionItem(n, out);
1238
cache->put(newKey, newItem);
1240
// if (!stack->empty()) {
1241
// error(-1, "Extra values on stack at end of PostScript function");
1245
GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
1253
if (!(tok = getToken(str))) {
1254
error(-1, "Unexpected end of PostScript function stream");
1257
p = tok->getCString();
1258
if (isdigit(*p) || *p == '.' || *p == '-') {
1260
for (++p; *p; ++p) {
1266
resizeCode(*codePtr);
1268
code[*codePtr].type = psReal;
1269
code[*codePtr].real = gatof(tok->getCString());
1271
code[*codePtr].type = psInt;
1272
code[*codePtr].intg = atoi(tok->getCString());
1276
} else if (!tok->cmp("{")) {
1280
resizeCode(opPtr + 2);
1281
if (!parseCode(str, codePtr)) {
1284
if (!(tok = getToken(str))) {
1285
error(-1, "Unexpected end of PostScript function stream");
1288
if (!tok->cmp("{")) {
1290
if (!parseCode(str, codePtr)) {
1294
if (!(tok = getToken(str))) {
1295
error(-1, "Unexpected end of PostScript function stream");
1301
if (!tok->cmp("if")) {
1303
error(-1, "Got 'if' operator with two blocks in PostScript function");
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")) {
1312
error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
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;
1322
error(-1, "Expected if/ifelse operator in PostScript function");
1327
} else if (!tok->cmp("}")) {
1329
resizeCode(*codePtr);
1330
code[*codePtr].type = psOperator;
1331
code[*codePtr].op = psOpReturn;
1337
// invariant: psOpNames[a] < tok < psOpNames[b]
1340
cmp = tok->cmp(psOpNames[mid]);
1343
} else if (cmp < 0) {
1350
error(-1, "Unknown operator '%s' in PostScript function",
1356
resizeCode(*codePtr);
1357
code[*codePtr].type = psOperator;
1358
code[*codePtr].op = (PSOp)a;
1365
GooString *PostScriptFunction::getToken(Stream *str) {
1370
s = new GooString();
1373
if ((c = str->getChar()) == EOF) {
1376
codeString->append(c);
1378
if (c == '\x0a' || c == '\x0d') {
1381
} else if (c == '%') {
1383
} else if (!isspace(c)) {
1387
if (c == '{' || c == '}') {
1389
} else if (isdigit(c) || c == '.' || c == '-') {
1392
c = str->lookChar();
1393
if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
1397
codeString->append(c);
1402
c = str->lookChar();
1403
if (c == EOF || !isalnum(c)) {
1407
codeString->append(c);
1413
void PostScriptFunction::resizeCode(int newSize) {
1414
if (newSize >= codeSize) {
1416
code = (PSObject *)greallocn(code, codeSize, sizeof(PSObject));
1420
void PostScriptFunction::exec(PSStack *stack, int codePtr) {
1422
double r1, r2, result;
1426
switch (code[codePtr].type) {
1428
stack->pushInt(code[codePtr++].intg);
1431
stack->pushReal(code[codePtr++].real);
1434
switch (code[codePtr++].op) {
1436
if (stack->topIsInt()) {
1437
stack->pushInt(abs(stack->popInt()));
1439
stack->pushReal(fabs(stack->popNum()));
1443
if (stack->topTwoAreInts()) {
1444
i2 = stack->popInt();
1445
i1 = stack->popInt();
1446
stack->pushInt(i1 + i2);
1448
r2 = stack->popNum();
1449
r1 = stack->popNum();
1450
stack->pushReal(r1 + r2);
1454
if (stack->topTwoAreInts()) {
1455
i2 = stack->popInt();
1456
i1 = stack->popInt();
1457
stack->pushInt(i1 & i2);
1459
b2 = stack->popBool();
1460
b1 = stack->popBool();
1461
stack->pushBool(b1 && b2);
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);
1472
i2 = stack->popInt();
1473
i1 = stack->popInt();
1475
stack->pushInt(i1 << i2);
1476
} else if (i2 < 0) {
1477
stack->pushInt((int)((Guint)i1 >> i2));
1483
if (!stack->topIsInt()) {
1484
stack->pushReal(ceil(stack->popNum()));
1488
stack->copy(stack->popInt());
1491
stack->pushReal(cos(stack->popNum() * M_PI / 180.0));
1494
if (!stack->topIsInt()) {
1495
stack->pushInt((int)stack->popNum());
1499
if (!stack->topIsReal()) {
1500
stack->pushReal(stack->popNum());
1504
r2 = stack->popNum();
1505
r1 = stack->popNum();
1506
stack->pushReal(r1 / r2);
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);
1521
b2 = stack->popBool();
1522
b1 = stack->popBool();
1523
stack->pushBool(b1 == b2);
1530
r2 = stack->popNum();
1531
r1 = stack->popNum();
1532
stack->pushReal(pow(r1, r2));
1535
stack->pushBool(gFalse);
1538
if (!stack->topIsInt()) {
1539
stack->pushReal(floor(stack->popNum()));
1543
if (stack->topTwoAreInts()) {
1544
i2 = stack->popInt();
1545
i1 = stack->popInt();
1546
stack->pushBool(i1 >= i2);
1548
r2 = stack->popNum();
1549
r1 = stack->popNum();
1550
stack->pushBool(r1 >= r2);
1554
if (stack->topTwoAreInts()) {
1555
i2 = stack->popInt();
1556
i1 = stack->popInt();
1557
stack->pushBool(i1 > i2);
1559
r2 = stack->popNum();
1560
r1 = stack->popNum();
1561
stack->pushBool(r1 > r2);
1565
i2 = stack->popInt();
1566
i1 = stack->popInt();
1567
stack->pushInt(i1 / i2);
1570
stack->index(stack->popInt());
1573
if (stack->topTwoAreInts()) {
1574
i2 = stack->popInt();
1575
i1 = stack->popInt();
1576
stack->pushBool(i1 <= i2);
1578
r2 = stack->popNum();
1579
r1 = stack->popNum();
1580
stack->pushBool(r1 <= r2);
1584
stack->pushReal(log(stack->popNum()));
1587
stack->pushReal(log10(stack->popNum()));
1590
if (stack->topTwoAreInts()) {
1591
i2 = stack->popInt();
1592
i1 = stack->popInt();
1593
stack->pushBool(i1 < i2);
1595
r2 = stack->popNum();
1596
r1 = stack->popNum();
1597
stack->pushBool(r1 < r2);
1601
i2 = stack->popInt();
1602
i1 = stack->popInt();
1603
stack->pushInt(i1 % i2);
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);
1612
r2 = stack->popNum();
1613
r1 = stack->popNum();
1614
stack->pushReal(r1 * r2);
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);
1627
b2 = stack->popBool();
1628
b1 = stack->popBool();
1629
stack->pushBool(b1 != b2);
1633
if (stack->topIsInt()) {
1634
stack->pushInt(-stack->popInt());
1636
stack->pushReal(-stack->popNum());
1640
if (stack->topIsInt()) {
1641
stack->pushInt(~stack->popInt());
1643
stack->pushBool(!stack->popBool());
1647
if (stack->topTwoAreInts()) {
1648
i2 = stack->popInt();
1649
i1 = stack->popInt();
1650
stack->pushInt(i1 | i2);
1652
b2 = stack->popBool();
1653
b1 = stack->popBool();
1654
stack->pushBool(b1 || b2);
1661
i2 = stack->popInt();
1662
i1 = stack->popInt();
1663
stack->roll(i1, i2);
1666
if (!stack->topIsInt()) {
1667
r1 = stack->popNum();
1668
stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5));
1672
stack->pushReal(sin(stack->popNum() * M_PI / 180.0));
1675
stack->pushReal(sqrt(stack->popNum()));
1678
if (stack->topTwoAreInts()) {
1679
i2 = stack->popInt();
1680
i1 = stack->popInt();
1681
stack->pushInt(i1 - i2);
1683
r2 = stack->popNum();
1684
r1 = stack->popNum();
1685
stack->pushReal(r1 - r2);
1689
stack->pushBool(gTrue);
1692
if (!stack->topIsInt()) {
1693
r1 = stack->popNum();
1694
stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1));
1698
if (stack->topTwoAreInts()) {
1699
i2 = stack->popInt();
1700
i1 = stack->popInt();
1701
stack->pushInt(i1 ^ i2);
1703
b2 = stack->popBool();
1704
b1 = stack->popBool();
1705
stack->pushBool(b1 ^ b2);
1709
b1 = stack->popBool();
1711
exec(stack, codePtr + 2);
1713
codePtr = code[codePtr + 1].blk;
1716
b1 = stack->popBool();
1718
exec(stack, codePtr + 2);
1720
exec(stack, code[codePtr].blk);
1722
codePtr = code[codePtr + 1].blk;
1729
error(-1, "Internal: bad object in PostScript function code");