1 //========================================================================
5 // Copyright 2001-2003 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
) {
384 for (k
= m
- 1; 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
) {
419 //----- initialize the generic stuff
424 error(-1, "Exponential function with more than one input");
429 if (dict
->lookup("C0", &obj1
)->isArray()) {
430 if (hasRange
&& obj1
.arrayGetLength() != n
) {
431 error(-1, "Function's C0 array is wrong length");
434 n
= obj1
.arrayGetLength();
435 for (i
= 0; i
< n
; ++i
) {
436 obj1
.arrayGet(i
, &obj2
);
438 error(-1, "Illegal value in function C0 array");
441 c0
[i
] = obj2
.getNum();
445 if (hasRange
&& n
!= 1) {
446 error(-1, "Function's C0 array is wrong length");
455 if (dict
->lookup("C1", &obj1
)->isArray()) {
456 if (obj1
.arrayGetLength() != n
) {
457 error(-1, "Function's C1 array is wrong length");
460 for (i
= 0; i
< n
; ++i
) {
461 obj1
.arrayGet(i
, &obj2
);
463 error(-1, "Illegal value in function C1 array");
466 c1
[i
] = obj2
.getNum();
471 error(-1, "Function's C1 array is wrong length");
479 if (!dict
->lookup("N", &obj1
)->isNum()) {
480 error(-1, "Function has missing or invalid N");
497 ExponentialFunction::~ExponentialFunction() {
500 ExponentialFunction::ExponentialFunction(ExponentialFunction
*func
) {
501 memcpy(this, func
, sizeof(ExponentialFunction
));
504 void ExponentialFunction::transform(double *in
, double *out
) {
508 if (in
[0] < domain
[0][0]) {
510 } else if (in
[0] > domain
[0][1]) {
515 for (i
= 0; i
< n
; ++i
) {
516 out
[i
] = c0
[i
] + pow(x
, e
) * (c1
[i
] - c0
[i
]);
518 if (out
[i
] < range
[i
][0]) {
519 out
[i
] = range
[i
][0];
520 } else if (out
[i
] > range
[i
][1]) {
521 out
[i
] = range
[i
][1];
528 //------------------------------------------------------------------------
530 //------------------------------------------------------------------------
532 StitchingFunction::StitchingFunction(Object
*funcObj
, Dict
*dict
) {
541 //----- initialize the generic stuff
546 error(-1, "Stitching function with more than one input");
551 if (!dict
->lookup("Functions", &obj1
)->isArray()) {
552 error(-1, "Missing 'Functions' entry in stitching function");
555 k
= obj1
.arrayGetLength();
556 funcs
= (Function
**)gmalloc(k
* sizeof(Function
*));
557 bounds
= (double *)gmalloc((k
+ 1) * sizeof(double));
558 encode
= (double *)gmalloc(2 * k
* sizeof(double));
559 for (i
= 0; i
< k
; ++i
) {
562 for (i
= 0; i
< k
; ++i
) {
563 if (!(funcs
[i
] = Function::parse(obj1
.arrayGet(i
, &obj2
)))) {
566 if (i
> 0 && (funcs
[i
]->getInputSize() != 1 ||
567 funcs
[i
]->getOutputSize() != funcs
[0]->getOutputSize())) {
568 error(-1, "Incompatible subfunctions in stitching function");
576 if (!dict
->lookup("Bounds", &obj1
)->isArray() ||
577 obj1
.arrayGetLength() != k
- 1) {
578 error(-1, "Missing or invalid 'Bounds' entry in stitching function");
581 bounds
[0] = domain
[0][0];
582 for (i
= 1; i
< k
; ++i
) {
583 if (!obj1
.arrayGet(i
- 1, &obj2
)->isNum()) {
584 error(-1, "Invalid type in 'Bounds' array in stitching function");
587 bounds
[i
] = obj2
.getNum();
590 bounds
[k
] = domain
[0][1];
594 if (!dict
->lookup("Encode", &obj1
)->isArray() ||
595 obj1
.arrayGetLength() != 2 * k
) {
596 error(-1, "Missing or invalid 'Encode' entry in stitching function");
599 for (i
= 0; i
< 2 * k
; ++i
) {
600 if (!obj1
.arrayGet(i
, &obj2
)->isNum()) {
601 error(-1, "Invalid type in 'Encode' array in stitching function");
604 encode
[i
] = obj2
.getNum();
618 StitchingFunction::StitchingFunction(StitchingFunction
*func
) {
622 funcs
= (Function
**)gmalloc(k
* sizeof(Function
*));
623 for (i
= 0; i
< k
; ++i
) {
624 funcs
[i
] = func
->funcs
[i
]->copy();
626 bounds
= (double *)gmalloc((k
+ 1) * sizeof(double));
627 memcpy(bounds
, func
->bounds
, (k
+ 1) * sizeof(double));
628 encode
= (double *)gmalloc(2 * k
* sizeof(double));
629 memcpy(encode
, func
->encode
, 2 * k
* sizeof(double));
633 StitchingFunction::~StitchingFunction() {
637 for (i
= 0; i
< k
; ++i
) {
648 void StitchingFunction::transform(double *in
, double *out
) {
652 if (in
[0] < domain
[0][0]) {
654 } else if (in
[0] > domain
[0][1]) {
659 for (i
= 0; i
< k
- 1; ++i
) {
660 if (x
< bounds
[i
+1]) {
664 x
= encode
[2*i
] + ((x
- bounds
[i
]) / (bounds
[i
+1] - bounds
[i
])) *
665 (encode
[2*i
+1] - encode
[2*i
]);
666 funcs
[i
]->transform(&x
, out
);
669 //------------------------------------------------------------------------
670 // PostScriptFunction
671 //------------------------------------------------------------------------
719 // Note: 'if' and 'ifelse' are parsed separately.
720 // The rest are listed here in alphabetical order.
721 // The index in this table is equivalent to the entry in PSOp.
722 char *psOpNames
[] = {
765 #define nPSOps (sizeof(psOpNames) / sizeof(char *))
775 // In the code array, 'if'/'ifelse' operators take up three slots
776 // plus space for the code in the subclause(s).
778 // +---------------------------------+
779 // | psOperator: psOpIf / psOpIfelse |
780 // +---------------------------------+
781 // | psBlock: ptr=<A> |
782 // +---------------------------------+
783 // | psBlock: ptr=<B> |
784 // +---------------------------------+
787 // | psOperator: psOpReturn |
788 // +---------------------------------+
789 // <A> | else clause |
791 // | psOperator: psOpReturn |
792 // +---------------------------------+
795 // For 'if', pointer <A> is present in the code stream but unused.
800 GBool booln
; // boolean (stack only)
801 int intg
; // integer (stack and code)
802 double real
; // real (stack and code)
803 PSOp op
; // operator (code only)
804 int blk
; // if/ifelse block pointer (code only)
808 #define psStackSize 100
813 PSStack() { sp
= psStackSize
; }
814 void pushBool(GBool booln
);
815 void pushInt(int intg
);
816 void pushReal(double real
);
820 GBool
empty() { return sp
== psStackSize
; }
821 GBool
topIsInt() { return sp
< psStackSize
&& stack
[sp
].type
== psInt
; }
822 GBool
topTwoAreInts()
823 { return sp
< psStackSize
- 1 &&
824 stack
[sp
].type
== psInt
&&
825 stack
[sp
+1].type
== psInt
; }
826 GBool
topIsReal() { return sp
< psStackSize
&& stack
[sp
].type
== psReal
; }
827 GBool
topTwoAreNums()
828 { return sp
< psStackSize
- 1 &&
829 (stack
[sp
].type
== psInt
|| stack
[sp
].type
== psReal
) &&
830 (stack
[sp
+1].type
== psInt
|| stack
[sp
+1].type
== psReal
); }
832 void roll(int n
, int j
);
838 GBool
checkOverflow(int n
= 1);
839 GBool
checkUnderflow();
840 GBool
checkType(PSObjectType t1
, PSObjectType t2
);
842 PSObject stack
[psStackSize
];
846 GBool
PSStack::checkOverflow(int n
) {
848 error(-1, "Stack overflow in PostScript function");
854 GBool
PSStack::checkUnderflow() {
855 if (sp
== psStackSize
) {
856 error(-1, "Stack underflow in PostScript function");
862 GBool
PSStack::checkType(PSObjectType t1
, PSObjectType t2
) {
863 if (stack
[sp
].type
!= t1
&& stack
[sp
].type
!= t2
) {
864 error(-1, "Type mismatch in PostScript function");
870 void PSStack::pushBool(GBool booln
) {
871 if (checkOverflow()) {
872 stack
[--sp
].type
= psBool
;
873 stack
[sp
].booln
= booln
;
877 void PSStack::pushInt(int intg
) {
878 if (checkOverflow()) {
879 stack
[--sp
].type
= psInt
;
880 stack
[sp
].intg
= intg
;
884 void PSStack::pushReal(double real
) {
885 if (checkOverflow()) {
886 stack
[--sp
].type
= psReal
;
887 stack
[sp
].real
= real
;
891 GBool
PSStack::popBool() {
892 if (checkUnderflow() && checkType(psBool
, psBool
)) {
893 return stack
[sp
++].booln
;
898 int PSStack::popInt() {
899 if (checkUnderflow() && checkType(psInt
, psInt
)) {
900 return stack
[sp
++].intg
;
905 double PSStack::popNum() {
908 if (checkUnderflow() && checkType(psInt
, psReal
)) {
909 ret
= (stack
[sp
].type
== psInt
) ? (double)stack
[sp
].intg
: stack
[sp
].real
;
916 void PSStack::copy(int n
) {
919 if (!checkOverflow(n
)) {
922 for (i
= sp
+ n
- 1; i
<= sp
; ++i
) {
923 stack
[i
- n
] = stack
[i
];
928 void PSStack::roll(int n
, int j
) {
940 if (n
<= 0 || j
== 0) {
943 for (i
= 0; i
< j
; ++i
) {
945 for (k
= sp
; k
< sp
+ n
- 1; ++k
) {
946 stack
[k
] = stack
[k
+1];
948 stack
[sp
+ n
- 1] = obj
;
952 void PSStack::index(int i
) {
953 if (!checkOverflow()) {
957 stack
[sp
] = stack
[sp
+ 1 + i
];
960 void PSStack::pop() {
961 if (!checkUnderflow()) {
967 PostScriptFunction::PostScriptFunction(Object
*funcObj
, Dict
*dict
) {
976 //----- initialize the generic stuff
981 error(-1, "Type 4 function is missing range");
985 //----- get the stream
986 if (!funcObj
->isStream()) {
987 error(-1, "Type 4 function isn't a stream");
990 str
= funcObj
->getStream();
992 //----- parse the function
994 if (!(tok
= getToken(str
)) || tok
->cmp("{")) {
995 error(-1, "Expected '{' at start of PostScript function");
1003 if (!parseCode(str
, &codePtr
)) {
1016 PostScriptFunction::PostScriptFunction(PostScriptFunction
*func
) {
1017 memcpy(this, func
, sizeof(PostScriptFunction
));
1018 code
= (PSObject
*)gmalloc(codeSize
* sizeof(PSObject
));
1019 memcpy(code
, func
->code
, codeSize
* sizeof(PSObject
));
1022 PostScriptFunction::~PostScriptFunction() {
1026 void PostScriptFunction::transform(double *in
, double *out
) {
1030 stack
= new PSStack();
1031 for (i
= 0; i
< m
; ++i
) {
1032 //~ may need to check for integers here
1033 stack
->pushReal(in
[i
]);
1036 for (i
= n
- 1; i
>= 0; --i
) {
1037 out
[i
] = stack
->popNum();
1038 if (out
[i
] < range
[i
][0]) {
1039 out
[i
] = range
[i
][0];
1040 } else if (out
[i
] > range
[i
][1]) {
1041 out
[i
] = range
[i
][1];
1044 // if (!stack->empty()) {
1045 // error(-1, "Extra values on stack at end of PostScript function");
1050 GBool
PostScriptFunction::parseCode(Stream
*str
, int *codePtr
) {
1058 if (!(tok
= getToken(str
))) {
1059 error(-1, "Unexpected end of PostScript function stream");
1062 p
= tok
->getCString();
1063 if (isdigit(*p
) || *p
== '.' || *p
== '-') {
1065 for (++p
; *p
; ++p
) {
1071 resizeCode(*codePtr
);
1073 code
[*codePtr
].type
= psReal
;
1074 code
[*codePtr
].real
= atof(tok
->getCString());
1076 code
[*codePtr
].type
= psInt
;
1077 code
[*codePtr
].intg
= atoi(tok
->getCString());
1081 } else if (!tok
->cmp("{")) {
1085 resizeCode(opPtr
+ 2);
1086 if (!parseCode(str
, codePtr
)) {
1089 if (!(tok
= getToken(str
))) {
1090 error(-1, "Unexpected end of PostScript function stream");
1093 if (!tok
->cmp("{")) {
1095 if (!parseCode(str
, codePtr
)) {
1099 if (!(tok
= getToken(str
))) {
1100 error(-1, "Unexpected end of PostScript function stream");
1106 if (!tok
->cmp("if")) {
1108 error(-1, "Got 'if' operator with two blocks in PostScript function");
1111 code
[opPtr
].type
= psOperator
;
1112 code
[opPtr
].op
= psOpIf
;
1113 code
[opPtr
+2].type
= psBlock
;
1114 code
[opPtr
+2].blk
= *codePtr
;
1115 } else if (!tok
->cmp("ifelse")) {
1117 error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
1120 code
[opPtr
].type
= psOperator
;
1121 code
[opPtr
].op
= psOpIfelse
;
1122 code
[opPtr
+1].type
= psBlock
;
1123 code
[opPtr
+1].blk
= elsePtr
;
1124 code
[opPtr
+2].type
= psBlock
;
1125 code
[opPtr
+2].blk
= *codePtr
;
1127 error(-1, "Expected if/ifelse operator in PostScript function");
1132 } else if (!tok
->cmp("}")) {
1134 resizeCode(*codePtr
);
1135 code
[*codePtr
].type
= psOperator
;
1136 code
[*codePtr
].op
= psOpReturn
;
1142 // invariant: psOpNames[a] < tok < psOpNames[b]
1145 cmp
= tok
->cmp(psOpNames
[mid
]);
1148 } else if (cmp
< 0) {
1155 error(-1, "Unknown operator '%s' in PostScript function",
1161 resizeCode(*codePtr
);
1162 code
[*codePtr
].type
= psOperator
;
1163 code
[*codePtr
].op
= (PSOp
)a
;
1170 GString
*PostScriptFunction::getToken(Stream
*str
) {
1177 } while (c
!= EOF
&& isspace(c
));
1178 if (c
== '{' || c
== '}') {
1180 } else if (isdigit(c
) || c
== '.' || c
== '-') {
1183 c
= str
->lookChar();
1184 if (c
== EOF
|| !(isdigit(c
) || c
== '.' || c
== '-')) {
1192 c
= str
->lookChar();
1193 if (c
== EOF
|| !isalnum(c
)) {
1202 void PostScriptFunction::resizeCode(int newSize
) {
1203 if (newSize
>= codeSize
) {
1205 code
= (PSObject
*)grealloc(code
, codeSize
* sizeof(PSObject
));
1209 void PostScriptFunction::exec(PSStack
*stack
, int codePtr
) {
1215 switch (code
[codePtr
].type
) {
1217 stack
->pushInt(code
[codePtr
++].intg
);
1220 stack
->pushReal(code
[codePtr
++].real
);
1223 switch (code
[codePtr
++].op
) {
1225 if (stack
->topIsInt()) {
1226 stack
->pushInt(abs(stack
->popInt()));
1228 stack
->pushReal(fabs(stack
->popNum()));
1232 if (stack
->topTwoAreInts()) {
1233 i2
= stack
->popInt();
1234 i1
= stack
->popInt();
1235 stack
->pushInt(i1
+ i2
);
1237 r2
= stack
->popNum();
1238 r1
= stack
->popNum();
1239 stack
->pushReal(r1
+ r2
);
1243 if (stack
->topTwoAreInts()) {
1244 i2
= stack
->popInt();
1245 i1
= stack
->popInt();
1246 stack
->pushInt(i1
& i2
);
1248 b2
= stack
->popBool();
1249 b1
= stack
->popBool();
1250 stack
->pushBool(b1
&& b2
);
1254 r2
= stack
->popNum();
1255 r1
= stack
->popNum();
1256 stack
->pushReal(atan2(r1
, r2
));
1259 i2
= stack
->popInt();
1260 i1
= stack
->popInt();
1262 stack
->pushInt(i1
<< i2
);
1263 } else if (i2
< 0) {
1264 stack
->pushInt((int)((Guint
)i1
>> i2
));
1270 if (!stack
->topIsInt()) {
1271 stack
->pushReal(ceil(stack
->popNum()));
1275 stack
->copy(stack
->popInt());
1278 stack
->pushReal(cos(stack
->popNum()));
1281 if (!stack
->topIsInt()) {
1282 stack
->pushInt((int)stack
->popNum());
1286 if (!stack
->topIsReal()) {
1287 stack
->pushReal(stack
->popNum());
1291 r2
= stack
->popNum();
1292 r1
= stack
->popNum();
1293 stack
->pushReal(r1
/ r2
);
1299 if (stack
->topTwoAreInts()) {
1300 i2
= stack
->popInt();
1301 i1
= stack
->popInt();
1302 stack
->pushBool(i1
== i2
);
1303 } else if (stack
->topTwoAreNums()) {
1304 r2
= stack
->popNum();
1305 r1
= stack
->popNum();
1306 stack
->pushBool(r1
== r2
);
1308 b2
= stack
->popBool();
1309 b1
= stack
->popBool();
1310 stack
->pushBool(b1
== b2
);
1317 r2
= stack
->popNum();
1318 r1
= stack
->popNum();
1319 stack
->pushReal(pow(r1
, r2
));
1322 stack
->pushBool(gFalse
);
1325 if (!stack
->topIsInt()) {
1326 stack
->pushReal(floor(stack
->popNum()));
1330 if (stack
->topTwoAreInts()) {
1331 i2
= stack
->popInt();
1332 i1
= stack
->popInt();
1333 stack
->pushBool(i1
>= i2
);
1335 r2
= stack
->popNum();
1336 r1
= stack
->popNum();
1337 stack
->pushBool(r1
>= r2
);
1341 if (stack
->topTwoAreInts()) {
1342 i2
= stack
->popInt();
1343 i1
= stack
->popInt();
1344 stack
->pushBool(i1
> i2
);
1346 r2
= stack
->popNum();
1347 r1
= stack
->popNum();
1348 stack
->pushBool(r1
> r2
);
1352 i2
= stack
->popInt();
1353 i1
= stack
->popInt();
1354 stack
->pushInt(i1
/ i2
);
1357 stack
->index(stack
->popInt());
1360 if (stack
->topTwoAreInts()) {
1361 i2
= stack
->popInt();
1362 i1
= stack
->popInt();
1363 stack
->pushBool(i1
<= i2
);
1365 r2
= stack
->popNum();
1366 r1
= stack
->popNum();
1367 stack
->pushBool(r1
<= r2
);
1371 stack
->pushReal(log(stack
->popNum()));
1374 stack
->pushReal(log10(stack
->popNum()));
1377 if (stack
->topTwoAreInts()) {
1378 i2
= stack
->popInt();
1379 i1
= stack
->popInt();
1380 stack
->pushBool(i1
< i2
);
1382 r2
= stack
->popNum();
1383 r1
= stack
->popNum();
1384 stack
->pushBool(r1
< r2
);
1388 i2
= stack
->popInt();
1389 i1
= stack
->popInt();
1390 stack
->pushInt(i1
% i2
);
1393 if (stack
->topTwoAreInts()) {
1394 i2
= stack
->popInt();
1395 i1
= stack
->popInt();
1396 //~ should check for out-of-range, and push a real instead
1397 stack
->pushInt(i1
* i2
);
1399 r2
= stack
->popNum();
1400 r1
= stack
->popNum();
1401 stack
->pushReal(r1
* r2
);
1405 if (stack
->topTwoAreInts()) {
1406 i2
= stack
->popInt();
1407 i1
= stack
->popInt();
1408 stack
->pushBool(i1
!= i2
);
1409 } else if (stack
->topTwoAreNums()) {
1410 r2
= stack
->popNum();
1411 r1
= stack
->popNum();
1412 stack
->pushBool(r1
!= r2
);
1414 b2
= stack
->popBool();
1415 b1
= stack
->popBool();
1416 stack
->pushBool(b1
!= b2
);
1420 if (stack
->topIsInt()) {
1421 stack
->pushInt(-stack
->popInt());
1423 stack
->pushReal(-stack
->popNum());
1427 if (stack
->topIsInt()) {
1428 stack
->pushInt(~stack
->popInt());
1430 stack
->pushBool(!stack
->popBool());
1434 if (stack
->topTwoAreInts()) {
1435 i2
= stack
->popInt();
1436 i1
= stack
->popInt();
1437 stack
->pushInt(i1
| i2
);
1439 b2
= stack
->popBool();
1440 b1
= stack
->popBool();
1441 stack
->pushBool(b1
|| b2
);
1448 i2
= stack
->popInt();
1449 i1
= stack
->popInt();
1450 stack
->roll(i1
, i2
);
1453 if (!stack
->topIsInt()) {
1454 r1
= stack
->popNum();
1455 stack
->pushReal((r1
>= 0) ? floor(r1
+ 0.5) : ceil(r1
- 0.5));
1459 stack
->pushReal(sin(stack
->popNum()));
1462 stack
->pushReal(sqrt(stack
->popNum()));
1465 if (stack
->topTwoAreInts()) {
1466 i2
= stack
->popInt();
1467 i1
= stack
->popInt();
1468 stack
->pushInt(i1
- i2
);
1470 r2
= stack
->popNum();
1471 r1
= stack
->popNum();
1472 stack
->pushReal(r1
- r2
);
1476 stack
->pushBool(gTrue
);
1479 if (!stack
->topIsInt()) {
1480 r1
= stack
->popNum();
1481 stack
->pushReal((r1
>= 0) ? floor(r1
) : ceil(r1
));
1485 if (stack
->topTwoAreInts()) {
1486 i2
= stack
->popInt();
1487 i1
= stack
->popInt();
1488 stack
->pushInt(i1
^ i2
);
1490 b2
= stack
->popBool();
1491 b1
= stack
->popBool();
1492 stack
->pushBool(b1
^ b2
);
1496 b1
= stack
->popBool();
1498 exec(stack
, codePtr
+ 2);
1500 codePtr
= code
[codePtr
+ 1].blk
;
1503 b1
= stack
->popBool();
1505 exec(stack
, codePtr
+ 2);
1507 exec(stack
, code
[codePtr
].blk
);
1509 codePtr
= code
[codePtr
+ 1].blk
;
1516 error(-1, "Internal: bad object in PostScript function code");