📄 gfx.cc
字号:
ignoreUndef = 0; for (i = 0; i < 6; ++i) { baseMatrix[i] = state->getCTM()[i]; } formDepth = 0; abortCheckCbk = abortCheckCbkA; abortCheckCbkData = abortCheckCbkDataA; // set crop box if (cropBox) { state->moveTo(cropBox->x1, cropBox->y1); state->lineTo(cropBox->x2, cropBox->y1); state->lineTo(cropBox->x2, cropBox->y2); state->lineTo(cropBox->x1, cropBox->y2); state->closePath(); state->clip(); out->clip(state); state->clearPath(); }}Gfx::~Gfx() { while (state->hasSaves()) { restoreState(); } if (!subPage) { out->endPage(); } while (res) { popResources(); } if (state) { delete state; }}void Gfx::display(Object *obj, GBool topLevel) { Object obj2; int i; if (obj->isArray()) { for (i = 0; i < obj->arrayGetLength(); ++i) { obj->arrayGet(i, &obj2); if (!obj2.isStream()) { error(-1, "Weird page contents"); obj2.free(); return; } obj2.free(); } } else if (!obj->isStream()) { error(-1, "Weird page contents"); return; } parser = new Parser(xref, new Lexer(xref, obj), gFalse); go(topLevel); delete parser; parser = NULL;}void Gfx::go(GBool topLevel) { Object obj; Object args[maxArgs]; int numArgs, i; int lastAbortCheck; // scan a sequence of objects updateLevel = lastAbortCheck = 0; numArgs = 0; parser->getObj(&obj); while (!obj.isEOF()) { // got a command - execute it if (obj.isCmd()) { if (printCommands) { obj.print(stdout); for (i = 0; i < numArgs; ++i) { printf(" "); args[i].print(stdout); } printf("\n"); fflush(stdout); } execOp(&obj, args, numArgs); obj.free(); for (i = 0; i < numArgs; ++i) args[i].free(); numArgs = 0; // periodically update display if (++updateLevel >= 20000) { out->dump(); updateLevel = 0; } // check for an abort if (abortCheckCbk) { if (updateLevel - lastAbortCheck > 10) { if ((*abortCheckCbk)(abortCheckCbkData)) { break; } lastAbortCheck = updateLevel; } } // got an argument - save it } else if (numArgs < maxArgs) { args[numArgs++] = obj; // too many arguments - something is wrong } else { error(getPos(), "Too many args in content stream"); if (printCommands) { printf("throwing away arg: "); obj.print(stdout); printf("\n"); fflush(stdout); } obj.free(); } // grab the next object parser->getObj(&obj); } obj.free(); // args at end with no command if (numArgs > 0) { error(getPos(), "Leftover args in content stream"); if (printCommands) { printf("%d leftovers:", numArgs); for (i = 0; i < numArgs; ++i) { printf(" "); args[i].print(stdout); } printf("\n"); fflush(stdout); } for (i = 0; i < numArgs; ++i) args[i].free(); } // update display if (topLevel && updateLevel > 0) { out->dump(); }}void Gfx::execOp(Object *cmd, Object args[], int numArgs) { Operator *op; char *name; Object *argPtr; int i; // find operator name = cmd->getCmd(); if (!(op = findOp(name))) { if (ignoreUndef == 0) error(getPos(), "Unknown operator '%s'", name); return; } // type check args argPtr = args; if (op->numArgs >= 0) { if (numArgs < op->numArgs) { error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name); return; } if (numArgs > op->numArgs) {#if 0 error(getPos(), "Too many (%d) args to '%s' operator", numArgs, name);#endif argPtr += numArgs - op->numArgs; numArgs = op->numArgs; } } else { if (numArgs > -op->numArgs) { error(getPos(), "Too many (%d) args to '%s' operator", numArgs, name); return; } } for (i = 0; i < numArgs; ++i) { if (!checkArg(&argPtr[i], op->tchk[i])) { error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)", i, name, argPtr[i].getTypeName()); return; } } // do it (this->*op->func)(argPtr, numArgs);}Operator *Gfx::findOp(char *name) { int a, b, m, cmp; a = -1; b = numOps; // invariant: opTab[a] < name < opTab[b] while (b - a > 1) { m = (a + b) / 2; cmp = strcmp(opTab[m].name, name); if (cmp < 0) a = m; else if (cmp > 0) b = m; else a = b = m; } if (cmp != 0) return NULL; return &opTab[a];}GBool Gfx::checkArg(Object *arg, TchkType type) { switch (type) { case tchkBool: return arg->isBool(); case tchkInt: return arg->isInt(); case tchkNum: return arg->isNum(); case tchkString: return arg->isString(); case tchkName: return arg->isName(); case tchkArray: return arg->isArray(); case tchkProps: return arg->isDict() || arg->isName(); case tchkSCN: return arg->isNum() || arg->isName(); case tchkNone: return gFalse; } return gFalse;}int Gfx::getPos() { return parser ? parser->getPos() : -1;}//------------------------------------------------------------------------// graphics state operators//------------------------------------------------------------------------void Gfx::opSave(Object args[], int numArgs) { saveState();}void Gfx::opRestore(Object args[], int numArgs) { restoreState();}void Gfx::opConcat(Object args[], int numArgs) { state->concatCTM(args[0].getNum(), args[1].getNum(), args[2].getNum(), args[3].getNum(), args[4].getNum(), args[5].getNum()); out->updateCTM(state, args[0].getNum(), args[1].getNum(), args[2].getNum(), args[3].getNum(), args[4].getNum(), args[5].getNum()); fontChanged = gTrue;}void Gfx::opSetDash(Object args[], int numArgs) { Array *a; int length; Object obj; double *dash; int i; a = args[0].getArray(); length = a->getLength(); if (length == 0) { dash = NULL; } else { dash = (double *)gmallocn(length, sizeof(double)); for (i = 0; i < length; ++i) { dash[i] = a->get(i, &obj)->getNum(); obj.free(); } } state->setLineDash(dash, length, args[1].getNum()); out->updateLineDash(state);}void Gfx::opSetFlat(Object args[], int numArgs) { state->setFlatness((int)args[0].getNum()); out->updateFlatness(state);}void Gfx::opSetLineJoin(Object args[], int numArgs) { state->setLineJoin(args[0].getInt()); out->updateLineJoin(state);}void Gfx::opSetLineCap(Object args[], int numArgs) { state->setLineCap(args[0].getInt()); out->updateLineCap(state);}void Gfx::opSetMiterLimit(Object args[], int numArgs) { state->setMiterLimit(args[0].getNum()); out->updateMiterLimit(state);}void Gfx::opSetLineWidth(Object args[], int numArgs) { state->setLineWidth(args[0].getNum()); out->updateLineWidth(state);}void Gfx::opSetExtGState(Object args[], int numArgs) { Object obj1, obj2, obj3, obj4, obj5; GfxBlendMode mode; GBool haveFillOP; Function *funcs[4]; GfxColor backdropColor; GBool haveBackdropColor; GfxColorSpace *blendingColorSpace; GBool alpha, isolated, knockout; int i; if (!res->lookupGState(args[0].getName(), &obj1)) { return; } if (!obj1.isDict()) { error(getPos(), "ExtGState '%s' is wrong type", args[0].getName()); obj1.free(); return; } if (printCommands) { printf(" gfx state dict: "); obj1.print(); printf("\n"); } // transparency support: blend mode, fill/stroke opacity if (!obj1.dictLookup("BM", &obj2)->isNull()) { if (state->parseBlendMode(&obj2, &mode)) { state->setBlendMode(mode); out->updateBlendMode(state); } else { error(getPos(), "Invalid blend mode in ExtGState"); } } obj2.free(); if (obj1.dictLookup("ca", &obj2)->isNum()) { state->setFillOpacity(obj2.getNum()); out->updateFillOpacity(state); } obj2.free(); if (obj1.dictLookup("CA", &obj2)->isNum()) { state->setStrokeOpacity(obj2.getNum()); out->updateStrokeOpacity(state); } obj2.free(); // fill/stroke overprint if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) { state->setFillOverprint(obj2.getBool()); out->updateFillOverprint(state); } obj2.free(); if (obj1.dictLookup("OP", &obj2)->isBool()) { state->setStrokeOverprint(obj2.getBool()); out->updateStrokeOverprint(state); if (!haveFillOP) { state->setFillOverprint(obj2.getBool()); out->updateFillOverprint(state); } } obj2.free(); // stroke adjust if (obj1.dictLookup("SA", &obj2)->isBool()) { state->setStrokeAdjust(obj2.getBool()); out->updateStrokeAdjust(state); } obj2.free(); // transfer function if (obj1.dictLookup("TR2", &obj2)->isNull()) { obj2.free(); obj1.dictLookup("TR", &obj2); } if (obj2.isName("Default") || obj2.isName("Identity")) { funcs[0] = funcs[1] = funcs[2] = funcs[3] = NULL; state->setTransfer(funcs); out->updateTransfer(state); } else if (obj2.isArray() && obj2.arrayGetLength() == 4) { for (i = 0; i < 4; ++i) { obj2.arrayGet(i, &obj3); funcs[i] = Function::parse(&obj3); obj3.free(); if (!funcs[i]) { break; } } if (i == 4) { state->setTransfer(funcs); out->updateTransfer(state); } } else if (obj2.isName() || obj2.isDict() || obj2.isStream()) { if ((funcs[0] = Function::parse(&obj2))) { funcs[1] = funcs[2] = funcs[3] = NULL; state->setTransfer(funcs); out->updateTransfer(state); } } else if (!obj2.isNull()) { error(getPos(), "Invalid transfer function in ExtGState"); } obj2.free(); // soft mask if (!obj1.dictLookup("SMask", &obj2)->isNull()) { if (obj2.isName("None")) { out->clearSoftMask(state); } else if (obj2.isDict()) { if (obj2.dictLookup("S", &obj3)->isName("Alpha")) { alpha = gTrue; } else { // "Luminosity" alpha = gFalse; } obj3.free(); funcs[0] = NULL; if (!obj2.dictLookup("TR", &obj3)->isNull()) { funcs[0] = Function::parse(&obj3); if (funcs[0]->getInputSize() != 1 || funcs[0]->getOutputSize() != 1) { error(getPos(), "Invalid transfer function in soft mask in ExtGState"); delete funcs[0]; funcs[0] = NULL; } } obj3.free(); if ((haveBackdropColor = obj2.dictLookup("BC", &obj3)->isArray())) { for (i = 0; i < gfxColorMaxComps; ++i) { backdropColor.c[i] = 0; } for (i = 0; i < obj3.arrayGetLength() && i < gfxColorMaxComps; ++i) { obj3.arrayGet(i, &obj4); if (obj4.isNum()) { backdropColor.c[i] = dblToCol(obj4.getNum()); } obj4.free(); } } obj3.free(); if (obj2.dictLookup("G", &obj3)->isStream()) { if (obj3.streamGetDict()->lookup("Group", &obj4)->isDict()) { blendingColorSpace = NULL; isolated = knockout = gFalse; if (!obj4.dictLookup("CS", &obj5)->isNull()) { blendingColorSpace = GfxColorSpace::parse(&obj5); } obj5.free(); if (obj4.dictLookup("I", &obj5)->isBool()) { isolated = obj5.getBool(); } obj5.free(); if (obj4.dictLookup("K", &obj5)->isBool()) { knockout = obj5.getBool(); } obj5.free(); if (!haveBackdropColor) { if (blendingColorSpace) { blendingColorSpace->getDefaultColor(&backdropColor); } else { //~ need to get the parent or default color space (?) for (i = 0; i < gfxColorMaxComps; ++i) { backdropColor.c[i] = 0; } } } doSoftMask(&obj3, alpha, blendingColorSpace, isolated, knockout, funcs[0], &backdropColor); if (funcs[0]) { delete funcs[0]; } } else { error(getPos(), "Invalid soft mask in ExtGState - missing group"); } obj4.free(); } else { error(getPos(), "Invalid soft mask in ExtGState - missing group"); } obj3.free(); } else if (!obj2.isNull()) { error(getPos(), "Invalid soft mask in ExtGState"); } } obj2.free(); obj1.free();}void Gfx::doSoftMask(Object *str, GBool alpha, GfxColorSpace *blendingColorSpace, GBool isolated, GBool knockout, Function *transferFunc, GfxColor *backdropColor) { Dict *dict, *resDict; double m[6], bbox[4]; Object obj1, obj2; int i; // check for excessive recursion if (formDepth > 20) { return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -