]>
git.ipfire.org Git - thirdparty/cups.git/blob - pdftops/Function.cxx
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
) {
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 for (i
= 1; i
< m
; ++i
) {
233 idxMul
[i
] = idxMul
[i
-1] * sampleSize
[i
-1];
236 //----- BitsPerSample
237 if (!dict
->lookup("BitsPerSample", &obj1
)->isInt()) {
238 error(-1, "Function has missing or invalid BitsPerSample");
241 sampleBits
= obj1
.getInt();
242 sampleMul
= 1.0 / (double)((1 << sampleBits
) - 1);
246 if (dict
->lookup("Encode", &obj1
)->isArray() &&
247 obj1
.arrayGetLength() == 2*m
) {
248 for (i
= 0; i
< m
; ++i
) {
249 obj1
.arrayGet(2*i
, &obj2
);
251 error(-1, "Illegal value in function encode array");
254 encode
[i
][0] = obj2
.getNum();
256 obj1
.arrayGet(2*i
+1, &obj2
);
258 error(-1, "Illegal value in function encode array");
261 encode
[i
][1] = obj2
.getNum();
265 for (i
= 0; i
< m
; ++i
) {
267 encode
[i
][1] = sampleSize
[i
] - 1;
271 for (i
= 0; i
< m
; ++i
) {
272 inputMul
[i
] = (encode
[i
][1] - encode
[i
][0]) /
273 (domain
[i
][1] - domain
[i
][0]);
277 if (dict
->lookup("Decode", &obj1
)->isArray() &&
278 obj1
.arrayGetLength() == 2*n
) {
279 for (i
= 0; i
< n
; ++i
) {
280 obj1
.arrayGet(2*i
, &obj2
);
282 error(-1, "Illegal value in function decode array");
285 decode
[i
][0] = obj2
.getNum();
287 obj1
.arrayGet(2*i
+1, &obj2
);
289 error(-1, "Illegal value in function decode array");
292 decode
[i
][1] = obj2
.getNum();
296 for (i
= 0; i
< n
; ++i
) {
297 decode
[i
][0] = range
[i
][0];
298 decode
[i
][1] = range
[i
][1];
305 for (i
= 0; i
< m
; ++i
)
306 nSamples
*= sampleSize
[i
];
307 samples
= (double *)gmallocn(nSamples
, sizeof(double));
310 bitMask
= (1 << sampleBits
) - 1;
312 for (i
= 0; i
< nSamples
; ++i
) {
313 if (sampleBits
== 8) {
315 } else if (sampleBits
== 16) {
317 s
= (s
<< 8) + str
->getChar();
318 } else if (sampleBits
== 32) {
320 s
= (s
<< 8) + str
->getChar();
321 s
= (s
<< 8) + str
->getChar();
322 s
= (s
<< 8) + str
->getChar();
324 while (bits
< sampleBits
) {
325 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
328 s
= (buf
>> (bits
- sampleBits
)) & bitMask
;
331 samples
[i
] = (double)s
* sampleMul
;
346 SampledFunction::~SampledFunction() {
352 SampledFunction::SampledFunction(SampledFunction
*func
) {
353 memcpy(this, func
, sizeof(SampledFunction
));
354 samples
= (double *)gmallocn(nSamples
, sizeof(double));
355 memcpy(samples
, func
->samples
, nSamples
* sizeof(double));
358 void SampledFunction::transform(double *in
, double *out
) {
360 int e
[funcMaxInputs
][2];
361 double efrac0
[funcMaxInputs
];
362 double efrac1
[funcMaxInputs
];
363 double s
[1 << funcMaxInputs
];
366 // map input values into sample array
367 for (i
= 0; i
< m
; ++i
) {
368 x
= (in
[i
] - domain
[i
][0]) * inputMul
[i
] + encode
[i
][0];
371 } else if (x
> sampleSize
[i
] - 1) {
372 x
= sampleSize
[i
] - 1;
375 if ((e
[i
][1] = e
[i
][0] + 1) >= sampleSize
[i
]) {
376 // this happens if in[i] = domain[i][1]
379 efrac1
[i
] = x
- e
[i
][0];
380 efrac0
[i
] = 1 - efrac1
[i
];
383 // for each output, do m-linear interpolation
384 for (i
= 0; i
< n
; ++i
) {
386 // pull 2^m values out of the sample array
387 for (j
= 0; j
< (1<<m
); ++j
) {
389 for (k
= 0, t
= j
; k
< m
; ++k
, t
>>= 1) {
390 idx
+= idxMul
[k
] * (e
[k
][t
& 1]);
395 // do m sets of interpolations
396 for (j
= 0, t
= (1<<m
); j
< m
; ++j
, t
>>= 1) {
397 for (k
= 0; k
< t
; k
+= 2) {
398 s
[k
>> 1] = efrac0
[j
] * s
[k
] + efrac1
[j
] * s
[k
+1];
402 // map output value to range
403 out
[i
] = s
[0] * (decode
[i
][1] - decode
[i
][0]) + decode
[i
][0];
404 if (out
[i
] < range
[i
][0]) {
405 out
[i
] = range
[i
][0];
406 } else if (out
[i
] > range
[i
][1]) {
407 out
[i
] = range
[i
][1];
412 //------------------------------------------------------------------------
413 // ExponentialFunction
414 //------------------------------------------------------------------------
416 ExponentialFunction::ExponentialFunction(Object
*funcObj
, Dict
*dict
) {
422 //----- initialize the generic stuff
427 error(-1, "Exponential function with more than one input");
432 if (dict
->lookup("C0", &obj1
)->isArray()) {
433 if (hasRange
&& obj1
.arrayGetLength() != n
) {
434 error(-1, "Function's C0 array is wrong length");
437 n
= obj1
.arrayGetLength();
438 for (i
= 0; i
< n
; ++i
) {
439 obj1
.arrayGet(i
, &obj2
);
441 error(-1, "Illegal value in function C0 array");
444 c0
[i
] = obj2
.getNum();
448 if (hasRange
&& n
!= 1) {
449 error(-1, "Function's C0 array is wrong length");
458 if (dict
->lookup("C1", &obj1
)->isArray()) {
459 if (obj1
.arrayGetLength() != n
) {
460 error(-1, "Function's C1 array is wrong length");
463 for (i
= 0; i
< n
; ++i
) {
464 obj1
.arrayGet(i
, &obj2
);
466 error(-1, "Illegal value in function C1 array");
469 c1
[i
] = obj2
.getNum();
474 error(-1, "Function's C1 array is wrong length");
482 if (!dict
->lookup("N", &obj1
)->isNum()) {
483 error(-1, "Function has missing or invalid N");
500 ExponentialFunction::~ExponentialFunction() {
503 ExponentialFunction::ExponentialFunction(ExponentialFunction
*func
) {
504 memcpy(this, func
, sizeof(ExponentialFunction
));
507 void ExponentialFunction::transform(double *in
, double *out
) {
511 if (in
[0] < domain
[0][0]) {
513 } else if (in
[0] > domain
[0][1]) {
518 for (i
= 0; i
< n
; ++i
) {
519 out
[i
] = c0
[i
] + pow(x
, e
) * (c1
[i
] - c0
[i
]);
521 if (out
[i
] < range
[i
][0]) {
522 out
[i
] = range
[i
][0];
523 } else if (out
[i
] > range
[i
][1]) {
524 out
[i
] = range
[i
][1];
531 //------------------------------------------------------------------------
533 //------------------------------------------------------------------------
535 StitchingFunction::StitchingFunction(Object
*funcObj
, Dict
*dict
) {
544 //----- initialize the generic stuff
549 error(-1, "Stitching function with more than one input");
554 if (!dict
->lookup("Functions", &obj1
)->isArray()) {
555 error(-1, "Missing 'Functions' entry in stitching function");
558 k
= obj1
.arrayGetLength();
559 funcs
= (Function
**)gmallocn(k
, sizeof(Function
*));
560 bounds
= (double *)gmallocn(k
+ 1, sizeof(double));
561 encode
= (double *)gmallocn(2 * k
, sizeof(double));
562 for (i
= 0; i
< k
; ++i
) {
565 for (i
= 0; i
< k
; ++i
) {
566 if (!(funcs
[i
] = Function::parse(obj1
.arrayGet(i
, &obj2
)))) {
569 if (i
> 0 && (funcs
[i
]->getInputSize() != 1 ||
570 funcs
[i
]->getOutputSize() != funcs
[0]->getOutputSize())) {
571 error(-1, "Incompatible subfunctions in stitching function");
579 if (!dict
->lookup("Bounds", &obj1
)->isArray() ||
580 obj1
.arrayGetLength() != k
- 1) {
581 error(-1, "Missing or invalid 'Bounds' entry in stitching function");
584 bounds
[0] = domain
[0][0];
585 for (i
= 1; i
< k
; ++i
) {
586 if (!obj1
.arrayGet(i
- 1, &obj2
)->isNum()) {
587 error(-1, "Invalid type in 'Bounds' array in stitching function");
590 bounds
[i
] = obj2
.getNum();
593 bounds
[k
] = domain
[0][1];
597 if (!dict
->lookup("Encode", &obj1
)->isArray() ||
598 obj1
.arrayGetLength() != 2 * k
) {
599 error(-1, "Missing or invalid 'Encode' entry in stitching function");
602 for (i
= 0; i
< 2 * k
; ++i
) {
603 if (!obj1
.arrayGet(i
, &obj2
)->isNum()) {
604 error(-1, "Invalid type in 'Encode' array in stitching function");
607 encode
[i
] = obj2
.getNum();
621 StitchingFunction::StitchingFunction(StitchingFunction
*func
) {
625 funcs
= (Function
**)gmallocn(k
, sizeof(Function
*));
626 for (i
= 0; i
< k
; ++i
) {
627 funcs
[i
] = func
->funcs
[i
]->copy();
629 bounds
= (double *)gmallocn(k
+ 1, sizeof(double));
630 memcpy(bounds
, func
->bounds
, (k
+ 1) * sizeof(double));
631 encode
= (double *)gmallocn(2 * k
, sizeof(double));
632 memcpy(encode
, func
->encode
, 2 * k
* sizeof(double));
636 StitchingFunction::~StitchingFunction() {
640 for (i
= 0; i
< k
; ++i
) {
651 void StitchingFunction::transform(double *in
, double *out
) {
655 if (in
[0] < domain
[0][0]) {
657 } else if (in
[0] > domain
[0][1]) {
662 for (i
= 0; i
< k
- 1; ++i
) {
663 if (x
< bounds
[i
+1]) {
667 x
= encode
[2*i
] + ((x
- bounds
[i
]) / (bounds
[i
+1] - bounds
[i
])) *
668 (encode
[2*i
+1] - encode
[2*i
]);
669 funcs
[i
]->transform(&x
, out
);
672 //------------------------------------------------------------------------
673 // PostScriptFunction
674 //------------------------------------------------------------------------
722 // Note: 'if' and 'ifelse' are parsed separately.
723 // The rest are listed here in alphabetical order.
724 // The index in this table is equivalent to the entry in PSOp.
725 char *psOpNames
[] = {
768 #define nPSOps (sizeof(psOpNames) / sizeof(char *))
778 // In the code array, 'if'/'ifelse' operators take up three slots
779 // plus space for the code in the subclause(s).
781 // +---------------------------------+
782 // | psOperator: psOpIf / psOpIfelse |
783 // +---------------------------------+
784 // | psBlock: ptr=<A> |
785 // +---------------------------------+
786 // | psBlock: ptr=<B> |
787 // +---------------------------------+
790 // | psOperator: psOpReturn |
791 // +---------------------------------+
792 // <A> | else clause |
794 // | psOperator: psOpReturn |
795 // +---------------------------------+
798 // For 'if', pointer <A> is present in the code stream but unused.
803 GBool booln
; // boolean (stack only)
804 int intg
; // integer (stack and code)
805 double real
; // real (stack and code)
806 PSOp op
; // operator (code only)
807 int blk
; // if/ifelse block pointer (code only)
811 #define psStackSize 100
816 PSStack() { sp
= psStackSize
; }
817 void pushBool(GBool booln
);
818 void pushInt(int intg
);
819 void pushReal(double real
);
823 GBool
empty() { return sp
== psStackSize
; }
824 GBool
topIsInt() { return sp
< psStackSize
&& stack
[sp
].type
== psInt
; }
825 GBool
topTwoAreInts()
826 { return sp
< psStackSize
- 1 &&
827 stack
[sp
].type
== psInt
&&
828 stack
[sp
+1].type
== psInt
; }
829 GBool
topIsReal() { return sp
< psStackSize
&& stack
[sp
].type
== psReal
; }
830 GBool
topTwoAreNums()
831 { return sp
< psStackSize
- 1 &&
832 (stack
[sp
].type
== psInt
|| stack
[sp
].type
== psReal
) &&
833 (stack
[sp
+1].type
== psInt
|| stack
[sp
+1].type
== psReal
); }
835 void roll(int n
, int j
);
841 GBool
checkOverflow(int n
= 1);
842 GBool
checkUnderflow();
843 GBool
checkType(PSObjectType t1
, PSObjectType t2
);
845 PSObject stack
[psStackSize
];
849 GBool
PSStack::checkOverflow(int n
) {
851 error(-1, "Stack overflow in PostScript function");
857 GBool
PSStack::checkUnderflow() {
858 if (sp
== psStackSize
) {
859 error(-1, "Stack underflow in PostScript function");
865 GBool
PSStack::checkType(PSObjectType t1
, PSObjectType t2
) {
866 if (stack
[sp
].type
!= t1
&& stack
[sp
].type
!= t2
) {
867 error(-1, "Type mismatch in PostScript function");
873 void PSStack::pushBool(GBool booln
) {
874 if (checkOverflow()) {
875 stack
[--sp
].type
= psBool
;
876 stack
[sp
].booln
= booln
;
880 void PSStack::pushInt(int intg
) {
881 if (checkOverflow()) {
882 stack
[--sp
].type
= psInt
;
883 stack
[sp
].intg
= intg
;
887 void PSStack::pushReal(double real
) {
888 if (checkOverflow()) {
889 stack
[--sp
].type
= psReal
;
890 stack
[sp
].real
= real
;
894 GBool
PSStack::popBool() {
895 if (checkUnderflow() && checkType(psBool
, psBool
)) {
896 return stack
[sp
++].booln
;
901 int PSStack::popInt() {
902 if (checkUnderflow() && checkType(psInt
, psInt
)) {
903 return stack
[sp
++].intg
;
908 double PSStack::popNum() {
911 if (checkUnderflow() && checkType(psInt
, psReal
)) {
912 ret
= (stack
[sp
].type
== psInt
) ? (double)stack
[sp
].intg
: stack
[sp
].real
;
919 void PSStack::copy(int n
) {
922 if (sp
+ n
> psStackSize
) {
923 error(-1, "Stack underflow in PostScript function");
926 if (!checkOverflow(n
)) {
929 for (i
= sp
+ n
- 1; i
>= sp
; --i
) {
930 stack
[i
- n
] = stack
[i
];
935 void PSStack::roll(int n
, int j
) {
947 if (n
<= 0 || j
== 0) {
950 for (i
= 0; i
< j
; ++i
) {
952 for (k
= sp
; k
< sp
+ n
- 1; ++k
) {
953 stack
[k
] = stack
[k
+1];
955 stack
[sp
+ n
- 1] = obj
;
959 void PSStack::index(int i
) {
960 if (!checkOverflow()) {
964 stack
[sp
] = stack
[sp
+ 1 + i
];
967 void PSStack::pop() {
968 if (!checkUnderflow()) {
974 PostScriptFunction::PostScriptFunction(Object
*funcObj
, Dict
*dict
) {
983 //----- initialize the generic stuff
988 error(-1, "Type 4 function is missing range");
992 //----- get the stream
993 if (!funcObj
->isStream()) {
994 error(-1, "Type 4 function isn't a stream");
997 str
= funcObj
->getStream();
999 //----- parse the function
1000 codeString
= new GString();
1002 if (!(tok
= getToken(str
)) || tok
->cmp("{")) {
1003 error(-1, "Expected '{' at start of PostScript function");
1011 if (!parseCode(str
, &codePtr
)) {
1024 PostScriptFunction::PostScriptFunction(PostScriptFunction
*func
) {
1025 memcpy(this, func
, sizeof(PostScriptFunction
));
1026 code
= (PSObject
*)gmallocn(codeSize
, sizeof(PSObject
));
1027 memcpy(code
, func
->code
, codeSize
* sizeof(PSObject
));
1028 codeString
= func
->codeString
->copy();
1031 PostScriptFunction::~PostScriptFunction() {
1036 void PostScriptFunction::transform(double *in
, double *out
) {
1040 stack
= new PSStack();
1041 for (i
= 0; i
< m
; ++i
) {
1042 //~ may need to check for integers here
1043 stack
->pushReal(in
[i
]);
1046 for (i
= n
- 1; i
>= 0; --i
) {
1047 out
[i
] = stack
->popNum();
1048 if (out
[i
] < range
[i
][0]) {
1049 out
[i
] = range
[i
][0];
1050 } else if (out
[i
] > range
[i
][1]) {
1051 out
[i
] = range
[i
][1];
1054 // if (!stack->empty()) {
1055 // error(-1, "Extra values on stack at end of PostScript function");
1060 GBool
PostScriptFunction::parseCode(Stream
*str
, int *codePtr
) {
1068 if (!(tok
= getToken(str
))) {
1069 error(-1, "Unexpected end of PostScript function stream");
1072 p
= tok
->getCString();
1073 if (isdigit(*p
) || *p
== '.' || *p
== '-') {
1075 for (++p
; *p
; ++p
) {
1081 resizeCode(*codePtr
);
1083 code
[*codePtr
].type
= psReal
;
1084 code
[*codePtr
].real
= atof(tok
->getCString());
1086 code
[*codePtr
].type
= psInt
;
1087 code
[*codePtr
].intg
= atoi(tok
->getCString());
1091 } else if (!tok
->cmp("{")) {
1095 resizeCode(opPtr
+ 2);
1096 if (!parseCode(str
, codePtr
)) {
1099 if (!(tok
= getToken(str
))) {
1100 error(-1, "Unexpected end of PostScript function stream");
1103 if (!tok
->cmp("{")) {
1105 if (!parseCode(str
, codePtr
)) {
1109 if (!(tok
= getToken(str
))) {
1110 error(-1, "Unexpected end of PostScript function stream");
1116 if (!tok
->cmp("if")) {
1118 error(-1, "Got 'if' operator with two blocks in PostScript function");
1121 code
[opPtr
].type
= psOperator
;
1122 code
[opPtr
].op
= psOpIf
;
1123 code
[opPtr
+2].type
= psBlock
;
1124 code
[opPtr
+2].blk
= *codePtr
;
1125 } else if (!tok
->cmp("ifelse")) {
1127 error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
1130 code
[opPtr
].type
= psOperator
;
1131 code
[opPtr
].op
= psOpIfelse
;
1132 code
[opPtr
+1].type
= psBlock
;
1133 code
[opPtr
+1].blk
= elsePtr
;
1134 code
[opPtr
+2].type
= psBlock
;
1135 code
[opPtr
+2].blk
= *codePtr
;
1137 error(-1, "Expected if/ifelse operator in PostScript function");
1142 } else if (!tok
->cmp("}")) {
1144 resizeCode(*codePtr
);
1145 code
[*codePtr
].type
= psOperator
;
1146 code
[*codePtr
].op
= psOpReturn
;
1152 // invariant: psOpNames[a] < tok < psOpNames[b]
1156 cmp
= tok
->cmp(psOpNames
[mid
]);
1159 } else if (cmp
< 0) {
1166 error(-1, "Unknown operator '%s' in PostScript function",
1172 resizeCode(*codePtr
);
1173 code
[*codePtr
].type
= psOperator
;
1174 code
[*codePtr
].op
= (PSOp
)a
;
1181 GString
*PostScriptFunction::getToken(Stream
*str
) {
1189 codeString
->append(c
);
1191 } while (c
!= EOF
&& isspace(c
));
1192 if (c
== '{' || c
== '}') {
1194 } else if (isdigit(c
) || c
== '.' || c
== '-') {
1197 c
= str
->lookChar();
1198 if (c
== EOF
|| !(isdigit(c
) || c
== '.' || c
== '-')) {
1202 codeString
->append(c
);
1207 c
= str
->lookChar();
1208 if (c
== EOF
|| !isalnum(c
)) {
1212 codeString
->append(c
);
1218 void PostScriptFunction::resizeCode(int newSize
) {
1219 if (newSize
>= codeSize
) {
1221 code
= (PSObject
*)greallocn(code
, codeSize
, sizeof(PSObject
));
1225 void PostScriptFunction::exec(PSStack
*stack
, int codePtr
) {
1231 switch (code
[codePtr
].type
) {
1233 stack
->pushInt(code
[codePtr
++].intg
);
1236 stack
->pushReal(code
[codePtr
++].real
);
1239 switch (code
[codePtr
++].op
) {
1241 if (stack
->topIsInt()) {
1242 stack
->pushInt(abs(stack
->popInt()));
1244 stack
->pushReal(fabs(stack
->popNum()));
1248 if (stack
->topTwoAreInts()) {
1249 i2
= stack
->popInt();
1250 i1
= stack
->popInt();
1251 stack
->pushInt(i1
+ i2
);
1253 r2
= stack
->popNum();
1254 r1
= stack
->popNum();
1255 stack
->pushReal(r1
+ r2
);
1259 if (stack
->topTwoAreInts()) {
1260 i2
= stack
->popInt();
1261 i1
= stack
->popInt();
1262 stack
->pushInt(i1
& i2
);
1264 b2
= stack
->popBool();
1265 b1
= stack
->popBool();
1266 stack
->pushBool(b1
&& b2
);
1270 r2
= stack
->popNum();
1271 r1
= stack
->popNum();
1272 stack
->pushReal(atan2(r1
, r2
));
1275 i2
= stack
->popInt();
1276 i1
= stack
->popInt();
1278 stack
->pushInt(i1
<< i2
);
1279 } else if (i2
< 0) {
1280 stack
->pushInt((int)((Guint
)i1
>> i2
));
1286 if (!stack
->topIsInt()) {
1287 stack
->pushReal(ceil(stack
->popNum()));
1291 stack
->copy(stack
->popInt());
1294 stack
->pushReal(cos(stack
->popNum()));
1297 if (!stack
->topIsInt()) {
1298 stack
->pushInt((int)stack
->popNum());
1302 if (!stack
->topIsReal()) {
1303 stack
->pushReal(stack
->popNum());
1307 r2
= stack
->popNum();
1308 r1
= stack
->popNum();
1309 stack
->pushReal(r1
/ r2
);
1315 if (stack
->topTwoAreInts()) {
1316 i2
= stack
->popInt();
1317 i1
= stack
->popInt();
1318 stack
->pushBool(i1
== i2
);
1319 } else if (stack
->topTwoAreNums()) {
1320 r2
= stack
->popNum();
1321 r1
= stack
->popNum();
1322 stack
->pushBool(r1
== r2
);
1324 b2
= stack
->popBool();
1325 b1
= stack
->popBool();
1326 stack
->pushBool(b1
== b2
);
1333 r2
= stack
->popNum();
1334 r1
= stack
->popNum();
1335 stack
->pushReal(pow(r1
, r2
));
1338 stack
->pushBool(gFalse
);
1341 if (!stack
->topIsInt()) {
1342 stack
->pushReal(floor(stack
->popNum()));
1346 if (stack
->topTwoAreInts()) {
1347 i2
= stack
->popInt();
1348 i1
= stack
->popInt();
1349 stack
->pushBool(i1
>= i2
);
1351 r2
= stack
->popNum();
1352 r1
= stack
->popNum();
1353 stack
->pushBool(r1
>= r2
);
1357 if (stack
->topTwoAreInts()) {
1358 i2
= stack
->popInt();
1359 i1
= stack
->popInt();
1360 stack
->pushBool(i1
> i2
);
1362 r2
= stack
->popNum();
1363 r1
= stack
->popNum();
1364 stack
->pushBool(r1
> r2
);
1368 i2
= stack
->popInt();
1369 i1
= stack
->popInt();
1370 stack
->pushInt(i1
/ i2
);
1373 stack
->index(stack
->popInt());
1376 if (stack
->topTwoAreInts()) {
1377 i2
= stack
->popInt();
1378 i1
= stack
->popInt();
1379 stack
->pushBool(i1
<= i2
);
1381 r2
= stack
->popNum();
1382 r1
= stack
->popNum();
1383 stack
->pushBool(r1
<= r2
);
1387 stack
->pushReal(log(stack
->popNum()));
1390 stack
->pushReal(log10(stack
->popNum()));
1393 if (stack
->topTwoAreInts()) {
1394 i2
= stack
->popInt();
1395 i1
= stack
->popInt();
1396 stack
->pushBool(i1
< i2
);
1398 r2
= stack
->popNum();
1399 r1
= stack
->popNum();
1400 stack
->pushBool(r1
< r2
);
1404 i2
= stack
->popInt();
1405 i1
= stack
->popInt();
1406 stack
->pushInt(i1
% i2
);
1409 if (stack
->topTwoAreInts()) {
1410 i2
= stack
->popInt();
1411 i1
= stack
->popInt();
1412 //~ should check for out-of-range, and push a real instead
1413 stack
->pushInt(i1
* i2
);
1415 r2
= stack
->popNum();
1416 r1
= stack
->popNum();
1417 stack
->pushReal(r1
* r2
);
1421 if (stack
->topTwoAreInts()) {
1422 i2
= stack
->popInt();
1423 i1
= stack
->popInt();
1424 stack
->pushBool(i1
!= i2
);
1425 } else if (stack
->topTwoAreNums()) {
1426 r2
= stack
->popNum();
1427 r1
= stack
->popNum();
1428 stack
->pushBool(r1
!= r2
);
1430 b2
= stack
->popBool();
1431 b1
= stack
->popBool();
1432 stack
->pushBool(b1
!= b2
);
1436 if (stack
->topIsInt()) {
1437 stack
->pushInt(-stack
->popInt());
1439 stack
->pushReal(-stack
->popNum());
1443 if (stack
->topIsInt()) {
1444 stack
->pushInt(~stack
->popInt());
1446 stack
->pushBool(!stack
->popBool());
1450 if (stack
->topTwoAreInts()) {
1451 i2
= stack
->popInt();
1452 i1
= stack
->popInt();
1453 stack
->pushInt(i1
| i2
);
1455 b2
= stack
->popBool();
1456 b1
= stack
->popBool();
1457 stack
->pushBool(b1
|| b2
);
1464 i2
= stack
->popInt();
1465 i1
= stack
->popInt();
1466 stack
->roll(i1
, i2
);
1469 if (!stack
->topIsInt()) {
1470 r1
= stack
->popNum();
1471 stack
->pushReal((r1
>= 0) ? floor(r1
+ 0.5) : ceil(r1
- 0.5));
1475 stack
->pushReal(sin(stack
->popNum()));
1478 stack
->pushReal(sqrt(stack
->popNum()));
1481 if (stack
->topTwoAreInts()) {
1482 i2
= stack
->popInt();
1483 i1
= stack
->popInt();
1484 stack
->pushInt(i1
- i2
);
1486 r2
= stack
->popNum();
1487 r1
= stack
->popNum();
1488 stack
->pushReal(r1
- r2
);
1492 stack
->pushBool(gTrue
);
1495 if (!stack
->topIsInt()) {
1496 r1
= stack
->popNum();
1497 stack
->pushReal((r1
>= 0) ? floor(r1
) : ceil(r1
));
1501 if (stack
->topTwoAreInts()) {
1502 i2
= stack
->popInt();
1503 i1
= stack
->popInt();
1504 stack
->pushInt(i1
^ i2
);
1506 b2
= stack
->popBool();
1507 b1
= stack
->popBool();
1508 stack
->pushBool(b1
^ b2
);
1512 b1
= stack
->popBool();
1514 exec(stack
, codePtr
+ 2);
1516 codePtr
= code
[codePtr
+ 1].blk
;
1519 b1
= stack
->popBool();
1521 exec(stack
, codePtr
+ 2);
1523 exec(stack
, code
[codePtr
].blk
);
1525 codePtr
= code
[codePtr
+ 1].blk
;
1532 error(-1, "Internal: bad object in PostScript function code");