00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifdef __GNUC__
00010 #pragma implementation
00011 #endif
00012
00013 #include <aconf.h>
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include <ctype.h>
00017 #include <math.h>
00018 #include "gmem.h"
00019 #include "Object.h"
00020 #include "Dict.h"
00021 #include "Stream.h"
00022 #include "Error.h"
00023 #include "Function.h"
00024
00025
00026
00027
00028
00029 Function::Function() {
00030 }
00031
00032 Function::~Function() {
00033 }
00034
00035 Function *Function::parse(Object *funcObj) {
00036 Function *func;
00037 Dict *dict;
00038 int funcType;
00039 Object obj1;
00040
00041 if (funcObj->isStream()) {
00042 dict = funcObj->streamGetDict();
00043 } else if (funcObj->isDict()) {
00044 dict = funcObj->getDict();
00045 } else if (funcObj->isName("Identity")) {
00046 return new IdentityFunction();
00047 } else {
00048 error(-1, "Expected function dictionary or stream");
00049 return NULL;
00050 }
00051
00052 if (!dict->lookup("FunctionType", &obj1)->isInt()) {
00053 error(-1, "Function type is missing or wrong type");
00054 obj1.free();
00055 return NULL;
00056 }
00057 funcType = obj1.getInt();
00058 obj1.free();
00059
00060 if (funcType == 0) {
00061 func = new SampledFunction(funcObj, dict);
00062 } else if (funcType == 2) {
00063 func = new ExponentialFunction(funcObj, dict);
00064 } else if (funcType == 3) {
00065 func = new StitchingFunction(funcObj, dict);
00066 } else if (funcType == 4) {
00067 func = new PostScriptFunction(funcObj, dict);
00068 } else {
00069 error(-1, "Unimplemented function type (%d)", funcType);
00070 return NULL;
00071 }
00072 if (!func->isOk()) {
00073 delete func;
00074 return NULL;
00075 }
00076
00077 return func;
00078 }
00079
00080 GBool Function::init(Dict *dict) {
00081 Object obj1, obj2;
00082 int i;
00083
00084
00085 if (!dict->lookup("Domain", &obj1)->isArray()) {
00086 error(-1, "Function is missing domain");
00087 goto err2;
00088 }
00089 m = obj1.arrayGetLength() / 2;
00090 if (m > funcMaxInputs) {
00091 error(-1, "Functions with more than %d inputs are unsupported",
00092 funcMaxInputs);
00093 goto err2;
00094 }
00095 for (i = 0; i < m; ++i) {
00096 obj1.arrayGet(2*i, &obj2);
00097 if (!obj2.isNum()) {
00098 error(-1, "Illegal value in function domain array");
00099 goto err1;
00100 }
00101 domain[i][0] = obj2.getNum();
00102 obj2.free();
00103 obj1.arrayGet(2*i+1, &obj2);
00104 if (!obj2.isNum()) {
00105 error(-1, "Illegal value in function domain array");
00106 goto err1;
00107 }
00108 domain[i][1] = obj2.getNum();
00109 obj2.free();
00110 }
00111 obj1.free();
00112
00113
00114 hasRange = gFalse;
00115 n = 0;
00116 if (dict->lookup("Range", &obj1)->isArray()) {
00117 hasRange = gTrue;
00118 n = obj1.arrayGetLength() / 2;
00119 if (n > funcMaxOutputs) {
00120 error(-1, "Functions with more than %d outputs are unsupported",
00121 funcMaxOutputs);
00122 goto err2;
00123 }
00124 for (i = 0; i < n; ++i) {
00125 obj1.arrayGet(2*i, &obj2);
00126 if (!obj2.isNum()) {
00127 error(-1, "Illegal value in function range array");
00128 goto err1;
00129 }
00130 range[i][0] = obj2.getNum();
00131 obj2.free();
00132 obj1.arrayGet(2*i+1, &obj2);
00133 if (!obj2.isNum()) {
00134 error(-1, "Illegal value in function range array");
00135 goto err1;
00136 }
00137 range[i][1] = obj2.getNum();
00138 obj2.free();
00139 }
00140 }
00141 obj1.free();
00142
00143 return gTrue;
00144
00145 err1:
00146 obj2.free();
00147 err2:
00148 obj1.free();
00149 return gFalse;
00150 }
00151
00152
00153
00154
00155
00156 IdentityFunction::IdentityFunction() {
00157 int i;
00158
00159
00160
00161 m = funcMaxInputs;
00162 n = funcMaxOutputs;
00163 for (i = 0; i < funcMaxInputs; ++i) {
00164 domain[i][0] = 0;
00165 domain[i][1] = 1;
00166 }
00167 hasRange = gFalse;
00168 }
00169
00170 IdentityFunction::~IdentityFunction() {
00171 }
00172
00173 void IdentityFunction::transform(fouble *in, fouble *out) {
00174 int i;
00175
00176 for (i = 0; i < funcMaxOutputs; ++i) {
00177 out[i] = in[i];
00178 }
00179 }
00180
00181
00182
00183
00184
00185 SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
00186 Stream *str;
00187 int nSamples, sampleBits;
00188 fouble sampleMul;
00189 Object obj1, obj2;
00190 Guint buf, bitMask;
00191 int bits;
00192 int s;
00193 int i;
00194
00195 samples = NULL;
00196 ok = gFalse;
00197
00198
00199 if (!init(dict)) {
00200 goto err1;
00201 }
00202 if (!hasRange) {
00203 error(-1, "Type 0 function is missing range");
00204 goto err1;
00205 }
00206
00207
00208 if (!funcObj->isStream()) {
00209 error(-1, "Type 0 function isn't a stream");
00210 goto err1;
00211 }
00212 str = funcObj->getStream();
00213
00214
00215 if (!dict->lookup("Size", &obj1)->isArray() ||
00216 obj1.arrayGetLength() != m) {
00217 error(-1, "Function has missing or invalid size array");
00218 goto err2;
00219 }
00220 for (i = 0; i < m; ++i) {
00221 obj1.arrayGet(i, &obj2);
00222 if (!obj2.isInt()) {
00223 error(-1, "Illegal value in function size array");
00224 goto err3;
00225 }
00226 sampleSize[i] = obj2.getInt();
00227 obj2.free();
00228 }
00229 obj1.free();
00230
00231
00232 if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
00233 error(-1, "Function has missing or invalid BitsPerSample");
00234 goto err2;
00235 }
00236 sampleBits = obj1.getInt();
00237 sampleMul = 1.0 / (fouble)((1 << sampleBits) - 1);
00238 obj1.free();
00239
00240
00241 if (dict->lookup("Encode", &obj1)->isArray() &&
00242 obj1.arrayGetLength() == 2*m) {
00243 for (i = 0; i < m; ++i) {
00244 obj1.arrayGet(2*i, &obj2);
00245 if (!obj2.isNum()) {
00246 error(-1, "Illegal value in function encode array");
00247 goto err3;
00248 }
00249 encode[i][0] = obj2.getNum();
00250 obj2.free();
00251 obj1.arrayGet(2*i+1, &obj2);
00252 if (!obj2.isNum()) {
00253 error(-1, "Illegal value in function encode array");
00254 goto err3;
00255 }
00256 encode[i][1] = obj2.getNum();
00257 obj2.free();
00258 }
00259 } else {
00260 for (i = 0; i < m; ++i) {
00261 encode[i][0] = 0;
00262 encode[i][1] = sampleSize[i] - 1;
00263 }
00264 }
00265 obj1.free();
00266
00267
00268 if (dict->lookup("Decode", &obj1)->isArray() &&
00269 obj1.arrayGetLength() == 2*n) {
00270 for (i = 0; i < n; ++i) {
00271 obj1.arrayGet(2*i, &obj2);
00272 if (!obj2.isNum()) {
00273 error(-1, "Illegal value in function decode array");
00274 goto err3;
00275 }
00276 decode[i][0] = obj2.getNum();
00277 obj2.free();
00278 obj1.arrayGet(2*i+1, &obj2);
00279 if (!obj2.isNum()) {
00280 error(-1, "Illegal value in function decode array");
00281 goto err3;
00282 }
00283 decode[i][1] = obj2.getNum();
00284 obj2.free();
00285 }
00286 } else {
00287 for (i = 0; i < n; ++i) {
00288 decode[i][0] = range[i][0];
00289 decode[i][1] = range[i][1];
00290 }
00291 }
00292 obj1.free();
00293
00294
00295 nSamples = n;
00296 for (i = 0; i < m; ++i)
00297 nSamples *= sampleSize[i];
00298 samples = (fouble *)gmalloc(nSamples * sizeof(fouble));
00299 buf = 0;
00300 bits = 0;
00301 bitMask = (1 << sampleBits) - 1;
00302 str->reset();
00303 for (i = 0; i < nSamples; ++i) {
00304 if (sampleBits == 8) {
00305 s = str->getChar();
00306 } else if (sampleBits == 16) {
00307 s = str->getChar();
00308 s = (s << 8) + str->getChar();
00309 } else if (sampleBits == 32) {
00310 s = str->getChar();
00311 s = (s << 8) + str->getChar();
00312 s = (s << 8) + str->getChar();
00313 s = (s << 8) + str->getChar();
00314 } else {
00315 while (bits < sampleBits) {
00316 buf = (buf << 8) | (str->getChar() & 0xff);
00317 bits += 8;
00318 }
00319 s = (buf >> (bits - sampleBits)) & bitMask;
00320 bits -= sampleBits;
00321 }
00322 samples[i] = (fouble)s * sampleMul;
00323 }
00324 str->close();
00325
00326 ok = gTrue;
00327 return;
00328
00329 err3:
00330 obj2.free();
00331 err2:
00332 obj1.free();
00333 err1:
00334 return;
00335 }
00336
00337 SampledFunction::~SampledFunction() {
00338 if (samples) {
00339 gfree(samples);
00340 }
00341 }
00342
00343 SampledFunction::SampledFunction(SampledFunction *func) {
00344 int nSamples, i;
00345
00346 memcpy(this, func, sizeof(SampledFunction));
00347
00348 nSamples = n;
00349 for (i = 0; i < m; ++i) {
00350 nSamples *= sampleSize[i];
00351 }
00352 samples = (fouble *)gmalloc(nSamples * sizeof(fouble));
00353 memcpy(samples, func->samples, nSamples * sizeof(fouble));
00354 }
00355
00356 void SampledFunction::transform(fouble *in, fouble *out) {
00357 fouble x;
00358 int e[2][funcMaxInputs];
00359 fouble efrac[funcMaxInputs];
00360 fouble s0[1 << funcMaxInputs], s1[1 << funcMaxInputs];
00361 int i, j, k, idx;
00362
00363
00364 for (i = 0; i < m; ++i) {
00365 x = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
00366 (encode[i][1] - encode[i][0]) + encode[i][0];
00367 if (x < 0) {
00368 x = 0;
00369 } else if (x > sampleSize[i] - 1) {
00370 x = sampleSize[i] - 1;
00371 }
00372 e[0][i] = (int)floor(x);
00373 e[1][i] = (int)ceil(x);
00374 efrac[i] = x - e[0][i];
00375 }
00376
00377
00378 for (i = 0; i < n; ++i) {
00379
00380
00381 for (j = 0; j < (1<<m); ++j) {
00382 idx = e[j & 1][m - 1];
00383 for (k = m - 2; k >= 0; --k) {
00384 idx = idx * sampleSize[k] + e[(j >> k) & 1][k];
00385 }
00386 idx = idx * n + i;
00387 s0[j] = samples[idx];
00388 }
00389
00390
00391 for (j = 0; j < m; ++j) {
00392 for (k = 0; k < (1 << (m - j)); k += 2) {
00393 s1[k >> 1] = (1 - efrac[j]) * s0[k] + efrac[j] * s0[k+1];
00394 }
00395 memcpy(s0, s1, (1 << (m - j - 1)) * sizeof(fouble));
00396 }
00397
00398
00399 out[i] = s0[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
00400 if (out[i] < range[i][0]) {
00401 out[i] = range[i][0];
00402 } else if (out[i] > range[i][1]) {
00403 out[i] = range[i][1];
00404 }
00405 }
00406 }
00407
00408
00409
00410
00411
00412 ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
00413 Object obj1, obj2;
00414 GBool hasN;
00415 int i;
00416
00417 ok = gFalse;
00418
00419
00420 if (!init(dict)) {
00421 goto err1;
00422 }
00423 if (m != 1) {
00424 error(-1, "Exponential function with more than one input");
00425 goto err1;
00426 }
00427 hasN = hasRange;
00428
00429
00430 for (i = 0; i < funcMaxOutputs; ++i) {
00431 c0[i] = 0;
00432 c1[i] = 1;
00433 }
00434
00435
00436 if (dict->lookup("C0", &obj1)->isArray()) {
00437 if (!hasN) {
00438 n = obj1.arrayGetLength();
00439 hasN = gTrue;
00440 } else if (obj1.arrayGetLength() != n) {
00441 error(-1, "Function's C0 array is wrong length");
00442 goto err2;
00443 }
00444 for (i = 0; i < n; ++i) {
00445 obj1.arrayGet(i, &obj2);
00446 if (!obj2.isNum()) {
00447 error(-1, "Illegal value in function C0 array");
00448 goto err3;
00449 }
00450 c0[i] = obj2.getNum();
00451 obj2.free();
00452 }
00453 }
00454 obj1.free();
00455
00456
00457 if (dict->lookup("C1", &obj1)->isArray()) {
00458 if (!hasN) {
00459 n = obj1.arrayGetLength();
00460 hasN = gTrue;
00461 } else if (obj1.arrayGetLength() != n) {
00462 error(-1, "Function's C1 array is wrong length");
00463 goto err2;
00464 }
00465 for (i = 0; i < n; ++i) {
00466 obj1.arrayGet(i, &obj2);
00467 if (!obj2.isNum()) {
00468 error(-1, "Illegal value in function C1 array");
00469 goto err3;
00470 }
00471 c1[i] = obj2.getNum();
00472 obj2.free();
00473 }
00474 }
00475 obj1.free();
00476
00477
00478 if (!dict->lookup("N", &obj1)->isNum()) {
00479 error(-1, "Function has missing or invalid N");
00480 goto err2;
00481 }
00482 e = obj1.getNum();
00483 obj1.free();
00484
00485
00486
00487 if (!hasN) {
00488 error(-1, "Exponential function does not define number of output values");
00489 n = 1;
00490 }
00491
00492 ok = gTrue;
00493 return;
00494
00495 err3:
00496 obj2.free();
00497 err2:
00498 obj1.free();
00499 err1:
00500 return;
00501 }
00502
00503 ExponentialFunction::~ExponentialFunction() {
00504 }
00505
00506 ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
00507 memcpy(this, func, sizeof(ExponentialFunction));
00508 }
00509
00510 void ExponentialFunction::transform(fouble *in, fouble *out) {
00511 fouble x;
00512 int i;
00513
00514 if (in[0] < domain[0][0]) {
00515 x = domain[0][0];
00516 } else if (in[0] > domain[0][1]) {
00517 x = domain[0][1];
00518 } else {
00519 x = in[0];
00520 }
00521 for (i = 0; i < n; ++i) {
00522 out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
00523 if (hasRange) {
00524 if (out[i] < range[i][0]) {
00525 out[i] = range[i][0];
00526 } else if (out[i] > range[i][1]) {
00527 out[i] = range[i][1];
00528 }
00529 }
00530 }
00531 return;
00532 }
00533
00534
00535
00536
00537
00538 StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
00539 Object obj1, obj2;
00540 int i;
00541
00542 ok = gFalse;
00543 funcs = NULL;
00544 bounds = NULL;
00545 encode = NULL;
00546
00547
00548 if (!init(dict)) {
00549 goto err1;
00550 }
00551 if (m != 1) {
00552 error(-1, "Stitching function with more than one input");
00553 goto err1;
00554 }
00555
00556
00557 if (!dict->lookup("Functions", &obj1)->isArray()) {
00558 error(-1, "Missing 'Functions' entry in stitching function");
00559 goto err1;
00560 }
00561 k = obj1.arrayGetLength();
00562 funcs = (Function **)gmalloc(k * sizeof(Function *));
00563 bounds = (fouble *)gmalloc((k + 1) * sizeof(fouble));
00564 encode = (fouble *)gmalloc(2 * k * sizeof(fouble));
00565 for (i = 0; i < k; ++i) {
00566 funcs[i] = NULL;
00567 }
00568 for (i = 0; i < k; ++i) {
00569 if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) {
00570 goto err2;
00571 }
00572 if (i > 0 && (funcs[i]->getInputSize() != 1 ||
00573 funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
00574 error(-1, "Incompatible subfunctions in stitching function");
00575 goto err2;
00576 }
00577 obj2.free();
00578 }
00579 obj1.free();
00580
00581
00582 if (!dict->lookup("Bounds", &obj1)->isArray() ||
00583 obj1.arrayGetLength() != k - 1) {
00584 error(-1, "Missing or invalid 'Bounds' entry in stitching function");
00585 goto err1;
00586 }
00587 bounds[0] = domain[0][0];
00588 for (i = 1; i < k; ++i) {
00589 if (!obj1.arrayGet(i - 1, &obj2)->isNum()) {
00590 error(-1, "Invalid type in 'Bounds' array in stitching function");
00591 goto err2;
00592 }
00593 bounds[i] = obj2.getNum();
00594 obj2.free();
00595 }
00596 bounds[k] = domain[0][1];
00597 obj1.free();
00598
00599
00600 if (!dict->lookup("Encode", &obj1)->isArray() ||
00601 obj1.arrayGetLength() != 2 * k) {
00602 error(-1, "Missing or invalid 'Encode' entry in stitching function");
00603 goto err1;
00604 }
00605 for (i = 0; i < 2 * k; ++i) {
00606 if (!obj1.arrayGet(i, &obj2)->isNum()) {
00607 error(-1, "Invalid type in 'Encode' array in stitching function");
00608 goto err2;
00609 }
00610 encode[i] = obj2.getNum();
00611 obj2.free();
00612 }
00613 obj1.free();
00614
00615 ok = gTrue;
00616 return;
00617
00618 err2:
00619 obj2.free();
00620 err1:
00621 obj1.free();
00622 }
00623
00624 StitchingFunction::StitchingFunction(StitchingFunction *func) {
00625 k = func->k;
00626 funcs = (Function **)gmalloc(k * sizeof(Function *));
00627 memcpy(funcs, func->funcs, k * sizeof(Function *));
00628 bounds = (fouble *)gmalloc((k + 1) * sizeof(fouble));
00629 memcpy(bounds, func->bounds, (k + 1) * sizeof(fouble));
00630 encode = (fouble *)gmalloc(2 * k * sizeof(fouble));
00631 memcpy(encode, func->encode, 2 * k * sizeof(fouble));
00632 ok = gTrue;
00633 }
00634
00635 StitchingFunction::~StitchingFunction() {
00636 int i;
00637
00638 for (i = 0; i < k; ++i) {
00639 if (funcs[i]) {
00640 delete funcs[i];
00641 }
00642 }
00643 gfree(funcs);
00644 gfree(bounds);
00645 gfree(encode);
00646 }
00647
00648 void StitchingFunction::transform(fouble *in, fouble *out) {
00649 fouble x;
00650 int i;
00651
00652 if (in[0] < domain[0][0]) {
00653 x = domain[0][0];
00654 } else if (in[0] > domain[0][1]) {
00655 x = domain[0][1];
00656 } else {
00657 x = in[0];
00658 }
00659 for (i = 0; i < k - 1; ++i) {
00660 if (x < bounds[i+1]) {
00661 break;
00662 }
00663 }
00664 x = encode[2*i] + ((x - bounds[i]) / (bounds[i+1] - bounds[i])) *
00665 (encode[2*i+1] - encode[2*i]);
00666 funcs[i]->transform(&x, out);
00667 }
00668
00669
00670
00671
00672
00673 enum PSOp {
00674 psOpAbs,
00675 psOpAdd,
00676 psOpAnd,
00677 psOpAtan,
00678 psOpBitshift,
00679 psOpCeiling,
00680 psOpCopy,
00681 psOpCos,
00682 psOpCvi,
00683 psOpCvr,
00684 psOpDiv,
00685 psOpDup,
00686 psOpEq,
00687 psOpExch,
00688 psOpExp,
00689 psOpFalse,
00690 psOpFloor,
00691 psOpGe,
00692 psOpGt,
00693 psOpIdiv,
00694 psOpIndex,
00695 psOpLe,
00696 psOpLn,
00697 psOpLog,
00698 psOpLt,
00699 psOpMod,
00700 psOpMul,
00701 psOpNe,
00702 psOpNeg,
00703 psOpNot,
00704 psOpOr,
00705 psOpPop,
00706 psOpRoll,
00707 psOpRound,
00708 psOpSin,
00709 psOpSqrt,
00710 psOpSub,
00711 psOpTrue,
00712 psOpTruncate,
00713 psOpXor,
00714 psOpIf,
00715 psOpIfelse,
00716 psOpReturn
00717 };
00718
00719
00720
00721
00722 char *psOpNames[] = {
00723 "abs",
00724 "add",
00725 "and",
00726 "atan",
00727 "bitshift",
00728 "ceiling",
00729 "copy",
00730 "cos",
00731 "cvi",
00732 "cvr",
00733 "div",
00734 "dup",
00735 "eq",
00736 "exch",
00737 "exp",
00738 "false",
00739 "floor",
00740 "ge",
00741 "gt",
00742 "idiv",
00743 "index",
00744 "le",
00745 "ln",
00746 "log",
00747 "lt",
00748 "mod",
00749 "mul",
00750 "ne",
00751 "neg",
00752 "not",
00753 "or",
00754 "pop",
00755 "roll",
00756 "round",
00757 "sin",
00758 "sqrt",
00759 "sub",
00760 "true",
00761 "truncate",
00762 "xor"
00763 };
00764
00765 #define nPSOps (sizeof(psOpNames) / sizeof(char *))
00766
00767 enum PSObjectType {
00768 psBool,
00769 psInt,
00770 psReal,
00771 psOperator,
00772 psBlock
00773 };
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 struct PSObject {
00798 PSObjectType type;
00799 fouble real;
00800 union {
00801 GBool booln;
00802 int intg;
00803 PSOp op;
00804 int blk;
00805 };
00806 };
00807
00808 #define psStackSize 100
00809
00810 class PSStack {
00811 public:
00812
00813 PSStack() { sp = psStackSize; }
00814 void pushBool(GBool booln);
00815 void pushInt(int intg);
00816 void pushReal(fouble real);
00817 GBool popBool();
00818 int popInt();
00819 fouble popNum();
00820 GBool empty() { return sp == psStackSize; }
00821 GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; }
00822 GBool topTwoAreInts()
00823 { return sp < psStackSize - 1 &&
00824 stack[sp].type == psInt &&
00825 stack[sp+1].type == psInt; }
00826 GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; }
00827 GBool topTwoAreNums()
00828 { return sp < psStackSize - 1 &&
00829 (stack[sp].type == psInt || stack[sp].type == psReal) &&
00830 (stack[sp+1].type == psInt || stack[sp+1].type == psReal); }
00831 void copy(int n);
00832 void roll(int n, int j);
00833 void index(int i);
00834 void pop();
00835
00836 private:
00837
00838 GBool checkOverflow(int n = 1);
00839 GBool checkUnderflow();
00840 GBool checkType(PSObjectType t1, PSObjectType t2);
00841
00842 PSObject stack[psStackSize];
00843 int sp;
00844 };
00845
00846 GBool PSStack::checkOverflow(int n) {
00847 if (sp - n < 0) {
00848 error(-1, "Stack overflow in PostScript function");
00849 return gFalse;
00850 }
00851 return gTrue;
00852 }
00853
00854 GBool PSStack::checkUnderflow() {
00855 if (sp == psStackSize) {
00856 error(-1, "Stack underflow in PostScript function");
00857 return gFalse;
00858 }
00859 return gTrue;
00860 }
00861
00862 GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) {
00863 if (stack[sp].type != t1 && stack[sp].type != t2) {
00864 error(-1, "Type mismatch in PostScript function");
00865 return gFalse;
00866 }
00867 return gTrue;
00868 }
00869
00870 void PSStack::pushBool(GBool booln) {
00871 if (checkOverflow()) {
00872 stack[--sp].type = psBool;
00873 stack[sp].booln = booln;
00874 }
00875 }
00876
00877 void PSStack::pushInt(int intg) {
00878 if (checkOverflow()) {
00879 stack[--sp].type = psInt;
00880 stack[sp].intg = intg;
00881 }
00882 }
00883
00884 void PSStack::pushReal(fouble real) {
00885 if (checkOverflow()) {
00886 stack[--sp].type = psReal;
00887 stack[sp].real = real;
00888 }
00889 }
00890
00891 GBool PSStack::popBool() {
00892 if (checkUnderflow() && checkType(psBool, psBool)) {
00893 return stack[sp++].booln;
00894 }
00895 return gFalse;
00896 }
00897
00898 int PSStack::popInt() {
00899 if (checkUnderflow() && checkType(psInt, psInt)) {
00900 return stack[sp++].intg;
00901 }
00902 return 0;
00903 }
00904
00905 fouble PSStack::popNum() {
00906 fouble ret;
00907
00908 if (checkUnderflow() && checkType(psInt, psReal)) {
00909 ret = (stack[sp].type == psInt) ? (fouble)stack[sp].intg : stack[sp].real;
00910 ++sp;
00911 return ret;
00912 }
00913 return 0;
00914 }
00915
00916 void PSStack::copy(int n) {
00917 int i;
00918
00919 if (!checkOverflow(n)) {
00920 return;
00921 }
00922 for (i = sp + n - 1; i <= sp; ++i) {
00923 stack[i - n] = stack[i];
00924 }
00925 sp -= n;
00926 }
00927
00928 void PSStack::roll(int n, int j) {
00929 PSObject obj;
00930 int i, k;
00931
00932 if (j >= 0) {
00933 j %= n;
00934 } else {
00935 j = -j % n;
00936 if (j != 0) {
00937 j = n - j;
00938 }
00939 }
00940 if (n <= 0 || j == 0) {
00941 return;
00942 }
00943 for (i = 0; i < j; ++i) {
00944 obj = stack[sp];
00945 for (k = sp; k < sp + n - 1; ++k) {
00946 stack[k] = stack[k+1];
00947 }
00948 stack[sp + n - 1] = obj;
00949 }
00950 }
00951
00952 void PSStack::index(int i) {
00953 if (!checkOverflow()) {
00954 return;
00955 }
00956 --sp;
00957 stack[sp] = stack[sp + 1 + i];
00958 }
00959
00960 void PSStack::pop() {
00961 if (!checkUnderflow()) {
00962 return;
00963 }
00964 ++sp;
00965 }
00966
00967 PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
00968 Stream *str;
00969 int codePtr;
00970 GString *tok;
00971
00972 code = NULL;
00973 codeSize = 0;
00974 ok = gFalse;
00975
00976
00977 if (!init(dict)) {
00978 goto err1;
00979 }
00980 if (!hasRange) {
00981 error(-1, "Type 4 function is missing range");
00982 goto err1;
00983 }
00984
00985
00986 if (!funcObj->isStream()) {
00987 error(-1, "Type 4 function isn't a stream");
00988 goto err1;
00989 }
00990 str = funcObj->getStream();
00991
00992
00993 str->reset();
00994 if (!(tok = getToken(str)) || tok->cmp("{")) {
00995 error(-1, "Expected '{' at start of PostScript function");
00996 if (tok) {
00997 delete tok;
00998 }
00999 goto err1;
01000 }
01001 delete tok;
01002 codePtr = 0;
01003 if (!parseCode(str, &codePtr)) {
01004 goto err2;
01005 }
01006 str->close();
01007
01008 ok = gTrue;
01009
01010 err2:
01011 str->close();
01012 err1:
01013 return;
01014 }
01015
01016 PostScriptFunction::PostScriptFunction(PostScriptFunction *func) {
01017 memcpy(this, func, sizeof(PostScriptFunction));
01018 code = (PSObject *)gmalloc(codeSize * sizeof(PSObject));
01019 memcpy(code, func->code, codeSize * sizeof(PSObject));
01020 }
01021
01022 PostScriptFunction::~PostScriptFunction() {
01023 gfree(code);
01024 }
01025
01026 void PostScriptFunction::transform(fouble *in, fouble *out) {
01027 PSStack *stack;
01028 int i;
01029
01030 stack = new PSStack();
01031 for (i = 0; i < m; ++i) {
01032
01033 stack->pushReal(in[i]);
01034 }
01035 exec(stack, 0);
01036 for (i = n - 1; i >= 0; --i) {
01037 out[i] = stack->popNum();
01038 if (out[i] < range[i][0]) {
01039 out[i] = range[i][0];
01040 } else if (out[i] > range[i][1]) {
01041 out[i] = range[i][1];
01042 }
01043 }
01044
01045
01046
01047 delete stack;
01048 }
01049
01050 GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
01051 GString *tok;
01052 char *p;
01053 GBool isReal;
01054 int opPtr, elsePtr;
01055 int a, b, mid, cmp;
01056
01057 while (1) {
01058 if (!(tok = getToken(str))) {
01059 error(-1, "Unexpected end of PostScript function stream");
01060 return gFalse;
01061 }
01062 p = tok->getCString();
01063 if (isdigit(*p) || *p == '.' || *p == '-') {
01064 isReal = gFalse;
01065 for (++p; *p; ++p) {
01066 if (*p == '.') {
01067 isReal = gTrue;
01068 break;
01069 }
01070 }
01071 resizeCode(*codePtr);
01072 if (isReal) {
01073 code[*codePtr].type = psReal;
01074 code[*codePtr].real = atof(tok->getCString());
01075 } else {
01076 code[*codePtr].type = psInt;
01077 code[*codePtr].intg = atoi(tok->getCString());
01078 }
01079 ++*codePtr;
01080 delete tok;
01081 } else if (!tok->cmp("{")) {
01082 delete tok;
01083 opPtr = *codePtr;
01084 *codePtr += 3;
01085 resizeCode(opPtr + 2);
01086 if (!parseCode(str, codePtr)) {
01087 return gFalse;
01088 }
01089 if (!(tok = getToken(str))) {
01090 error(-1, "Unexpected end of PostScript function stream");
01091 return gFalse;
01092 }
01093 if (!tok->cmp("{")) {
01094 elsePtr = *codePtr;
01095 if (!parseCode(str, codePtr)) {
01096 return gFalse;
01097 }
01098 } else {
01099 elsePtr = -1;
01100 }
01101 delete tok;
01102 if (!(tok = getToken(str))) {
01103 error(-1, "Unexpected end of PostScript function stream");
01104 return gFalse;
01105 }
01106 if (!tok->cmp("if")) {
01107 if (elsePtr >= 0) {
01108 error(-1, "Got 'if' operator with two blocks in PostScript function");
01109 return gFalse;
01110 }
01111 code[opPtr].type = psOperator;
01112 code[opPtr].op = psOpIf;
01113 code[opPtr+2].type = psBlock;
01114 code[opPtr+2].blk = *codePtr;
01115 } else if (!tok->cmp("ifelse")) {
01116 if (elsePtr < 0) {
01117 error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
01118 return gFalse;
01119 }
01120 code[opPtr].type = psOperator;
01121 code[opPtr].op = psOpIfelse;
01122 code[opPtr+1].type = psBlock;
01123 code[opPtr+1].blk = elsePtr;
01124 code[opPtr+2].type = psBlock;
01125 code[opPtr+2].blk = *codePtr;
01126 } else {
01127 error(-1, "Expected if/ifelse operator in PostScript function");
01128 delete tok;
01129 return gFalse;
01130 }
01131 delete tok;
01132 } else if (!tok->cmp("}")) {
01133 delete tok;
01134 resizeCode(*codePtr);
01135 code[*codePtr].type = psOperator;
01136 code[*codePtr].op = psOpReturn;
01137 ++*codePtr;
01138 break;
01139 } else {
01140 a = -1;
01141 b = nPSOps;
01142
01143 while (b - a > 1) {
01144 mid = (a + b) / 2;
01145 cmp = tok->cmp(psOpNames[mid]);
01146 if (cmp > 0) {
01147 a = mid;
01148 } else if (cmp < 0) {
01149 b = mid;
01150 } else {
01151 a = b = mid;
01152 }
01153 }
01154 if (cmp != 0) {
01155 error(-1, "Unknown operator '%s' in PostScript function",
01156 tok->getCString());
01157 delete tok;
01158 return gFalse;
01159 }
01160 delete tok;
01161 resizeCode(*codePtr);
01162 code[*codePtr].type = psOperator;
01163 code[*codePtr].op = (PSOp)a;
01164 ++*codePtr;
01165 }
01166 }
01167 return gTrue;
01168 }
01169
01170 GString *PostScriptFunction::getToken(Stream *str) {
01171 GString *s;
01172 int c;
01173
01174 s = new GString();
01175 do {
01176 c = str->getChar();
01177 } while (c != EOF && isspace(c));
01178 if (c == '{' || c == '}') {
01179 s->append((char)c);
01180 } else if (isdigit(c) || c == '.' || c == '-') {
01181 while (1) {
01182 s->append((char)c);
01183 c = str->lookChar();
01184 if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
01185 break;
01186 }
01187 str->getChar();
01188 }
01189 } else {
01190 while (1) {
01191 s->append((char)c);
01192 c = str->lookChar();
01193 if (c == EOF || !isalnum(c)) {
01194 break;
01195 }
01196 str->getChar();
01197 }
01198 }
01199 return s;
01200 }
01201
01202 void PostScriptFunction::resizeCode(int newSize) {
01203 if (newSize >= codeSize) {
01204 codeSize += 64;
01205 code = (PSObject *)grealloc(code, codeSize * sizeof(PSObject));
01206 }
01207 }
01208
01209 void PostScriptFunction::exec(PSStack *stack, int codePtr) {
01210 int i1, i2;
01211 fouble r1, r2;
01212 GBool b1, b2;
01213
01214 while (1) {
01215 switch (code[codePtr].type) {
01216 case psInt:
01217 stack->pushInt(code[codePtr++].intg);
01218 break;
01219 case psReal:
01220 stack->pushReal(code[codePtr++].real);
01221 break;
01222 case psOperator:
01223 switch (code[codePtr++].op) {
01224 case psOpAbs:
01225 if (stack->topIsInt()) {
01226 stack->pushInt(abs(stack->popInt()));
01227 } else {
01228 stack->pushReal(fabs(stack->popNum()));
01229 }
01230 break;
01231 case psOpAdd:
01232 if (stack->topTwoAreInts()) {
01233 i2 = stack->popInt();
01234 i1 = stack->popInt();
01235 stack->pushInt(i1 + i2);
01236 } else {
01237 r2 = stack->popNum();
01238 r1 = stack->popNum();
01239 stack->pushReal(r1 + r2);
01240 }
01241 break;
01242 case psOpAnd:
01243 if (stack->topTwoAreInts()) {
01244 i2 = stack->popInt();
01245 i1 = stack->popInt();
01246 stack->pushInt(i1 & i2);
01247 } else {
01248 b2 = stack->popBool();
01249 b1 = stack->popBool();
01250 stack->pushReal(b1 && b2);
01251 }
01252 break;
01253 case psOpAtan:
01254 r2 = stack->popNum();
01255 r1 = stack->popNum();
01256 stack->pushReal(atan2(r1, r2));
01257 break;
01258 case psOpBitshift:
01259 i2 = stack->popInt();
01260 i1 = stack->popInt();
01261 if (i2 > 0) {
01262 stack->pushInt(i1 << i2);
01263 } else if (i2 < 0) {
01264 stack->pushInt((int)((Guint)i1 >> i2));
01265 } else {
01266 stack->pushInt(i1);
01267 }
01268 break;
01269 case psOpCeiling:
01270 if (!stack->topIsInt()) {
01271 stack->pushReal(ceil(stack->popNum()));
01272 }
01273 break;
01274 case psOpCopy:
01275 stack->copy(stack->popInt());
01276 break;
01277 case psOpCos:
01278 stack->pushReal(cos(stack->popNum()));
01279 break;
01280 case psOpCvi:
01281 if (!stack->topIsInt()) {
01282 stack->pushInt((int)stack->popNum());
01283 }
01284 break;
01285 case psOpCvr:
01286 if (!stack->topIsReal()) {
01287 stack->pushReal(stack->popNum());
01288 }
01289 break;
01290 case psOpDiv:
01291 r2 = stack->popNum();
01292 r1 = stack->popNum();
01293 stack->pushReal(r1 / r2);
01294 break;
01295 case psOpDup:
01296 stack->copy(1);
01297 break;
01298 case psOpEq:
01299 if (stack->topTwoAreInts()) {
01300 i2 = stack->popInt();
01301 i1 = stack->popInt();
01302 stack->pushBool(i1 == i2);
01303 } else if (stack->topTwoAreNums()) {
01304 r2 = stack->popNum();
01305 r1 = stack->popNum();
01306 stack->pushBool(r1 == r2);
01307 } else {
01308 b2 = stack->popBool();
01309 b1 = stack->popBool();
01310 stack->pushBool(b1 == b2);
01311 }
01312 break;
01313 case psOpExch:
01314 stack->roll(2, 1);
01315 break;
01316 case psOpExp:
01317 r2 = stack->popInt();
01318 r1 = stack->popInt();
01319 stack->pushReal(pow(r1, r2));
01320 break;
01321 case psOpFalse:
01322 stack->pushBool(gFalse);
01323 break;
01324 case psOpFloor:
01325 if (!stack->topIsInt()) {
01326 stack->pushReal(floor(stack->popNum()));
01327 }
01328 break;
01329 case psOpGe:
01330 if (stack->topTwoAreInts()) {
01331 i2 = stack->popInt();
01332 i1 = stack->popInt();
01333 stack->pushBool(i1 >= i2);
01334 } else {
01335 r2 = stack->popNum();
01336 r1 = stack->popNum();
01337 stack->pushBool(r1 >= r2);
01338 }
01339 break;
01340 case psOpGt:
01341 if (stack->topTwoAreInts()) {
01342 i2 = stack->popInt();
01343 i1 = stack->popInt();
01344 stack->pushBool(i1 > i2);
01345 } else {
01346 r2 = stack->popNum();
01347 r1 = stack->popNum();
01348 stack->pushBool(r1 > r2);
01349 }
01350 break;
01351 case psOpIdiv:
01352 i2 = stack->popInt();
01353 i1 = stack->popInt();
01354 stack->pushInt(i1 / i2);
01355 break;
01356 case psOpIndex:
01357 stack->index(stack->popInt());
01358 break;
01359 case psOpLe:
01360 if (stack->topTwoAreInts()) {
01361 i2 = stack->popInt();
01362 i1 = stack->popInt();
01363 stack->pushBool(i1 <= i2);
01364 } else {
01365 r2 = stack->popNum();
01366 r1 = stack->popNum();
01367 stack->pushBool(r1 <= r2);
01368 }
01369 break;
01370 case psOpLn:
01371 stack->pushReal(log(stack->popNum()));
01372 break;
01373 case psOpLog:
01374 stack->pushReal(log10(stack->popNum()));
01375 break;
01376 case psOpLt:
01377 if (stack->topTwoAreInts()) {
01378 i2 = stack->popInt();
01379 i1 = stack->popInt();
01380 stack->pushBool(i1 < i2);
01381 } else {
01382 r2 = stack->popNum();
01383 r1 = stack->popNum();
01384 stack->pushBool(r1 < r2);
01385 }
01386 break;
01387 case psOpMod:
01388 i2 = stack->popInt();
01389 i1 = stack->popInt();
01390 stack->pushInt(i1 % i2);
01391 break;
01392 case psOpMul:
01393 if (stack->topTwoAreInts()) {
01394 i2 = stack->popInt();
01395 i1 = stack->popInt();
01396
01397 stack->pushInt(i1 * i2);
01398 } else {
01399 r2 = stack->popNum();
01400 r1 = stack->popNum();
01401 stack->pushReal(r1 * r2);
01402 }
01403 break;
01404 case psOpNe:
01405 if (stack->topTwoAreInts()) {
01406 i2 = stack->popInt();
01407 i1 = stack->popInt();
01408 stack->pushBool(i1 != i2);
01409 } else if (stack->topTwoAreNums()) {
01410 r2 = stack->popNum();
01411 r1 = stack->popNum();
01412 stack->pushBool(r1 != r2);
01413 } else {
01414 b2 = stack->popBool();
01415 b1 = stack->popBool();
01416 stack->pushBool(b1 != b2);
01417 }
01418 break;
01419 case psOpNeg:
01420 if (stack->topIsInt()) {
01421 stack->pushInt(-stack->popInt());
01422 } else {
01423 stack->pushReal(-stack->popNum());
01424 }
01425 break;
01426 case psOpNot:
01427 if (stack->topIsInt()) {
01428 stack->pushInt(~stack->popInt());
01429 } else {
01430 stack->pushReal(!stack->popBool());
01431 }
01432 break;
01433 case psOpOr:
01434 if (stack->topTwoAreInts()) {
01435 i2 = stack->popInt();
01436 i1 = stack->popInt();
01437 stack->pushInt(i1 | i2);
01438 } else {
01439 b2 = stack->popBool();
01440 b1 = stack->popBool();
01441 stack->pushReal(b1 || b2);
01442 }
01443 break;
01444 case psOpPop:
01445 stack->pop();
01446 break;
01447 case psOpRoll:
01448 i2 = stack->popInt();
01449 i1 = stack->popInt();
01450 stack->roll(i1, i2);
01451 break;
01452 case psOpRound:
01453 if (!stack->topIsInt()) {
01454 r1 = stack->popNum();
01455 stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5));
01456 }
01457 break;
01458 case psOpSin:
01459 stack->pushReal(cos(stack->popNum()));
01460 break;
01461 case psOpSqrt:
01462 stack->pushReal(sqrt(stack->popNum()));
01463 break;
01464 case psOpSub:
01465 if (stack->topTwoAreInts()) {
01466 i2 = stack->popInt();
01467 i1 = stack->popInt();
01468 stack->pushInt(i1 - i2);
01469 } else {
01470 r2 = stack->popNum();
01471 r1 = stack->popNum();
01472 stack->pushReal(r1 - r2);
01473 }
01474 break;
01475 case psOpTrue:
01476 stack->pushBool(gTrue);
01477 break;
01478 case psOpTruncate:
01479 if (!stack->topIsInt()) {
01480 r1 = stack->popNum();
01481 stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1));
01482 }
01483 break;
01484 case psOpXor:
01485 if (stack->topTwoAreInts()) {
01486 i2 = stack->popInt();
01487 i1 = stack->popInt();
01488 stack->pushInt(i1 ^ i2);
01489 } else {
01490 b2 = stack->popBool();
01491 b1 = stack->popBool();
01492 stack->pushReal(b1 ^ b2);
01493 }
01494 break;
01495 case psOpIf:
01496 b1 = stack->popBool();
01497 if (b1) {
01498 exec(stack, codePtr + 2);
01499 }
01500 codePtr = code[codePtr + 1].blk;
01501 break;
01502 case psOpIfelse:
01503 b1 = stack->popBool();
01504 if (b1) {
01505 exec(stack, codePtr + 2);
01506 } else {
01507 exec(stack, code[codePtr].blk);
01508 }
01509 codePtr = code[codePtr + 1].blk;
01510 break;
01511 case psOpReturn:
01512 return;
01513 }
01514 break;
01515 default:
01516 error(-1, "Internal: bad object in PostScript function code");
01517 break;
01518 }
01519 }
01520 }