33Function::~Function() {
36Function *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);
81GBool 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();
157IdentityFunction::IdentityFunction() {
164 for (i = 0; i < funcMaxInputs; ++i) {
171IdentityFunction::~IdentityFunction() {
174void IdentityFunction::transform(
const double *in,
double *out)
const {
177 for (i = 0; i < funcMaxOutputs; ++i) {
186SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
188 int nSamples, sampleBits;
204 error(-1,
"Type 0 function is missing range");
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();
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;
338SampledFunction::~SampledFunction() {
344SampledFunction::SampledFunction(
const 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));
357void SampledFunction::transform(
const double *in,
double *out)
const {
359 int e[2][funcMaxInputs];
360 double efrac[funcMaxInputs];
361 double s0[1 << funcMaxInputs], s1[1 << funcMaxInputs];
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];
379 for (i = 0; i < n; ++i) {
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];
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));
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];
413ExponentialFunction::ExponentialFunction(Object *, Dict *dict) {
425 error(-1,
"Exponential function with more than one input");
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");
489 error(-1,
"Exponential function does not define number of output values");
504ExponentialFunction::~ExponentialFunction() {
507ExponentialFunction::ExponentialFunction(
const ExponentialFunction *func) {
508 memcpy(
this, func,
sizeof(ExponentialFunction));
511void ExponentialFunction::transform(
const double *in,
double *out)
const {
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];
539StitchingFunction::StitchingFunction(Object *, Dict *dict) {
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();
625StitchingFunction::StitchingFunction(
const 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));
636StitchingFunction::~StitchingFunction() {
639 for (i = 0; i < k; ++i) {
649void StitchingFunction::transform(
const double *in,
double *out)
const {
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);
723const char *psOpNames[] = {
766#define nPSOps (sizeof(psOpNames) / sizeof(char *))
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];
847GBool PSStack::checkOverflow(
int n) {
849 error(-1,
"Stack overflow in PostScript function");
855GBool PSStack::checkUnderflow() {
856 if (sp == psStackSize) {
857 error(-1,
"Stack underflow in PostScript function");
863GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) {
864 if (stack[sp].type != t1 && stack[sp].type != t2) {
865 error(-1,
"Type mismatch in PostScript function");
871void PSStack::pushBool(GBool booln) {
872 if (checkOverflow()) {
873 stack[--sp].type = psBool;
874 stack[sp].booln = booln;
878void PSStack::pushInt(
int intg) {
879 if (checkOverflow()) {
880 stack[--sp].type = psInt;
881 stack[sp].intg = intg;
885void PSStack::pushReal(
double real) {
886 if (checkOverflow()) {
887 stack[--sp].type = psReal;
888 stack[sp].real = real;
892GBool PSStack::popBool() {
893 if (checkUnderflow() && checkType(psBool, psBool)) {
894 return stack[sp++].booln;
899int PSStack::popInt() {
900 if (checkUnderflow() && checkType(psInt, psInt)) {
901 return stack[sp++].intg;
906double PSStack::popNum() {
909 if (checkUnderflow() && checkType(psInt, psReal)) {
910 ret = (stack[sp].type == psInt) ? (
double)stack[sp].intg : stack[sp].real;
917void PSStack::copy(
int n) {
920 if (!checkOverflow(n)) {
923 for (i = sp + n - 1; i <= sp; ++i) {
924 stack[i - n] = stack[i];
929void 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;
953void PSStack::index(
int i) {
954 if (!checkOverflow()) {
958 stack[sp] = stack[sp + 1 + i];
962 if (!checkUnderflow()) {
968PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
982 error(-1,
"Type 4 function is missing range");
987 if (!funcObj->isStream()) {
988 error(-1,
"Type 4 function isn't a stream");
991 str = funcObj->getStream();
995 if (!(tok = getToken(str)) || tok->cmp(
"{")) {
996 error(-1,
"Expected '{' at start of PostScript function");
1004 if (!parseCode(str, &codePtr)) {
1017PostScriptFunction::PostScriptFunction(
const PostScriptFunction *func) {
1018 memcpy(
this, func,
sizeof(PostScriptFunction));
1019 code = (PSObject *)gmalloc(codeSize *
sizeof(PSObject));
1020 memcpy(code, func->code, codeSize *
sizeof(PSObject));
1023PostScriptFunction::~PostScriptFunction() {
1027void PostScriptFunction::transform(
const double *in,
double *out)
const {
1031 stack =
new PSStack();
1032 for (i = 0; i < m; ++i) {
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];
1051GBool 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;
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;
1171GString *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)) {
1203void PostScriptFunction::resizeCode(
int newSize) {
1204 if (newSize >= codeSize) {
1206 code = (PSObject *)grealloc(code, codeSize *
sizeof(PSObject));
1210void PostScriptFunction::exec(PSStack *stack,
int codePtr)
const {
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();
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");