📄 function.cc
字号:
PostScriptFunction::PostScriptFunction(PostScriptFunction *func) { memcpy(this, func, sizeof(PostScriptFunction)); code = (PSObject *)gmallocn(codeSize, sizeof(PSObject)); memcpy(code, func->code, codeSize * sizeof(PSObject)); codeString = func->codeString->copy();}PostScriptFunction::~PostScriptFunction() { gfree(code); delete codeString;}void PostScriptFunction::transform(double *in, double *out) { PSStack *stack; int i; stack = new PSStack(); for (i = 0; i < m; ++i) { //~ may need to check for integers here stack->pushReal(in[i]); } exec(stack, 0); for (i = n - 1; i >= 0; --i) { out[i] = stack->popNum(); if (out[i] < range[i][0]) { out[i] = range[i][0]; } else if (out[i] > range[i][1]) { out[i] = range[i][1]; } } // if (!stack->empty()) { // error(-1, "Extra values on stack at end of PostScript function"); // } delete stack;}GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) { GString *tok; char *p; GBool isReal; int opPtr, elsePtr; int a, b, mid, cmp; while (1) { if (!(tok = getToken(str))) { error(-1, "Unexpected end of PostScript function stream"); return gFalse; } p = tok->getCString(); if (isdigit(*p) || *p == '.' || *p == '-') { isReal = gFalse; for (++p; *p; ++p) { if (*p == '.') { isReal = gTrue; break; } } resizeCode(*codePtr); if (isReal) { code[*codePtr].type = psReal; code[*codePtr].real = atof(tok->getCString()); } else { code[*codePtr].type = psInt; code[*codePtr].intg = atoi(tok->getCString()); } ++*codePtr; delete tok; } else if (!tok->cmp("{")) { delete tok; opPtr = *codePtr; *codePtr += 3; resizeCode(opPtr + 2); if (!parseCode(str, codePtr)) { return gFalse; } if (!(tok = getToken(str))) { error(-1, "Unexpected end of PostScript function stream"); return gFalse; } if (!tok->cmp("{")) { elsePtr = *codePtr; if (!parseCode(str, codePtr)) { return gFalse; } delete tok; if (!(tok = getToken(str))) { error(-1, "Unexpected end of PostScript function stream"); return gFalse; } } else { elsePtr = -1; } if (!tok->cmp("if")) { if (elsePtr >= 0) { error(-1, "Got 'if' operator with two blocks in PostScript function"); return gFalse; } code[opPtr].type = psOperator; code[opPtr].op = psOpIf; code[opPtr+2].type = psBlock; code[opPtr+2].blk = *codePtr; } else if (!tok->cmp("ifelse")) { if (elsePtr < 0) { error(-1, "Got 'ifelse' operator with one blocks in PostScript function"); return gFalse; } code[opPtr].type = psOperator; code[opPtr].op = psOpIfelse; code[opPtr+1].type = psBlock; code[opPtr+1].blk = elsePtr; code[opPtr+2].type = psBlock; code[opPtr+2].blk = *codePtr; } else { error(-1, "Expected if/ifelse operator in PostScript function"); delete tok; return gFalse; } delete tok; } else if (!tok->cmp("}")) { delete tok; resizeCode(*codePtr); code[*codePtr].type = psOperator; code[*codePtr].op = psOpReturn; ++*codePtr; break; } else { a = -1; b = nPSOps; // invariant: psOpNames[a] < tok < psOpNames[b] while (b - a > 1) { mid = (a + b) / 2; cmp = tok->cmp(psOpNames[mid]); if (cmp > 0) { a = mid; } else if (cmp < 0) { b = mid; } else { a = b = mid; } } if (cmp != 0) { error(-1, "Unknown operator '%s' in PostScript function", tok->getCString()); delete tok; return gFalse; } delete tok; resizeCode(*codePtr); code[*codePtr].type = psOperator; code[*codePtr].op = (PSOp)a; ++*codePtr; } } return gTrue;}GString *PostScriptFunction::getToken(Stream *str) { GString *s; int c; GBool comment; s = new GString(); comment = gFalse; while (1) { if ((c = str->getChar()) == EOF) { break; } codeString->append(c); if (comment) { if (c == '\x0a' || c == '\x0d') { comment = gFalse; } } else if (c == '%') { comment = gTrue; } else if (!isspace(c)) { break; } } if (c == '{' || c == '}') { s->append((char)c); } else if (isdigit(c) || c == '.' || c == '-') { while (1) { s->append((char)c); c = str->lookChar(); if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) { break; } str->getChar(); codeString->append(c); } } else { while (1) { s->append((char)c); c = str->lookChar(); if (c == EOF || !isalnum(c)) { break; } str->getChar(); codeString->append(c); } } return s;}void PostScriptFunction::resizeCode(int newSize) { if (newSize >= codeSize) { codeSize += 64; code = (PSObject *)greallocn(code, codeSize, sizeof(PSObject)); }}void PostScriptFunction::exec(PSStack *stack, int codePtr) { int i1, i2; double r1, r2; GBool b1, b2; while (1) { switch (code[codePtr].type) { case psInt: stack->pushInt(code[codePtr++].intg); break; case psReal: stack->pushReal(code[codePtr++].real); break; case psOperator: switch (code[codePtr++].op) { case psOpAbs: if (stack->topIsInt()) { stack->pushInt(abs(stack->popInt())); } else { stack->pushReal(fabs(stack->popNum())); } break; case psOpAdd: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushInt(i1 + i2); } else { r2 = stack->popNum(); r1 = stack->popNum(); stack->pushReal(r1 + r2); } break; case psOpAnd: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushInt(i1 & i2); } else { b2 = stack->popBool(); b1 = stack->popBool(); stack->pushBool(b1 && b2); } break; case psOpAtan: r2 = stack->popNum(); r1 = stack->popNum(); stack->pushReal(atan2(r1, r2)); break; case psOpBitshift: i2 = stack->popInt(); i1 = stack->popInt(); if (i2 > 0) { stack->pushInt(i1 << i2); } else if (i2 < 0) { stack->pushInt((int)((Guint)i1 >> i2)); } else { stack->pushInt(i1); } break; case psOpCeiling: if (!stack->topIsInt()) { stack->pushReal(ceil(stack->popNum())); } break; case psOpCopy: stack->copy(stack->popInt()); break; case psOpCos: stack->pushReal(cos(stack->popNum())); break; case psOpCvi: if (!stack->topIsInt()) { stack->pushInt((int)stack->popNum()); } break; case psOpCvr: if (!stack->topIsReal()) { stack->pushReal(stack->popNum()); } break; case psOpDiv: r2 = stack->popNum(); r1 = stack->popNum(); stack->pushReal(r1 / r2); break; case psOpDup: stack->copy(1); break; case psOpEq: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushBool(i1 == i2); } else if (stack->topTwoAreNums()) { r2 = stack->popNum(); r1 = stack->popNum(); stack->pushBool(r1 == r2); } else { b2 = stack->popBool(); b1 = stack->popBool(); stack->pushBool(b1 == b2); } break; case psOpExch: stack->roll(2, 1); break; case psOpExp: r2 = stack->popNum(); r1 = stack->popNum(); stack->pushReal(pow(r1, r2)); break; case psOpFalse: stack->pushBool(gFalse); break; case psOpFloor: if (!stack->topIsInt()) { stack->pushReal(floor(stack->popNum())); } break; case psOpGe: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushBool(i1 >= i2); } else { r2 = stack->popNum(); r1 = stack->popNum(); stack->pushBool(r1 >= r2); } break; case psOpGt: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushBool(i1 > i2); } else { r2 = stack->popNum(); r1 = stack->popNum(); stack->pushBool(r1 > r2); } break; case psOpIdiv: i2 = stack->popInt(); i1 = stack->popInt(); stack->pushInt(i1 / i2); break; case psOpIndex: stack->index(stack->popInt()); break; case psOpLe: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushBool(i1 <= i2); } else { r2 = stack->popNum(); r1 = stack->popNum(); stack->pushBool(r1 <= r2); } break; case psOpLn: stack->pushReal(log(stack->popNum())); break; case psOpLog: stack->pushReal(log10(stack->popNum())); break; case psOpLt: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushBool(i1 < i2); } else { r2 = stack->popNum(); r1 = stack->popNum(); stack->pushBool(r1 < r2); } break; case psOpMod: i2 = stack->popInt(); i1 = stack->popInt(); stack->pushInt(i1 % i2); break; case psOpMul: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); //~ should check for out-of-range, and push a real instead stack->pushInt(i1 * i2); } else { r2 = stack->popNum(); r1 = stack->popNum(); stack->pushReal(r1 * r2); } break; case psOpNe: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushBool(i1 != i2); } else if (stack->topTwoAreNums()) { r2 = stack->popNum(); r1 = stack->popNum(); stack->pushBool(r1 != r2); } else { b2 = stack->popBool(); b1 = stack->popBool(); stack->pushBool(b1 != b2); } break; case psOpNeg: if (stack->topIsInt()) { stack->pushInt(-stack->popInt()); } else { stack->pushReal(-stack->popNum()); } break; case psOpNot: if (stack->topIsInt()) { stack->pushInt(~stack->popInt()); } else { stack->pushBool(!stack->popBool()); } break; case psOpOr: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushInt(i1 | i2); } else { b2 = stack->popBool(); b1 = stack->popBool(); stack->pushBool(b1 || b2); } break; case psOpPop: stack->pop(); break; case psOpRoll: i2 = stack->popInt(); i1 = stack->popInt(); stack->roll(i1, i2); break; case psOpRound: if (!stack->topIsInt()) { r1 = stack->popNum(); stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5)); } break; case psOpSin: stack->pushReal(sin(stack->popNum())); break; case psOpSqrt: stack->pushReal(sqrt(stack->popNum())); break; case psOpSub: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushInt(i1 - i2); } else { r2 = stack->popNum(); r1 = stack->popNum(); stack->pushReal(r1 - r2); } break; case psOpTrue: stack->pushBool(gTrue); break; case psOpTruncate: if (!stack->topIsInt()) { r1 = stack->popNum(); stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1)); } break; case psOpXor: if (stack->topTwoAreInts()) { i2 = stack->popInt(); i1 = stack->popInt(); stack->pushInt(i1 ^ i2); } else { b2 = stack->popBool(); b1 = stack->popBool(); stack->pushBool(b1 ^ b2); } break; case psOpIf: b1 = stack->popBool(); if (b1) { exec(stack, codePtr + 2); } codePtr = code[codePtr + 1].blk; break; case psOpIfelse: b1 = stack->popBool(); if (b1) { exec(stack, codePtr + 2); } else { exec(stack, code[codePtr].blk); } codePtr = code[codePtr + 1].blk; break; case psOpReturn: return; } break; default: error(-1, "Internal: bad object in PostScript function code"); break; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -