📄 splashoutputdev.cc
字号:
strObj.free(); fclose(tmpFile); goto err2; } strObj.streamReset(); while ((c = strObj.streamGetChar()) != EOF) { fputc(c, tmpFile); } strObj.streamClose(); strObj.free(); fclose(tmpFile); fileName = tmpFileName; // if there is an external font file, use it } else if (!(fileName = gfxFont->getExtFontFile())) { // look for a display font mapping or a substitute font if (gfxFont->isCIDFont()) { if (((GfxCIDFont *)gfxFont)->getCollection()) { dfp = globalParams-> getDisplayCIDFont(gfxFont->getName(), ((GfxCIDFont *)gfxFont)->getCollection()); } } else { if (gfxFont->getName()) { dfp = globalParams->getDisplayFont(gfxFont->getName()); } if (!dfp) { // 8-bit font substitution if (gfxFont->isFixedWidth()) { substIdx = 8; } else if (gfxFont->isSerif()) { substIdx = 4; } else { substIdx = 0; } if (gfxFont->isBold()) { substIdx += 2; } if (gfxFont->isItalic()) { substIdx += 1; } substName = new GString(splashOutSubstFonts[substIdx].name); dfp = globalParams->getDisplayFont(substName); delete substName; id->setSubstIdx(substIdx); } } if (!dfp) { error(-1, "Couldn't find a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } switch (dfp->kind) { case displayFontT1: fileName = dfp->t1.fileName; fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1; break; case displayFontTT: fileName = dfp->tt.fileName; fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType; break; } } // load the font file switch (fontType) { case fontType1: if (!(fontFile = fontEngine->loadType1Font( id, fileName->getCString(), fileName == tmpFileName, ((Gfx8BitFont *)gfxFont)->getEncoding()))) { error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontType1C: if (!(fontFile = fontEngine->loadType1CFont( id, fileName->getCString(), fileName == tmpFileName, ((Gfx8BitFont *)gfxFont)->getEncoding()))) { error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontType1COT: if (!(fontFile = fontEngine->loadOpenTypeT1CFont( id, fileName->getCString(), fileName == tmpFileName, ((Gfx8BitFont *)gfxFont)->getEncoding()))) { error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontTrueType: case fontTrueTypeOT: if ((ff = FoFiTrueType::load(fileName->getCString()))) { codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff); n = 256; delete ff; } else { codeToGID = NULL; n = 0; } if (!(fontFile = fontEngine->loadTrueTypeFont( id, fileName->getCString(), fileName == tmpFileName, codeToGID, n))) { error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontCIDType0: case fontCIDType0C: if (!(fontFile = fontEngine->loadCIDFont( id, fileName->getCString(), fileName == tmpFileName))) { error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontCIDType0COT: if (!(fontFile = fontEngine->loadOpenTypeCFFFont( id, fileName->getCString(), fileName == tmpFileName))) { error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontCIDType2: case fontCIDType2OT: codeToGID = NULL; n = 0; if (dfp) { // create a CID-to-GID mapping, via Unicode if ((ctu = ((GfxCIDFont *)gfxFont)->getToUnicode())) { if ((ff = FoFiTrueType::load(fileName->getCString()))) { // look for a Unicode cmap for (cmap = 0; cmap < ff->getNumCmaps(); ++cmap) { if ((ff->getCmapPlatform(cmap) == 3 && ff->getCmapEncoding(cmap) == 1) || ff->getCmapPlatform(cmap) == 0) { break; } } if (cmap < ff->getNumCmaps()) { // map CID -> Unicode -> GID n = ctu->getLength(); codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort)); for (code = 0; code < n; ++code) { if (ctu->mapToUnicode(code, uBuf, 8) > 0) { codeToGID[code] = ff->mapCodeToGID(cmap, uBuf[0]); } else { codeToGID[code] = 0; } } } delete ff; } ctu->decRefCnt(); } else { error(-1, "Couldn't find a mapping to Unicode for font '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); } } else { if (((GfxCIDFont *)gfxFont)->getCIDToGID()) { n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(); codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort)); memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(), n * sizeof(Gushort)); } } if (!(fontFile = fontEngine->loadTrueTypeFont( id, fileName->getCString(), fileName == tmpFileName, codeToGID, n))) { error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; default: // this shouldn't happen goto err2; } } // get the font matrix textMat = state->getTextMat(); fontSize = state->getFontSize(); m11 = textMat[0] * fontSize * state->getHorizScaling(); m12 = textMat[1] * fontSize * state->getHorizScaling(); m21 = textMat[2] * fontSize; m22 = textMat[3] * fontSize; // for substituted fonts: adjust the font matrix -- compare the // width of 'm' in the original font and the substituted font substIdx = ((SplashOutFontFileID *)fontFile->getID())->getSubstIdx(); if (substIdx >= 0) { for (code = 0; code < 256; ++code) { if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) && name[0] == 'm' && name[1] == '\0') { break; } } if (code < 256) { w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code); w2 = splashOutSubstFonts[substIdx].mWidth; if (!gfxFont->isSymbolic()) { // if real font is substantially narrower than substituted // font, reduce the font size accordingly if (w1 > 0.01 && w1 < 0.9 * w2) { w1 /= w2; m11 *= w1; m21 *= w1; } } } } // create the scaled font mat[0] = m11; mat[1] = m12; mat[2] = m21; mat[3] = m22; font = fontEngine->getFont(fontFile, mat, splash->getMatrix()); if (tmpFileName) { delete tmpFileName; } return; err2: delete id; err1: if (tmpFileName) { unlink(tmpFileName->getCString()); delete tmpFileName; } return;}void SplashOutputDev::stroke(GfxState *state) { SplashPath *path; if (state->getStrokeColorSpace()->isNonMarking()) { return; } path = convertPath(state, state->getPath()); splash->stroke(path); delete path;}void SplashOutputDev::fill(GfxState *state) { SplashPath *path; if (state->getFillColorSpace()->isNonMarking()) { return; } path = convertPath(state, state->getPath()); splash->fill(path, gFalse); delete path;}void SplashOutputDev::eoFill(GfxState *state) { SplashPath *path; if (state->getFillColorSpace()->isNonMarking()) { return; } path = convertPath(state, state->getPath()); splash->fill(path, gTrue); delete path;}void SplashOutputDev::clip(GfxState *state) { SplashPath *path; path = convertPath(state, state->getPath()); splash->clipToPath(path, gFalse); delete path;}void SplashOutputDev::eoClip(GfxState *state) { SplashPath *path; path = convertPath(state, state->getPath()); splash->clipToPath(path, gTrue); delete path;}void SplashOutputDev::clipToStrokePath(GfxState *state) { SplashPath *path, *path2; path = convertPath(state, state->getPath()); path2 = splash->makeStrokePath(path); delete path; splash->clipToPath(path2, gFalse); delete path2;}SplashPath *SplashOutputDev::convertPath(GfxState *state, GfxPath *path) { SplashPath *sPath; GfxSubpath *subpath; int i, j; sPath = new SplashPath(); for (i = 0; i < path->getNumSubpaths(); ++i) { subpath = path->getSubpath(i); if (subpath->getNumPoints() > 0) { sPath->moveTo((SplashCoord)subpath->getX(0), (SplashCoord)subpath->getY(0)); j = 1; while (j < subpath->getNumPoints()) { if (subpath->getCurve(j)) { sPath->curveTo((SplashCoord)subpath->getX(j), (SplashCoord)subpath->getY(j), (SplashCoord)subpath->getX(j+1), (SplashCoord)subpath->getY(j+1), (SplashCoord)subpath->getX(j+2), (SplashCoord)subpath->getY(j+2)); j += 3; } else { sPath->lineTo((SplashCoord)subpath->getX(j), (SplashCoord)subpath->getY(j)); ++j; } } if (subpath->isClosed()) { sPath->close(); } } } return sPath;}void SplashOutputDev::drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, CharCode code, int nBytes, Unicode *u, int uLen) { SplashPath *path; int render; // check for invisible text -- this is used by Acrobat Capture render = state->getRender(); if (render == 3) { return; } if (needFontUpdate) { doUpdateFont(state); } if (!font) { return; } x -= originX; y -= originY; // fill if (!(render & 1)) { if (!state->getFillColorSpace()->isNonMarking()) { splash->fillChar((SplashCoord)x, (SplashCoord)y, code, font); } } // stroke if ((render & 3) == 1 || (render & 3) == 2) { if (!state->getStrokeColorSpace()->isNonMarking()) { if ((path = font->getGlyphPath(code))) { path->offset((SplashCoord)x, (SplashCoord)y); splash->stroke(path); delete path; } } } // clip if (render & 4) { if ((path = font->getGlyphPath(code))) { path->offset((SplashCoord)x, (SplashCoord)y); if (textClipPath) { textClipPath->append(path); delete path; } else { textClipPath = path; } } }}GBool SplashOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen) { GfxFont *gfxFont; Ref *fontID; double *ctm, *bbox; T3FontCache *t3Font; T3GlyphStack *t3gs; GBool validBBox; double x1, y1, xMin, yMin, xMax, yMax, xt, yt; int i, j; if (!(gfxFont = state->getFont())) { return gFalse; } fontID = gfxFont->getID(); ctm = state->getCTM(); state->transform(0, 0, &xt, &yt); // is it the first (MRU) font in the cache? if (!(nT3Fonts > 0 && t3FontCache[0]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3]))) { // is the font elsewhere in the cache? for (i = 1; i < nT3Fonts; ++i) { if (t3FontCache[i]->matches(fontID, ctm[0], ctm[1], ctm[2], ctm[3])) { t3Font = t3FontCache[i]; for (j = i; j > 0; --j) { t3FontCache[j] = t3FontCache[j - 1]; } t3FontCache[0] = t3Font; break; } } if (i >= nT3Fonts) { // create new entry in the font cache if (nT3Fonts == splashOutT3FontCacheSize) { delete t3FontCache[nT3Fonts - 1]; --nT3Fonts; } for (j = nT3Fonts; j > 0; --j) { t3FontCache[j] = t3FontCache[j - 1]; } ++nT3Fonts; bbox = gfxFont->getFontBBox(); if (bbox[0] == 0 && bbox[1] == 0 && bbox[2] == 0 && bbox[3] == 0) { // unspecified bounding box -- just take a guess xMin = xt - 5; xMax = xMin + 30; yMax = yt + 15; yMin = yMax - 45; validBBox = gFalse; } else { state->transform(bbox[0], bbox[1], &x1, &y1); xMin = xMax = x1; yMin = yMax = y1; state->transform(bbox[0], bbox[3], &x1, &y1); if (x1 < xMin) { xMin = x1; } else if (x1 > xMax) { xMax = x1; } if (y1 < yMin) { yMin = y1; } else if (y1 > yMax) { yMax = y1; } state->transform(bbox[2], bbox[1], &x1, &y1); if (x1 < xMin) { xMin = x1; } else if (x1 > xMax) { xMax = x1; } if (y1 < yMin) { yMin = y1; } else if (y1 > yMax) { yMax = y1; } state->transform(bbox[2], bbox[3], &x1, &y1); if (x1 < xMin) { xMin = x1; } else if (x1 > xMax) { xMax = x1; } if (y1 < yMin) { yMin = y1; } else if (y1 > yMax) { yMax = y1; } validBBox = gTrue; } t3FontCache[0] = new T3FontCache(fontID, ctm[0], ctm[1], ctm[2], ctm[3], (int)floor(xMin - xt), (int)floor(yMin - yt),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -