📄 psoutputdev.cc
字号:
} }}void PSOutputDev::setupResources(Dict *resDict) { Object xObjDict, xObjRef, xObj, patDict, patRef, pat, resObj; Ref ref0, ref1; GBool skip; int i, j; setupFonts(resDict); setupImages(resDict); setupForms(resDict); //----- recursively scan XObjects resDict->lookup("XObject", &xObjDict); if (xObjDict.isDict()) { for (i = 0; i < xObjDict.dictGetLength(); ++i) { // avoid infinite recursion on XObjects skip = gFalse; if ((xObjDict.dictGetValNF(i, &xObjRef)->isRef())) { ref0 = xObjRef.getRef(); for (j = 0; j < xobjStack->getLength(); ++j) { ref1 = *(Ref *)xobjStack->get(j); if (ref1.num == ref0.num && ref1.gen == ref0.gen) { skip = gTrue; break; } } if (!skip) { xobjStack->append(&ref0); } } if (!skip) { // process the XObject's resource dictionary xObjDict.dictGetVal(i, &xObj); if (xObj.isStream()) { xObj.streamGetDict()->lookup("Resources", &resObj); if (resObj.isDict()) { setupResources(resObj.getDict()); } resObj.free(); } xObj.free(); } if (xObjRef.isRef() && !skip) { xobjStack->del(xobjStack->getLength() - 1); } xObjRef.free(); } } xObjDict.free(); //----- recursively scan Patterns resDict->lookup("Pattern", &patDict); if (patDict.isDict()) { inType3Char = gTrue; for (i = 0; i < patDict.dictGetLength(); ++i) { // avoid infinite recursion on Patterns skip = gFalse; if ((patDict.dictGetValNF(i, &patRef)->isRef())) { ref0 = patRef.getRef(); for (j = 0; j < xobjStack->getLength(); ++j) { ref1 = *(Ref *)xobjStack->get(j); if (ref1.num == ref0.num && ref1.gen == ref0.gen) { skip = gTrue; break; } } if (!skip) { xobjStack->append(&ref0); } } if (!skip) { // process the Pattern's resource dictionary patDict.dictGetVal(i, &pat); if (pat.isStream()) { pat.streamGetDict()->lookup("Resources", &resObj); if (resObj.isDict()) { setupResources(resObj.getDict()); } resObj.free(); } pat.free(); } if (patRef.isRef() && !skip) { xobjStack->del(xobjStack->getLength() - 1); } patRef.free(); } inType3Char = gFalse; } patDict.free();}void PSOutputDev::setupFonts(Dict *resDict) { Object obj1, obj2; Ref r; GfxFontDict *gfxFontDict; GfxFont *font; int i; gfxFontDict = NULL; resDict->lookupNF("Font", &obj1); if (obj1.isRef()) { obj1.fetch(xref, &obj2); if (obj2.isDict()) { r = obj1.getRef(); gfxFontDict = new GfxFontDict(xref, &r, obj2.getDict()); } obj2.free(); } else if (obj1.isDict()) { gfxFontDict = new GfxFontDict(xref, NULL, obj1.getDict()); } if (gfxFontDict) { for (i = 0; i < gfxFontDict->getNumFonts(); ++i) { if ((font = gfxFontDict->getFont(i))) { setupFont(font, resDict); } } delete gfxFontDict; } obj1.free();}void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { Ref fontFileID; GString *name; PSFontParam *fontParam; GString *psName; char buf[16]; GBool subst; UnicodeMap *uMap; char *charName; double xs, ys; int code; double w1, w2; double *fm; int i, j; // check if font is already set up for (i = 0; i < fontIDLen; ++i) { if (fontIDs[i].num == font->getID()->num && fontIDs[i].gen == font->getID()->gen) { return; } } // add entry to fontIDs list if (fontIDLen >= fontIDSize) { fontIDSize += 64; fontIDs = (Ref *)greallocn(fontIDs, fontIDSize, sizeof(Ref)); } fontIDs[fontIDLen++] = *font->getID(); xs = ys = 1; subst = gFalse; // check for resident 8-bit font if (font->getName() && (fontParam = globalParams->getPSFont(font->getName()))) { psName = new GString(fontParam->psFontName->getCString()); // check for embedded Type 1 font } else if (globalParams->getPSEmbedType1() && font->getType() == fontType1 && font->getEmbeddedFontID(&fontFileID)) { psName = filterPSName(font->getEmbeddedFontName()); setupEmbeddedType1Font(&fontFileID, psName); // check for embedded Type 1C font } else if (globalParams->getPSEmbedType1() && font->getType() == fontType1C && font->getEmbeddedFontID(&fontFileID)) { // use the PDF font name because the embedded font name might // not include the subset prefix psName = filterPSName(font->getOrigName()); setupEmbeddedType1CFont(font, &fontFileID, psName); // check for embedded OpenType - Type 1C font } else if (globalParams->getPSEmbedType1() && font->getType() == fontType1COT && font->getEmbeddedFontID(&fontFileID)) { // use the PDF font name because the embedded font name might // not include the subset prefix psName = filterPSName(font->getOrigName()); setupEmbeddedOpenTypeT1CFont(font, &fontFileID, psName); // check for external Type 1 font file } else if (globalParams->getPSEmbedType1() && font->getType() == fontType1 && font->getExtFontFile()) { // this assumes that the PS font name matches the PDF font name psName = font->getName()->copy(); setupExternalType1Font(font->getExtFontFile(), psName); // check for embedded TrueType font } else if (globalParams->getPSEmbedTrueType() && (font->getType() == fontTrueType || font->getType() == fontTrueTypeOT) && font->getEmbeddedFontID(&fontFileID)) { psName = filterPSName(font->getEmbeddedFontName()); setupEmbeddedTrueTypeFont(font, &fontFileID, psName); // check for external TrueType font file } else if (globalParams->getPSEmbedTrueType() && font->getType() == fontTrueType && font->getExtFontFile()) { psName = filterPSName(font->getName()); setupExternalTrueTypeFont(font, psName); // check for embedded CID PostScript font } else if (globalParams->getPSEmbedCIDPostScript() && font->getType() == fontCIDType0C && font->getEmbeddedFontID(&fontFileID)) { psName = filterPSName(font->getEmbeddedFontName()); setupEmbeddedCIDType0Font(font, &fontFileID, psName); // check for embedded CID TrueType font } else if (globalParams->getPSEmbedCIDTrueType() && (font->getType() == fontCIDType2 || font->getType() == fontCIDType2OT) && font->getEmbeddedFontID(&fontFileID)) { psName = filterPSName(font->getEmbeddedFontName()); //~ should check to see if font actually uses vertical mode setupEmbeddedCIDTrueTypeFont(font, &fontFileID, psName, gTrue); // check for embedded OpenType - CID CFF font } else if (globalParams->getPSEmbedCIDPostScript() && font->getType() == fontCIDType0COT && font->getEmbeddedFontID(&fontFileID)) { psName = filterPSName(font->getEmbeddedFontName()); setupEmbeddedOpenTypeCFFFont(font, &fontFileID, psName); // check for Type 3 font } else if (font->getType() == fontType3) { psName = GString::format("T3_{0:d}_{1:d}", font->getID()->num, font->getID()->gen); setupType3Font(font, psName, parentResDict); // do 8-bit font substitution } else if (!font->isCIDFont()) { subst = gTrue; name = font->getName(); psName = NULL; if (name) { for (i = 0; psFonts[i]; ++i) { if (name->cmp(psFonts[i]) == 0) { psName = new GString(psFonts[i]); break; } } } if (!psName) { if (font->isFixedWidth()) { i = 8; } else if (font->isSerif()) { i = 4; } else { i = 0; } if (font->isBold()) { i += 2; } if (font->isItalic()) { i += 1; } psName = new GString(psSubstFonts[i].psName); for (code = 0; code < 256; ++code) { if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) && charName[0] == 'm' && charName[1] == '\0') { break; } } if (code < 256) { w1 = ((Gfx8BitFont *)font)->getWidth(code); } else { w1 = 0; } w2 = psSubstFonts[i].mWidth; xs = w1 / w2; if (xs < 0.1) { xs = 1; } if (font->getType() == fontType3) { // This is a hack which makes it possible to substitute for some // Type 3 fonts. The problem is that it's impossible to know what // the base coordinate system used in the font is without actually // rendering the font. ys = xs; fm = font->getFontMatrix(); if (fm[0] != 0) { ys *= fm[3] / fm[0]; } } else { ys = 1; } } // do 16-bit font substitution } else if ((fontParam = globalParams-> getPSFont16(font->getName(), ((GfxCIDFont *)font)->getCollection(), font->getWMode()))) { subst = gTrue; psName = fontParam->psFontName->copy(); if (font16EncLen >= font16EncSize) { font16EncSize += 16; font16Enc = (PSFont16Enc *)greallocn(font16Enc, font16EncSize, sizeof(PSFont16Enc)); } font16Enc[font16EncLen].fontID = *font->getID(); font16Enc[font16EncLen].enc = fontParam->encoding->copy(); if ((uMap = globalParams->getUnicodeMap(font16Enc[font16EncLen].enc))) { uMap->decRefCnt(); ++font16EncLen; } else { error(-1, "Couldn't find Unicode map for 16-bit font encoding '%s'", font16Enc[font16EncLen].enc->getCString()); } // give up - can't do anything with this font } else { error(-1, "Couldn't find a font to substitute for '%s' ('%s' character collection)", font->getName() ? font->getName()->getCString() : "(unnamed)", ((GfxCIDFont *)font)->getCollection() ? ((GfxCIDFont *)font)->getCollection()->getCString() : "(unknown)"); return; } // generate PostScript code to set up the font if (font->isCIDFont()) { if (level == psLevel3 || level == psLevel3Sep) { writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16L3\n", font->getID()->num, font->getID()->gen, psName, font->getWMode()); } else { writePSFmt("/F{0:d}_{1:d} /{2:t} {3:d} pdfMakeFont16\n", font->getID()->num, font->getID()->gen, psName, font->getWMode()); } } else { writePSFmt("/F{0:d}_{1:d} /{2:t} {3:.4g} {4:.4g}\n", font->getID()->num, font->getID()->gen, psName, xs, ys); for (i = 0; i < 256; i += 8) { writePS((char *)((i == 0) ? "[ " : " ")); for (j = 0; j < 8; ++j) { if (font->getType() == fontTrueType && !subst && !((Gfx8BitFont *)font)->getHasEncoding()) { sprintf(buf, "c%02x", i+j); charName = buf; } else { charName = ((Gfx8BitFont *)font)->getCharName(i+j); // this is a kludge for broken PDF files that encode char 32 // as .notdef if (i+j == 32 && charName && !strcmp(charName, ".notdef")) { charName = "space"; } } writePS("/"); writePSName(charName ? charName : (char *)".notdef"); // the empty name is legal in PDF and PostScript, but PostScript // uses a double-slash (//...) for "immediately evaluated names", // so we need to add a space character here if (charName && !charName[0]) { writePS(" "); } } writePS((i == 256-8) ? (char *)"]\n" : (char *)"\n"); } writePS("pdfMakeFont\n"); } delete psName;}void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) { static char hexChar[17] = "0123456789abcdef"; Object refObj, strObj, obj1, obj2, obj3; Dict *dict; int length1, length2, length3; int c; int start[4]; GBool binMode; int i; // check if font is already embedded for (i = 0; i < fontFileIDLen; ++i) { if (fontFileIDs[i].num == id->num && fontFileIDs[i].gen == id->gen) return; } // add entry to fontFileIDs list if (fontFileIDLen >= fontFileIDSize) { fontFileIDSize += 64; fontFileIDs = (Ref *)greallocn(fontFileIDs, fontFileIDSize, sizeof(Ref)); } fontFileIDs[fontFileIDLen++] = *id; // get the font stream and info refObj.initRef(id->num, id->gen); refObj.fetch(xref, &strObj); refObj.free(); if (!strObj.isStream()) { error(-1, "Embedded font file object is not a stream"); goto err1; } if (!(dict = strObj.streamGetDict())) { error(-1, "Embedded font stream is missing its dictionary"); goto err1; } dict->lookup("Length1", &obj1); dict->lookup("Length2", &obj2); dict->lookup("Length3", &obj3); if (!obj1.isInt() || !obj2.isInt() || !obj3.isInt()) { error(-1, "Missing length fields in embedded font stream dictionary"); obj1.free(); obj2.free(); obj3.free(); goto err1; } length1 = obj1.getInt(); length2 = obj2.getInt(); length3 = obj3.getInt(); obj1.free(); obj2.free(); obj3.free(); // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); embFontList->append("%%+ font "); embFontList->append(psName->getCString()); embFontList->append("\n"); // copy ASCII portion of font strObj.streamReset(); for (i = 0; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) { writePSChar(c); } // figure out if encrypted portion is binary or ASCII binMode = gFalse; for (i = 0; i < 4; ++i) { start[i] = strObj.streamGetChar(); if (start[i] == EOF) { error(-1, "Unexpected end of file in embedded font stream"); goto err1; } if (!((start[i] >= '0' && start[i] <= '9') || (start[i] >= 'A' && start[i] <= 'F') || (start[i] >= 'a' && start[i] <= 'f'))) binMode = gTrue; } // convert binary data to ASCII if (binMode) { for (i = 0; i < 4; ++i) { writePSChar(hexChar[(start[i] >> 4) & 0x0f]); writePSChar(hexChar[start[i] & 0x0f]); }#if 0 // this causes trouble for various PostScript printers // if Length2 is incorrect (too small), font data gets chopped, so // we take a few extra characters from the trailer just in case length2 += length3 >= 8 ? 8 : length3;#endif while (i < length2) { if ((c = strObj.streamGetChar()) == EOF) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -