📄 function.cc
字号:
x = domain[0][1]; } else { x = in[0]; } for (i = 0; i < n; ++i) { out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]); if (hasRange) { if (out[i] < range[i][0]) { out[i] = range[i][0]; } else if (out[i] > range[i][1]) { out[i] = range[i][1]; } } } return;}//------------------------------------------------------------------------// StitchingFunction//------------------------------------------------------------------------StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) { Object obj1, obj2; int i; ok = gFalse; funcs = NULL; bounds = NULL; encode = NULL; scale = NULL; //----- initialize the generic stuff if (!init(dict)) { goto err1; } if (m != 1) { error(-1, "Stitching function with more than one input"); goto err1; } //----- Functions if (!dict->lookup("Functions", &obj1)->isArray()) { error(-1, "Missing 'Functions' entry in stitching function"); goto err1; } k = obj1.arrayGetLength(); funcs = (Function **)gmallocn(k, sizeof(Function *)); bounds = (double *)gmallocn(k + 1, sizeof(double)); encode = (double *)gmallocn(2 * k, sizeof(double)); scale = (double *)gmallocn(k, sizeof(double)); for (i = 0; i < k; ++i) { funcs[i] = NULL; } for (i = 0; i < k; ++i) { if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) { goto err2; } if (i > 0 && (funcs[i]->getInputSize() != 1 || funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) { error(-1, "Incompatible subfunctions in stitching function"); goto err2; } obj2.free(); } obj1.free(); //----- Bounds if (!dict->lookup("Bounds", &obj1)->isArray() || obj1.arrayGetLength() != k - 1) { error(-1, "Missing or invalid 'Bounds' entry in stitching function"); goto err1; } bounds[0] = domain[0][0]; for (i = 1; i < k; ++i) { if (!obj1.arrayGet(i - 1, &obj2)->isNum()) { error(-1, "Invalid type in 'Bounds' array in stitching function"); goto err2; } bounds[i] = obj2.getNum(); obj2.free(); } bounds[k] = domain[0][1]; obj1.free(); //----- Encode if (!dict->lookup("Encode", &obj1)->isArray() || obj1.arrayGetLength() != 2 * k) { error(-1, "Missing or invalid 'Encode' entry in stitching function"); goto err1; } for (i = 0; i < 2 * k; ++i) { if (!obj1.arrayGet(i, &obj2)->isNum()) { error(-1, "Invalid type in 'Encode' array in stitching function"); goto err2; } encode[i] = obj2.getNum(); obj2.free(); } obj1.free(); //----- pre-compute the scale factors for (i = 0; i < k; ++i) { if (bounds[i] == bounds[i+1]) { // avoid a divide-by-zero -- in this situation, function i will // never be used anyway scale[i] = 0; } else { scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]); } } ok = gTrue; return; err2: obj2.free(); err1: obj1.free();}StitchingFunction::StitchingFunction(StitchingFunction *func) { int i; k = func->k; funcs = (Function **)gmallocn(k, sizeof(Function *)); for (i = 0; i < k; ++i) { funcs[i] = func->funcs[i]->copy(); } bounds = (double *)gmallocn(k + 1, sizeof(double)); memcpy(bounds, func->bounds, (k + 1) * sizeof(double)); encode = (double *)gmallocn(2 * k, sizeof(double)); memcpy(encode, func->encode, 2 * k * sizeof(double)); scale = (double *)gmallocn(k, sizeof(double)); memcpy(scale, func->scale, k * sizeof(double)); ok = gTrue;}StitchingFunction::~StitchingFunction() { int i; if (funcs) { for (i = 0; i < k; ++i) { if (funcs[i]) { delete funcs[i]; } } } gfree(funcs); gfree(bounds); gfree(encode); gfree(scale);}void StitchingFunction::transform(double *in, double *out) { double x; int i; if (in[0] < domain[0][0]) { x = domain[0][0]; } else if (in[0] > domain[0][1]) { x = domain[0][1]; } else { x = in[0]; } for (i = 0; i < k - 1; ++i) { if (x < bounds[i+1]) { break; } } x = encode[2*i] + (x - bounds[i]) * scale[i]; funcs[i]->transform(&x, out);}//------------------------------------------------------------------------// PostScriptFunction//------------------------------------------------------------------------enum PSOp { psOpAbs, psOpAdd, psOpAnd, psOpAtan, psOpBitshift, psOpCeiling, psOpCopy, psOpCos, psOpCvi, psOpCvr, psOpDiv, psOpDup, psOpEq, psOpExch, psOpExp, psOpFalse, psOpFloor, psOpGe, psOpGt, psOpIdiv, psOpIndex, psOpLe, psOpLn, psOpLog, psOpLt, psOpMod, psOpMul, psOpNe, psOpNeg, psOpNot, psOpOr, psOpPop, psOpRoll, psOpRound, psOpSin, psOpSqrt, psOpSub, psOpTrue, psOpTruncate, psOpXor, psOpIf, psOpIfelse, psOpReturn};// Note: 'if' and 'ifelse' are parsed separately.// The rest are listed here in alphabetical order.// The index in this table is equivalent to the entry in PSOp.char *psOpNames[] = { "abs", "add", "and", "atan", "bitshift", "ceiling", "copy", "cos", "cvi", "cvr", "div", "dup", "eq", "exch", "exp", "false", "floor", "ge", "gt", "idiv", "index", "le", "ln", "log", "lt", "mod", "mul", "ne", "neg", "not", "or", "pop", "roll", "round", "sin", "sqrt", "sub", "true", "truncate", "xor"};#define nPSOps (sizeof(psOpNames) / sizeof(char *))enum PSObjectType { psBool, psInt, psReal, psOperator, psBlock};// In the code array, 'if'/'ifelse' operators take up three slots// plus space for the code in the subclause(s).//// +---------------------------------+// | psOperator: psOpIf / psOpIfelse |// +---------------------------------+// | psBlock: ptr=<A> |// +---------------------------------+// | psBlock: ptr=<B> |// +---------------------------------+// | if clause |// | ... |// | psOperator: psOpReturn |// +---------------------------------+// <A> | else clause |// | ... |// | psOperator: psOpReturn |// +---------------------------------+// <B> | ... |//// For 'if', pointer <A> is present in the code stream but unused.struct PSObject { PSObjectType type; union { GBool booln; // boolean (stack only) int intg; // integer (stack and code) double real; // real (stack and code) PSOp op; // operator (code only) int blk; // if/ifelse block pointer (code only) };};#define psStackSize 100class PSStack {public: PSStack() { sp = psStackSize; } void pushBool(GBool booln); void pushInt(int intg); void pushReal(double real); GBool popBool(); int popInt(); double popNum(); GBool empty() { return sp == psStackSize; } GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; } GBool topTwoAreInts() { return sp < psStackSize - 1 && stack[sp].type == psInt && stack[sp+1].type == psInt; } GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; } GBool topTwoAreNums() { return sp < psStackSize - 1 && (stack[sp].type == psInt || stack[sp].type == psReal) && (stack[sp+1].type == psInt || stack[sp+1].type == psReal); } void copy(int n); void roll(int n, int j); void index(int i); void pop();private: GBool checkOverflow(int n = 1); GBool checkUnderflow(); GBool checkType(PSObjectType t1, PSObjectType t2); PSObject stack[psStackSize]; int sp;};GBool PSStack::checkOverflow(int n) { if (sp - n < 0) { error(-1, "Stack overflow in PostScript function"); return gFalse; } return gTrue;}GBool PSStack::checkUnderflow() { if (sp == psStackSize) { error(-1, "Stack underflow in PostScript function"); return gFalse; } return gTrue;}GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) { if (stack[sp].type != t1 && stack[sp].type != t2) { error(-1, "Type mismatch in PostScript function"); return gFalse; } return gTrue;}void PSStack::pushBool(GBool booln) { if (checkOverflow()) { stack[--sp].type = psBool; stack[sp].booln = booln; }}void PSStack::pushInt(int intg) { if (checkOverflow()) { stack[--sp].type = psInt; stack[sp].intg = intg; }}void PSStack::pushReal(double real) { if (checkOverflow()) { stack[--sp].type = psReal; stack[sp].real = real; }}GBool PSStack::popBool() { if (checkUnderflow() && checkType(psBool, psBool)) { return stack[sp++].booln; } return gFalse;}int PSStack::popInt() { if (checkUnderflow() && checkType(psInt, psInt)) { return stack[sp++].intg; } return 0;}double PSStack::popNum() { double ret; if (checkUnderflow() && checkType(psInt, psReal)) { ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real; ++sp; return ret; } return 0;}void PSStack::copy(int n) { int i; if (sp + n > psStackSize) { error(-1, "Stack underflow in PostScript function"); return; } if (!checkOverflow(n)) { return; } for (i = sp + n - 1; i >= sp; --i) { stack[i - n] = stack[i]; } sp -= n;}void PSStack::roll(int n, int j) { PSObject obj; int i, k; if (j >= 0) { j %= n; } else { j = -j % n; if (j != 0) { j = n - j; } } if (n <= 0 || j == 0) { return; } for (i = 0; i < j; ++i) { obj = stack[sp]; for (k = sp; k < sp + n - 1; ++k) { stack[k] = stack[k+1]; } stack[sp + n - 1] = obj; }}void PSStack::index(int i) { if (!checkOverflow()) { return; } --sp; stack[sp] = stack[sp + 1 + i];}void PSStack::pop() { if (!checkUnderflow()) { return; } ++sp;}PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) { Stream *str; int codePtr; GString *tok; code = NULL; codeSize = 0; ok = gFalse; //----- initialize the generic stuff if (!init(dict)) { goto err1; } if (!hasRange) { error(-1, "Type 4 function is missing range"); goto err1; } //----- get the stream if (!funcObj->isStream()) { error(-1, "Type 4 function isn't a stream"); goto err1; } str = funcObj->getStream(); //----- parse the function codeString = new GString(); str->reset(); if (!(tok = getToken(str)) || tok->cmp("{")) { error(-1, "Expected '{' at start of PostScript function"); if (tok) { delete tok; } goto err1; } delete tok; codePtr = 0; if (!parseCode(str, &codePtr)) { goto err2; } str->close(); ok = gTrue; err2: str->close(); err1: return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -