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