diff --git a/poppler/GlobalParams.cc b/poppler/GlobalParams.cc index 77a053d..904b7fb 100644 --- a/poppler/GlobalParams.cc +++ b/poppler/GlobalParams.cc @@ -552,6 +552,7 @@ GlobalParams::GlobalParams(const char *customPopplerDataDir) #ifdef _WIN32 // baseDir will be set by a call to setBaseDir baseDir = new GooString(); + substFiles = new GooHash(gTrue); #else baseDir = appendToPath(getHomeDir(), ".xpdf"); #endif @@ -788,6 +789,9 @@ GlobalParams::~GlobalParams() { deleteGooHash(fontFiles, GooString); deleteGooList(fontDirs, GooString); deleteGooHash(ccFontFiles, GooString); +#ifdef _WIN32 + deleteGooHash(substFiles, GooString); +#endif delete sysFonts; if (psFile) { delete psFile; diff --git a/poppler/GlobalParams.h b/poppler/GlobalParams.h index d72793d..68cfd16 100644 --- a/poppler/GlobalParams.h +++ b/poppler/GlobalParams.h @@ -289,6 +289,7 @@ private: GooList *toUnicodeDirs; // list of ToUnicode CMap dirs [GooString] #ifdef _WIN32 GBool baseFontsInitialized; + GooHash *substFiles; // windows font substitutes (for CID fonts) #endif GooHash *fontFiles; // font files: font name mapped to path // [GString] diff --git a/poppler/GlobalParamsWin.cc b/poppler/GlobalParamsWin.cc index c62e2cd..c106db3 100644 --- a/poppler/GlobalParamsWin.cc +++ b/poppler/GlobalParamsWin.cc @@ -40,6 +40,11 @@ description for all fonts available in Windows. That's how MuPDF works. #include "FontEncodingTables.h" #include "GlobalParams.h" #include "GfxFont.h" +#include +#include "Object.h" +#include "Stream.h" +#include "Lexer.h" +#include "Parser.h" #if MULTITHREADED # define lockGlobalParams gLockMutex(&mutex) @@ -58,6 +63,7 @@ description for all fonts available in Windows. That's how MuPDF works. #endif #define DEFAULT_SUBSTITUTE_FONT "Helvetica" +#define DEFAULT_CID_FONT "MS-Mincho" static struct { const char *name; @@ -147,6 +153,8 @@ static struct { {"Georgia-Bold", NULL, "georgiab.ttf"}, {"Georgia-Italic", NULL, "georgiai.ttf"}, {"Georgia-BoldItalic", NULL, "georgiaz.ttf"}, + // default CID font: + {"MS-Mincho", NULL, "msmincho.ttf"}, {NULL} }; @@ -346,6 +354,12 @@ SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum, void GlobalParams::setupBaseFonts(char * dir) { + const char *dataRoot = popplerDataDir ? popplerDataDir : POPPLER_DATADIR; + GooString *fileName = NULL; + struct stat buf; + FILE *file; + int size = 0; + if (baseFontsInitialized) return; baseFontsInitialized = true; @@ -381,20 +395,81 @@ void GlobalParams::setupBaseFonts(char * dir) if (winFontDir[0]) { sysFonts->scanWindowsFonts(new GooString(winFontDir)); } + + fileName = new GooString(dataRoot); + fileName->append("/cidfmap"); + if (stat(fileName->getCString(), &buf) == 0) { + size = buf.st_size; + } + // try to open file + file = fopen(fileName->getCString(), "rb"); + + if (file != NULL) { + Parser *parser; + Object obj1, obj2; + + obj1.initNull(); + parser = new Parser(NULL, + new Lexer(NULL, + new FileStream(file, 0, gFalse, size, &obj1)), + gTrue); + obj1.free(); + parser->getObj(&obj1); + while (!obj1.isEOF()) { + parser->getObj(&obj2); + if (obj1.isName()) { + // Substitutions + if (obj2.isDict()) { + Object obj3; + obj2.getDict()->lookup("Path", &obj3); + if (obj3.isString()) + addFontFile(new GooString(obj1.getName()), obj3.getString()->copy()); + obj3.free(); + // Aliases + } else if (obj2.isName()) { + substFiles->add(new GooString(obj1.getName()), new GooString(obj2.getName())); + } + } + obj2.free(); + obj1.free(); + parser->getObj(&obj1); + // skip trailing ';' + while (obj1.isCmd(";")) { + obj1.free(); + parser->getObj(&obj1); + } + } + fclose(file); + delete parser; + } } -static char *findSubstituteName(const char *origName) +static char *findSubstituteName(GfxFont *font, GooHash *substFiles, const char *origName) { assert(origName); if (!origName) return NULL; + GooString *name2 = new GooString(origName); + int n = strlen(origName); + // remove trailing "-Identity-H" + if (n > 11 && !strcmp(name2->getCString() + n - 11, "-Identity-H")) { + name2->del(n - 11, 11); + n -= 11; + } + GooString *substName = (GooString *)substFiles->lookup(name2); + if (substName != NULL) { + delete name2; + return substName->getCString(); + } + /* TODO: try to at least guess bold/italic/bolditalic from the name */ - return DEFAULT_SUBSTITUTE_FONT; + delete name2; + return (font->isCIDFont()) ? DEFAULT_CID_FONT: DEFAULT_SUBSTITUTE_FONT; } /* Windows implementation of external font matching code */ GooString *GlobalParams::findSystemFontFile(GfxFont *font, SysFontType *type, - int *fontNum, GooString * /*substituteFontName*/) { + int *fontNum, GooString *substituteFontName) { SysFontInfo *fi; GooString *path = NULL; GooString *fontName = font->getName(); @@ -406,14 +481,21 @@ GooString *GlobalParams::findSystemFontFile(GfxFont *font, *type = fi->type; *fontNum = fi->fontNum; } else { - GooString *substFontName = new GooString(findSubstituteName(fontName->getCString())); + GooString *substFontName = new GooString(findSubstituteName(font, substFiles, fontName->getCString())); + GooString *path2 = NULL; error(errSyntaxError, -1, "Couldn't find a font for '{0:t}', subst is '{1:t}'", fontName, substFontName); - if ((fi = sysFonts->find(substFontName, gFalse))) { - path = fi->path->copy(); - *type = fi->type; - *fontNum = fi->fontNum; - } - } + if ((path2 = (GooString *)fontFiles->lookup(substFontName))) { + path = new GooString(path2); + if (substituteFontName) + substituteFontName->Set(path->getCString()); + if (!strcasecmp(path->getCString() + path->getLength() - 4, ".ttc")) { + *type = sysFontTTC; + } else { + *type = sysFontTTF; + } + *fontNum = 0; + } + } unlockGlobalParams; return path; } diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc index d8e3ac3..19d705c 100644 --- a/poppler/PSOutputDev.cc +++ b/poppler/PSOutputDev.cc @@ -1815,6 +1815,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { setupType3Font(font, psName, parentResDict); } else { fontLoc = font->locateFont(xref, gTrue); + if (fontLoc != NULL) { switch (fontLoc->locType) { case gfxFontLocEmbedded: switch (fontLoc->fontType) { @@ -1886,6 +1887,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) { psName = fontLoc->path->copy(); break; } + } if (!psName) { if (font->isCIDFont()) { @@ -2363,9 +2365,6 @@ void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font, FoFiTrueType *ffTT; int *codeToGID; int codeToGIDLen; - CharCodeToUnicode *ctu; - Unicode *uBuf; - int cmap, code; // beginning comment writePSFmt("%%BeginResource: font {0:t}\n", psName); @@ -2381,57 +2380,40 @@ void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font, if (ffTT->getEmbeddingRights() >= 1) { // create a CID-to-GID mapping, via Unicode - if ((ctu = ((GfxCIDFont *)font)->getToUnicode())) { - // look for a Unicode cmap - for (cmap = 0; cmap < ffTT->getNumCmaps(); ++cmap) { - if ((ffTT->getCmapPlatform(cmap) == 3 && - ffTT->getCmapEncoding(cmap) == 1) || - ffTT->getCmapPlatform(cmap) == 0) { - break; - } - } - if (cmap < ffTT->getNumCmaps()) { - // map CID -> Unicode -> GID - codeToGIDLen = ctu->getLength(); - codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int)); - for (code = 0; code < codeToGIDLen; ++code) { - int n = ctu->mapToUnicode(code, &uBuf); - if (n > 0) { - codeToGID[code] = ffTT->mapCodeToGID(cmap, uBuf[0]); + codeToGID = NULL; + codeToGIDLen = 0; + if (((GfxCIDFont *)font)->getCIDToGID()) { + codeToGIDLen = ((GfxCIDFont *)font)->getCIDToGIDLen(); + if (codeToGIDLen) { + codeToGID = (int *)gmallocn(codeToGIDLen, sizeof(int)); + memcpy(codeToGID, ((GfxCIDFont *)font)->getCIDToGID(), + codeToGIDLen * sizeof(int)); + } + } else { + codeToGID = ((GfxCIDFont *)font)->getCodeToGIDMap(ffTT, &codeToGIDLen); + } + if (ffTT->isOpenTypeCFF()) { + ffTT->convertToCIDType0(psName->getCString(), + codeToGID, codeToGIDLen, + outputFunc, outputStream); + } else if (globalParams->getPSLevel() >= psLevel3) { + // Level 3: use a CID font + ffTT->convertToCIDType2(psName->getCString(), + codeToGID, codeToGIDLen, + needVerticalMetrics, + outputFunc, outputStream); } else { - codeToGID[code] = 0; + // otherwise: use a non-CID composite font + ffTT->convertToType0(psName->getCString(), + codeToGID, codeToGIDLen, + needVerticalMetrics, + outputFunc, outputStream); } - } - if (ffTT->isOpenTypeCFF()) { - ffTT->convertToCIDType0(psName->getCString(), - codeToGID, codeToGIDLen, - outputFunc, outputStream); - } else if (globalParams->getPSLevel() >= psLevel3) { - // Level 3: use a CID font - ffTT->convertToCIDType2(psName->getCString(), - codeToGID, codeToGIDLen, - needVerticalMetrics, - outputFunc, outputStream); - } else { - // otherwise: use a non-CID composite font - ffTT->convertToType0(psName->getCString(), - codeToGID, codeToGIDLen, - needVerticalMetrics, - outputFunc, outputStream); - } - gfree(codeToGID); - } - ctu->decRefCnt(); - } else { - error(errSyntaxError, -1, - "Couldn't find a mapping to Unicode for font '{0:s}'", - font->getName() ? font->getName()->getCString() : "(unnamed)"); - } + gfree(codeToGID); } else { error(errSyntaxError, -1, "TrueType font '%s' does not allow embedding", font->getName() ? font->getName()->getCString() : "(unnamed)"); - } delete ffTT; }