gfx.cc
来自「source code: Covert TXT to PDF」· CC 代码 · 共 2,586 行 · 第 1/5 页
CC
2,586 行
mat = font->getFontMatrix(); newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2]; newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3]; newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2]; newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3]; newCTM[0] *= state->getFontSize(); newCTM[3] *= state->getFontSize(); newCTM[0] *= state->getHorizScaling(); newCTM[2] *= state->getHorizScaling(); state->textTransformDelta(0, state->getRise(), &riseX, &riseY); curX = state->getCurX(); curY = state->getCurY(); lineX = state->getLineX(); lineY = state->getLineY(); oldParser = parser; p = s->getCString(); len = s->getLength(); while (len > 0) { n = font->getNextChar(p, len, &code, u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, &dx, &dy, &originX, &originY); dx = dx * state->getFontSize() + state->getCharSpace(); if (n == 1 && *p == ' ') { dx += state->getWordSpace(); } dx *= state->getHorizScaling(); dy *= state->getFontSize(); state->textTransformDelta(dx, dy, &tdx, &tdy); state->transform(curX + riseX, curY + riseY, &x, &y); out->saveState(state); state = state->save(); state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y); //~ out->updateCTM(???) if (!out->beginType3Char(state, code, u, uLen)) { ((Gfx8BitFont *)font)->getCharProc(code, &charProc); if ((resDict = ((Gfx8BitFont *)font)->getResources())) { pushResources(resDict); } if (charProc.isStream()) { display(&charProc, gFalse); } else { error(getPos(), "Missing or bad Type3 CharProc entry"); } out->endType3Char(state); if (resDict) { popResources(); } charProc.free(); } state = state->restore(); out->restoreState(state); // GfxState::restore() does *not* restore the current position, // so we deal with it here using (curX, curY) and (lineX, lineY) curX += tdx; curY += tdy; state->moveTo(curX, curY); state->textSetPos(lineX, lineY); p += n; len -= n; } parser = oldParser; } else if (out->useDrawChar()) { state->textTransformDelta(0, state->getRise(), &riseX, &riseY); p = s->getCString(); len = s->getLength(); while (len > 0) { n = font->getNextChar(p, len, &code, u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, &dx, &dy, &originX, &originY); if (wMode) { dx *= state->getFontSize(); dy = dy * state->getFontSize() + state->getCharSpace(); if (n == 1 && *p == ' ') { dy += state->getWordSpace(); } } else { dx = dx * state->getFontSize() + state->getCharSpace(); if (n == 1 && *p == ' ') { dx += state->getWordSpace(); } dx *= state->getHorizScaling(); dy *= state->getFontSize(); } state->textTransformDelta(dx, dy, &tdx, &tdy); originX *= state->getFontSize(); originY *= state->getFontSize(); state->textTransformDelta(originX, originY, &tOriginX, &tOriginY); out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY, tdx, tdy, tOriginX, tOriginY, code, u, uLen); state->shift(tdx, tdy); p += n; len -= n; } } else { dx = dy = 0; p = s->getCString(); len = s->getLength(); nChars = nSpaces = 0; while (len > 0) { n = font->getNextChar(p, len, &code, u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, &dx2, &dy2, &originX, &originY); dx += dx2; dy += dy2; if (n == 1 && *p == ' ') { ++nSpaces; } ++nChars; p += n; len -= n; } if (wMode) { dx *= state->getFontSize(); dy = dy * state->getFontSize() + nChars * state->getCharSpace() + nSpaces * state->getWordSpace(); } else { dx = dx * state->getFontSize() + nChars * state->getCharSpace() + nSpaces * state->getWordSpace(); dx *= state->getHorizScaling(); dy *= state->getFontSize(); } state->textTransformDelta(dx, dy, &tdx, &tdy); out->drawString(state, s); state->shift(tdx, tdy); } if (out->useDrawChar()) { out->endString(state); } updateLevel += 10 * s->getLength();}//------------------------------------------------------------------------// XObject operators//------------------------------------------------------------------------void Gfx::opXObject(Object args[], int numArgs) { Object obj1, obj2, obj3, refObj;#if OPI_SUPPORT Object opiDict;#endif if (!res->lookupXObject(args[0].getName(), &obj1)) { return; } if (!obj1.isStream()) { error(getPos(), "XObject '%s' is wrong type", args[0].getName()); obj1.free(); return; }#if OPI_SUPPORT obj1.streamGetDict()->lookup("OPI", &opiDict); if (opiDict.isDict()) { out->opiBegin(state, opiDict.getDict()); }#endif obj1.streamGetDict()->lookup("Subtype", &obj2); if (obj2.isName("Image")) { res->lookupXObjectNF(args[0].getName(), &refObj); doImage(&refObj, obj1.getStream(), gFalse); refObj.free(); } else if (obj2.isName("Form")) { doForm(&obj1); } else if (obj2.isName("PS")) { obj1.streamGetDict()->lookup("Level1", &obj3); out->psXObject(obj1.getStream(), obj3.isStream() ? obj3.getStream() : (Stream *)NULL); } else if (obj2.isName()) { error(getPos(), "Unknown XObject subtype '%s'", obj2.getName()); } else { error(getPos(), "XObject subtype is missing or wrong type"); } obj2.free();#if OPI_SUPPORT if (opiDict.isDict()) { out->opiEnd(state, opiDict.getDict()); } opiDict.free();#endif obj1.free();}void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { Dict *dict; int width, height; int bits; GBool mask; GBool invert; GfxColorSpace *colorSpace; GfxImageColorMap *colorMap; Object maskObj; GBool haveMask; int maskColors[2*gfxColorMaxComps]; Object obj1, obj2; int i; // get stream dict dict = str->getDict(); // get size dict->lookup("Width", &obj1); if (obj1.isNull()) { obj1.free(); dict->lookup("W", &obj1); } if (!obj1.isInt()) goto err2; width = obj1.getInt(); obj1.free(); dict->lookup("Height", &obj1); if (obj1.isNull()) { obj1.free(); dict->lookup("H", &obj1); } if (!obj1.isInt()) goto err2; height = obj1.getInt(); obj1.free(); // image or mask? dict->lookup("ImageMask", &obj1); if (obj1.isNull()) { obj1.free(); dict->lookup("IM", &obj1); } mask = gFalse; if (obj1.isBool()) mask = obj1.getBool(); else if (!obj1.isNull()) goto err2; obj1.free(); // bit depth dict->lookup("BitsPerComponent", &obj1); if (obj1.isNull()) { obj1.free(); dict->lookup("BPC", &obj1); } if (!obj1.isInt()) goto err2; bits = obj1.getInt(); obj1.free(); // display a mask if (mask) { // check for inverted mask if (bits != 1) goto err1; invert = gFalse; dict->lookup("Decode", &obj1); if (obj1.isNull()) { obj1.free(); dict->lookup("D", &obj1); } if (obj1.isArray()) { obj1.arrayGet(0, &obj2); if (obj2.isInt() && obj2.getInt() == 1) invert = gTrue; obj2.free(); } else if (!obj1.isNull()) { goto err2; } obj1.free(); // draw it out->drawImageMask(state, ref, str, width, height, invert, inlineImg); } else { // get color space and color map dict->lookup("ColorSpace", &obj1); if (obj1.isNull()) { obj1.free(); dict->lookup("CS", &obj1); } if (obj1.isName()) { res->lookupColorSpace(obj1.getName(), &obj2); if (!obj2.isNull()) { obj1.free(); obj1 = obj2; } else { obj2.free(); } } colorSpace = GfxColorSpace::parse(&obj1); obj1.free(); if (!colorSpace) { goto err1; } dict->lookup("Decode", &obj1); if (obj1.isNull()) { obj1.free(); dict->lookup("D", &obj1); } colorMap = new GfxImageColorMap(bits, &obj1, colorSpace); obj1.free(); if (!colorMap->isOk()) { delete colorMap; goto err1; } // get the mask haveMask = gFalse; dict->lookup("Mask", &maskObj); if (maskObj.isArray()) { for (i = 0; i < maskObj.arrayGetLength(); ++i) { maskObj.arrayGet(i, &obj1); maskColors[i] = obj1.getInt(); obj1.free(); } haveMask = gTrue; } // draw it out->drawImage(state, ref, str, width, height, colorMap, haveMask ? maskColors : (int *)NULL, inlineImg); delete colorMap; maskObj.free(); } if ((i = width * height) > 1000) { i = 1000; } updateLevel += i; return; err2: obj1.free(); err1: error(getPos(), "Bad image parameters");}void Gfx::doForm(Object *str) { Dict *dict; Object matrixObj, bboxObj; double m[6], bbox[6]; Object resObj; Dict *resDict; Object obj1; int i; // get stream dict dict = str->streamGetDict(); // check form type dict->lookup("FormType", &obj1); if (!(obj1.isInt() && obj1.getInt() == 1)) { error(getPos(), "Unknown form type"); } obj1.free(); // get bounding box dict->lookup("BBox", &bboxObj); if (!bboxObj.isArray()) { matrixObj.free(); bboxObj.free(); error(getPos(), "Bad form bounding box"); return; } for (i = 0; i < 4; ++i) { bboxObj.arrayGet(i, &obj1); bbox[i] = obj1.getNum(); obj1.free(); } bboxObj.free(); // get matrix dict->lookup("Matrix", &matrixObj); if (matrixObj.isArray()) { for (i = 0; i < 6; ++i) { matrixObj.arrayGet(i, &obj1); m[i] = obj1.getNum(); obj1.free(); } } else { m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; m[4] = 0; m[5] = 0; } matrixObj.free(); // get resources dict->lookup("Resources", &resObj); resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; // draw it doForm1(str, resDict, m, bbox); resObj.free();}void Gfx::doAnnot(Object *str, double xMin, double yMin, double xMax, double yMax) { Dict *dict, *resDict; Object matrixObj, bboxObj, resObj; Object obj1; double m[6], bbox[6], ictm[6]; double *ctm; double formX0, formY0, formX1, formY1; double annotX0, annotY0, annotX1, annotY1; double det, x, y, sx, sy; int i; // get stream dict dict = str->streamGetDict(); // get the form bounding box dict->lookup("BBox", &bboxObj); if (!bboxObj.isArray()) { bboxObj.free(); error(getPos(), "Bad form bounding box"); return; } for (i = 0; i < 4; ++i) { bboxObj.arrayGet(i, &obj1); bbox[i] = obj1.getNum(); obj1.free(); } bboxObj.free(); // get the form matrix dict->lookup("Matrix", &matrixObj); if (matrixObj.isArray()) { for (i = 0; i < 6; ++i) { matrixObj.arrayGet(i, &obj1); m[i] = obj1.getNum(); obj1.free(); } } else { m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; m[4] = 0; m[5] = 0; } matrixObj.free(); // transform the form bbox from form space to user space formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4]; formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5]; formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4]; formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5]; // transform the annotation bbox from default user space to user // space: (bbox * baseMatrix) * iCTM ctm = state->getCTM(); det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); ictm[0] = ctm[3] * det; ictm[1] = -ctm[1] * det; ictm[2] = -ctm[2] * det; ictm[3] = ctm[0] * det; ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4]; y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5]; annotX0 = ictm[0] * x + ictm[2] * y + ictm[4]; annotY0 = ictm[1] * x + ictm[3] * y + ictm[5]; x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4]; y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5]; annotX1 = ictm[0] * x + ictm[2] * y + ictm[4]; annotY1 = ictm[1] * x + ictm[3] * y + ictm[5]; // swap min/max coords if (formX0 > formX1) { x = formX0; formX0 = formX1; formX1 = x; } if (formY0 > formY1) { y = formY0; formY0 = formY1; formY1 = y; } if (annotX0 > annotX1) { x = annotX0; annotX0 = annotX1; annotX1 = x; } if (annotY0 > annotY1) { y = annotY0; annotY0 = annotY1; annotY1 = y; } // scale the form to fit the annotation bbox if (formX1 == formX0) { // this shouldn't happen sx = 1; } else { sx = (annotX1 - annotX0) / (formX1 - formX0); } if (formY1 == formY0) { // this shouldn't happen sy = 1; } else { sy = (annotY1 - annotY0) / (formY1 - formY0); } m[0] *= sx; m[2] *= sx; m[4] = (m[4] - formX0) * sx + annotX0; m[1] *= sy; m[3] *= sy; m[5] = (m[5] - formY0) * sy + annotY0; // get resources dict->lookup("Resources", &resObj); resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; // draw it doForm1(str, resDict, m, bbox); resObj.free(); bboxObj.free();}void Gfx::doForm1(Object
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?