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(xObject
*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(xObject
*funcObj
, Dict
*dict
) {
200 //----- initialize the generic stuff
205 error(-1, "Type 0 function is missing range");
208 if (m
> sampledFuncMaxInputs
) {
209 error(-1, "Sampled functions with more than %d inputs are unsupported",
210 sampledFuncMaxInputs
);
215 sBuf
= (double *)gmallocn(1 << m
, sizeof(double));
217 //----- get the stream
218 if (!funcObj
->isStream()) {
219 error(-1, "Type 0 function isn't a stream");
222 str
= funcObj
->getStream();
225 if (!dict
->lookup("Size", &obj1
)->isArray() ||
226 obj1
.arrayGetLength() != m
) {
227 error(-1, "Function has missing or invalid size array");
230 for (i
= 0; i
< m
; ++i
) {
231 obj1
.arrayGet(i
, &obj2
);
233 error(-1, "Illegal value in function size array");
236 sampleSize
[i
] = obj2
.getInt();
241 for (i
= 1; i
< m
; ++i
) {
242 idxMul
[i
] = idxMul
[i
-1] * sampleSize
[i
-1];
245 //----- BitsPerSample
246 if (!dict
->lookup("BitsPerSample", &obj1
)->isInt()) {
247 error(-1, "Function has missing or invalid BitsPerSample");
250 sampleBits
= obj1
.getInt();
251 sampleMul
= 1.0 / (pow(2.0, (double)sampleBits
) - 1);
255 if (dict
->lookup("Encode", &obj1
)->isArray() &&
256 obj1
.arrayGetLength() == 2*m
) {
257 for (i
= 0; i
< m
; ++i
) {
258 obj1
.arrayGet(2*i
, &obj2
);
260 error(-1, "Illegal value in function encode array");
263 encode
[i
][0] = obj2
.getNum();
265 obj1
.arrayGet(2*i
+1, &obj2
);
267 error(-1, "Illegal value in function encode array");
270 encode
[i
][1] = obj2
.getNum();
274 for (i
= 0; i
< m
; ++i
) {
276 encode
[i
][1] = sampleSize
[i
] - 1;
280 for (i
= 0; i
< m
; ++i
) {
281 inputMul
[i
] = (encode
[i
][1] - encode
[i
][0]) /
282 (domain
[i
][1] - domain
[i
][0]);
286 if (dict
->lookup("Decode", &obj1
)->isArray() &&
287 obj1
.arrayGetLength() == 2*n
) {
288 for (i
= 0; i
< n
; ++i
) {
289 obj1
.arrayGet(2*i
, &obj2
);
291 error(-1, "Illegal value in function decode array");
294 decode
[i
][0] = obj2
.getNum();
296 obj1
.arrayGet(2*i
+1, &obj2
);
298 error(-1, "Illegal value in function decode array");
301 decode
[i
][1] = obj2
.getNum();
305 for (i
= 0; i
< n
; ++i
) {
306 decode
[i
][0] = range
[i
][0];
307 decode
[i
][1] = range
[i
][1];
314 for (i
= 0; i
< m
; ++i
)
315 nSamples
*= sampleSize
[i
];
316 samples
= (double *)gmallocn(nSamples
, sizeof(double));
319 bitMask
= (1 << sampleBits
) - 1;
321 for (i
= 0; i
< nSamples
; ++i
) {
322 if (sampleBits
== 8) {
324 } else if (sampleBits
== 16) {
326 s
= (s
<< 8) + str
->getChar();
327 } else if (sampleBits
== 32) {
329 s
= (s
<< 8) + str
->getChar();
330 s
= (s
<< 8) + str
->getChar();
331 s
= (s
<< 8) + str
->getChar();
333 while (bits
< sampleBits
) {
334 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
337 s
= (buf
>> (bits
- sampleBits
)) & bitMask
;
340 samples
[i
] = (double)s
* sampleMul
;
355 SampledFunction::~SampledFunction() {
364 SampledFunction::SampledFunction(SampledFunction
*func
) {
365 memcpy(this, func
, sizeof(SampledFunction
));
366 samples
= (double *)gmallocn(nSamples
, sizeof(double));
367 memcpy(samples
, func
->samples
, nSamples
* sizeof(double));
368 sBuf
= (double *)gmallocn(1 << m
, sizeof(double));
371 void SampledFunction::transform(double *in
, double *out
) {
373 int e
[funcMaxInputs
][2];
374 double efrac0
[funcMaxInputs
];
375 double efrac1
[funcMaxInputs
];
378 // map input values into sample array
379 for (i
= 0; i
< m
; ++i
) {
380 x
= (in
[i
] - domain
[i
][0]) * inputMul
[i
] + encode
[i
][0];
383 } else if (x
> sampleSize
[i
] - 1) {
384 x
= sampleSize
[i
] - 1;
387 if ((e
[i
][1] = e
[i
][0] + 1) >= sampleSize
[i
]) {
388 // this happens if in[i] = domain[i][1]
391 efrac1
[i
] = x
- e
[i
][0];
392 efrac0
[i
] = 1 - efrac1
[i
];
395 // for each output, do m-linear interpolation
396 for (i
= 0; i
< n
; ++i
) {
398 // pull 2^m values out of the sample array
399 for (j
= 0; j
< (1<<m
); ++j
) {
401 for (k
= 0, t
= j
; k
< m
; ++k
, t
>>= 1) {
402 idx
+= idxMul
[k
] * (e
[k
][t
& 1]);
404 sBuf
[j
] = samples
[idx
];
407 // do m sets of interpolations
408 for (j
= 0, t
= (1<<m
); j
< m
; ++j
, t
>>= 1) {
409 for (k
= 0; k
< t
; k
+= 2) {
410 sBuf
[k
>> 1] = efrac0
[j
] * sBuf
[k
] + efrac1
[j
] * sBuf
[k
+1];
414 // map output value to range
415 out
[i
] = sBuf
[0] * (decode
[i
][1] - decode
[i
][0]) + decode
[i
][0];
416 if (out
[i
] < range
[i
][0]) {
417 out
[i
] = range
[i
][0];
418 } else if (out
[i
] > range
[i
][1]) {
419 out
[i
] = range
[i
][1];
424 //------------------------------------------------------------------------
425 // ExponentialFunction
426 //------------------------------------------------------------------------
428 ExponentialFunction::ExponentialFunction(xObject
*funcObj
, Dict
*dict
) {
434 //----- initialize the generic stuff
439 error(-1, "Exponential function with more than one input");
444 if (dict
->lookup("C0", &obj1
)->isArray()) {
445 if (hasRange
&& obj1
.arrayGetLength() != n
) {
446 error(-1, "Function's C0 array is wrong length");
449 n
= obj1
.arrayGetLength();
450 for (i
= 0; i
< n
; ++i
) {
451 obj1
.arrayGet(i
, &obj2
);
453 error(-1, "Illegal value in function C0 array");
456 c0
[i
] = obj2
.getNum();
460 if (hasRange
&& n
!= 1) {
461 error(-1, "Function's C0 array is wrong length");
470 if (dict
->lookup("C1", &obj1
)->isArray()) {
471 if (obj1
.arrayGetLength() != n
) {
472 error(-1, "Function's C1 array is wrong length");
475 for (i
= 0; i
< n
; ++i
) {
476 obj1
.arrayGet(i
, &obj2
);
478 error(-1, "Illegal value in function C1 array");
481 c1
[i
] = obj2
.getNum();
486 error(-1, "Function's C1 array is wrong length");
494 if (!dict
->lookup("N", &obj1
)->isNum()) {
495 error(-1, "Function has missing or invalid N");
512 ExponentialFunction::~ExponentialFunction() {
515 ExponentialFunction::ExponentialFunction(ExponentialFunction
*func
) {
516 memcpy(this, func
, sizeof(ExponentialFunction
));
519 void ExponentialFunction::transform(double *in
, double *out
) {
523 if (in
[0] < domain
[0][0]) {
525 } else if (in
[0] > domain
[0][1]) {
530 for (i
= 0; i
< n
; ++i
) {
531 out
[i
] = c0
[i
] + pow(x
, e
) * (c1
[i
] - c0
[i
]);
533 if (out
[i
] < range
[i
][0]) {
534 out
[i
] = range
[i
][0];
535 } else if (out
[i
] > range
[i
][1]) {
536 out
[i
] = range
[i
][1];
543 //------------------------------------------------------------------------
545 //------------------------------------------------------------------------
547 StitchingFunction::StitchingFunction(xObject
*funcObj
, Dict
*dict
) {
557 //----- initialize the generic stuff
562 error(-1, "Stitching function with more than one input");
567 if (!dict
->lookup("Functions", &obj1
)->isArray()) {
568 error(-1, "Missing 'Functions' entry in stitching function");
571 k
= obj1
.arrayGetLength();
572 funcs
= (Function
**)gmallocn(k
, sizeof(Function
*));
573 bounds
= (double *)gmallocn(k
+ 1, sizeof(double));
574 encode
= (double *)gmallocn(2 * k
, sizeof(double));
575 scale
= (double *)gmallocn(k
, sizeof(double));
576 for (i
= 0; i
< k
; ++i
) {
579 for (i
= 0; i
< k
; ++i
) {
580 if (!(funcs
[i
] = Function::parse(obj1
.arrayGet(i
, &obj2
)))) {
583 if (i
> 0 && (funcs
[i
]->getInputSize() != 1 ||
584 funcs
[i
]->getOutputSize() != funcs
[0]->getOutputSize())) {
585 error(-1, "Incompatible subfunctions in stitching function");
593 if (!dict
->lookup("Bounds", &obj1
)->isArray() ||
594 obj1
.arrayGetLength() != k
- 1) {
595 error(-1, "Missing or invalid 'Bounds' entry in stitching function");
598 bounds
[0] = domain
[0][0];
599 for (i
= 1; i
< k
; ++i
) {
600 if (!obj1
.arrayGet(i
- 1, &obj2
)->isNum()) {
601 error(-1, "Invalid type in 'Bounds' array in stitching function");
604 bounds
[i
] = obj2
.getNum();
607 bounds
[k
] = domain
[0][1];
611 if (!dict
->lookup("Encode", &obj1
)->isArray() ||
612 obj1
.arrayGetLength() != 2 * k
) {
613 error(-1, "Missing or invalid 'Encode' entry in stitching function");
616 for (i
= 0; i
< 2 * k
; ++i
) {
617 if (!obj1
.arrayGet(i
, &obj2
)->isNum()) {
618 error(-1, "Invalid type in 'Encode' array in stitching function");
621 encode
[i
] = obj2
.getNum();
626 //----- pre-compute the scale factors
627 for (i
= 0; i
< k
; ++i
) {
628 if (bounds
[i
] == bounds
[i
+1]) {
629 // avoid a divide-by-zero -- in this situation, function i will
630 // never be used anyway
633 scale
[i
] = (encode
[2*i
+1] - encode
[2*i
]) / (bounds
[i
+1] - bounds
[i
]);
646 StitchingFunction::StitchingFunction(StitchingFunction
*func
) {
650 funcs
= (Function
**)gmallocn(k
, sizeof(Function
*));
651 for (i
= 0; i
< k
; ++i
) {
652 funcs
[i
] = func
->funcs
[i
]->copy();
654 bounds
= (double *)gmallocn(k
+ 1, sizeof(double));
655 memcpy(bounds
, func
->bounds
, (k
+ 1) * sizeof(double));
656 encode
= (double *)gmallocn(2 * k
, sizeof(double));
657 memcpy(encode
, func
->encode
, 2 * k
* sizeof(double));
658 scale
= (double *)gmallocn(k
, sizeof(double));
659 memcpy(scale
, func
->scale
, k
* sizeof(double));
663 StitchingFunction::~StitchingFunction() {
667 for (i
= 0; i
< k
; ++i
) {
679 void StitchingFunction::transform(double *in
, double *out
) {
683 if (in
[0] < domain
[0][0]) {
685 } else if (in
[0] > domain
[0][1]) {
690 for (i
= 0; i
< k
- 1; ++i
) {
691 if (x
< bounds
[i
+1]) {
695 x
= encode
[2*i
] + (x
- bounds
[i
]) * scale
[i
];
696 funcs
[i
]->transform(&x
, out
);
699 //------------------------------------------------------------------------
700 // PostScriptFunction
701 //------------------------------------------------------------------------
749 // Note: 'if' and 'ifelse' are parsed separately.
750 // The rest are listed here in alphabetical order.
751 // The index in this table is equivalent to the entry in PSOp.
752 const char *psOpNames
[] = {
795 #define nPSOps (sizeof(psOpNames) / sizeof(char *))
805 // In the code array, 'if'/'ifelse' operators take up three slots
806 // plus space for the code in the subclause(s).
808 // +---------------------------------+
809 // | psOperator: psOpIf / psOpIfelse |
810 // +---------------------------------+
811 // | psBlock: ptr=<A> |
812 // +---------------------------------+
813 // | psBlock: ptr=<B> |
814 // +---------------------------------+
817 // | psOperator: psOpReturn |
818 // +---------------------------------+
819 // <A> | else clause |
821 // | psOperator: psOpReturn |
822 // +---------------------------------+
825 // For 'if', pointer <A> is present in the code stream but unused.
830 GBool booln
; // boolean (stack only)
831 int intg
; // integer (stack and code)
832 double real
; // real (stack and code)
833 PSOp op
; // operator (code only)
834 int blk
; // if/ifelse block pointer (code only)
838 #define psStackSize 100
843 PSStack() { sp
= psStackSize
; }
844 void pushBool(GBool booln
);
845 void pushInt(int intg
);
846 void pushReal(double real
);
850 GBool
empty() { return sp
== psStackSize
; }
851 GBool
topIsInt() { return sp
< psStackSize
&& stack
[sp
].type
== psInt
; }
852 GBool
topTwoAreInts()
853 { return sp
< psStackSize
- 1 &&
854 stack
[sp
].type
== psInt
&&
855 stack
[sp
+1].type
== psInt
; }
856 GBool
topIsReal() { return sp
< psStackSize
&& stack
[sp
].type
== psReal
; }
857 GBool
topTwoAreNums()
858 { return sp
< psStackSize
- 1 &&
859 (stack
[sp
].type
== psInt
|| stack
[sp
].type
== psReal
) &&
860 (stack
[sp
+1].type
== psInt
|| stack
[sp
+1].type
== psReal
); }
862 void roll(int n
, int j
);
868 GBool
checkOverflow(int n
= 1);
869 GBool
checkUnderflow();
870 GBool
checkType(PSObjectType t1
, PSObjectType t2
);
872 PSObject stack
[psStackSize
];
876 GBool
PSStack::checkOverflow(int n
) {
878 error(-1, "Stack overflow in PostScript function");
884 GBool
PSStack::checkUnderflow() {
885 if (sp
== psStackSize
) {
886 error(-1, "Stack underflow in PostScript function");
892 GBool
PSStack::checkType(PSObjectType t1
, PSObjectType t2
) {
893 if (stack
[sp
].type
!= t1
&& stack
[sp
].type
!= t2
) {
894 error(-1, "Type mismatch in PostScript function");
900 void PSStack::pushBool(GBool booln
) {
901 if (checkOverflow()) {
902 stack
[--sp
].type
= psBool
;
903 stack
[sp
].booln
= booln
;
907 void PSStack::pushInt(int intg
) {
908 if (checkOverflow()) {
909 stack
[--sp
].type
= psInt
;
910 stack
[sp
].intg
= intg
;
914 void PSStack::pushReal(double real
) {
915 if (checkOverflow()) {
916 stack
[--sp
].type
= psReal
;
917 stack
[sp
].real
= real
;
921 GBool
PSStack::popBool() {
922 if (checkUnderflow() && checkType(psBool
, psBool
)) {
923 return stack
[sp
++].booln
;
928 int PSStack::popInt() {
929 if (checkUnderflow() && checkType(psInt
, psInt
)) {
930 return stack
[sp
++].intg
;
935 double PSStack::popNum() {
938 if (checkUnderflow() && checkType(psInt
, psReal
)) {
939 ret
= (stack
[sp
].type
== psInt
) ? (double)stack
[sp
].intg
: stack
[sp
].real
;
946 void PSStack::copy(int n
) {
949 if (sp
+ n
> psStackSize
) {
950 error(-1, "Stack underflow in PostScript function");
953 if (!checkOverflow(n
)) {
956 for (i
= sp
+ n
- 1; i
>= sp
; --i
) {
957 stack
[i
- n
] = stack
[i
];
962 void PSStack::roll(int n
, int j
) {
974 if (n
<= 0 || j
== 0) {
977 for (i
= 0; i
< j
; ++i
) {
979 for (k
= sp
; k
< sp
+ n
- 1; ++k
) {
980 stack
[k
] = stack
[k
+1];
982 stack
[sp
+ n
- 1] = obj
;
986 void PSStack::index(int i
) {
987 if (!checkOverflow()) {
991 stack
[sp
] = stack
[sp
+ 1 + i
];
994 void PSStack::pop() {
995 if (!checkUnderflow()) {
1001 PostScriptFunction::PostScriptFunction(xObject
*funcObj
, Dict
*dict
) {
1010 //----- initialize the generic stuff
1015 error(-1, "Type 4 function is missing range");
1019 //----- get the stream
1020 if (!funcObj
->isStream()) {
1021 error(-1, "Type 4 function isn't a stream");
1024 str
= funcObj
->getStream();
1026 //----- parse the function
1027 codeString
= new GString();
1029 if (!(tok
= getToken(str
)) || tok
->cmp("{")) {
1030 error(-1, "Expected '{' at start of PostScript function");
1038 if (!parseCode(str
, &codePtr
)) {
1051 PostScriptFunction::PostScriptFunction(PostScriptFunction
*func
) {
1052 memcpy(this, func
, sizeof(PostScriptFunction
));
1053 code
= (PSObject
*)gmallocn(codeSize
, sizeof(PSObject
));
1054 memcpy(code
, func
->code
, codeSize
* sizeof(PSObject
));
1055 codeString
= func
->codeString
->copy();
1058 PostScriptFunction::~PostScriptFunction() {
1063 void PostScriptFunction::transform(double *in
, double *out
) {
1067 stack
= new PSStack();
1068 for (i
= 0; i
< m
; ++i
) {
1069 //~ may need to check for integers here
1070 stack
->pushReal(in
[i
]);
1073 for (i
= n
- 1; i
>= 0; --i
) {
1074 out
[i
] = stack
->popNum();
1075 if (out
[i
] < range
[i
][0]) {
1076 out
[i
] = range
[i
][0];
1077 } else if (out
[i
] > range
[i
][1]) {
1078 out
[i
] = range
[i
][1];
1081 // if (!stack->empty()) {
1082 // error(-1, "Extra values on stack at end of PostScript function");
1087 GBool
PostScriptFunction::parseCode(Stream
*str
, int *codePtr
) {
1095 if (!(tok
= getToken(str
))) {
1096 error(-1, "Unexpected end of PostScript function stream");
1099 p
= tok
->getCString();
1100 if (isdigit(*p
) || *p
== '.' || *p
== '-') {
1102 for (++p
; *p
; ++p
) {
1108 resizeCode(*codePtr
);
1110 code
[*codePtr
].type
= psReal
;
1111 code
[*codePtr
].real
= atof(tok
->getCString());
1113 code
[*codePtr
].type
= psInt
;
1114 code
[*codePtr
].intg
= atoi(tok
->getCString());
1118 } else if (!tok
->cmp("{")) {
1122 resizeCode(opPtr
+ 2);
1123 if (!parseCode(str
, codePtr
)) {
1126 if (!(tok
= getToken(str
))) {
1127 error(-1, "Unexpected end of PostScript function stream");
1130 if (!tok
->cmp("{")) {
1132 if (!parseCode(str
, codePtr
)) {
1136 if (!(tok
= getToken(str
))) {
1137 error(-1, "Unexpected end of PostScript function stream");
1143 if (!tok
->cmp("if")) {
1145 error(-1, "Got 'if' operator with two blocks in PostScript function");
1148 code
[opPtr
].type
= psOperator
;
1149 code
[opPtr
].op
= psOpIf
;
1150 code
[opPtr
+2].type
= psBlock
;
1151 code
[opPtr
+2].blk
= *codePtr
;
1152 } else if (!tok
->cmp("ifelse")) {
1154 error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
1157 code
[opPtr
].type
= psOperator
;
1158 code
[opPtr
].op
= psOpIfelse
;
1159 code
[opPtr
+1].type
= psBlock
;
1160 code
[opPtr
+1].blk
= elsePtr
;
1161 code
[opPtr
+2].type
= psBlock
;
1162 code
[opPtr
+2].blk
= *codePtr
;
1164 error(-1, "Expected if/ifelse operator in PostScript function");
1169 } else if (!tok
->cmp("}")) {
1171 resizeCode(*codePtr
);
1172 code
[*codePtr
].type
= psOperator
;
1173 code
[*codePtr
].op
= psOpReturn
;
1179 // invariant: psOpNames[a] < tok < psOpNames[b]
1182 cmp
= tok
->cmp(psOpNames
[mid
]);
1185 } else if (cmp
< 0) {
1192 error(-1, "Unknown operator '%s' in PostScript function",
1198 resizeCode(*codePtr
);
1199 code
[*codePtr
].type
= psOperator
;
1200 code
[*codePtr
].op
= (PSOp
)a
;
1207 GString
*PostScriptFunction::getToken(Stream
*str
) {
1215 if ((c
= str
->getChar()) == EOF
) {
1218 codeString
->append(c
);
1220 if (c
== '\x0a' || c
== '\x0d') {
1223 } else if (c
== '%') {
1225 } else if (!isspace(c
)) {
1229 if (c
== '{' || c
== '}') {
1231 } else if (isdigit(c
) || c
== '.' || c
== '-') {
1234 c
= str
->lookChar();
1235 if (c
== EOF
|| !(isdigit(c
) || c
== '.' || c
== '-')) {
1239 codeString
->append(c
);
1244 c
= str
->lookChar();
1245 if (c
== EOF
|| !isalnum(c
)) {
1249 codeString
->append(c
);
1255 void PostScriptFunction::resizeCode(int newSize
) {
1256 if (newSize
>= codeSize
) {
1258 code
= (PSObject
*)greallocn(code
, codeSize
, sizeof(PSObject
));
1262 void PostScriptFunction::exec(PSStack
*stack
, int codePtr
) {
1268 switch (code
[codePtr
].type
) {
1270 stack
->pushInt(code
[codePtr
++].intg
);
1273 stack
->pushReal(code
[codePtr
++].real
);
1276 switch (code
[codePtr
++].op
) {
1278 if (stack
->topIsInt()) {
1279 stack
->pushInt(abs(stack
->popInt()));
1281 stack
->pushReal(fabs(stack
->popNum()));
1285 if (stack
->topTwoAreInts()) {
1286 i2
= stack
->popInt();
1287 i1
= stack
->popInt();
1288 stack
->pushInt(i1
+ i2
);
1290 r2
= stack
->popNum();
1291 r1
= stack
->popNum();
1292 stack
->pushReal(r1
+ r2
);
1296 if (stack
->topTwoAreInts()) {
1297 i2
= stack
->popInt();
1298 i1
= stack
->popInt();
1299 stack
->pushInt(i1
& i2
);
1301 b2
= stack
->popBool();
1302 b1
= stack
->popBool();
1303 stack
->pushBool(b1
&& b2
);
1307 r2
= stack
->popNum();
1308 r1
= stack
->popNum();
1309 stack
->pushReal(atan2(r1
, r2
));
1312 i2
= stack
->popInt();
1313 i1
= stack
->popInt();
1315 stack
->pushInt(i1
<< i2
);
1316 } else if (i2
< 0) {
1317 stack
->pushInt((int)((Guint
)i1
>> i2
));
1323 if (!stack
->topIsInt()) {
1324 stack
->pushReal(ceil(stack
->popNum()));
1328 stack
->copy(stack
->popInt());
1331 stack
->pushReal(cos(stack
->popNum()));
1334 if (!stack
->topIsInt()) {
1335 stack
->pushInt((int)stack
->popNum());
1339 if (!stack
->topIsReal()) {
1340 stack
->pushReal(stack
->popNum());
1344 r2
= stack
->popNum();
1345 r1
= stack
->popNum();
1346 stack
->pushReal(r1
/ r2
);
1352 if (stack
->topTwoAreInts()) {
1353 i2
= stack
->popInt();
1354 i1
= stack
->popInt();
1355 stack
->pushBool(i1
== i2
);
1356 } else if (stack
->topTwoAreNums()) {
1357 r2
= stack
->popNum();
1358 r1
= stack
->popNum();
1359 stack
->pushBool(r1
== r2
);
1361 b2
= stack
->popBool();
1362 b1
= stack
->popBool();
1363 stack
->pushBool(b1
== b2
);
1370 r2
= stack
->popNum();
1371 r1
= stack
->popNum();
1372 stack
->pushReal(pow(r1
, r2
));
1375 stack
->pushBool(gFalse
);
1378 if (!stack
->topIsInt()) {
1379 stack
->pushReal(floor(stack
->popNum()));
1383 if (stack
->topTwoAreInts()) {
1384 i2
= stack
->popInt();
1385 i1
= stack
->popInt();
1386 stack
->pushBool(i1
>= i2
);
1388 r2
= stack
->popNum();
1389 r1
= stack
->popNum();
1390 stack
->pushBool(r1
>= r2
);
1394 if (stack
->topTwoAreInts()) {
1395 i2
= stack
->popInt();
1396 i1
= stack
->popInt();
1397 stack
->pushBool(i1
> i2
);
1399 r2
= stack
->popNum();
1400 r1
= stack
->popNum();
1401 stack
->pushBool(r1
> r2
);
1405 i2
= stack
->popInt();
1406 i1
= stack
->popInt();
1407 stack
->pushInt(i1
/ i2
);
1410 stack
->index(stack
->popInt());
1413 if (stack
->topTwoAreInts()) {
1414 i2
= stack
->popInt();
1415 i1
= stack
->popInt();
1416 stack
->pushBool(i1
<= i2
);
1418 r2
= stack
->popNum();
1419 r1
= stack
->popNum();
1420 stack
->pushBool(r1
<= r2
);
1424 stack
->pushReal(log(stack
->popNum()));
1427 stack
->pushReal(log10(stack
->popNum()));
1430 if (stack
->topTwoAreInts()) {
1431 i2
= stack
->popInt();
1432 i1
= stack
->popInt();
1433 stack
->pushBool(i1
< i2
);
1435 r2
= stack
->popNum();
1436 r1
= stack
->popNum();
1437 stack
->pushBool(r1
< r2
);
1441 i2
= stack
->popInt();
1442 i1
= stack
->popInt();
1443 stack
->pushInt(i1
% i2
);
1446 if (stack
->topTwoAreInts()) {
1447 i2
= stack
->popInt();
1448 i1
= stack
->popInt();
1449 //~ should check for out-of-range, and push a real instead
1450 stack
->pushInt(i1
* i2
);
1452 r2
= stack
->popNum();
1453 r1
= stack
->popNum();
1454 stack
->pushReal(r1
* r2
);
1458 if (stack
->topTwoAreInts()) {
1459 i2
= stack
->popInt();
1460 i1
= stack
->popInt();
1461 stack
->pushBool(i1
!= i2
);
1462 } else if (stack
->topTwoAreNums()) {
1463 r2
= stack
->popNum();
1464 r1
= stack
->popNum();
1465 stack
->pushBool(r1
!= r2
);
1467 b2
= stack
->popBool();
1468 b1
= stack
->popBool();
1469 stack
->pushBool(b1
!= b2
);
1473 if (stack
->topIsInt()) {
1474 stack
->pushInt(-stack
->popInt());
1476 stack
->pushReal(-stack
->popNum());
1480 if (stack
->topIsInt()) {
1481 stack
->pushInt(~stack
->popInt());
1483 stack
->pushBool(!stack
->popBool());
1487 if (stack
->topTwoAreInts()) {
1488 i2
= stack
->popInt();
1489 i1
= stack
->popInt();
1490 stack
->pushInt(i1
| i2
);
1492 b2
= stack
->popBool();
1493 b1
= stack
->popBool();
1494 stack
->pushBool(b1
|| b2
);
1501 i2
= stack
->popInt();
1502 i1
= stack
->popInt();
1503 stack
->roll(i1
, i2
);
1506 if (!stack
->topIsInt()) {
1507 r1
= stack
->popNum();
1508 stack
->pushReal((r1
>= 0) ? floor(r1
+ 0.5) : ceil(r1
- 0.5));
1512 stack
->pushReal(sin(stack
->popNum()));
1515 stack
->pushReal(sqrt(stack
->popNum()));
1518 if (stack
->topTwoAreInts()) {
1519 i2
= stack
->popInt();
1520 i1
= stack
->popInt();
1521 stack
->pushInt(i1
- i2
);
1523 r2
= stack
->popNum();
1524 r1
= stack
->popNum();
1525 stack
->pushReal(r1
- r2
);
1529 stack
->pushBool(gTrue
);
1532 if (!stack
->topIsInt()) {
1533 r1
= stack
->popNum();
1534 stack
->pushReal((r1
>= 0) ? floor(r1
) : ceil(r1
));
1538 if (stack
->topTwoAreInts()) {
1539 i2
= stack
->popInt();
1540 i1
= stack
->popInt();
1541 stack
->pushInt(i1
^ i2
);
1543 b2
= stack
->popBool();
1544 b1
= stack
->popBool();
1545 stack
->pushBool(b1
^ b2
);
1549 b1
= stack
->popBool();
1551 exec(stack
, codePtr
+ 2);
1553 codePtr
= code
[codePtr
+ 1].blk
;
1556 b1
= stack
->popBool();
1558 exec(stack
, codePtr
+ 2);
1560 exec(stack
, code
[codePtr
].blk
);
1562 codePtr
= code
[codePtr
+ 1].blk
;
1569 error(-1, "Internal: bad xObject in PostScript function code");