1
//========================================================================
5
// Copyright 2001-2002 Glyph & Cog, LLC
7
//========================================================================
11
#ifdef USE_GCC_PRAGMAS
12
#pragma implementation
26
//------------------------------------------------------------------------
28
//------------------------------------------------------------------------
30
Function::Function() {
33
Function::~Function() {
36
Function *Function::parse(Object *funcObj) {
42
if (funcObj->isStream()) {
43
dict = funcObj->streamGetDict();
44
} else if (funcObj->isDict()) {
45
dict = funcObj->getDict();
46
} else if (funcObj->isName("Identity")) {
47
return new IdentityFunction();
49
error(-1, "Expected function dictionary or stream");
53
if (!dict->lookup("FunctionType", &obj1)->isInt()) {
54
error(-1, "Function type is missing or wrong type");
58
funcType = obj1.getInt();
62
func = new SampledFunction(funcObj, dict);
63
} else if (funcType == 2) {
64
func = new ExponentialFunction(funcObj, dict);
65
} else if (funcType == 3) {
66
func = new StitchingFunction(funcObj, dict);
67
} else if (funcType == 4) {
68
func = new PostScriptFunction(funcObj, dict);
70
error(-1, "Unimplemented function type (%d)", funcType);
81
GBool Function::init(Dict *dict) {
86
if (!dict->lookup("Domain", &obj1)->isArray()) {
87
error(-1, "Function is missing domain");
90
m = obj1.arrayGetLength() / 2;
91
if (m > funcMaxInputs) {
92
error(-1, "Functions with more than %d inputs are unsupported",
96
for (i = 0; i < m; ++i) {
97
obj1.arrayGet(2*i, &obj2);
99
error(-1, "Illegal value in function domain array");
102
domain[i][0] = obj2.getNum();
104
obj1.arrayGet(2*i+1, &obj2);
106
error(-1, "Illegal value in function domain array");
109
domain[i][1] = obj2.getNum();
117
if (dict->lookup("Range", &obj1)->isArray()) {
119
n = obj1.arrayGetLength() / 2;
120
if (n > funcMaxOutputs) {
121
error(-1, "Functions with more than %d outputs are unsupported",
125
for (i = 0; i < n; ++i) {
126
obj1.arrayGet(2*i, &obj2);
128
error(-1, "Illegal value in function range array");
131
range[i][0] = obj2.getNum();
133
obj1.arrayGet(2*i+1, &obj2);
135
error(-1, "Illegal value in function range array");
138
range[i][1] = obj2.getNum();
153
//------------------------------------------------------------------------
155
//------------------------------------------------------------------------
157
IdentityFunction::IdentityFunction() {
160
// fill these in with arbitrary values just in case they get used
164
for (i = 0; i < funcMaxInputs; ++i) {
171
IdentityFunction::~IdentityFunction() {
174
void IdentityFunction::transform(double *in, double *out) {
177
for (i = 0; i < funcMaxOutputs; ++i) {
182
//------------------------------------------------------------------------
184
//------------------------------------------------------------------------
186
SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
188
int nSamples, sampleBits;
199
//----- initialize the generic stuff
204
error(-1, "Type 0 function is missing range");
208
//----- get the stream
209
if (!funcObj->isStream()) {
210
error(-1, "Type 0 function isn't a stream");
213
str = funcObj->getStream();
216
if (!dict->lookup("Size", &obj1)->isArray() ||
217
obj1.arrayGetLength() != m) {
218
error(-1, "Function has missing or invalid size array");
221
for (i = 0; i < m; ++i) {
222
obj1.arrayGet(i, &obj2);
224
error(-1, "Illegal value in function size array");
227
sampleSize[i] = obj2.getInt();
232
//----- BitsPerSample
233
if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
234
error(-1, "Function has missing or invalid BitsPerSample");
237
sampleBits = obj1.getInt();
238
sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
242
if (dict->lookup("Encode", &obj1)->isArray() &&
243
obj1.arrayGetLength() == 2*m) {
244
for (i = 0; i < m; ++i) {
245
obj1.arrayGet(2*i, &obj2);
247
error(-1, "Illegal value in function encode array");
250
encode[i][0] = obj2.getNum();
252
obj1.arrayGet(2*i+1, &obj2);
254
error(-1, "Illegal value in function encode array");
257
encode[i][1] = obj2.getNum();
261
for (i = 0; i < m; ++i) {
263
encode[i][1] = sampleSize[i] - 1;
269
if (dict->lookup("Decode", &obj1)->isArray() &&
270
obj1.arrayGetLength() == 2*n) {
271
for (i = 0; i < n; ++i) {
272
obj1.arrayGet(2*i, &obj2);
274
error(-1, "Illegal value in function decode array");
277
decode[i][0] = obj2.getNum();
279
obj1.arrayGet(2*i+1, &obj2);
281
error(-1, "Illegal value in function decode array");
284
decode[i][1] = obj2.getNum();
288
for (i = 0; i < n; ++i) {
289
decode[i][0] = range[i][0];
290
decode[i][1] = range[i][1];
297
for (i = 0; i < m; ++i)
298
nSamples *= sampleSize[i];
299
samples = (double *)gmalloc(nSamples * sizeof(double));
302
bitMask = (1 << sampleBits) - 1;
304
for (i = 0; i < nSamples; ++i) {
305
if (sampleBits == 8) {
307
} else if (sampleBits == 16) {
309
s = (s << 8) + str->getChar();
310
} else if (sampleBits == 32) {
312
s = (s << 8) + str->getChar();
313
s = (s << 8) + str->getChar();
314
s = (s << 8) + str->getChar();
316
while (bits < sampleBits) {
317
buf = (buf << 8) | (str->getChar() & 0xff);
320
s = (buf >> (bits - sampleBits)) & bitMask;
323
samples[i] = (double)s * sampleMul;
338
SampledFunction::~SampledFunction() {
344
SampledFunction::SampledFunction(SampledFunction *func) {
347
memcpy(this, func, sizeof(SampledFunction));
350
for (i = 0; i < m; ++i) {
351
nSamples *= sampleSize[i];
353
samples = (double *)gmalloc(nSamples * sizeof(double));
354
memcpy(samples, func->samples, nSamples * sizeof(double));
357
void SampledFunction::transform(double *in, double *out) {
359
int e[2][funcMaxInputs];
360
double efrac[funcMaxInputs];
361
double s0[1 << funcMaxInputs], s1[1 << funcMaxInputs];
364
// map input values into sample array
365
for (i = 0; i < m; ++i) {
366
x = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
367
(encode[i][1] - encode[i][0]) + encode[i][0];
370
} else if (x > sampleSize[i] - 1) {
371
x = sampleSize[i] - 1;
373
e[0][i] = (int)floor(x);
374
e[1][i] = (int)ceil(x);
375
efrac[i] = x - e[0][i];
378
// for each output, do m-linear interpolation
379
for (i = 0; i < n; ++i) {
381
// pull 2^m values out of the sample array
382
for (j = 0; j < (1<<m); ++j) {
383
idx = e[j & 1][m - 1];
384
for (k = m - 2; k >= 0; --k) {
385
idx = idx * sampleSize[k] + e[(j >> k) & 1][k];
388
s0[j] = samples[idx];
391
// do m sets of interpolations
392
for (j = 0; j < m; ++j) {
393
for (k = 0; k < (1 << (m - j)); k += 2) {
394
s1[k >> 1] = (1 - efrac[j]) * s0[k] + efrac[j] * s0[k+1];
396
memcpy(s0, s1, (1 << (m - j - 1)) * sizeof(double));
399
// map output value to range
400
out[i] = s0[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
401
if (out[i] < range[i][0]) {
402
out[i] = range[i][0];
403
} else if (out[i] > range[i][1]) {
404
out[i] = range[i][1];
409
//------------------------------------------------------------------------
410
// ExponentialFunction
411
//------------------------------------------------------------------------
413
ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
420
//----- initialize the generic stuff
425
error(-1, "Exponential function with more than one input");
430
//----- default values
431
for (i = 0; i < funcMaxOutputs; ++i) {
437
if (dict->lookup("C0", &obj1)->isArray()) {
439
n = obj1.arrayGetLength();
441
} else if (obj1.arrayGetLength() != n) {
442
error(-1, "Function's C0 array is wrong length");
445
for (i = 0; i < n; ++i) {
446
obj1.arrayGet(i, &obj2);
448
error(-1, "Illegal value in function C0 array");
451
c0[i] = obj2.getNum();
458
if (dict->lookup("C1", &obj1)->isArray()) {
460
n = obj1.arrayGetLength();
462
} else if (obj1.arrayGetLength() != n) {
463
error(-1, "Function's C1 array is wrong length");
466
for (i = 0; i < n; ++i) {
467
obj1.arrayGet(i, &obj2);
469
error(-1, "Illegal value in function C1 array");
472
c1[i] = obj2.getNum();
479
if (!dict->lookup("N", &obj1)->isNum()) {
480
error(-1, "Function has missing or invalid N");
486
// this isn't supposed to happen, but I've run into (broken) PDF
487
// files where it does
489
error(-1, "Exponential function does not define number of output values");
504
ExponentialFunction::~ExponentialFunction() {
507
ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
508
memcpy(this, func, sizeof(ExponentialFunction));
511
void ExponentialFunction::transform(double *in, double *out) {
515
if (in[0] < domain[0][0]) {
517
} else if (in[0] > domain[0][1]) {
522
for (i = 0; i < n; ++i) {
523
out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
525
if (out[i] < range[i][0]) {
526
out[i] = range[i][0];
527
} else if (out[i] > range[i][1]) {
528
out[i] = range[i][1];
535
//------------------------------------------------------------------------
537
//------------------------------------------------------------------------
539
StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
548
//----- initialize the generic stuff
553
error(-1, "Stitching function with more than one input");
558
if (!dict->lookup("Functions", &obj1)->isArray()) {
559
error(-1, "Missing 'Functions' entry in stitching function");
562
k = obj1.arrayGetLength();
563
funcs = (Function **)gmalloc(k * sizeof(Function *));
564
bounds = (double *)gmalloc((k + 1) * sizeof(double));
565
encode = (double *)gmalloc(2 * k * sizeof(double));
566
for (i = 0; i < k; ++i) {
569
for (i = 0; i < k; ++i) {
570
if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) {
573
if (i > 0 && (funcs[i]->getInputSize() != 1 ||
574
funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
575
error(-1, "Incompatible subfunctions in stitching function");
583
if (!dict->lookup("Bounds", &obj1)->isArray() ||
584
obj1.arrayGetLength() != k - 1) {
585
error(-1, "Missing or invalid 'Bounds' entry in stitching function");
588
bounds[0] = domain[0][0];
589
for (i = 1; i < k; ++i) {
590
if (!obj1.arrayGet(i - 1, &obj2)->isNum()) {
591
error(-1, "Invalid type in 'Bounds' array in stitching function");
594
bounds[i] = obj2.getNum();
597
bounds[k] = domain[0][1];
601
if (!dict->lookup("Encode", &obj1)->isArray() ||
602
obj1.arrayGetLength() != 2 * k) {
603
error(-1, "Missing or invalid 'Encode' entry in stitching function");
606
for (i = 0; i < 2 * k; ++i) {
607
if (!obj1.arrayGet(i, &obj2)->isNum()) {
608
error(-1, "Invalid type in 'Encode' array in stitching function");
611
encode[i] = obj2.getNum();
625
StitchingFunction::StitchingFunction(StitchingFunction *func) {
627
funcs = (Function **)gmalloc(k * sizeof(Function *));
628
memcpy(funcs, func->funcs, k * sizeof(Function *));
629
bounds = (double *)gmalloc((k + 1) * sizeof(double));
630
memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
631
encode = (double *)gmalloc(2 * k * sizeof(double));
632
memcpy(encode, func->encode, 2 * k * sizeof(double));
636
StitchingFunction::~StitchingFunction() {
639
for (i = 0; i < k; ++i) {
649
void StitchingFunction::transform(double *in, double *out) {
653
if (in[0] < domain[0][0]) {
655
} else if (in[0] > domain[0][1]) {
660
for (i = 0; i < k - 1; ++i) {
661
if (x < bounds[i+1]) {
665
x = encode[2*i] + ((x - bounds[i]) / (bounds[i+1] - bounds[i])) *
666
(encode[2*i+1] - encode[2*i]);
667
funcs[i]->transform(&x, out);
670
//------------------------------------------------------------------------
671
// PostScriptFunction
672
//------------------------------------------------------------------------
720
// Note: 'if' and 'ifelse' are parsed separately.
721
// The rest are listed here in alphabetical order.
722
// The index in this table is equivalent to the entry in PSOp.
723
char *psOpNames[] = {
766
#define nPSOps (sizeof(psOpNames) / sizeof(char *))
776
// In the code array, 'if'/'ifelse' operators take up three slots
777
// plus space for the code in the subclause(s).
779
// +---------------------------------+
780
// | psOperator: psOpIf / psOpIfelse |
781
// +---------------------------------+
782
// | psBlock: ptr=<A> |
783
// +---------------------------------+
784
// | psBlock: ptr=<B> |
785
// +---------------------------------+
788
// | psOperator: psOpReturn |
789
// +---------------------------------+
790
// <A> | else clause |
792
// | psOperator: psOpReturn |
793
// +---------------------------------+
796
// For 'if', pointer <A> is present in the code stream but unused.
801
GBool booln; // boolean (stack only)
802
int intg; // integer (stack and code)
803
double real; // real (stack and code)
804
PSOp op; // operator (code only)
805
int blk; // if/ifelse block pointer (code only)
809
#define psStackSize 100
814
PSStack() { sp = psStackSize; }
815
void pushBool(GBool booln);
816
void pushInt(int intg);
817
void pushReal(double real);
821
GBool empty() { return sp == psStackSize; }
822
GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; }
823
GBool topTwoAreInts()
824
{ return sp < psStackSize - 1 &&
825
stack[sp].type == psInt &&
826
stack[sp+1].type == psInt; }
827
GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; }
828
GBool topTwoAreNums()
829
{ return sp < psStackSize - 1 &&
830
(stack[sp].type == psInt || stack[sp].type == psReal) &&
831
(stack[sp+1].type == psInt || stack[sp+1].type == psReal); }
833
void roll(int n, int j);
839
GBool checkOverflow(int n = 1);
840
GBool checkUnderflow();
841
GBool checkType(PSObjectType t1, PSObjectType t2);
843
PSObject stack[psStackSize];
847
GBool PSStack::checkOverflow(int n) {
849
error(-1, "Stack overflow in PostScript function");
855
GBool PSStack::checkUnderflow() {
856
if (sp == psStackSize) {
857
error(-1, "Stack underflow in PostScript function");
863
GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) {
864
if (stack[sp].type != t1 && stack[sp].type != t2) {
865
error(-1, "Type mismatch in PostScript function");
871
void PSStack::pushBool(GBool booln) {
872
if (checkOverflow()) {
873
stack[--sp].type = psBool;
874
stack[sp].booln = booln;
878
void PSStack::pushInt(int intg) {
879
if (checkOverflow()) {
880
stack[--sp].type = psInt;
881
stack[sp].intg = intg;
885
void PSStack::pushReal(double real) {
886
if (checkOverflow()) {
887
stack[--sp].type = psReal;
888
stack[sp].real = real;
892
GBool PSStack::popBool() {
893
if (checkUnderflow() && checkType(psBool, psBool)) {
894
return stack[sp++].booln;
899
int PSStack::popInt() {
900
if (checkUnderflow() && checkType(psInt, psInt)) {
901
return stack[sp++].intg;
906
double PSStack::popNum() {
909
if (checkUnderflow() && checkType(psInt, psReal)) {
910
ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real;
917
void PSStack::copy(int n) {
920
if (!checkOverflow(n)) {
923
for (i = sp + n - 1; i <= sp; ++i) {
924
stack[i - n] = stack[i];
929
void PSStack::roll(int n, int j) {
941
if (n <= 0 || j == 0) {
944
for (i = 0; i < j; ++i) {
946
for (k = sp; k < sp + n - 1; ++k) {
947
stack[k] = stack[k+1];
949
stack[sp + n - 1] = obj;
953
void PSStack::index(int i) {
954
if (!checkOverflow()) {
958
stack[sp] = stack[sp + 1 + i];
961
void PSStack::pop() {
962
if (!checkUnderflow()) {
968
PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
977
//----- initialize the generic stuff
982
error(-1, "Type 4 function is missing range");
986
//----- get the stream
987
if (!funcObj->isStream()) {
988
error(-1, "Type 4 function isn't a stream");
991
str = funcObj->getStream();
993
//----- parse the function
995
if (!(tok = getToken(str)) || tok->cmp("{")) {
996
error(-1, "Expected '{' at start of PostScript function");
1004
if (!parseCode(str, &codePtr)) {
1017
PostScriptFunction::PostScriptFunction(PostScriptFunction *func) {
1018
memcpy(this, func, sizeof(PostScriptFunction));
1019
code = (PSObject *)gmalloc(codeSize * sizeof(PSObject));
1020
memcpy(code, func->code, codeSize * sizeof(PSObject));
1023
PostScriptFunction::~PostScriptFunction() {
1027
void PostScriptFunction::transform(double *in, double *out) {
1031
stack = new PSStack();
1032
for (i = 0; i < m; ++i) {
1033
//~ may need to check for integers here
1034
stack->pushReal(in[i]);
1037
for (i = n - 1; i >= 0; --i) {
1038
out[i] = stack->popNum();
1039
if (out[i] < range[i][0]) {
1040
out[i] = range[i][0];
1041
} else if (out[i] > range[i][1]) {
1042
out[i] = range[i][1];
1045
// if (!stack->empty()) {
1046
// error(-1, "Extra values on stack at end of PostScript function");
1051
GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
1059
if (!(tok = getToken(str))) {
1060
error(-1, "Unexpected end of PostScript function stream");
1063
p = tok->getCString();
1064
if (isdigit(*p) || *p == '.' || *p == '-') {
1066
for (++p; *p; ++p) {
1072
resizeCode(*codePtr);
1074
code[*codePtr].type = psReal;
1075
code[*codePtr].real = atof(tok->getCString());
1077
code[*codePtr].type = psInt;
1078
code[*codePtr].intg = atoi(tok->getCString());
1082
} else if (!tok->cmp("{")) {
1086
resizeCode(opPtr + 2);
1087
if (!parseCode(str, codePtr)) {
1090
if (!(tok = getToken(str))) {
1091
error(-1, "Unexpected end of PostScript function stream");
1094
if (!tok->cmp("{")) {
1096
if (!parseCode(str, codePtr)) {
1100
if (!(tok = getToken(str))) {
1101
error(-1, "Unexpected end of PostScript function stream");
1107
if (!tok->cmp("if")) {
1109
error(-1, "Got 'if' operator with two blocks in PostScript function");
1112
code[opPtr].type = psOperator;
1113
code[opPtr].op = psOpIf;
1114
code[opPtr+2].type = psBlock;
1115
code[opPtr+2].blk = *codePtr;
1116
} else if (!tok->cmp("ifelse")) {
1118
error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
1121
code[opPtr].type = psOperator;
1122
code[opPtr].op = psOpIfelse;
1123
code[opPtr+1].type = psBlock;
1124
code[opPtr+1].blk = elsePtr;
1125
code[opPtr+2].type = psBlock;
1126
code[opPtr+2].blk = *codePtr;
1128
error(-1, "Expected if/ifelse operator in PostScript function");
1133
} else if (!tok->cmp("}")) {
1135
resizeCode(*codePtr);
1136
code[*codePtr].type = psOperator;
1137
code[*codePtr].op = psOpReturn;
1143
// invariant: psOpNames[a] < tok < psOpNames[b]
1146
cmp = tok->cmp(psOpNames[mid]);
1149
} else if (cmp < 0) {
1156
error(-1, "Unknown operator '%s' in PostScript function",
1162
resizeCode(*codePtr);
1163
code[*codePtr].type = psOperator;
1164
code[*codePtr].op = (PSOp)a;
1171
GString *PostScriptFunction::getToken(Stream *str) {
1178
} while (c != EOF && isspace(c));
1179
if (c == '{' || c == '}') {
1181
} else if (isdigit(c) || c == '.' || c == '-') {
1184
c = str->lookChar();
1185
if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
1193
c = str->lookChar();
1194
if (c == EOF || !isalnum(c)) {
1203
void PostScriptFunction::resizeCode(int newSize) {
1204
if (newSize >= codeSize) {
1206
code = (PSObject *)grealloc(code, codeSize * sizeof(PSObject));
1210
void PostScriptFunction::exec(PSStack *stack, int codePtr) {
1216
switch (code[codePtr].type) {
1218
stack->pushInt(code[codePtr++].intg);
1221
stack->pushReal(code[codePtr++].real);
1224
switch (code[codePtr++].op) {
1226
if (stack->topIsInt()) {
1227
stack->pushInt(abs(stack->popInt()));
1229
stack->pushReal(fabs(stack->popNum()));
1233
if (stack->topTwoAreInts()) {
1234
i2 = stack->popInt();
1235
i1 = stack->popInt();
1236
stack->pushInt(i1 + i2);
1238
r2 = stack->popNum();
1239
r1 = stack->popNum();
1240
stack->pushReal(r1 + r2);
1244
if (stack->topTwoAreInts()) {
1245
i2 = stack->popInt();
1246
i1 = stack->popInt();
1247
stack->pushInt(i1 & i2);
1249
b2 = stack->popBool();
1250
b1 = stack->popBool();
1251
stack->pushReal(b1 && b2);
1255
r2 = stack->popNum();
1256
r1 = stack->popNum();
1257
stack->pushReal(atan2(r1, r2));
1260
i2 = stack->popInt();
1261
i1 = stack->popInt();
1263
stack->pushInt(i1 << i2);
1264
} else if (i2 < 0) {
1265
stack->pushInt((int)((Guint)i1 >> i2));
1271
if (!stack->topIsInt()) {
1272
stack->pushReal(ceil(stack->popNum()));
1276
stack->copy(stack->popInt());
1279
stack->pushReal(cos(stack->popNum()));
1282
if (!stack->topIsInt()) {
1283
stack->pushInt((int)stack->popNum());
1287
if (!stack->topIsReal()) {
1288
stack->pushReal(stack->popNum());
1292
r2 = stack->popNum();
1293
r1 = stack->popNum();
1294
stack->pushReal(r1 / r2);
1300
if (stack->topTwoAreInts()) {
1301
i2 = stack->popInt();
1302
i1 = stack->popInt();
1303
stack->pushBool(i1 == i2);
1304
} else if (stack->topTwoAreNums()) {
1305
r2 = stack->popNum();
1306
r1 = stack->popNum();
1307
stack->pushBool(r1 == r2);
1309
b2 = stack->popBool();
1310
b1 = stack->popBool();
1311
stack->pushBool(b1 == b2);
1318
r2 = stack->popInt();
1319
r1 = stack->popInt();
1320
stack->pushReal(pow(r1, r2));
1323
stack->pushBool(gFalse);
1326
if (!stack->topIsInt()) {
1327
stack->pushReal(floor(stack->popNum()));
1331
if (stack->topTwoAreInts()) {
1332
i2 = stack->popInt();
1333
i1 = stack->popInt();
1334
stack->pushBool(i1 >= i2);
1336
r2 = stack->popNum();
1337
r1 = stack->popNum();
1338
stack->pushBool(r1 >= r2);
1342
if (stack->topTwoAreInts()) {
1343
i2 = stack->popInt();
1344
i1 = stack->popInt();
1345
stack->pushBool(i1 > i2);
1347
r2 = stack->popNum();
1348
r1 = stack->popNum();
1349
stack->pushBool(r1 > r2);
1353
i2 = stack->popInt();
1354
i1 = stack->popInt();
1355
stack->pushInt(i1 / i2);
1358
stack->index(stack->popInt());
1361
if (stack->topTwoAreInts()) {
1362
i2 = stack->popInt();
1363
i1 = stack->popInt();
1364
stack->pushBool(i1 <= i2);
1366
r2 = stack->popNum();
1367
r1 = stack->popNum();
1368
stack->pushBool(r1 <= r2);
1372
stack->pushReal(log(stack->popNum()));
1375
stack->pushReal(log10(stack->popNum()));
1378
if (stack->topTwoAreInts()) {
1379
i2 = stack->popInt();
1380
i1 = stack->popInt();
1381
stack->pushBool(i1 < i2);
1383
r2 = stack->popNum();
1384
r1 = stack->popNum();
1385
stack->pushBool(r1 < r2);
1389
i2 = stack->popInt();
1390
i1 = stack->popInt();
1391
stack->pushInt(i1 % i2);
1394
if (stack->topTwoAreInts()) {
1395
i2 = stack->popInt();
1396
i1 = stack->popInt();
1397
//~ should check for out-of-range, and push a real instead
1398
stack->pushInt(i1 * i2);
1400
r2 = stack->popNum();
1401
r1 = stack->popNum();
1402
stack->pushReal(r1 * r2);
1406
if (stack->topTwoAreInts()) {
1407
i2 = stack->popInt();
1408
i1 = stack->popInt();
1409
stack->pushBool(i1 != i2);
1410
} else if (stack->topTwoAreNums()) {
1411
r2 = stack->popNum();
1412
r1 = stack->popNum();
1413
stack->pushBool(r1 != r2);
1415
b2 = stack->popBool();
1416
b1 = stack->popBool();
1417
stack->pushBool(b1 != b2);
1421
if (stack->topIsInt()) {
1422
stack->pushInt(-stack->popInt());
1424
stack->pushReal(-stack->popNum());
1428
if (stack->topIsInt()) {
1429
stack->pushInt(~stack->popInt());
1431
stack->pushReal(!stack->popBool());
1435
if (stack->topTwoAreInts()) {
1436
i2 = stack->popInt();
1437
i1 = stack->popInt();
1438
stack->pushInt(i1 | i2);
1440
b2 = stack->popBool();
1441
b1 = stack->popBool();
1442
stack->pushReal(b1 || b2);
1449
i2 = stack->popInt();
1450
i1 = stack->popInt();
1451
stack->roll(i1, i2);
1454
if (!stack->topIsInt()) {
1455
r1 = stack->popNum();
1456
stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5));
1460
stack->pushReal(cos(stack->popNum()));
1463
stack->pushReal(sqrt(stack->popNum()));
1466
if (stack->topTwoAreInts()) {
1467
i2 = stack->popInt();
1468
i1 = stack->popInt();
1469
stack->pushInt(i1 - i2);
1471
r2 = stack->popNum();
1472
r1 = stack->popNum();
1473
stack->pushReal(r1 - r2);
1477
stack->pushBool(gTrue);
1480
if (!stack->topIsInt()) {
1481
r1 = stack->popNum();
1482
stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1));
1486
if (stack->topTwoAreInts()) {
1487
i2 = stack->popInt();
1488
i1 = stack->popInt();
1489
stack->pushInt(i1 ^ i2);
1491
b2 = stack->popBool();
1492
b1 = stack->popBool();
1493
stack->pushReal(b1 ^ b2);
1497
b1 = stack->popBool();
1499
exec(stack, codePtr + 2);
1501
codePtr = code[codePtr + 1].blk;
1504
b1 = stack->popBool();
1506
exec(stack, codePtr + 2);
1508
exec(stack, code[codePtr].blk);
1510
codePtr = code[codePtr + 1].blk;
1517
error(-1, "Internal: bad object in PostScript function code");