[poppler] Branch 'xpdf303merge' - poppler/Annot.cc poppler/ArthurOutputDev.cc poppler/CairoFontEngine.cc poppler/CharCodeToUnicode.h poppler/CMap.cc poppler/CMap.h poppler/FontInfo.cc poppler/Gfx.cc poppler/GfxFont.cc poppler/GfxFont.h poppler/GfxState.cc poppler/GfxState.h poppler/GlobalParams.cc poppler/GlobalParams.h poppler/GlobalParamsWin.cc poppler/PreScanOutputDev.cc poppler/PSOutputDev.cc poppler/PSOutputDev.h poppler/SplashOutputDev.cc poppler/XRef.cc
Albert Astals Cid
aacid at kemper.freedesktop.org
Wed Feb 1 13:55:48 PST 2012
poppler/Annot.cc | 6
poppler/ArthurOutputDev.cc | 47 --
poppler/CMap.cc | 153 ++++++++
poppler/CMap.h | 16
poppler/CairoFontEngine.cc | 43 --
poppler/CharCodeToUnicode.h | 1
poppler/FontInfo.cc | 8
poppler/Gfx.cc | 363 +++++++++++--------
poppler/GfxFont.cc | 831 +++++++++++++++++++++++++++++---------------
poppler/GfxFont.h | 34 -
poppler/GfxState.cc | 81 ++--
poppler/GfxState.h | 2
poppler/GlobalParams.cc | 738 ++++++++++++++++++++++-----------------
poppler/GlobalParams.h | 112 ++---
poppler/GlobalParamsWin.cc | 180 +++++++--
poppler/PSOutputDev.cc | 591 +++++++++++++++----------------
poppler/PSOutputDev.h | 12
poppler/PreScanOutputDev.cc | 10
poppler/SplashOutputDev.cc | 59 +--
poppler/XRef.cc | 16
20 files changed, 2008 insertions(+), 1295 deletions(-)
New commits:
commit 4fcd42cfa4424992cd4b36af38bc6230ce0706c9
Author: Albert Astals Cid <aacid at kde.org>
Date: Wed Feb 1 22:53:03 2012 +0100
[xpdf303] More merges from Thomas (with minor fixes from me)
Basically fonts related and some other small stuff
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 235120c..9f07b2f 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -3082,10 +3082,10 @@ void AnnotWidget::drawText(GooString *text, GooString *da, GfxResources *resourc
// We are forcing ZaDb but the font does not exist
// so create a fake one
Ref r; // dummy Ref, it's not used at all in this codepath
- r.num = 0;
- r.gen = 0;
+ r.num = -1;
+ r.gen = -1;
Dict *d = new Dict(xref);
- font = new Gfx8BitFont(xref, "ZaDb", r, new GooString("ZapfDingbats"), fontType1, d);
+ font = new Gfx8BitFont(xref, "ZaDb", r, new GooString("ZapfDingbats"), fontType1, r, d);
delete d;
freeFont = gTrue;
addDingbatsResource = gTrue;
diff --git a/poppler/ArthurOutputDev.cc b/poppler/ArthurOutputDev.cc
index f0c3090..92bc84f 100644
--- a/poppler/ArthurOutputDev.cc
+++ b/poppler/ArthurOutputDev.cc
@@ -270,18 +270,17 @@ void ArthurOutputDev::updateFont(GfxState *state)
{
#ifdef HAVE_SPLASH
GfxFont *gfxFont;
+ GfxFontLoc *fontLoc;
GfxFontType fontType;
SplashOutFontFileID *id;
SplashFontFile *fontFile;
SplashFontSrc *fontsrc = NULL;
FoFiTrueType *ff;
- Ref embRef;
Object refObj, strObj;
GooString *fileName;
char *tmpBuf;
int tmpBufLen;
int *codeToGID;
- DisplayFontParam *dfp;
double *textMat;
double m11, m12, m21, m22, fontSize;
SplashCoord mat[4];
@@ -309,36 +308,24 @@ void ArthurOutputDev::updateFont(GfxState *state)
} else {
- // if there is an embedded font, write it to disk
- if (gfxFont->getEmbeddedFontID(&embRef)) {
+ if (!(fontLoc = gfxFont->locateFont(xref, gFalse))) {
+ error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
+ gfxFont->getName() ? gfxFont->getName()->getCString()
+ : "(unnamed)");
+ goto err2;
+ }
+
+ // embedded font
+ if (fontLoc->locType == gfxFontLocEmbedded) {
+ // if there is an embedded font, read it to memory
tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen);
if (! tmpBuf)
goto err2;
- // if there is an external font file, use it
- } else if (!(fileName = gfxFont->getExtFontFile())) {
- // look for a display font mapping or a substitute font
- dfp = NULL;
- if (gfxFont->getName()) {
- dfp = globalParams->getDisplayFont(gfxFont);
- }
- if (!dfp) {
- error(errSyntaxError, -1, "Couldn't find a font for '{0: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;
- faceIndex = dfp->tt.faceIndex;
- break;
- }
+ // external font
+ } else { // gfxFontLocExternal
+ fileName = fontLoc->path;
+ fontType = fontLoc->fontType;
}
fontsrc = new SplashFontSrc;
@@ -346,7 +333,7 @@ void ArthurOutputDev::updateFont(GfxState *state)
fontsrc->setFile(fileName, gFalse);
else
fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue);
-
+
// load the font file
switch (fontType) {
case fontType1:
@@ -497,12 +484,14 @@ void ArthurOutputDev::updateFont(GfxState *state)
mat[2] = m21; mat[3] = -m22;
m_font = m_fontEngine->getFont(fontFile, mat, matrix);
+ delete fontLoc;
if (fontsrc && !fontsrc->isFile)
fontsrc->unref();
return;
err2:
delete id;
+ delete fontLoc;
err1:
if (fontsrc && !fontsrc->isFile)
fontsrc->unref();
diff --git a/poppler/CMap.cc b/poppler/CMap.cc
index e26849b..13f293a 100644
--- a/poppler/CMap.cc
+++ b/poppler/CMap.cc
@@ -62,6 +62,75 @@ static int getCharFromStream(void *data) {
//------------------------------------------------------------------------
+CMap *CMap::parse(CMapCache *cache, GooString *collectionA, Object *obj) {
+ CMap *cMap;
+ GooString *cMapNameA;
+
+ if (obj->isName()) {
+ cMapNameA = new GooString(obj->getName());
+ if (!(cMap = globalParams->getCMap(collectionA, cMapNameA))) {
+ error(errSyntaxError, -1,
+ "Unknown CMap '{0:t}' for character collection '{1:t}'",
+ cMapNameA, collectionA);
+ }
+ delete cMapNameA;
+ } else if (obj->isStream()) {
+ if (!(cMap = CMap::parse(NULL, collectionA, obj->getStream()))) {
+ error(errSyntaxError, -1, "Invalid CMap in Type 0 font");
+ }
+ } else {
+ error(errSyntaxError, -1, "Invalid Encoding in Type 0 font");
+ return NULL;
+ }
+ return cMap;
+}
+
+CMap *CMap::parse(CMapCache *cache, GooString *collectionA,
+ GooString *cMapNameA) {
+ FILE *f;
+ CMap *cMap;
+
+ if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) {
+
+ // Check for an identity CMap.
+ if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) {
+ return new CMap(collectionA->copy(), cMapNameA->copy(), 0);
+ }
+ if (!cMapNameA->cmp("Identity-V")) {
+ return new CMap(collectionA->copy(), cMapNameA->copy(), 1);
+ }
+
+ error(errSyntaxError, -1,
+ "Couldn't find '{0:t}' CMap file for '{1:t}' collection",
+ cMapNameA, collectionA);
+ return NULL;
+ }
+
+ cMap = new CMap(collectionA->copy(), cMapNameA->copy());
+ cMap->parse2(cache, &getCharFromFile, f);
+
+ fclose(f);
+
+ return cMap;
+}
+
+CMap *CMap::parse(CMapCache *cache, GooString *collectionA, Stream *str) {
+ Object obj1;
+ CMap *cMap;
+
+ cMap = new CMap(collectionA->copy(), NULL);
+
+ if (!str->getDict()->lookup("UseCMap", &obj1)->isNull()) {
+ cMap->useCMap(cache, &obj1);
+ }
+ obj1.free();
+
+ str->reset();
+ cMap->parse2(cache, &getCharFromStream, str);
+ str->close();
+ return cMap;
+}
+
CMap *CMap::parse(CMapCache *cache, GooString *collectionA,
GooString *cMapNameA, Stream *stream) {
FILE *f = NULL;
@@ -163,6 +232,76 @@ CMap *CMap::parse(CMapCache *cache, GooString *collectionA,
return cmap;
}
+void CMap::parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data) {
+ PSTokenizer *pst;
+ char tok1[256], tok2[256], tok3[256];
+ int n1, n2, n3;
+ Guint start, end, code;
+
+ pst = new PSTokenizer(getCharFunc, data);
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ while (pst->getToken(tok2, sizeof(tok2), &n2)) {
+ if (!strcmp(tok2, "usecmap")) {
+ if (tok1[0] == '/') {
+ useCMap(cache, tok1 + 1);
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok1, "/WMode")) {
+ wMode = atoi(tok2);
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "begincidchar")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endcidchar")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endcidchar")) {
+ error(errSyntaxError, -1, "Illegal entry in cidchar block in CMap");
+ break;
+ }
+ if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
+ n1 >= 4 && (n1 & 1) == 0)) {
+ error(errSyntaxError, -1, "Illegal entry in cidchar block in CMap");
+ continue;
+ }
+ tok1[n1 - 1] = '\0';
+ if (sscanf(tok1 + 1, "%x", &code) != 1) {
+ error(errSyntaxError, -1, "Illegal entry in cidchar block in CMap");
+ continue;
+ }
+ n1 = (n1 - 2) / 2;
+ addCIDs(code, code, n1, (CID)atoi(tok2));
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "begincidrange")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endcidrange")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endcidrange") ||
+ !pst->getToken(tok3, sizeof(tok3), &n3) ||
+ !strcmp(tok3, "endcidrange")) {
+ error(errSyntaxError, -1, "Illegal entry in cidrange block in CMap");
+ break;
+ }
+ if (tok1[0] == '<' && tok2[0] == '<' &&
+ n1 == n2 && n1 >= 4 && (n1 & 1) == 0) {
+ tok1[n1 - 1] = tok2[n1 - 1] = '\0';
+ sscanf(tok1 + 1, "%x", &start);
+ sscanf(tok2 + 1, "%x", &end);
+ n1 = (n1 - 2) / 2;
+ addCIDs(start, end, n1, (CID)atoi(tok3));
+ }
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else {
+ strcpy(tok1, tok2);
+ }
+ }
+ delete pst;
+}
+
CMap::CMap(GooString *collectionA, GooString *cMapNameA) {
int i;
@@ -218,6 +357,20 @@ void CMap::useCMap(CMapCache *cache, char *useName) {
subCMap->decRefCnt();
}
+void CMap::useCMap(CMapCache *cache, Object *obj) {
+ CMap *subCMap;
+
+ subCMap = CMap::parse(cache, collection, obj);
+ if (!subCMap) {
+ return;
+ }
+ isIdent = subCMap->isIdent;
+ if (subCMap->vector) {
+ copyVector(vector, subCMap->vector);
+ }
+ subCMap->decRefCnt();
+}
+
void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) {
int i, j;
diff --git a/poppler/CMap.h b/poppler/CMap.h
index f2e61f1..3f7085d 100644
--- a/poppler/CMap.h
+++ b/poppler/CMap.h
@@ -37,6 +37,7 @@
#endif
class GooString;
+class Object;
struct CMapVectorEntry;
class CMapCache;
class Stream;
@@ -46,6 +47,19 @@ class Stream;
class CMap {
public:
+ // Parse a CMap from <obj>, which can be a name or a stream. Sets
+ // the initial reference count to 1. Returns NULL on failure.
+ static CMap *parse(CMapCache *cache, GooString *collectionA, Object *obj);
+
+ // Create the CMap specified by <collection> and <cMapName>. Sets
+ // the initial reference count to 1. Returns NULL on failure.
+ static CMap *parse(CMapCache *cache, GooString *collectionA,
+ GooString *cMapNameA);
+
+ // Parse a CMap from <str>. Sets the initial reference count to 1.
+ // Returns NULL on failure.
+ static CMap *parse(CMapCache *cache, GooString *collectionA, Stream *str);
+
// Create the CMap specified by <collection> and <cMapName>. Sets
// the initial reference count to 1.
// Stream is a stream containing the CMap, can be NULL and
@@ -78,9 +92,11 @@ public:
private:
+ void parse2(CMapCache *cache, int (*getCharFunc)(void *), void *data);
CMap(GooString *collectionA, GooString *cMapNameA);
CMap(GooString *collectionA, GooString *cMapNameA, int wModeA);
void useCMap(CMapCache *cache, char *useName);
+ void useCMap(CMapCache *cache, Object *obj);
void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src);
void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID);
void freeCMapVector(CMapVectorEntry *vec);
diff --git a/poppler/CairoFontEngine.cc b/poppler/CairoFontEngine.cc
index 889b073..2b02523 100644
--- a/poppler/CairoFontEngine.cc
+++ b/poppler/CairoFontEngine.cc
@@ -381,15 +381,14 @@ CairoFreeTypeFont::~CairoFreeTypeFont() { }
CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref,
FT_Library lib, GBool useCIDs) {
- Ref embRef;
Object refObj, strObj;
GooString *fileName;
char *fileNameC;
char *font_data;
int font_data_len;
- DisplayFontParam *dfp;
int i, n;
GfxFontType fontType;
+ GfxFontLoc *fontLoc;
char **enc;
char *name;
FoFiTrueType *ff;
@@ -401,7 +400,6 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref,
int *codeToGID;
Guint codeToGIDLen;
- dfp = NULL;
codeToGID = NULL;
codeToGIDLen = 0;
font_data = NULL;
@@ -414,32 +412,23 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref,
ref = *gfxFont->getID();
fontType = gfxFont->getType();
- if (gfxFont->getEmbeddedFontID(&embRef)) {
+ if (!(fontLoc = gfxFont->locateFont(xref, gFalse))) {
+ error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
+ gfxFont->getName() ? gfxFont->getName()->getCString()
+ : "(unnamed)");
+ goto err2;
+ }
+
+ // embedded font
+ if (fontLoc->locType == gfxFontLocEmbedded) {
font_data = gfxFont->readEmbFontFile(xref, &font_data_len);
if (NULL == font_data)
goto err2;
- } else if (!(fileName = gfxFont->getExtFontFile())) {
- // look for a display font mapping or a substitute font
- dfp = NULL;
- if (gfxFont->getName()) {
- dfp = globalParams->getDisplayFont(gfxFont);
- }
- if (!dfp) {
- error(errSyntaxError, -1, "Couldn't find a font for '{0: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;
- }
+
+ // external font
+ } else { // gfxFontLocExternal
+ fileName = fontLoc->path;
+ fontType = fontLoc->fontType;
substitute = gTrue;
}
@@ -546,6 +535,7 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref,
break;
}
+ delete fontLoc;
return new CairoFreeTypeFont(ref,
font_face,
codeToGID, codeToGIDLen,
@@ -553,6 +543,7 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref,
err2:
/* hmm? */
+ delete fontLoc;
fprintf (stderr, "some font thing failed\n");
return NULL;
}
diff --git a/poppler/CharCodeToUnicode.h b/poppler/CharCodeToUnicode.h
index edc53f2..66417a1 100644
--- a/poppler/CharCodeToUnicode.h
+++ b/poppler/CharCodeToUnicode.h
@@ -89,6 +89,7 @@ public:
// Map a CharCode to Unicode.
int mapToUnicode(CharCode c, Unicode **u);
+ // Map a Unicode to CharCode.
int mapToCharCode(Unicode* u, CharCode *c, int usize);
// Return the mapping's length, i.e., one more than the max char
diff --git a/poppler/FontInfo.cc b/poppler/FontInfo.cc
index 9c6a97e..4847937 100644
--- a/poppler/FontInfo.cc
+++ b/poppler/FontInfo.cc
@@ -191,12 +191,8 @@ FontInfo::FontInfo(GfxFont *font, PDFDoc *doc) {
if (!emb)
{
- DisplayFontParam *dfp = globalParams->getDisplayFont(font);
- if (dfp)
- {
- if (dfp->kind == displayFontT1) file = dfp->t1.fileName->copy();
- else file = dfp->tt.fileName->copy();
- }
+ GooString *fontFile = globalParams->findFontFile(font->getName());
+ if (fontFile != NULL) file = fontFile->copy();
else file = NULL;
}
else file = NULL;
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index fc49da7..4fa9431 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -689,7 +689,8 @@ void Gfx::go(GBool topLevel) {
// scan a sequence of objects
pushStateGuard();
- updateLevel = lastAbortCheck = 0;
+ updateLevel = 1; // make sure even empty pages trigger a call to dump()
+ lastAbortCheck = 0;
numArgs = 0;
parser->getObj(&obj);
while (!obj.isEOF()) {
@@ -858,6 +859,7 @@ Operator *Gfx::findOp(char *name) {
a = -1;
b = numOps;
+ cmp = 0; // make gcc happy
// invariant: opTab[a] < name < opTab[b]
while (b - a > 1) {
m = (a + b) / 2;
@@ -964,6 +966,7 @@ void Gfx::opSetLineWidth(Object args[], int numArgs) {
void Gfx::opSetExtGState(Object args[], int numArgs) {
Object obj1, obj2, obj3, obj4, obj5;
+ Object args2[2];
GfxBlendMode mode;
GBool haveFillOP;
Function *funcs[4];
@@ -971,6 +974,7 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
GBool haveBackdropColor;
GfxColorSpace *blendingColorSpace;
GBool alpha, isolated, knockout;
+ double opac;
int i;
if (!res->lookupGState(args[0].getName(), &obj1)) {
@@ -987,6 +991,53 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
printf("\n");
}
+ // parameters that are also set by individual PDF operators
+ if (obj1.dictLookup("LW", &obj2)->isNum()) {
+ opSetLineWidth(&obj2, 1);
+ }
+ obj2.free();
+ if (obj1.dictLookup("LC", &obj2)->isInt()) {
+ opSetLineCap(&obj2, 1);
+ }
+ obj2.free();
+ if (obj1.dictLookup("LJ", &obj2)->isInt()) {
+ opSetLineJoin(&obj2, 1);
+ }
+ obj2.free();
+ if (obj1.dictLookup("ML", &obj2)->isNum()) {
+ opSetMiterLimit(&obj2, 1);
+ }
+ obj2.free();
+ if (obj1.dictLookup("D", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 2) {
+ obj2.arrayGet(0, &args2[0]);
+ obj2.arrayGet(1, &args2[1]);
+ if (args2[0].isArray() && args2[1].isNum()) {
+ opSetDash(args2, 2);
+ }
+ args2[0].free();
+ args2[1].free();
+ }
+ obj2.free();
+#if 0 //~ need to add a new version of GfxResources::lookupFont() that
+ //~ takes an indirect ref instead of a name
+ if (obj1.dictLookup("Font", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 2) {
+ obj2.arrayGet(0, &args2[0]);
+ obj2.arrayGet(1, &args2[1]);
+ if (args2[0].isDict() && args2[1].isNum()) {
+ opSetFont(args2, 2);
+ }
+ args2[0].free();
+ args2[1].free();
+ }
+ obj2.free();
+#endif
+ if (obj1.dictLookup("FL", &obj2)->isNum()) {
+ opSetFlat(&obj2, 1);
+ }
+ obj2.free();
+
// transparency support: blend mode, fill/stroke opacity
if (!obj1.dictLookup("BM", &obj2)->isNull()) {
if (state->parseBlendMode(&obj2, &mode)) {
@@ -998,17 +1049,19 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
}
obj2.free();
if (obj1.dictLookup("ca", &obj2)->isNum()) {
- state->setFillOpacity(obj2.getNum());
+ opac = obj2.getNum();
+ state->setFillOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac);
out->updateFillOpacity(state);
}
obj2.free();
if (obj1.dictLookup("CA", &obj2)->isNum()) {
- state->setStrokeOpacity(obj2.getNum());
+ opac = obj2.getNum();
+ state->setStrokeOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac);
out->updateStrokeOpacity(state);
}
obj2.free();
- // fill/stroke overprint
+ // fill/stroke overprint, overprint mode
if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) {
state->setFillOverprint(obj2.getBool());
out->updateFillOverprint(state);
@@ -1097,13 +1150,18 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
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(errSyntaxError, getPos(),
- "Invalid transfer function in soft mask in ExtGState");
- delete funcs[0];
+ if (obj3.isName("Default") ||
+ obj3.isName("Identity")) {
funcs[0] = NULL;
+ } else {
+ funcs[0] = Function::parse(&obj3);
+ if (funcs[0]->getInputSize() != 1 ||
+ funcs[0]->getOutputSize() != 1) {
+ error(errSyntaxError, getPos(),
+ "Invalid transfer function in soft mask in ExtGState");
+ delete funcs[0];
+ funcs[0] = NULL;
+ }
}
}
obj3.free();
@@ -1723,11 +1781,13 @@ void Gfx::opStroke(Object args[], int numArgs) {
//error(errSyntaxError, getPos(), "No path in stroke");
return;
}
- if (state->isPath() && !contentIsHidden()) {
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (state->isPath()) {
+ if (ocState) {
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1738,12 +1798,14 @@ void Gfx::opCloseStroke(Object * /*args[]*/, int /*numArgs*/) {
//error(errSyntaxError, getPos(), "No path in closepath/stroke");
return;
}
- state->closePath();
- if (state->isPath() && !contentIsHidden()) {
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (state->isPath()) {
+ state->closePath();
+ if (ocState) {
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1754,11 +1816,13 @@ void Gfx::opFill(Object args[], int numArgs) {
//error(errSyntaxError, getPos(), "No path in fill");
return;
}
- if (state->isPath() && !contentIsHidden()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gFalse);
- } else {
- out->fill(state);
+ if (state->isPath()) {
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
}
}
doEndPath();
@@ -1769,11 +1833,13 @@ void Gfx::opEOFill(Object args[], int numArgs) {
//error(errSyntaxError, getPos(), "No path in eofill");
return;
}
- if (state->isPath() && !contentIsHidden()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gTrue);
- } else {
- out->eoFill(state);
+ if (state->isPath()) {
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
}
}
doEndPath();
@@ -1784,16 +1850,18 @@ void Gfx::opFillStroke(Object args[], int numArgs) {
//error(errSyntaxError, getPos(), "No path in fill/stroke");
return;
}
- if (state->isPath() && !contentIsHidden()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gFalse);
- } else {
- out->fill(state);
- }
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (state->isPath()) {
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1804,17 +1872,19 @@ void Gfx::opCloseFillStroke(Object args[], int numArgs) {
//error(errSyntaxError, getPos(), "No path in closepath/fill/stroke");
return;
}
- if (state->isPath() && !contentIsHidden()) {
+ if (state->isPath()) {
state->closePath();
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gFalse);
- } else {
- out->fill(state);
- }
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1825,16 +1895,18 @@ void Gfx::opEOFillStroke(Object args[], int numArgs) {
//error(errSyntaxError, getPos(), "No path in eofill/stroke");
return;
}
- if (state->isPath() && !contentIsHidden()) {
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gTrue);
- } else {
- out->eoFill(state);
- }
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (state->isPath()) {
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -1845,17 +1917,19 @@ void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
//error(errSyntaxError, getPos(), "No path in closepath/eofill/stroke");
return;
}
- if (state->isPath() && !contentIsHidden()) {
+ if (state->isPath()) {
state->closePath();
- if (state->getFillColorSpace()->getMode() == csPattern) {
- doPatternFill(gTrue);
- } else {
- out->eoFill(state);
- }
- if (state->getStrokeColorSpace()->getMode() == csPattern) {
- doPatternStroke();
- } else {
- out->stroke(state);
+ if (ocState) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ doPatternStroke();
+ } else {
+ out->stroke(state);
+ }
}
}
doEndPath();
@@ -2123,25 +2197,23 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
for (i = 0; i < 4; ++i) {
m1[i] = m[i];
}
- if (!contentIsHidden()) {
- m1[4] = m[4];
- m1[5] = m[5];
- if (out->useTilingPatternFill() &&
- out->tilingPatternFill(state, this, catalog, tPat->getContentStream(),
- tPat->getMatrix(), tPat->getPaintType(), tPat->getTilingType(),
- tPat->getResDict(), m1, tPat->getBBox(),
- xi0, yi0, xi1, yi1, xstep, ystep)) {
- goto restore;
- } else {
- for (yi = yi0; yi < yi1; ++yi) {
- for (xi = xi0; xi < xi1; ++xi) {
- x = xi * xstep;
- y = yi * ystep;
- m1[4] = x * m[0] + y * m[2] + m[4];
- m1[5] = x * m[1] + y * m[3] + m[5];
- drawForm(tPat->getContentStream(), tPat->getResDict(),
- m1, tPat->getBBox());
- }
+ m1[4] = m[4];
+ m1[5] = m[5];
+ if (out->useTilingPatternFill() &&
+ out->tilingPatternFill(state, this, catalog, tPat->getContentStream(),
+ tPat->getMatrix(), tPat->getPaintType(), tPat->getTilingType(),
+ tPat->getResDict(), m1, tPat->getBBox(),
+ xi0, yi0, xi1, yi1, xstep, ystep)) {
+ goto restore;
+ } else {
+ for (yi = yi0; yi < yi1; ++yi) {
+ for (xi = xi0; xi < xi1; ++xi) {
+ x = xi * xstep;
+ y = yi * ystep;
+ m1[4] = x * m[0] + y * m[2] + m[4];
+ m1[5] = x * m[1] + y * m[3] + m[5];
+ drawForm(tPat->getContentStream(), tPat->getResDict(),
+ m1, tPat->getBBox());
}
}
}
@@ -2420,8 +2492,7 @@ void Gfx::doFunctionShFill1(GfxFunctionShading *shading,
state->lineTo(x0 * matrix[0] + y1 * matrix[2] + matrix[4],
x0 * matrix[1] + y1 * matrix[3] + matrix[5]);
state->closePath();
- if (!contentIsHidden())
- out->fill(state);
+ out->fill(state);
state->clearPath();
// the four corner colors are not close enough -- subdivide the
@@ -2741,8 +2812,7 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
}
if (!out->useFillColorStop()) {
- if (!contentIsHidden())
- out->fill(state);
+ out->fill(state);
state->clearPath();
}
@@ -2763,8 +2833,7 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
state->lineTo(xMax, yMin);
state->closePath();
}
- if (!contentIsHidden())
- out->fill(state);
+ out->fill(state);
state->clearPath();
}
}
@@ -3098,8 +3167,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
if (!out->useFillColorStop()) {
// fill the path
- if (!contentIsHidden())
- out->fill(state);
+ out->fill(state);
state->clearPath();
}
@@ -3125,8 +3193,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
state->lineTo(xMax, yMin);
state->closePath();
- if (!contentIsHidden())
- out->fill(state);
+ out->fill(state);
state->clearPath();
}
@@ -3157,8 +3224,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
}
state->closePath();
- if (!contentIsHidden())
- out->fill(state);
+ out->fill(state);
state->clearPath();
}
@@ -3190,8 +3256,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
}
state->closePath();
- if (!contentIsHidden())
- out->fill(state);
+ out->fill(state);
state->clearPath();
}
}
@@ -3201,7 +3266,7 @@ void Gfx::doGouraudTriangleShFill(GfxGouraudTriangleShading *shading) {
double x0, y0, x1, y1, x2, y2;
int i;
- if (out->useShadedFills( shading->getType()) && !contentIsHidden()) {
+ if (out->useShadedFills( shading->getType())) {
if (out->gouraudTriangleShadedFill( state, shading))
return;
}
@@ -3264,14 +3329,13 @@ void Gfx::gouraudFillTriangle(double x0, double y0, GfxColor *color0,
state->setFillColor(color0);
out->updateFillColor(state);
- path->reset(); assert(!path->isEnd());
- path->setCoord(x0,y0); path->next(); assert(!path->isEnd());
- path->setCoord(x1,y1); path->next(); assert(!path->isEnd());
- path->setCoord(x2,y2); path->next(); assert(!path->isEnd());
- path->setCoord(x0,y0); path->next(); assert( path->isEnd());
+ path->reset(); assert(!path->isEnd());
+ path->setCoord(x0,y0); path->next(); assert(!path->isEnd());
+ path->setCoord(x1,y1); path->next(); assert(!path->isEnd());
+ path->setCoord(x2,y2); path->next(); assert(!path->isEnd());
+ path->setCoord(x0,y0); path->next(); assert( path->isEnd());
+ out->fill(state);
- if (!contentIsHidden())
- out->fill(state);
} else {
x01 = 0.5 * (x0 + x1);
y01 = 0.5 * (y0 + y1);
@@ -3312,14 +3376,13 @@ void Gfx::gouraudFillTriangle(double x0, double y0, double color0,
state->setFillColor(&color);
out->updateFillColor(state);
- path->reset(); assert(!path->isEnd());
- path->setCoord(x0,y0); path->next(); assert(!path->isEnd());
- path->setCoord(x1,y1); path->next(); assert(!path->isEnd());
- path->setCoord(x2,y2); path->next(); assert(!path->isEnd());
- path->setCoord(x0,y0); path->next(); assert( path->isEnd());
+ path->reset(); assert(!path->isEnd());
+ path->setCoord(x0,y0); path->next(); assert(!path->isEnd());
+ path->setCoord(x1,y1); path->next(); assert(!path->isEnd());
+ path->setCoord(x2,y2); path->next(); assert(!path->isEnd());
+ path->setCoord(x0,y0); path->next(); assert( path->isEnd());
+ out->fill(state);
- if (!contentIsHidden())
- out->fill(state);
} else {
const double x01 = 0.5 * (x0 + x1);
const double y01 = 0.5 * (y0 + y1);
@@ -3353,7 +3416,7 @@ void Gfx::gouraudFillTriangle(double x0, double y0, double color0,
void Gfx::doPatchMeshShFill(GfxPatchMeshShading *shading) {
int start, i;
- if (out->useShadedFills( shading->getType()) && !contentIsHidden()) {
+ if (out->useShadedFills( shading->getType())) {
if (out->patchMeshShadedFill( state, shading))
return;
}
@@ -3444,8 +3507,7 @@ void Gfx::fillPatch(GfxPatch *patch, int colorComps, int patchColorComps, double
patch->x[1][0], patch->y[1][0],
patch->x[0][0], patch->y[0][0]);
state->closePath();
- if (!contentIsHidden())
- out->fill(state);
+ out->fill(state);
state->clearPath();
} else {
for (i = 0; i < 4; ++i) {
@@ -3616,7 +3678,6 @@ void Gfx::opSetTextLeading(Object args[], int numArgs) {
}
void Gfx::opSetTextRender(Object args[], int numArgs) {
- int rm = state->getRender();
state->setRender(args[0].getInt());
out->updateRender(state);
}
@@ -3953,15 +4014,12 @@ void Gfx::doShowText(GooString *s) {
originX *= state->getFontSize();
originY *= state->getFontSize();
state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
- if (!contentIsHidden()) {
- out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
+ out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
tdx, tdy, tOriginX, tOriginY, code, n, u, uLen);
- }
state->shift(tdx, tdy);
p += n;
len -= n;
}
-
} else {
dx = dy = 0;
p = s->getCString();
@@ -3993,8 +4051,7 @@ void Gfx::doShowText(GooString *s) {
dy *= state->getFontSize();
}
state->textTransformDelta(dx, dy, &tdx, &tdy);
- if (!contentIsHidden())
- out->drawString(state, s);
+ out->drawString(state, s);
state->shift(tdx, tdy);
}
@@ -4130,7 +4187,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
GBool maskInterpolate;
Stream *maskStr;
Object obj1, obj2;
- int i;
+ int i, n;
// get info from the stream
bits = 0;
@@ -4246,8 +4303,17 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
}
obj1.free();
+ // if drawing is disabled, skip over inline image data
+ if (!ocState) {
+ str->reset();
+ n = height * ((width + 7) / 8);
+ for (i = 0; i < n; ++i) {
+ str->getChar();
+ }
+ str->close();
+
// draw it
- if (!contentIsHidden()) {
+ } else {
if (state->getFillColorSpace()->getMode() == csPattern) {
doPatternImageMask(ref, str, width, height, invert, inlineImg);
} else {
@@ -4492,19 +4558,29 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
haveExplicitMask = gTrue;
}
+ // if drawing is disabled, skip over inline image data
+ if (!ocState) {
+ str->reset();
+ n = height * ((width * colorMap->getNumPixelComps() *
+ colorMap->getBits() + 7) / 8);
+ for (i = 0; i < n; ++i) {
+ str->getChar();
+ }
+ str->close();
+
// draw it
- if (haveSoftMask) {
- if (!contentIsHidden()) {
- out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, interpolate,
+ } else {
+ if (haveSoftMask) {
+ out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, interpolate,
maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate);
+ delete maskColorMap;
+ } else if (haveExplicitMask) {
+ out->drawMaskedImage(state, ref, str, width, height, colorMap, interpolate,
+ maskStr, maskWidth, maskHeight, maskInvert, maskInterpolate);
+ } else {
+ out->drawImage(state, ref, str, width, height, colorMap, interpolate,
+ haveColorKeyMask ? maskColors : (int *)NULL, inlineImg);
}
- delete maskColorMap;
- } else if (haveExplicitMask && !contentIsHidden ()) {
- out->drawMaskedImage(state, ref, str, width, height, colorMap, interpolate,
- maskStr, maskWidth, maskHeight, maskInvert, maskInterpolate);
- } else if (!contentIsHidden()) {
- out->drawImage(state, ref, str, width, height, colorMap, interpolate,
- haveColorKeyMask ? maskColors : (int *)NULL, inlineImg);
}
delete colorMap;
@@ -4757,6 +4833,9 @@ void Gfx::opBeginImage(Object args[], int numArgs) {
Stream *str;
int c1, c2;
+ // NB: this function is run even if ocState is false -- doImage() is
+ // responsible for skipping over the inline image data
+
// build dict/stream
str = buildImageStream();
@@ -4937,6 +5016,7 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
printf("\n");
fflush(stdout);
}
+ ocState = !contentIsHidden();
}
void Gfx::opEndMarkedContent(Object args[], int numArgs) {
@@ -4953,6 +5033,7 @@ void Gfx::opEndMarkedContent(Object args[], int numArgs) {
if (mcKind == gfxMCActualText)
out->endActualText(state);
+ ocState = !contentIsHidden();
}
void Gfx::opMarkPoint(Object args[], int numArgs) {
diff --git a/poppler/GfxFont.cc b/poppler/GfxFont.cc
index a5006f0..c839ad4 100644
--- a/poppler/GfxFont.cc
+++ b/poppler/GfxFont.cc
@@ -43,6 +43,8 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <math.h>
+#include <limits.h>
#include <algorithm>
#include "goo/gmem.h"
#include "Error.h"
@@ -53,6 +55,7 @@
#include "CharCodeToUnicode.h"
#include "FontEncodingTables.h"
#include "BuiltinFontTables.h"
+#include <fofi/FoFiIdentifier.h>
#include <fofi/FoFiType1.h>
#include <fofi/FoFiType1C.h>
#include <fofi/FoFiTrueType.h>
@@ -162,6 +165,12 @@ static int parseCharName(char *charName, Unicode *uBuf, int uLen,
GBool numeric, GBool hex, GBool variants);
//------------------------------------------------------------------------
+
+static int readFromStream(void *data) {
+ return ((Stream *)data)->getChar();
+}
+
+//------------------------------------------------------------------------
// GfxFontLoc
//------------------------------------------------------------------------
@@ -182,17 +191,13 @@ GfxFontLoc::~GfxFontLoc() {
}
//------------------------------------------------------------------------
-
-static int readFromStream(void *data) {
- return ((Stream *)data)->getChar();
-}
-
-//------------------------------------------------------------------------
// GfxFont
//------------------------------------------------------------------------
GfxFont *GfxFont::makeFont(XRef *xref, const char *tagA, Ref idA, Dict *fontDict) {
GooString *nameA;
+ Ref embFontIDA;
+ GfxFontType typeA;
GfxFont *font;
Object obj1;
@@ -204,41 +209,35 @@ GfxFont *GfxFont::makeFont(XRef *xref, const char *tagA, Ref idA, Dict *fontDict
}
obj1.free();
- // get font type
+ // get embedded font ID and font type
+ typeA = getFontType(xref, fontDict, &embFontIDA);
+
+ // create the font object
font = NULL;
- fontDict->lookup("Subtype", &obj1);
- if (obj1.isName("Type1") || obj1.isName("MMType1")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict);
- } else if (obj1.isName("Type1C")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict);
- } else if (obj1.isName("Type3")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict);
- } else if (obj1.isName("TrueType")) {
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict);
- } else if (obj1.isName("Type0")) {
- font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict);
+ if (typeA < fontCIDType0) {
+ font = new Gfx8BitFont(xref, tagA, idA, nameA, typeA, embFontIDA,
+ fontDict);
} else {
- error(errSyntaxError, -1, "Unknown font type: '{0:s}'",
- obj1.isName() ? obj1.getName() : "???");
- font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict);
+ font = new GfxCIDFont(xref, tagA, idA, nameA, typeA, embFontIDA,
+ fontDict);
}
- obj1.free();
return font;
}
-GfxFont::GfxFont(const char *tagA, Ref idA, GooString *nameA) {
+GfxFont::GfxFont(const char *tagA, Ref idA, GooString *nameA,
+ GfxFontType typeA, Ref embFontIDA) {
ok = gFalse;
tag = new GooString(tagA);
id = idA;
name = nameA;
+ type = typeA;
+ embFontID = embFontIDA;
embFontName = NULL;
- extFontFile = NULL;
family = NULL;
stretch = StretchNotDefined;
weight = WeightNotDefined;
refCnt = 1;
- dfp = NULL;
hasToUnicode = gFalse;
}
@@ -251,10 +250,6 @@ GfxFont::~GfxFont() {
if (embFontName) {
delete embFontName;
}
- if (extFontFile) {
- delete extFontFile;
- }
- delete dfp;
}
void GfxFont::incRefCnt() {
@@ -266,6 +261,200 @@ void GfxFont::decRefCnt() {
delete this;
}
+// This function extracts three pieces of information:
+// 1. the "expected" font type, i.e., the font type implied by
+// Font.Subtype, DescendantFont.Subtype, and
+// FontDescriptor.FontFile3.Subtype
+// 2. the embedded font object ID
+// 3. the actual font type - determined by examining the embedded font
+// if there is one, otherwise equal to the expected font type
+// If the expected and actual font types don't match, a warning
+// message is printed. The expected font type is not used for
+// anything else.
+GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) {
+ GfxFontType t, expectedType;
+ FoFiIdentifierType fft;
+ Dict *fontDict2;
+ Object subtype, fontDesc, obj1, obj2, obj3, obj4;
+ GBool isType0, err;
+
+ t = fontUnknownType;
+ embID->num = embID->gen = -1;
+ err = gFalse;
+
+ fontDict->lookup("Subtype", &subtype);
+ expectedType = fontUnknownType;
+ isType0 = gFalse;
+ if (subtype.isName("Type1") || subtype.isName("MMType1")) {
+ expectedType = fontType1;
+ } else if (subtype.isName("Type1C")) {
+ expectedType = fontType1C;
+ } else if (subtype.isName("Type3")) {
+ expectedType = fontType3;
+ } else if (subtype.isName("TrueType")) {
+ expectedType = fontTrueType;
+ } else if (subtype.isName("Type0")) {
+ isType0 = gTrue;
+ } else {
+ error(errSyntaxWarning, -1, "Unknown font type: '{0:s}'",
+ subtype.isName() ? subtype.getName() : "???");
+ }
+ subtype.free();
+
+ fontDict2 = fontDict;
+ if (fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() == 0) {
+ error(errSyntaxWarning, -1, "Empty DescendantFonts array in font");
+ obj2.initNull();
+ } else if (obj1.arrayGet(0, &obj2)->isDict()) {
+ if (!isType0) {
+ error(errSyntaxWarning, -1, "Non-CID font with DescendantFonts array");
+ }
+ fontDict2 = obj2.getDict();
+ fontDict2->lookup("Subtype", &subtype);
+ if (subtype.isName("CIDFontType0")) {
+ if (isType0) {
+ expectedType = fontCIDType0;
+ }
+ } else if (subtype.isName("CIDFontType2")) {
+ if (isType0) {
+ expectedType = fontCIDType2;
+ }
+ }
+ subtype.free();
+ }
+ } else {
+ obj2.initNull();
+ }
+
+ if (fontDict2->lookup("FontDescriptor", &fontDesc)->isDict()) {
+ if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) {
+ *embID = obj3.getRef();
+ if (expectedType != fontType1) {
+ err = gTrue;
+ }
+ }
+ obj3.free();
+ if (embID->num == -1 &&
+ fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) {
+ *embID = obj3.getRef();
+ if (isType0) {
+ expectedType = fontCIDType2;
+ } else if (expectedType != fontTrueType) {
+ err = gTrue;
+ }
+ }
+ obj3.free();
+ if (embID->num == -1 &&
+ fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) {
+ *embID = obj3.getRef();
+ if (obj3.fetch(xref, &obj4)->isStream()) {
+ obj4.streamGetDict()->lookup("Subtype", &subtype);
+ if (subtype.isName("Type1")) {
+ if (expectedType != fontType1) {
+ err = gTrue;
+ expectedType = isType0 ? fontCIDType0 : fontType1;
+ }
+ } else if (subtype.isName("Type1C")) {
+ if (expectedType == fontType1) {
+ expectedType = fontType1C;
+ } else if (expectedType != fontType1C) {
+ err = gTrue;
+ expectedType = isType0 ? fontCIDType0C : fontType1C;
+ }
+ } else if (subtype.isName("TrueType")) {
+ if (expectedType != fontTrueType) {
+ err = gTrue;
+ expectedType = isType0 ? fontCIDType2 : fontTrueType;
+ }
+ } else if (subtype.isName("CIDFontType0C")) {
+ if (expectedType == fontCIDType0) {
+ expectedType = fontCIDType0C;
+ } else {
+ err = gTrue;
+ expectedType = isType0 ? fontCIDType0C : fontType1C;
+ }
+ } else if (subtype.isName("OpenType")) {
+ if (expectedType == fontTrueType) {
+ expectedType = fontTrueTypeOT;
+ } else if (expectedType == fontType1) {
+ expectedType = fontType1COT;
+ } else if (expectedType == fontCIDType0) {
+ expectedType = fontCIDType0COT;
+ } else if (expectedType == fontCIDType2) {
+ expectedType = fontCIDType2OT;
+ } else {
+ err = gTrue;
+ }
+ } else {
+ error(errSyntaxError, -1, "Unknown font type '{0:s}'",
+ subtype.isName() ? subtype.getName() : "???");
+ }
+ subtype.free();
+ }
+ obj4.free();
+ }
+ obj3.free();
+ }
+ fontDesc.free();
+
+ t = fontUnknownType;
+ if (embID->num >= 0) {
+ obj3.initRef(embID->num, embID->gen);
+ obj3.fetch(xref, &obj4);
+ if (obj4.isStream()) {
+ obj4.streamReset();
+ fft = FoFiIdentifier::identifyStream(&readFromStream, obj4.getStream());
+ obj4.streamClose();
+ switch (fft) {
+ case fofiIdType1PFA:
+ case fofiIdType1PFB:
+ t = fontType1;
+ break;
+ case fofiIdCFF8Bit:
+ t = isType0 ? fontCIDType0C : fontType1C;
+ break;
+ case fofiIdCFFCID:
+ t = fontCIDType0C;
+ break;
+ case fofiIdTrueType:
+ case fofiIdTrueTypeCollection:
+ t = isType0 ? fontCIDType2 : fontTrueType;
+ break;
+ case fofiIdOpenTypeCFF8Bit:
+ t = expectedType; // hack: open type always == expected type? s. bug-poppler20605.pdf
+ break;
+ case fofiIdOpenTypeCFFCID:
+ t = fontCIDType0COT;
+ break;
+ default:
+ error(errSyntaxError, -1, "Embedded font file may be invalid");
+ break;
+ }
+ }
+ obj4.free();
+ obj3.free();
+ }
+
+ if (t == fontUnknownType) {
+ t = expectedType;
+ }
+
+ if (t != expectedType) {
+ err = gTrue;
+ }
+
+ if (err) {
+ error(errSyntaxWarning, -1,
+ "Mismatch between font type and embedded font file");
+ }
+
+ obj2.free();
+ obj1.free();
+
+ return t;
+}
+
void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
Object obj1, obj2, obj3, obj4;
double t;
@@ -274,8 +463,6 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
// assume Times-Roman by default (for substitution purposes)
flags = fontSerif;
- embFontID.num = -1;
- embFontID.gen = -1;
missingWidth = 0;
if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) {
@@ -339,100 +526,6 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
}
obj2.free();
- // look for embedded font file
- if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) {
- embFontID = obj2.getRef();
- if (type != fontType1) {
- error(errSyntaxError, -1, "Mismatch between font type and embedded font file");
- if (isCIDFont()) {
- error(errSyntaxError, -1, "CID font has FontFile attribute; assuming CIDType0");
- type = fontCIDType0;
- } else {
- type = fontType1;
- }
- }
- }
- obj2.free();
- if (embFontID.num == -1 &&
- obj1.dictLookupNF("FontFile2", &obj2)->isRef()) {
- embFontID = obj2.getRef();
- if (type != fontTrueType && type != fontCIDType2) {
- error(errSyntaxError, -1, "Mismatch between font type and embedded font file");
- type = isCIDFont() ? fontCIDType2 : fontTrueType;
- }
- }
- obj2.free();
- if (embFontID.num == -1 &&
- obj1.dictLookupNF("FontFile3", &obj2)->isRef()) {
- if (obj2.fetch(xref, &obj3)->isStream()) {
- obj3.streamGetDict()->lookup("Subtype", &obj4);
- if (obj4.isName("Type1")) {
- embFontID = obj2.getRef();
- if (type != fontType1) {
- error(errSyntaxError, -1, "Mismatch between font type and embedded font file");
- if (isCIDFont()) {
- error(errSyntaxError, -1, "Embedded CID font has type Type1; assuming CIDType0");
- type = fontCIDType0;
- } else {
- type = fontType1;
- }
- }
- } else if (obj4.isName("Type1C")) {
- embFontID = obj2.getRef();
- if (type != fontType1 && type != fontType1C) {
- error(errSyntaxError, -1, "Mismatch between font type and embedded font file");
- }
- if (isCIDFont()) {
- error(errSyntaxError, -1, "Embedded CID font has type Type1C; assuming CIDType0C");
- type = fontCIDType0C;
- } else {
- type = fontType1C;
- }
- } else if (obj4.isName("TrueType")) {
- embFontID = obj2.getRef();
- if (type != fontTrueType) {
- error(errSyntaxError, -1, "Mismatch between font type and embedded font file");
- if (isCIDFont()) {
- error(errSyntaxError, -1, "Embedded CID font has type TrueType; assuming CIDType2");
- type = fontCIDType2;
- } else {
- type = fontTrueType;
- }
- }
- } else if (obj4.isName("CIDFontType0C")) {
- embFontID = obj2.getRef();
- if (type != fontCIDType0) {
- error(errSyntaxError, -1, "Mismatch between font type and embedded font file");
- }
- if (isCIDFont()) {
- type = fontCIDType0C;
- } else {
- error(errSyntaxError, -1, "Embedded non-CID font has type CIDFontType0c; assuming Type1C");
- type = fontType1C;
- }
- } else if (obj4.isName("OpenType")) {
- embFontID = obj2.getRef();
- if (type == fontTrueType) {
- type = fontTrueTypeOT;
- } else if (type == fontType1) {
- type = fontType1COT;
- } else if (type == fontCIDType0) {
- type = fontCIDType0COT;
- } else if (type == fontCIDType2) {
- type = fontCIDType2OT;
- } else {
- error(errSyntaxError, -1, "Mismatch between font type and embedded font file");
- }
- } else {
- error(errSyntaxError, -1, "Unknown embedded font type '{0:s}'",
- obj4.isName() ? obj4.getName() : "???");
- }
- obj4.free();
- }
- obj3.free();
- }
- obj2.free();
-
// look for MissingWidth
obj1.dictLookup("MissingWidth", &obj2);
if (obj2.isNum()) {
@@ -444,8 +537,13 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
obj1.dictLookup("Ascent", &obj2);
if (obj2.isNum()) {
t = 0.001 * obj2.getNum();
- // some broken font descriptors set ascent and descent to 0
- if (t != 0) {
+ // some broken font descriptors specify a negative ascent
+ if (t < 0) {
+ t = -t;
+ }
+ // some broken font descriptors set ascent and descent to 0;
+ // others set it to ridiculous values (e.g., 32768)
+ if (t != 0 && t < 3) {
ascent = t;
}
}
@@ -453,14 +551,14 @@ void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
obj1.dictLookup("Descent", &obj2);
if (obj2.isNum()) {
t = 0.001 * obj2.getNum();
+ // some broken font descriptors specify a positive descent
+ if (t > 0) {
+ t = -t;
+ }
// some broken font descriptors set ascent and descent to 0
- if (t != 0) {
+ if (t != 0 && t > -3) {
descent = t;
}
- // some broken font descriptors specify a positive descent
- if (descent > 0) {
- descent = -descent;
- }
}
obj2.free();
@@ -502,45 +600,281 @@ CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
return ctu;
}
-void GfxFont::findExtFontFile() {
- static const char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL };
- static const char *ttExts[] = { ".ttf", ".ttc", NULL };
+GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) {
+ GfxFontLoc *fontLoc;
+ SysFontType sysFontType;
+ GooString *path, *base14Name, *substName;
+ PSFontParam16 *psFont16;
+ Object refObj, embFontObj;
+ int substIdx, fontNum;
+ GBool embed;
- if (name) {
- if (type == fontType1) {
- extFontFile = globalParams->findFontFile(name, type1Exts);
- } else if (type == fontTrueType) {
- extFontFile = globalParams->findFontFile(name, ttExts);
+ if (type == fontType3) {
+ return NULL;
+ }
+
+ //----- embedded font
+ if (embFontID.num >= 0) {
+ embed = gTrue;
+ refObj.initRef(embFontID.num, embFontID.gen);
+ refObj.fetch(xref, &embFontObj);
+ if (!embFontObj.isStream()) {
+ error(errSyntaxError, -1, "Embedded font object is wrong type");
+ embed = gFalse;
+ }
+ embFontObj.free();
+ refObj.free();
+ if (embed) {
+ if (ps) {
+ switch (type) {
+ case fontType1:
+ case fontType1C:
+ case fontType1COT:
+ embed = globalParams->getPSEmbedType1();
+ break;
+ case fontTrueType:
+ case fontTrueTypeOT:
+ embed = globalParams->getPSEmbedTrueType();
+ break;
+ case fontCIDType0C:
+ case fontCIDType0COT:
+ embed = globalParams->getPSEmbedCIDPostScript();
+ break;
+ case fontCIDType2:
+ case fontCIDType2OT:
+ embed = globalParams->getPSEmbedCIDTrueType();
+ break;
+ default:
+ break;
+ }
+ }
+ if (embed) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocEmbedded;
+ fontLoc->fontType = type;
+ fontLoc->embFontID = embFontID;
+ return fontLoc;
+ }
}
}
-}
-char *GfxFont::readExtFontFile(int *len) {
- FILE *f;
- char *buf;
+ //----- PS passthrough
+ if (ps && !isCIDFont() && globalParams->getPSFontPassthrough()) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = name->copy();
+ return fontLoc;
+ }
- if (!(f = fopen(extFontFile->getCString(), "rb"))) {
- error(errIO, -1, "External font file '{0:t}' vanished", extFontFile);
- return NULL;
+ //----- PS resident Base-14 font
+ if (ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = new GooString(((Gfx8BitFont *)this)->base14->base14Name);
+ return fontLoc;
+ }
+
+ //----- external font file (fontFile, fontDir)
+ if (name && (path = globalParams->findFontFile(name))) {
+ if ((fontLoc = getExternalFont(path, isCIDFont()))) {
+ return fontLoc;
+ }
+ }
+
+ //----- external font file for Base-14 font
+ if (!ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) {
+ base14Name = new GooString(((Gfx8BitFont *)this)->base14->base14Name);
+ if ((path = globalParams->findFontFile(base14Name))) {
+ if ((fontLoc = getExternalFont(path, gFalse))) {
+ delete base14Name;
+ return fontLoc;
+ }
+ }
+ delete base14Name;
}
- if (fseek(f, 0, SEEK_END) != 0) {
- error(errIO, -1, "Cannot seek to end of '{0:t}'", extFontFile);
- fclose(f);
+
+ //----- system font
+ if ((path = globalParams->findSystemFontFile(this, &sysFontType,
+ &fontNum))) {
+ if (isCIDFont()) {
+ if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocExternal;
+ fontLoc->fontType = fontCIDType2;
+ fontLoc->path = path;
+ fontLoc->fontNum = fontNum;
+ return fontLoc;
+ }
+ } else {
+ if (sysFontType == sysFontTTF || sysFontType == sysFontTTC) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocExternal;
+ fontLoc->fontType = fontTrueType;
+ fontLoc->path = path;
+ return fontLoc;
+ } else if (sysFontType == sysFontPFA || sysFontType == sysFontPFB) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocExternal;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = path;
+ fontLoc->fontNum = fontNum;
+ return fontLoc;
+ }
+ }
+ delete path;
+ }
+
+ if (!isCIDFont()) {
+
+ //----- 8-bit PS resident font
+ if (ps) {
+ if ((path = globalParams->getPSResidentFont(name))) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = path;
+ return fontLoc;
+ }
+ }
+
+ //----- 8-bit font substitution
+ if (flags & fontFixedWidth) {
+ substIdx = 0;
+ } else if (flags & fontSerif) {
+ substIdx = 8;
+ } else {
+ substIdx = 4;
+ }
+ if (isBold()) {
+ substIdx += 2;
+ }
+ if (isItalic()) {
+ substIdx += 1;
+ }
+ substName = new GooString(base14SubstFonts[substIdx]);
+ if (ps) {
+ error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'",
+ base14SubstFonts[substIdx], name);
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontType1;
+ fontLoc->path = substName;
+ fontLoc->substIdx = substIdx;
+ return fontLoc;
+ } else {
+ path = globalParams->findFontFile(substName);
+ delete substName;
+ if (path) {
+ if ((fontLoc = getExternalFont(path, gFalse))) {
+ error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'",
+ base14SubstFonts[substIdx], (name == NULL) ? new GooString("") : name);
+ name = new GooString(base14SubstFonts[substIdx]);
+ fontLoc->substIdx = substIdx;
+ return fontLoc;
+ }
+ }
+ }
+
+ // failed to find a substitute font
return NULL;
}
- *len = (int)ftell(f);
- if (fseek(f, 0, SEEK_SET) != 0) {
- error(errIO, -1, "Cannot seek to start of '{0:t}'", extFontFile);
- fclose(f);
+
+ //----- 16-bit PS resident font
+ if (ps && ((psFont16 = globalParams->getPSResidentFont16(
+ name,
+ ((GfxCIDFont *)this)->getWMode())))) {
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontCIDType0; // this is not used
+ fontLoc->path = psFont16->psFontName->copy();
+ fontLoc->encoding = psFont16->encoding->copy();
+ fontLoc->wMode = psFont16->wMode;
+ return fontLoc;
+ }
+ if (ps && ((psFont16 = globalParams->getPSResidentFontCC(
+ ((GfxCIDFont *)this)->getCollection(),
+ ((GfxCIDFont *)this)->getWMode())))) {
+ error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'",
+ psFont16->psFontName, name);
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocResident;
+ fontLoc->fontType = fontCIDType0; // this is not used
+ fontLoc->path = psFont16->psFontName->copy();
+ fontLoc->encoding = psFont16->encoding->copy();
+ fontLoc->wMode = psFont16->wMode;
+ return fontLoc;
+ }
+
+ //----- CID font substitution
+ if ((path = globalParams->findCCFontFile(
+ ((GfxCIDFont *)this)->getCollection()))) {
+ if ((fontLoc = getExternalFont(path, gTrue))) {
+ error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'",
+ fontLoc->path, name);
+ return fontLoc;
+ }
+ }
+
+ // failed to find a substitute font
+ return NULL;
+}
+
+GfxFontLoc *GfxFont::locateBase14Font(GooString *base14Name) {
+ GooString *path;
+
+ path = globalParams->findFontFile(base14Name);
+ if (!path) {
return NULL;
}
- buf = (char *)gmalloc(*len);
- if ((int)fread(buf, 1, *len, f) != *len) {
- error(errIO, -1, "Error reading external font file '{0:t}'",
- extFontFile);
+ return getExternalFont(path, gFalse);
+}
+
+GfxFontLoc *GfxFont::getExternalFont(GooString *path, GBool cid) {
+ FoFiIdentifierType fft;
+ GfxFontType fontType;
+ GfxFontLoc *fontLoc;
+
+ fft = FoFiIdentifier::identifyFile(path->getCString());
+ switch (fft) {
+ case fofiIdType1PFA:
+ case fofiIdType1PFB:
+ fontType = fontType1;
+ break;
+ case fofiIdCFF8Bit:
+ fontType = fontType1C;
+ break;
+ case fofiIdCFFCID:
+ fontType = fontCIDType0C;
+ break;
+ case fofiIdTrueType:
+ case fofiIdTrueTypeCollection:
+ fontType = cid ? fontCIDType2 : fontTrueType;
+ break;
+ case fofiIdOpenTypeCFF8Bit:
+ fontType = fontType1COT;
+ break;
+ case fofiIdOpenTypeCFFCID:
+ fontType = fontCIDType0COT;
+ break;
+ case fofiIdUnknown:
+ case fofiIdError:
+ default:
+ fontType = fontUnknownType;
+ break;
+ }
+ if (fontType == fontUnknownType ||
+ (cid ? (fontType < fontCIDType0)
+ : (fontType >= fontCIDType0))) {
+ delete path;
+ return NULL;
}
- fclose(f);
- return buf;
+ fontLoc = new GfxFontLoc();
+ fontLoc->locType = gfxFontLocExternal;
+ fontLoc->fontType = fontType;
+ fontLoc->path = path;
+ return fontLoc;
}
char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
@@ -574,9 +908,8 @@ char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
//------------------------------------------------------------------------
Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
- GfxFontType typeA, Dict *fontDict):
- GfxFont(tagA, idA, nameA)
-{
+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict):
+ GfxFont(tagA, idA, nameA, typeA, embFontIDA) {
GooString *name2;
BuiltinFont *builtinFont;
const char **baseEnc;
@@ -598,7 +931,6 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA
int n, i, a, b, m;
refCnt = 1;
- type = typeA;
ctu = NULL;
// do font name substitution for various aliases of the Base 14 font
@@ -670,9 +1002,6 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA
fontBBox[3] = 0.001 * builtinFont->bbox[3];
}
- // look for an external font file
- findExtFontFile();
-
// get font matrix
fontMat[0] = fontMat[3] = 1;
fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
@@ -753,54 +1082,45 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA
baseEnc = winAnsiEncoding;
}
- // check embedded or external font file for base encoding
+ // check embedded font file for base encoding
// (only for Type 1 fonts - trying to get an encoding out of a
// TrueType font is a losing proposition)
ffT1 = NULL;
ffT1C = NULL;
buf = NULL;
- if (type == fontType1 && (extFontFile || embFontID.num >= 0)) {
- if (extFontFile) {
- ffT1 = FoFiType1::load(extFontFile->getCString());
- } else {
- buf = readEmbFontFile(xref, &len);
- ffT1 = FoFiType1::make(buf, len);
- }
- if (ffT1) {
- if (ffT1->getName()) {
- if (embFontName) {
- delete embFontName;
+ if (type == fontType1 && embFontID.num >= 0) {
+ if ((buf = readEmbFontFile(xref, &len))) {
+ if ((ffT1 = FoFiType1::make(buf, len))) {
+ if (ffT1->getName()) {
+ if (embFontName) {
+ delete embFontName;
+ }
+ embFontName = new GooString(ffT1->getName());
}
- embFontName = new GooString(ffT1->getName());
- }
- if (!baseEnc) {
- baseEnc = (const char **)ffT1->getEncoding();
- baseEncFromFontFile = gTrue;
- }
- }
- } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) {
- if (extFontFile) {
- ffT1C = FoFiType1C::load(extFontFile->getCString());
- } else {
- buf = readEmbFontFile(xref, &len);
- ffT1C = FoFiType1C::make(buf, len);
- }
- if (ffT1C) {
- if (ffT1C->getName()) {
- if (embFontName) {
- delete embFontName;
+ if (!baseEnc) {
+ baseEnc = (const char **)ffT1->getEncoding();
+ baseEncFromFontFile = gTrue;
}
- embFontName = new GooString(ffT1C->getName());
}
- if (!baseEnc) {
- baseEnc = (const char **)ffT1C->getEncoding();
- baseEncFromFontFile = gTrue;
+ gfree(buf);
+ }
+ } else if (type == fontType1C && embFontID.num >= 0) {
+ if ((buf = readEmbFontFile(xref, &len))) {
+ if ((ffT1C = FoFiType1C::make(buf, len))) {
+ if (ffT1C->getName()) {
+ if (embFontName) {
+ delete embFontName;
+ }
+ embFontName = new GooString(ffT1C->getName());
+ }
+ if (!baseEnc) {
+ baseEnc = (const char **)ffT1C->getEncoding();
+ baseEncFromFontFile = gTrue;
+ }
}
+ gfree(buf);
}
}
- if (buf) {
- gfree(buf);
- }
// get default base encoding
if (!baseEnc) {
@@ -826,8 +1146,7 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA
// T1C->T1 conversion (since the 'seac' operator depends on having
// the accents in the encoding), so we fill in any gaps from
// StandardEncoding
- if (type == fontType1C && (extFontFile || embFontID.num >= 0) &&
- baseEncFromFontFile) {
+ if (type == fontType1C && embFontID.num >= 0 && baseEncFromFontFile) {
for (i = 0; i < 256; ++i) {
if (!enc[i] && standardEncoding[i]) {
enc[i] = (char *)standardEncoding[i];
@@ -997,7 +1316,7 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA
obj1.arrayGet(code - firstChar, &obj2);
if (obj2.isNum()) {
widths[code] = obj2.getNum() * mul;
- if (widths[code] != widths[firstChar]) {
+ if (fabs(widths[code] - widths[firstChar]) > 0.00001) {
flags &= ~fontFixedWidth;
}
}
@@ -1243,9 +1562,10 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
// TrueType font has a Macintosh Roman cmap, use it, and
// reverse map the char names through MacRomanEncoding to
// get char codes.
- // 1b. If the TrueType font has a Microsoft Unicode cmap or a
- // non-Microsoft Unicode cmap, use it, and use the Unicode
- // indexes, not the char codes.
+ // 1b. If the PDF font is not symbolic or the PDF font is not
+ // embedded, and the TrueType font has a Microsoft Unicode
+ // cmap or a non-Microsoft Unicode cmap, use it, and use the
+ // Unicode indexes, not the char codes.
// 1c. If the PDF font is symbolic and the TrueType font has a
// Microsoft Symbol cmap, use it, and use char codes
// directly (possibly with an offset of 0xf000).
@@ -1281,7 +1601,8 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
if (usesMacRomanEnc && macRomanCmap >= 0) {
cmap = macRomanCmap;
useMacRoman = gTrue;
- } else if (unicodeCmap >= 0) {
+ } else if ((!(flags & fontSymbolic) || embFontID.num < 0) &&
+ unicodeCmap >= 0) {
cmap = unicodeCmap;
useUnicode = gTrue;
} else if ((flags & fontSymbolic) && msSymbolCmap >= 0) {
@@ -1308,6 +1629,8 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
if ((code = globalParams->getMacRomanCharCode(charName))) {
map[i] = ff->mapCodeToGID(cmap, code);
}
+ } else {
+ map[i] = -1;
}
}
@@ -1321,6 +1644,7 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
{
n = ctu->mapToUnicode((CharCode)i, &uAux);
if (n > 0) map[i] = ff->mapCodeToGID(cmap, uAux[0]);
+ else map[i] = -1;
}
}
@@ -1336,7 +1660,7 @@ int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
// try the TrueType 'post' table to handle any unmapped characters
for (i = 0; i < 256; ++i) {
- if (!map[i] && (charName = enc[i])) {
+ if (map[i] <= 0 && (charName = enc[i])) {
map[i] = ff->mapNameToGID(charName);
}
}
@@ -1380,11 +1704,10 @@ struct cmpWidthExcepVFunctor {
};
GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
- Dict *fontDict):
- GfxFont(tagA, idA, nameA)
+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict):
+ GfxFont(tagA, idA, nameA, typeA, embFontIDA)
{
Dict *desFontDict;
- GooString *collection, *cMapName;
Object desFontDictObj;
Object obj1, obj2, obj3, obj4, obj5, obj6;
CharCodeToUnicode *utu;
@@ -1397,9 +1720,10 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
ascent = 0.95;
descent = -0.35;
fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
+ collection = NULL;
cMap = NULL;
- cMapName = NULL;
ctu = NULL;
+ ctuUsesCharCode = gTrue;
widths.defWidth = 1.0;
widths.defHeight = -1.0;
widths.defVY = 0.880;
@@ -1411,8 +1735,9 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
cidToGIDLen = 0;
// get the descendant font
- if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
- error(errSyntaxError, -1, "Missing DescendantFonts entry in Type 0 font");
+ if (!fontDict->lookup("DescendantFonts", &obj1)->isArray() ||
+ obj1.arrayGetLength() == 0) {
+ error(errSyntaxError, -1, "Missing or empty DescendantFonts entry in Type 0 font");
obj1.free();
goto err1;
}
@@ -1423,28 +1748,9 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
obj1.free();
desFontDict = desFontDictObj.getDict();
- // font type
- if (!desFontDict->lookup("Subtype", &obj1)) {
- error(errSyntaxError, -1, "Missing Subtype entry in Type 0 descendant font");
- goto err3;
- }
- if (obj1.isName("CIDFontType0")) {
- type = fontCIDType0;
- } else if (obj1.isName("CIDFontType2")) {
- type = fontCIDType2;
- } else {
- error(errSyntaxError, -1, "Unknown Type 0 descendant font type '{0:s}'",
- obj1.isName() ? obj1.getName() : "???");
- goto err3;
- }
- obj1.free();
-
// get info from font descriptor
readFontDescriptor(xref, desFontDict);
- // look for an external font file
- findExtFontFile();
-
//----- encoding info -----
// char collection
@@ -1456,7 +1762,7 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
obj1.dictLookup("Ordering", &obj3);
if (!obj2.isString() || !obj3.isString()) {
error(errSyntaxError, -1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
- goto err4;
+ goto err3;
}
collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
obj3.free();
@@ -1465,6 +1771,7 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
// look for a ToUnicode CMap
if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) {
+ ctuUsesCharCode = gFalse;
// the "Adobe-Identity" and "Adobe-UCS" collections don't have
// cidToUnicode files
@@ -1488,7 +1795,6 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
for (size_t i = 0; i < sizeof(knownCollections)/sizeof(knownCollections[0]); i++) {
if (collection->cmp(knownCollections[i]) == 0) {
error(errSyntaxError, -1, "Missing language pack for '{0:t}' mapping", collection);
- delete collection;
goto err2;
}
}
@@ -1519,40 +1825,13 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
}
// encoding (i.e., CMap)
- //~ also need to deal with the UseCMap entry in the stream dict
- if (!fontDict->lookup("Encoding", &obj1)->isName()) {
- GBool success = gFalse;
- if (obj1.isStream()) {
- Object objName;
- Stream *s = obj1.getStream();
- s->getDict()->lookup("CMapName", &objName);
- if (objName.isName())
- {
- cMapName = new GooString(objName.getName());
- cMap = globalParams->getCMap(collection, cMapName, s);
- success = gTrue;
- }
- objName.free();
- }
-
- if (!success) {
- error(errSyntaxError, -1, "Missing or invalid Encoding entry in Type 0 font");
- delete collection;
- goto err3;
- }
- } else {
- cMapName = new GooString(obj1.getName());
- cMap = globalParams->getCMap(collection, cMapName);
+ if (fontDict->lookup("Encoding", &obj1)->isNull()) {
+ error(errSyntaxError, -1, "Missing Encoding entry in Type 0 font");
+ goto err2;
+ }
+ if (!(cMap = CMap::parse(NULL, collection, &obj1))) {
+ goto err2;
}
- if (!cMap) {
- error(errSyntaxError, -1, "Unknown CMap '{0:t}' for character collection '{1:t}'",
- cMapName, collection);
- delete collection;
- delete cMapName;
- goto err2;
- }
- delete collection;
- delete cMapName;
obj1.free();
// CIDToGIDMap (for embedded TrueType fonts)
@@ -1730,17 +2009,19 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
ok = gTrue;
return;
- err4:
+ err3:
obj3.free();
obj2.free();
- err3:
- obj1.free();
err2:
+ obj1.free();
desFontDictObj.free();
err1:;
}
GfxCIDFont::~GfxCIDFont() {
+ if (collection) {
+ delete collection;
+ }
if (cMap) {
cMap->decRefCnt();
}
diff --git a/poppler/GfxFont.h b/poppler/GfxFont.h
index 2207b9f..0c32e0f 100644
--- a/poppler/GfxFont.h
+++ b/poppler/GfxFont.h
@@ -43,7 +43,6 @@ class Dict;
class CMap;
class CharCodeToUnicode;
class FoFiTrueType;
-class DisplayFontParam;
struct GfxFontCIDWidths;
struct Base14FontMapEntry;
@@ -171,7 +170,8 @@ public:
// Build a GfxFont object.
static GfxFont *makeFont(XRef *xref, const char *tagA, Ref idA, Dict *fontDict);
- GfxFont(const char *tagA, Ref idA, GooString *nameA);
+ GfxFont(const char *tagA, Ref idA, GooString *nameA,
+ GfxFontType typeA, Ref embFontIDA);
GBool isOk() { return ok; }
@@ -213,10 +213,6 @@ public:
// NULL if there is no embedded font.
GooString *getEmbeddedFontName() { return embFontName; }
- // Get the name of the external font file. Returns NULL if there
- // is no external font file.
- GooString *getExtFontFile() { return extFontFile; }
-
// Get font descriptor flags.
int getFlags() { return flags; }
GBool isFixedWidth() { return flags & fontFixedWidth; }
@@ -241,8 +237,14 @@ public:
// Return the writing mode (0=horizontal, 1=vertical).
virtual int getWMode() { return 0; }
+ // Locate the font file for this font. If <ps> is true, includes PS
+ // printer-resident fonts. Returns NULL on failure.
+ GfxFontLoc *locateFont(XRef *xref, GBool ps);
+
+ // Locate a Base-14 font file for a specified font name.
+ static GfxFontLoc *locateBase14Font(GooString *base14Name);
+
// Read an external or embedded font file into a buffer.
- char *readExtFontFile(int *len);
char *readEmbFontFile(XRef *xref, int *len);
// Get the next char from a string <s> of <len> bytes, returning the
@@ -258,19 +260,15 @@ public:
// Does this font have a toUnicode map?
GBool hasToUnicodeCMap() { return hasToUnicode; }
- /* XXX: dfp shouldn't be public, however the font finding code is currently in
- * GlobalParams. Instead it should be inside the GfxFont class. However,
- * getDisplayFont currently uses FCcfg so moving it is not as simple. */
- /* XXX: related to this is the fact that all of the extFontFile stuff is dead */
- DisplayFontParam *dfp;
protected:
virtual ~GfxFont();
+ static GfxFontType getFontType(XRef *xref, Dict *fontDict, Ref *embID);
void readFontDescriptor(XRef *xref, Dict *fontDict);
CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits,
CharCodeToUnicode *ctu);
- void findExtFontFile();
+ static GfxFontLoc *getExternalFont(GooString *path, GBool cid);
GooString *tag; // PDF font tag
Ref id; // reference (used as unique ID)
@@ -282,7 +280,6 @@ protected:
int flags; // font descriptor flags
GooString *embFontName; // name of embedded font
Ref embFontID; // ref to embedded font file stream
- GooString *extFontFile; // external font file name
double fontMat[6]; // font matrix (Type 3 only)
double fontBBox[4]; // font bounding box (Type 3 only)
double missingWidth; // "default" width
@@ -301,7 +298,7 @@ class Gfx8BitFont: public GfxFont {
public:
Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
- GfxFontType typeA, Dict *fontDict);
+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict);
virtual int getNextChar(char *s, int len, CharCode *code,
Unicode **u, int *uLen,
@@ -351,6 +348,8 @@ private:
double widths[256]; // character widths
Object charProcs; // Type 3 CharProcs dictionary
Object resources; // Type 3 Resources dictionary
+
+ friend class GfxFont;
};
//------------------------------------------------------------------------
@@ -361,7 +360,7 @@ class GfxCIDFont: public GfxFont {
public:
GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GooString *nameA,
- Dict *fontDict);
+ GfxFontType typeA, Ref embFontIDA, Dict *fontDict);
virtual GBool isCIDFont() { return gTrue; }
@@ -393,8 +392,11 @@ private:
int mapCodeToGID(FoFiTrueType *ff, int cmapi,
Unicode unicode, GBool wmode);
+ GooString *collection; // collection name
CMap *cMap; // char code --> CID
CharCodeToUnicode *ctu; // CID --> Unicode
+ GBool ctuUsesCharCode; // true: ctu maps char code to Unicode;
+ // false: ctu maps CID to Unicode
GfxFontCIDWidths widths; // character widths
int *cidToGID; // CID --> GID mapping (for embedded
// TrueType fonts)
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index de6f17b..4ea9d93 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -1568,10 +1568,11 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, Gfx *gfx, int recursion)
}
nCompsA = obj2.getInt();
obj2.free();
- if (nCompsA > gfxColorMaxComps) {
- error(errSyntaxWarning, -1, "ICCBased color space with too many ({0:d} > {1:d}) components",
- nCompsA, gfxColorMaxComps);
- nCompsA = gfxColorMaxComps;
+ if (nCompsA > 4) {
+ error(errSyntaxError, -1,
+ "ICCBased color space with too many ({0:d} > 4) components",
+ nCompsA);
+ nCompsA = 4;
}
if (dict->lookup("Alternate", &obj2)->isNull() ||
!(altA = GfxColorSpace::parse(&obj2, gfx, recursion + 1))) {
@@ -2286,13 +2287,6 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, Gfx *gfx, int recursion)
}
obj1.free();
cs = new GfxDeviceNColorSpace(nCompsA, namesA, altA, funcA);
- cs->nonMarking = gTrue;
- for (i = 0; i < nCompsA; ++i) {
- cs->names[i] = namesA[i];
- if (namesA[i]->cmp("None")) {
- cs->nonMarking = gFalse;
- }
- }
return cs;
err4:
@@ -4767,7 +4761,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
GfxIndexedColorSpace *indexedCS;
GfxSeparationColorSpace *sepCS;
int maxPixel, indexHigh;
- Guchar *lookup2;
+ Guchar *indexedLookup;
Function *sepFunc;
Object obj;
double x[gfxColorMaxComps];
@@ -4791,7 +4785,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
// initialize
for (k = 0; k < gfxColorMaxComps; ++k) {
- lookup[k] = NULL;
+ lookup2[k] = NULL;
}
byte_lookup = NULL;
@@ -4829,10 +4823,18 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
// Construct a lookup table -- this stores pre-computed decoded
// values for each component, i.e., the result of applying the
// decode mapping to each possible image pixel component value.
- //
+ for (k = 0; k < nComps; ++k) {
+ lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
+ sizeof(GfxColorComp));
+ for (i = 0; i <= maxPixel; ++i) {
+ lookup[k][i] = dblToCol(decodeLow[k] +
+ (i * decodeRange[k]) / maxPixel);
+ }
+ }
+
// Optimization: for Indexed and Separation color spaces (which have
- // only one component), we store color values in the lookup table
- // rather than component values.
+ // only one component), we pre-compute a second lookup table with
+ // color values
colorSpace2 = NULL;
nComps2 = 0;
useByteLookup = gFalse;
@@ -4845,14 +4847,14 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
colorSpace2 = indexedCS->getBase();
indexHigh = indexedCS->getIndexHigh();
nComps2 = colorSpace2->getNComps();
- lookup2 = indexedCS->getLookup();
+ indexedLookup = indexedCS->getLookup();
colorSpace2->getDefaultRanges(x, y, indexHigh);
if (colorSpace2->useGetGrayLine() || colorSpace2->useGetRGBLine()) {
byte_lookup = (Guchar *)gmallocn ((maxPixel + 1), nComps2);
useByteLookup = gTrue;
}
for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
+ lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
sizeof(GfxColorComp));
for (i = 0; i <= maxPixel; ++i) {
j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
@@ -4862,8 +4864,8 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
j = indexHigh;
}
- mapped = x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k];
- lookup[k][i] = dblToCol(mapped);
+ mapped = x[k] + (indexedLookup[j*nComps2 + k] / 255.0) * y[k];
+ lookup2[k][i] = dblToCol(mapped);
if (useByteLookup)
byte_lookup[i * nComps2 + k] = (Guchar) (mapped * 255);
}
@@ -4879,12 +4881,12 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
useByteLookup = gTrue;
}
for (k = 0; k < nComps2; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
+ lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
sizeof(GfxColorComp));
for (i = 0; i <= maxPixel; ++i) {
x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
sepFunc->transform(x, y);
- lookup[k][i] = dblToCol(y[k]);
+ lookup2[k][i] = dblToCol(y[k]);
if (useByteLookup)
byte_lookup[i*nComps2 + k] = (Guchar) (y[k] * 255);
}
@@ -4896,11 +4898,11 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
useByteLookup = gTrue;
}
for (k = 0; k < nComps; ++k) {
- lookup[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
+ lookup2[k] = (GfxColorComp *)gmallocn(maxPixel + 1,
sizeof(GfxColorComp));
for (i = 0; i <= maxPixel; ++i) {
mapped = decodeLow[k] + (i * decodeRange[k]) / maxPixel;
- lookup[k][i] = dblToCol(mapped);
+ lookup2[k][i] = dblToCol(mapped);
if (useByteLookup) {
int byte;
@@ -4971,7 +4973,7 @@ GfxImageColorMap::~GfxImageColorMap() {
delete colorSpace;
for (i = 0; i < gfxColorMaxComps; ++i) {
- gfree(lookup[i]);
+ gfree(lookup2[i]);
}
gfree(byte_lookup);
}
@@ -4982,12 +4984,12 @@ void GfxImageColorMap::getGray(Guchar *x, GfxGray *gray) {
if (colorSpace2) {
for (i = 0; i < nComps2; ++i) {
- color.c[i] = lookup[i][x[0]];
+ color.c[i] = lookup2[i][x[0]];
}
colorSpace2->getGray(&color, gray);
} else {
for (i = 0; i < nComps; ++i) {
- color.c[i] = lookup[i][x[i]];
+ color.c[i] = lookup2[i][x[i]];
}
colorSpace->getGray(&color, gray);
}
@@ -4999,12 +5001,12 @@ void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
if (colorSpace2) {
for (i = 0; i < nComps2; ++i) {
- color.c[i] = lookup[i][x[0]];
+ color.c[i] = lookup2[i][x[0]];
}
colorSpace2->getRGB(&color, rgb);
} else {
for (i = 0; i < nComps; ++i) {
- color.c[i] = lookup[i][x[i]];
+ color.c[i] = lookup2[i][x[i]];
}
colorSpace->getRGB(&color, rgb);
}
@@ -5334,13 +5336,18 @@ void GfxPath::moveTo(double x, double y) {
}
void GfxPath::lineTo(double x, double y) {
- if (justMoved) {
+ if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) {
if (n >= size) {
size *= 2;
subpaths = (GfxSubpath **)
greallocn(subpaths, size, sizeof(GfxSubpath *));
}
- subpaths[n] = new GfxSubpath(firstX, firstY);
+ if (justMoved) {
+ subpaths[n] = new GfxSubpath(firstX, firstY);
+ } else {
+ subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(),
+ subpaths[n-1]->getLastY());
+ }
++n;
justMoved = gFalse;
}
@@ -5349,13 +5356,18 @@ void GfxPath::lineTo(double x, double y) {
void GfxPath::curveTo(double x1, double y1, double x2, double y2,
double x3, double y3) {
- if (justMoved) {
+ if (justMoved || (n > 0 && subpaths[n-1]->isClosed())) {
if (n >= size) {
size *= 2;
subpaths = (GfxSubpath **)
greallocn(subpaths, size, sizeof(GfxSubpath *));
}
- subpaths[n] = new GfxSubpath(firstX, firstY);
+ if (justMoved) {
+ subpaths[n] = new GfxSubpath(firstX, firstY);
+ } else {
+ subpaths[n] = new GfxSubpath(subpaths[n-1]->getLastX(),
+ subpaths[n-1]->getLastY());
+ }
++n;
justMoved = gFalse;
}
@@ -5571,9 +5583,6 @@ GfxState::~GfxState() {
// this gets set to NULL by restore()
delete path;
}
- if (saved) {
- delete saved;
- }
if (font) {
font->decRefCnt();
}
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index 6edab64..856ec3f 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -1120,6 +1120,8 @@ private:
int nComps2; // number of components in colorSpace2
GfxColorComp * // lookup table
lookup[gfxColorMaxComps];
+ GfxColorComp * // optimized case lookup table
+ lookup2[gfxColorMaxComps];
Guchar *byte_lookup;
double // minimum values for each component
decodeLow[gfxColorMaxComps];
diff --git a/poppler/GlobalParams.cc b/poppler/GlobalParams.cc
index d2c007f..ab399db 100644
--- a/poppler/GlobalParams.cc
+++ b/poppler/GlobalParams.cc
@@ -122,37 +122,21 @@ extern XpdfPluginVecTable xpdfPluginVecTable;
GlobalParams *globalParams = NULL;
//------------------------------------------------------------------------
-// DisplayFontParam
+// PSFontParam16
//------------------------------------------------------------------------
-DisplayFontParam::DisplayFontParam(GooString *nameA,
- DisplayFontParamKind kindA) {
+PSFontParam16::PSFontParam16(GooString *nameA, int wModeA,
+ GooString *psFontNameA, GooString *encodingA) {
name = nameA;
- kind = kindA;
- switch (kind) {
- case displayFontT1:
- t1.fileName = NULL;
- break;
- case displayFontTT:
- tt.fileName = NULL;
- break;
- }
+ wMode = wModeA;
+ psFontName = psFontNameA;
+ encoding = encodingA;
}
-DisplayFontParam::~DisplayFontParam() {
+PSFontParam16::~PSFontParam16() {
delete name;
- switch (kind) {
- case displayFontT1:
- if (t1.fileName) {
- delete t1.fileName;
- }
- break;
- case displayFontTT:
- if (tt.fileName) {
- delete tt.fileName;
- }
- break;
- }
+ delete psFontName;
+ delete encoding;
}
#if ENABLE_RELOCATABLE && defined(_WIN32)
@@ -211,182 +195,123 @@ get_poppler_datadir (void)
#endif
-#ifdef _WIN32
-
//------------------------------------------------------------------------
-// WinFontInfo
+// SysFontInfo
//------------------------------------------------------------------------
-class WinFontInfo: public DisplayFontParam {
+class SysFontInfo {
public:
- GBool bold, italic;
-
- static WinFontInfo *make(GooString *nameA, GBool boldA, GBool italicA,
- HKEY regKey, char *winFontDir);
- WinFontInfo(GooString *nameA, GBool boldA, GBool italicA,
- GooString *fileNameA);
- virtual ~WinFontInfo();
- GBool equals(WinFontInfo *fi);
+ GooString *name;
+ GBool bold;
+ GBool italic;
+ GooString *path;
+ SysFontType type;
+ int fontNum; // for TrueType collections
+
+ SysFontInfo(GooString *nameA, GBool boldA, GBool italicA,
+ GooString *pathA, SysFontType typeA, int fontNumA);
+ ~SysFontInfo();
+ GBool match(SysFontInfo *fi);
+ GBool match(GooString *nameA, GBool boldA, GBool italicA);
};
-WinFontInfo *WinFontInfo::make(GooString *nameA, GBool boldA, GBool italicA,
- HKEY regKey, char *winFontDir) {
- GooString *regName;
- GooString *fileNameA;
- char buf[MAX_PATH];
- DWORD n;
- char c;
- int i;
-
- //----- find the font file
- fileNameA = NULL;
- regName = nameA->copy();
- if (boldA) {
- regName->append(" Bold");
- }
- if (italicA) {
- regName->append(" Italic");
- }
- regName->append(" (TrueType)");
- n = sizeof(buf);
- if (RegQueryValueEx(regKey, regName->getCString(), NULL, NULL,
- (LPBYTE)buf, &n) == ERROR_SUCCESS) {
- fileNameA = new GooString(winFontDir);
- fileNameA->append('\\')->append(buf);
- }
- delete regName;
- if (!fileNameA) {
- delete nameA;
- return NULL;
- }
-
- //----- normalize the font name
- i = 0;
- while (i < nameA->getLength()) {
- c = nameA->getChar(i);
- if (c == ' ' || c == ',' || c == '-') {
- nameA->del(i);
- } else {
- ++i;
- }
- }
-
- return new WinFontInfo(nameA, boldA, italicA, fileNameA);
-}
-
-WinFontInfo::WinFontInfo(GooString *nameA, GBool boldA, GBool italicA,
- GooString *fileNameA):
- DisplayFontParam(nameA, displayFontTT)
-{
+SysFontInfo::SysFontInfo(GooString *nameA, GBool boldA, GBool italicA,
+ GooString *pathA, SysFontType typeA, int fontNumA) {
+ name = nameA;
bold = boldA;
italic = italicA;
- tt.fileName = fileNameA;
+ path = pathA;
+ type = typeA;
+ fontNum = fontNumA;
}
-WinFontInfo::~WinFontInfo() {
+SysFontInfo::~SysFontInfo() {
+ delete name;
+ delete path;
}
-GBool WinFontInfo::equals(WinFontInfo *fi) {
- return !name->cmp(fi->name) && bold == fi->bold && italic == fi->italic;
+GBool SysFontInfo::match(SysFontInfo *fi) {
+ return !strcasecmp(name->getCString(), fi->name->getCString()) &&
+ bold == fi->bold && italic == fi->italic;
+}
+
+GBool SysFontInfo::match(GooString *nameA, GBool boldA, GBool italicA) {
+ return !strcasecmp(name->getCString(), nameA->getCString()) &&
+ bold == boldA && italic == italicA;
}
//------------------------------------------------------------------------
-// WinFontList
+// SysFontList
//------------------------------------------------------------------------
-class WinFontList {
+class SysFontList {
public:
- WinFontList(char *winFontDirA);
- ~WinFontList();
- WinFontInfo *find(GooString *font);
+ SysFontList();
+ ~SysFontList();
+ SysFontInfo *find(GooString *name, GBool exact);
+#ifdef WIN32
+ void scanWindowsFonts(GooString *winFontDir);
+#endif
+#ifdef WITH_FONTCONFIGURATION_FONTCONFIG
+ void addFcFont(SysFontInfo *si) {fonts->append(si);}
+#endif
private:
- void add(WinFontInfo *fi);
- static int CALLBACK enumFunc1(CONST LOGFONT *font,
- CONST TEXTMETRIC *metrics,
- DWORD type, LPARAM data);
- static int CALLBACK enumFunc2(CONST LOGFONT *font,
- CONST TEXTMETRIC *metrics,
- DWORD type, LPARAM data);
-
- GooList *fonts; // [WinFontInfo]
- HDC dc; // (only used during enumeration)
- HKEY regKey; // (only used during enumeration)
- char *winFontDir; // (only used during enumeration)
-};
+#ifdef WIN32
+ SysFontInfo *makeWindowsFont(char *name, int fontNum,
+ char *path);
+#endif
-WinFontList::WinFontList(char *winFontDirA) {
- OSVERSIONINFO version;
- char *path;
+ GooList *fonts; // [SysFontInfo]
+};
+SysFontList::SysFontList() {
fonts = new GooList();
- dc = GetDC(NULL);
- winFontDir = winFontDirA;
- version.dwOSVersionInfoSize = sizeof(version);
- GetVersionEx(&version);
- if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\";
- } else {
- path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\";
- }
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0,
- KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
- ®Key) == ERROR_SUCCESS) {
- EnumFonts(dc, NULL, &WinFontList::enumFunc1, (LPARAM)this);
- RegCloseKey(regKey);
- }
- ReleaseDC(NULL, dc);
}
-WinFontList::~WinFontList() {
- deleteGooList(fonts, WinFontInfo);
+SysFontList::~SysFontList() {
+ deleteGooList(fonts, SysFontInfo);
}
-void WinFontList::add(WinFontInfo *fi) {
- int i;
-
- for (i = 0; i < fonts->getLength(); ++i) {
- if (((WinFontInfo *)fonts->get(i))->equals(fi)) {
- delete fi;
- return;
- }
- }
- fonts->append(fi);
-}
-
-WinFontInfo *WinFontList::find(GooString *font) {
- GooString *name;
+SysFontInfo *SysFontList::find(GooString *name, GBool exact) {
+ GooString *name2;
GBool bold, italic;
- WinFontInfo *fi;
+ SysFontInfo *fi;
char c;
int n, i;
- name = font->copy();
+ name2 = name->copy();
// remove space, comma, dash chars
i = 0;
- while (i < name->getLength()) {
- c = name->getChar(i);
+ while (i < name2->getLength()) {
+ c = name2->getChar(i);
if (c == ' ' || c == ',' || c == '-') {
- name->del(i);
+ name2->del(i);
} else {
++i;
}
}
- n = name->getLength();
+ n = name2->getLength();
// remove trailing "MT" (Foo-MT, Foo-BoldMT, etc.)
- if (!strcmp(name->getCString() + n - 2, "MT")) {
- name->del(n - 2, 2);
+ if (n > 2 && !strcmp(name2->getCString() + n - 2, "MT")) {
+ name2->del(n - 2, 2);
n -= 2;
}
+ // look for "Regular"
+ if (n > 7 && !strcmp(name2->getCString() + n - 7, "Regular")) {
+ name2->del(n - 7, 7);
+ n -= 7;
+ }
+
// look for "Italic"
- if (!strcmp(name->getCString() + n - 6, "Italic")) {
- name->del(n - 6, 6);
+ if (n > 6 && !strcmp(name2->getCString() + n - 6, "Italic")) {
+ name2->del(n - 6, 6);
italic = gTrue;
n -= 6;
} else {
@@ -394,8 +319,8 @@ WinFontInfo *WinFontList::find(GooString *font) {
}
// look for "Bold"
- if (!strcmp(name->getCString() + n - 4, "Bold")) {
- name->del(n - 4, 4);
+ if (n > 4 && !strcmp(name2->getCString() + n - 4, "Bold")) {
+ name2->del(n - 4, 4);
bold = gTrue;
n -= 4;
} else {
@@ -403,78 +328,57 @@ WinFontInfo *WinFontList::find(GooString *font) {
}
// remove trailing "MT" (FooMT-Bold, etc.)
- if (!strcmp(name->getCString() + n - 2, "MT")) {
- name->del(n - 2, 2);
+ if (n > 2 && !strcmp(name2->getCString() + n - 2, "MT")) {
+ name2->del(n - 2, 2);
n -= 2;
}
// remove trailing "PS"
- if (!strcmp(name->getCString() + n - 2, "PS")) {
- name->del(n - 2, 2);
+ if (n > 2 && !strcmp(name2->getCString() + n - 2, "PS")) {
+ name2->del(n - 2, 2);
n -= 2;
}
+ // remove trailing "IdentityH"
+ if (n > 9 && !strcmp(name2->getCString() + n - 9, "IdentityH")) {
+ name2->del(n - 9, 9);
+ n -= 9;
+ }
+
// search for the font
fi = NULL;
for (i = 0; i < fonts->getLength(); ++i) {
- fi = (WinFontInfo *)fonts->get(i);
- if (!fi->name->cmp(name) && fi->bold == bold && fi->italic == italic) {
+ fi = (SysFontInfo *)fonts->get(i);
+ if (fi->match(name2, bold, italic)) {
break;
}
fi = NULL;
}
-
- delete name;
- return fi;
-}
-
-int CALLBACK WinFontList::enumFunc1(CONST LOGFONT *font,
- CONST TEXTMETRIC *metrics,
- DWORD type, LPARAM data) {
- WinFontList *fl = (WinFontList *)data;
-
- EnumFonts(fl->dc, font->lfFaceName, &WinFontList::enumFunc2, (LPARAM)fl);
- return 1;
-}
-
-int CALLBACK WinFontList::enumFunc2(CONST LOGFONT *font,
- CONST TEXTMETRIC *metrics,
- DWORD type, LPARAM data) {
- WinFontList *fl = (WinFontList *)data;
- WinFontInfo *fi;
-
- if (type & TRUETYPE_FONTTYPE) {
- if ((fi = WinFontInfo::make(new GooString(font->lfFaceName),
- font->lfWeight >= 600,
- font->lfItalic ? gTrue : gFalse,
- fl->regKey, fl->winFontDir))) {
- fl->add(fi);
+ if (!fi && !exact && bold) {
+ // try ignoring the bold flag
+ for (i = 0; i < fonts->getLength(); ++i) {
+ fi = (SysFontInfo *)fonts->get(i);
+ if (fi->match(name2, gFalse, italic)) {
+ break;
+ }
+ fi = NULL;
+ }
+ }
+ if (!fi && !exact && (bold || italic)) {
+ // try ignoring the bold and italic flags
+ for (i = 0; i < fonts->getLength(); ++i) {
+ fi = (SysFontInfo *)fonts->get(i);
+ if (fi->match(name2, gFalse, gFalse)) {
+ break;
+ }
+ fi = NULL;
}
}
- return 1;
-}
-
-#endif // _WIN32
-
-//------------------------------------------------------------------------
-// PSFontParam
-//------------------------------------------------------------------------
-PSFontParam::PSFontParam(GooString *pdfFontNameA, int wModeA,
- GooString *psFontNameA, GooString *encodingA) {
- pdfFontName = pdfFontNameA;
- wMode = wModeA;
- psFontName = psFontNameA;
- encoding = encodingA;
+ delete name2;
+ return fi;
}
-PSFontParam::~PSFontParam() {
- delete pdfFontName;
- delete psFontName;
- if (encoding) {
- delete encoding;
- }
-}
#ifdef ENABLE_PLUGINS
//------------------------------------------------------------------------
@@ -656,18 +560,23 @@ GlobalParams::GlobalParams(const char *customPopplerDataDir)
unicodeMaps = new GooHash(gTrue);
cMapDirs = new GooHash(gTrue);
toUnicodeDirs = new GooList();
- displayFonts = new GooHash();
+ fontFiles = new GooHash(gTrue);
+ fontDirs = new GooList();
+ ccFontFiles = new GooHash(gTrue);
+ sysFonts = new SysFontList();
psExpandSmaller = gFalse;
psShrinkLarger = gTrue;
psCenter = gTrue;
psLevel = psLevel2;
- psFonts = new GooHash();
- psNamedFonts16 = new GooList();
- psFonts16 = new GooList();
+ psFile = NULL;
+ psResidentFonts = new GooHash(gTrue);
+ psResidentFonts16 = new GooList();
+ psResidentFontsCC = new GooList();
psEmbedType1 = gTrue;
psEmbedTrueType = gTrue;
psEmbedCIDPostScript = gTrue;
psEmbedCIDTrueType = gTrue;
+ psFontPassthrough = gFalse;
psSubstFonts = gTrue;
psPreload = gFalse;
psOPI = gFalse;
@@ -683,7 +592,6 @@ GlobalParams::GlobalParams(const char *customPopplerDataDir)
#endif
textPageBreaks = gTrue;
textKeepTinyChars = gFalse;
- fontDirs = new GooList();
enableFreeType = gTrue;
disableFreeTypeHinting = gFalse;
antialias = gTrue;
@@ -712,9 +620,7 @@ GlobalParams::GlobalParams(const char *customPopplerDataDir)
#ifdef _WIN32
baseFontsInitialized = gFalse;
- winFontList = NULL;
#endif
-
#ifdef ENABLE_PLUGINS
plugins = new GooList();
securityHandlers = new GooList();
@@ -875,15 +781,17 @@ GlobalParams::~GlobalParams() {
deleteGooHash(residentUnicodeMaps, UnicodeMap);
deleteGooHash(unicodeMaps, GooString);
deleteGooList(toUnicodeDirs, GooString);
- deleteGooHash(displayFonts, DisplayFontParam);
-#ifdef _WIN32
- delete winFontList;
-#endif
- deleteGooHash(psFonts, PSFontParam);
- deleteGooList(psNamedFonts16, PSFontParam);
- deleteGooList(psFonts16, PSFontParam);
- delete textEncoding;
+ deleteGooHash(fontFiles, GooString);
deleteGooList(fontDirs, GooString);
+ deleteGooHash(ccFontFiles, GooString);
+ delete sysFonts;
+ if (psFile) {
+ delete psFile;
+ }
+ deleteGooHash(psResidentFonts, GooString);
+ deleteGooList(psResidentFonts16, PSFontParam16);
+ deleteGooList(psResidentFontsCC, PSFontParam16);
+ delete textEncoding;
GooHashIter *iter;
GooString *key;
@@ -1187,21 +1095,71 @@ static FcPattern *buildFcPattern(GfxFont *font)
}
#endif
+GooString *GlobalParams::findFontFile(GooString *fontName) {
+ static const char *exts[] = { ".pfa", ".pfb", ".ttf", ".ttc" };
+ GooString *path, *dir;
+#ifdef WIN32
+ GooString *fontNameU;
+#endif
+ const char *ext;
+ FILE *f;
+ int i, j;
+
+ lockGlobalParams;
+ setupBaseFonts(NULL);
+ if ((path = (GooString *)fontFiles->lookup(fontName))) {
+ path = path->copy();
+ unlockGlobalParams;
+ return path;
+ }
+ for (i = 0; i < fontDirs->getLength(); ++i) {
+ dir = (GooString *)fontDirs->get(i);
+ for (j = 0; j < (int)(sizeof(exts) / sizeof(exts[0])); ++j) {
+ ext = exts[j];
+#ifdef WIN32
+ fontNameU = fileNameToUTF8(fontName->getCString());
+ path = appendToPath(dir->copy(), fontNameU->getCString());
+ delete fontNameU;
+#else
+ path = appendToPath(dir->copy(), fontName->getCString());
+#endif
+ path->append(ext);
+ if ((f = openFile(path->getCString(), "rb"))) {
+ fclose(f);
+ unlockGlobalParams;
+ return path;
+ }
+ delete path;
+ }
+ }
+ unlockGlobalParams;
+ return NULL;
+}
+
/* if you can't or don't want to use Fontconfig, you need to implement
this function for your platform. For Windows, it's in GlobalParamsWin.cc
*/
#if WITH_FONTCONFIGURATION_FONTCONFIG
-DisplayFontParam *GlobalParams::getDisplayFont(GfxFont *font) {
- DisplayFontParam *dfp;
- FcPattern *p=0;
+// not needed for fontconfig
+void GlobalParams::setupBaseFonts(char *dir) {
+}
+GooString *GlobalParams::findSystemFontFile(GfxFont *font,
+ SysFontType *type,
+ int *fontNum) {
+ SysFontInfo *fi = NULL;
+ FcPattern *p=0;
+ GooString *path = NULL;
GooString *fontName = font->getName();
if (!fontName) return NULL;
-
+ fontName = fontName->copy();
lockGlobalParams;
- dfp = font->dfp;
- if (!dfp)
- {
+
+ if ((fi = sysFonts->find(fontName, gTrue))) {
+ path = fi->path->copy();
+ *type = fi->type;
+ *fontNum = fi->fontNum;
+ } else {
FcChar8* s;
char * ext;
FcResult res;
@@ -1230,38 +1188,70 @@ DisplayFontParam *GlobalParams::getDisplayFont(GfxFont *font) {
first: fonts support the language
second: all fonts (fall back)
*/
- while (dfp == NULL)
+ while (fi == NULL)
{
for (i = 0; i < set->nfont; ++i)
{
- res = FcPatternGetString(set->fonts[i], FC_FILE, 0, &s);
- if (res != FcResultMatch || !s)
- continue;
- if (lb != NULL) {
- FcLangSet *l;
- res = FcPatternGetLangSet(set->fonts[i], FC_LANG, 0, &l);
- if (res != FcResultMatch || !FcLangSetContains(l,lb)) {
- continue;
- }
- }
- ext = strrchr((char*)s,'.');
- if (!ext)
- continue;
- if (!strncasecmp(ext,".ttf",4) || !strncasecmp(ext, ".ttc", 4))
- {
- dfp = new DisplayFontParam(fontName->copy(), displayFontTT);
- dfp->tt.fileName = new GooString((char*)s);
- FcPatternGetInteger(set->fonts[i], FC_INDEX, 0, &(dfp->tt.faceIndex));
- }
- else if (!strncasecmp(ext,".pfa",4) || !strncasecmp(ext,".pfb",4))
- {
- dfp = new DisplayFontParam(fontName->copy(), displayFontT1);
- dfp->t1.fileName = new GooString((char*)s);
- }
- else
- continue;
- font->dfp = dfp;
- break;
+ res = FcPatternGetString(set->fonts[i], FC_FILE, 0, &s);
+ if (res != FcResultMatch || !s)
+ continue;
+ if (lb != NULL) {
+ FcLangSet *l;
+ res = FcPatternGetLangSet(set->fonts[i], FC_LANG, 0, &l);
+ if (res != FcResultMatch || !FcLangSetContains(l,lb)) {
+ continue;
+ }
+ }
+ ext = strrchr((char*)s,'.');
+ if (!ext)
+ continue;
+ if (!strncasecmp(ext,".ttf",4) || !strncasecmp(ext, ".ttc", 4))
+ {
+ int weight, slant;
+ GBool bold = font->isBold();
+ GBool italic = font->isItalic();
+ FcPatternGetInteger(set->fonts[i], FC_WEIGHT, 0, &weight);
+ FcPatternGetInteger(set->fonts[i], FC_SLANT, 0, &slant);
+ if (weight == FC_WEIGHT_DEMIBOLD || weight == FC_WEIGHT_BOLD
+ || weight == FC_WEIGHT_EXTRABOLD || weight == FC_WEIGHT_BLACK)
+ {
+ bold = gTrue;
+ }
+ if (slant == FC_SLANT_ITALIC)
+ italic = gTrue;
+ *fontNum = 0;
+ *type = (!strncasecmp(ext,".ttf",4)) ? sysFontTTF : sysFontTTC;
+ FcPatternGetInteger(set->fonts[i], FC_INDEX, 0, fontNum);
+ fi = new SysFontInfo(fontName->copy(), bold, italic,
+ new GooString((char*)s), *type, *fontNum);
+ sysFonts->addFcFont(fi);
+ path = new GooString((char*)s);
+ }
+ else if (!strncasecmp(ext,".pfa",4) || !strncasecmp(ext,".pfb",4))
+ {
+ int weight, slant;
+ GBool bold = font->isBold();
+ GBool italic = font->isItalic();
+ FcPatternGetInteger(set->fonts[i], FC_WEIGHT, 0, &weight);
+ FcPatternGetInteger(set->fonts[i], FC_SLANT, 0, &slant);
+ if (weight == FC_WEIGHT_DEMIBOLD || weight == FC_WEIGHT_BOLD
+ || weight == FC_WEIGHT_EXTRABOLD || weight == FC_WEIGHT_BLACK)
+ {
+ bold = gTrue;
+ }
+ if (slant == FC_SLANT_ITALIC)
+ italic = gTrue;
+ *fontNum = 0;
+ *type = (!strncasecmp(ext,".pfa",4)) ? sysFontPFA : sysFontPFB;
+ FcPatternGetInteger(set->fonts[i], FC_INDEX, 0, fontNum);
+ fi = new SysFontInfo(fontName->copy(), bold, italic,
+ new GooString((char*)s), *type, *fontNum);
+ sysFonts->addFcFont(fi);
+ path = new GooString((char*)s);
+ }
+ else
+ continue;
+ break;
}
if (lb != NULL) {
FcLangSetDestroy(lb);
@@ -1273,18 +1263,124 @@ DisplayFontParam *GlobalParams::getDisplayFont(GfxFont *font) {
}
FcFontSetDestroy(set);
}
+ if (path == NULL && (fi = sysFonts->find(fontName, gFalse))) {
+ path = fi->path->copy();
+ *type = fi->type;
+ *fontNum = fi->fontNum;
+ }
fin:
if (p)
FcPatternDestroy(p);
-
unlockGlobalParams;
- return dfp;
+ return path;
}
-#endif
-#if WITH_FONTCONFIGURATION_WIN32
+
+#elif WITH_FONTCONFIGURATION_WIN32
#include "GlobalParamsWin.cc"
+#else
+static struct {
+ const char *name;
+ const char *t1FileName;
+ const char *ttFileName;
+} displayFontTab[] = {
+ {"Courier", "n022003l.pfb", "cour.ttf"},
+ {"Courier-Bold", "n022004l.pfb", "courbd.ttf"},
+ {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf"},
+ {"Courier-Oblique", "n022023l.pfb", "couri.ttf"},
+ {"Helvetica", "n019003l.pfb", "arial.ttf"},
+ {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf"},
+ {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf"},
+ {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf"},
+ {"Symbol", "s050000l.pfb", NULL},
+ {"Times-Bold", "n021004l.pfb", "timesbd.ttf"},
+ {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf"},
+ {"Times-Italic", "n021023l.pfb", "timesi.ttf"},
+ {"Times-Roman", "n021003l.pfb", "times.ttf"},
+ {"ZapfDingbats", "d050000l.pfb", NULL},
+ {NULL}
+};
+
+static const char *displayFontDirs[] = {
+ "/usr/share/ghostscript/fonts",
+ "/usr/local/share/ghostscript/fonts",
+ "/usr/share/fonts/default/Type1",
+ "/usr/share/fonts/default/ghostscript",
+ "/usr/share/fonts/type1/gsfonts",
+ NULL
+};
+
+void GlobalParams::setupBaseFonts(char *dir) {
+ GooString *fontName;
+ GooString *fileName;
+ FILE *f;
+ int i, j;
+
+ for (i = 0; displayFontTab[i].name; ++i) {
+ if (fontFiles->lookup(displayFontTab[i].name)) {
+ continue;
+ }
+ fontName = new GooString(displayFontTab[i].name);
+ fileName = NULL;
+ if (dir) {
+ fileName = appendToPath(new GooString(dir), displayFontTab[i].t1FileName);
+ if ((f = fopen(fileName->getCString(), "rb"))) {
+ fclose(f);
+ } else {
+ delete fileName;
+ fileName = NULL;
+ }
+ }
+ for (j = 0; !fileName && displayFontDirs[j]; ++j) {
+ fileName = appendToPath(new GooString(displayFontDirs[j]),
+ displayFontTab[i].t1FileName);
+ if ((f = fopen(fileName->getCString(), "rb"))) {
+ fclose(f);
+ } else {
+ delete fileName;
+ fileName = NULL;
+ }
+ }
+ if (!fileName) {
+ error(errConfig, -1, "No display font for '{0:s}'",
+ displayFontTab[i].name);
+ delete fontName;
+ continue;
+ }
+ addFontFile(fontName, fileName);
+ }
+
+}
+
+GooString *GlobalParams::findSystemFontFile(GfxFont *font,
+ SysFontType *type,
+ int *fontNum) {
+ SysFontInfo *fi;
+ GooString *path;
+
+ path = NULL;
+ lockGlobalParams;
+ if ((fi = sysFonts->find(font->getName(), gFalse))) {
+ path = fi->path->copy();
+ *type = fi->type;
+ *fontNum = fi->fontNum;
+ }
+ unlockGlobalParams;
+ return path;
+}
#endif
+GooString *GlobalParams::findCCFontFile(GooString *collection) {
+ GooString *path;
+
+ lockGlobalParams;
+ if ((path = (GooString *)ccFontFiles->lookup(collection))) {
+ path = path->copy();
+ }
+ unlockGlobalParams;
+ return path;
+}
+
+
GBool GlobalParams::getPSExpandSmaller() {
GBool f;
@@ -1321,41 +1417,62 @@ PSLevel GlobalParams::getPSLevel() {
return level;
}
-PSFontParam *GlobalParams::getPSFont(GooString *fontName) {
- PSFontParam *p;
+GooString *GlobalParams::getPSResidentFont(GooString *fontName) {
+ GooString *psName;
lockGlobalParams;
- p = (PSFontParam *)psFonts->lookup(fontName);
+ psName = (GooString *)psResidentFonts->lookup(fontName);
unlockGlobalParams;
- return p;
+ return psName;
}
-PSFontParam *GlobalParams::getPSFont16(GooString *fontName,
- GooString *collection, int wMode) {
- PSFontParam *p;
+GooList *GlobalParams::getPSResidentFonts() {
+ GooList *names;
+ GooHashIter *iter;
+ GooString *name;
+ GooString *psName;
+
+ names = new GooList();
+ lockGlobalParams;
+ psResidentFonts->startIter(&iter);
+ while (psResidentFonts->getNext(&iter, &name, (void **)&psName)) {
+ names->append(psName->copy());
+ }
+ unlockGlobalParams;
+ return names;
+}
+
+PSFontParam16 *GlobalParams::getPSResidentFont16(GooString *fontName,
+ int wMode) {
+ PSFontParam16 *p;
int i;
lockGlobalParams;
p = NULL;
- if (fontName) {
- for (i = 0; i < psNamedFonts16->getLength(); ++i) {
- p = (PSFontParam *)psNamedFonts16->get(i);
- if (!p->pdfFontName->cmp(fontName) &&
- p->wMode == wMode) {
- break;
- }
- p = NULL;
+ for (i = 0; i < psResidentFonts16->getLength(); ++i) {
+ p = (PSFontParam16 *)psResidentFonts16->get(i);
+ if (!(p->name->cmp(fontName)) && p->wMode == wMode) {
+ break;
}
+ p = NULL;
}
- if (!p && collection) {
- for (i = 0; i < psFonts16->getLength(); ++i) {
- p = (PSFontParam *)psFonts16->get(i);
- if (!p->pdfFontName->cmp(collection) &&
- p->wMode == wMode) {
- break;
- }
- p = NULL;
+ unlockGlobalParams;
+ return p;
+}
+
+PSFontParam16 *GlobalParams::getPSResidentFontCC(GooString *collection,
+ int wMode) {
+ PSFontParam16 *p;
+ int i;
+
+ lockGlobalParams;
+ p = NULL;
+ for (i = 0; i < psResidentFontsCC->getLength(); ++i) {
+ p = (PSFontParam16 *)psResidentFontsCC->get(i);
+ if (!(p->name->cmp(collection)) && p->wMode == wMode) {
+ break;
}
+ p = NULL;
}
unlockGlobalParams;
return p;
@@ -1397,11 +1514,11 @@ GBool GlobalParams::getPSEmbedCIDTrueType() {
return e;
}
-GBool GlobalParams::getPSSubstFonts() {
+GBool GlobalParams::getPSFontPassthrough() {
GBool e;
lockGlobalParams;
- e = psSubstFonts;
+ e = psFontPassthrough;
unlockGlobalParams;
return e;
}
@@ -1478,30 +1595,6 @@ GBool GlobalParams::getTextKeepTinyChars() {
return tiny;
}
-GooString *GlobalParams::findFontFile(GooString *fontName, const char **exts) {
- GooString *dir, *fileName;
- const char **ext;
- FILE *f;
- int i;
-
- lockGlobalParams;
- for (i = 0; i < fontDirs->getLength(); ++i) {
- dir = (GooString *)fontDirs->get(i);
- for (ext = exts; *ext; ++ext) {
- fileName = appendToPath(dir->copy(), fontName->getCString());
- fileName->append(*ext);
- if ((f = openFile(fileName->getCString(), "rb"))) {
- fclose(f);
- unlockGlobalParams;
- return fileName;
- }
- delete fileName;
- }
- }
- unlockGlobalParams;
- return NULL;
-}
-
GBool GlobalParams::getEnableFreeType() {
GBool f;
@@ -1752,6 +1845,21 @@ GooList *GlobalParams::getEncodingNames()
// functions to set parameters
//------------------------------------------------------------------------
+void GlobalParams::addFontFile(GooString *fontName, GooString *path) {
+ lockGlobalParams;
+ fontFiles->add(fontName, path);
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSFile(char *file) {
+ lockGlobalParams;
+ if (psFile) {
+ delete psFile;
+ }
+ psFile = new GooString(file);
+ unlockGlobalParams;
+}
+
void GlobalParams::setPSExpandSmaller(GBool expand) {
lockGlobalParams;
psExpandSmaller = expand;
@@ -1806,6 +1914,12 @@ void GlobalParams::setPSSubstFonts(GBool substFonts) {
unlockGlobalParams;
}
+void GlobalParams::setPSFontPassthrough(GBool passthrough) {
+ lockGlobalParams;
+ psFontPassthrough = passthrough;
+ unlockGlobalParams;
+}
+
void GlobalParams::setPSPreload(GBool preload) {
lockGlobalParams;
psPreload = preload;
diff --git a/poppler/GlobalParams.h b/poppler/GlobalParams.h
index bcaeda3..35f4473 100644
--- a/poppler/GlobalParams.h
+++ b/poppler/GlobalParams.h
@@ -60,9 +60,7 @@ struct XpdfSecurityHandler;
class GlobalParams;
class GfxFont;
class Stream;
-#ifdef _WIN32
-class WinFontList;
-#endif
+class SysFontList;
//------------------------------------------------------------------------
@@ -71,60 +69,27 @@ extern GlobalParams *globalParams;
//------------------------------------------------------------------------
-enum DisplayFontParamKind {
- displayFontT1,
- displayFontTT
-};
-
-struct DisplayFontParamT1 {
- GooString *fileName;
-};
-
-struct DisplayFontParamTT {
- GooString *fileName;
- int faceIndex;
-};
-
-class DisplayFontParam {
-public:
-
- GooString *name; // font name for 8-bit fonts and named
- // CID fonts; collection name for
- // generic CID fonts
- DisplayFontParamKind kind;
- union {
- DisplayFontParamT1 t1;
- DisplayFontParamTT tt;
- };
-
- DisplayFontParam(GooString *nameA, DisplayFontParamKind kindA);
- void setFileName(GooString *fileNameA) {
- if (displayFontT1 == kind)
- t1.fileName = fileNameA;
- else {
- assert(displayFontTT == kind);
- tt.fileName = fileNameA;
- }
- }
- virtual ~DisplayFontParam();
+enum SysFontType {
+ sysFontPFA,
+ sysFontPFB,
+ sysFontTTF,
+ sysFontTTC
};
//------------------------------------------------------------------------
-class PSFontParam {
+class PSFontParam16 {
public:
- GooString *pdfFontName; // PDF font name for 8-bit fonts and
- // named 16-bit fonts; char collection
- // name for generic 16-bit fonts
- int wMode; // writing mode (0=horiz, 1=vert) for
- // 16-bit fonts
+ GooString *name; // PDF font name for psResidentFont16;
+ // char collection name for psResidentFontCC
+ int wMode; // writing mode (0=horiz, 1=vert)
GooString *psFontName; // PostScript font name
- GooString *encoding; // encoding, for 16-bit fonts only
+ GooString *encoding; // encoding
- PSFontParam(GooString *pdfFontNameA, int wModeA,
- GooString *psFontNameA, GooString *encodingA);
- ~PSFontParam();
+ PSFontParam16(GooString *nameA, int wModeA,
+ GooString *psFontNameA, GooString *encodingA);
+ ~PSFontParam16();
};
//------------------------------------------------------------------------
@@ -167,10 +132,7 @@ public:
~GlobalParams();
void setBaseDir(const char *dir);
-
-#if WITH_FONTCONFIGURATION_WIN32
void setupBaseFonts(char *dir);
-#endif
//----- accessors
@@ -182,18 +144,23 @@ public:
FILE *getUnicodeMapFile(GooString *encodingName);
FILE *findCMapFile(GooString *collection, GooString *cMapName);
FILE *findToUnicodeFile(GooString *name);
- DisplayFontParam *getDisplayFont(GfxFont *font);
+ GooString *findFontFile(GooString *fontName);
+ GooString *findSystemFontFile(GfxFont *font, SysFontType *type,
+ int *fontNum);
+ GooString *findCCFontFile(GooString *collection);
GBool getPSExpandSmaller();
GBool getPSShrinkLarger();
GBool getPSCenter();
PSLevel getPSLevel();
- PSFontParam *getPSFont(GooString *fontName);
- PSFontParam *getPSFont16(GooString *fontName, GooString *collection, int wMode);
+ GooString *getPSResidentFont(GooString *fontName);
+ GooList *getPSResidentFonts();
+ PSFontParam16 *getPSResidentFont16(GooString *fontName, int wMode);
+ PSFontParam16 *getPSResidentFontCC(GooString *collection, int wMode);
GBool getPSEmbedType1();
GBool getPSEmbedTrueType();
GBool getPSEmbedCIDPostScript();
GBool getPSEmbedCIDTrueType();
- GBool getPSSubstFonts();
+ GBool getPSFontPassthrough();
GBool getPSPreload();
GBool getPSOPI();
GBool getPSASCIIHex();
@@ -202,7 +169,6 @@ public:
EndOfLineKind getTextEOL();
GBool getTextPageBreaks();
GBool getTextKeepTinyChars();
- GooString *findFontFile(GooString *fontName, const char **exts);
GBool getEnableFreeType();
GBool getDisableFreeTypeHinting();
GBool getAntialias();
@@ -235,6 +201,8 @@ public:
GooList *getEncodingNames();
//----- functions to set parameters
+ void addFontFile(GooString *fontName, GooString *path);
+ void setPSFile(char *file);
void setPSExpandSmaller(GBool expand);
void setPSShrinkLarger(GBool shrink);
void setPSCenter(GBool center);
@@ -244,6 +212,7 @@ public:
void setPSEmbedCIDPostScript(GBool embed);
void setPSEmbedCIDTrueType(GBool embed);
void setPSSubstFonts(GBool substFonts);
+ void setPSFontPassthrough(GBool passthrough);
void setPSPreload(GBool preload);
void setPSOPI(GBool opi);
void setPSASCIIHex(GBool hex);
@@ -310,25 +279,35 @@ private:
GooHash *cMapDirs; // list of CMap dirs, indexed by collection
// name [GooList[GooString]]
GooList *toUnicodeDirs; // list of ToUnicode CMap dirs [GooString]
- GooHash *displayFonts; // display font info, indexed by font name
- // [DisplayFontParam]
#ifdef _WIN32
GBool baseFontsInitialized;
- WinFontList *winFontList; // system TrueType fonts
#endif
+ GooHash *fontFiles; // font files: font name mapped to path
+ // [GString]
+ GooList *fontDirs; // list of font dirs [GString]
+ GooHash *ccFontFiles; // character collection font files:
+ // collection name mapped to path [GString]
+ SysFontList *sysFonts; // system fonts
+ GooString *psFile; // PostScript file or command (for xpdf)
GBool psExpandSmaller; // expand smaller pages to fill paper
GBool psShrinkLarger; // shrink larger pages to fit paper
GBool psCenter; // center pages on the paper
PSLevel psLevel; // PostScript level to generate
- GooHash *psFonts; // PostScript font info, indexed by PDF
- // font name [PSFontParam]
- GooList *psNamedFonts16; // named 16-bit fonts [PSFontParam]
- GooList *psFonts16; // generic 16-bit fonts [PSFontParam]
+ GooHash *psResidentFonts; // 8-bit fonts resident in printer:
+ // PDF font name mapped to PS font name
+ // [GString]
+ GooList *psResidentFonts16; // 16-bit fonts resident in printer:
+ // PDF font name mapped to font info
+ // [PSFontParam16]
+ GooList *psResidentFontsCC; // 16-bit character collection fonts
+ // resident in printer: collection name
+ // mapped to font info [PSFontParam16]
GBool psEmbedType1; // embed Type 1 fonts?
GBool psEmbedTrueType; // embed TrueType fonts?
GBool psEmbedCIDPostScript; // embed CID PostScript fonts?
GBool psEmbedCIDTrueType; // embed CID TrueType fonts?
GBool psSubstFonts; // substitute missing fonts?
+ GBool psFontPassthrough; // pass all fonts through as-is?
GBool psPreload; // preload PostScript images and forms into
// memory
GBool psOPI; // generate PostScript OPI comments?
@@ -340,7 +319,6 @@ private:
// output
GBool textPageBreaks; // insert end-of-page markers?
GBool textKeepTinyChars; // keep all characters in text output
- GooList *fontDirs; // list of font dirs [GooString]
GBool enableFreeType; // FreeType enable flag
GBool disableFreeTypeHinting; // FreeType disable hinting flag
GBool antialias; // anti-aliasing enable flag
@@ -367,8 +345,8 @@ private:
CMapCache *cMapCache;
#ifdef ENABLE_PLUGINS
- GList *plugins; // list of plugins [Plugin]
- GList *securityHandlers; // list of loaded security handlers
+ GooList *plugins; // list of plugins [Plugin]
+ GooList *securityHandlers; // list of loaded security handlers
// [XpdfSecurityHandler]
#endif
diff --git a/poppler/GlobalParamsWin.cc b/poppler/GlobalParamsWin.cc
index 5af717a..54ce4f7 100644
--- a/poppler/GlobalParamsWin.cc
+++ b/poppler/GlobalParamsWin.cc
@@ -60,9 +60,9 @@ description for all fonts available in Windows. That's how MuPDF works.
#define DEFAULT_SUBSTITUTE_FONT "Helvetica"
static struct {
- const char *name;
- const char *t1FileName;
- const char *ttFileName;
+ char *name;
+ char *t1FileName;
+ char *ttFileName;
} displayFontTab[] = {
{"Courier", "n022003l.pfb", "cour.ttf"},
{"Courier-Bold", "n022004l.pfb", "courbd.ttf"},
@@ -218,11 +218,124 @@ static bool FileExists(const char *path)
return false;
}
-static void AddFont(GooHash *displayFonts, char *fontName, GooString *fontPath, DisplayFontParamKind kind)
-{
- DisplayFontParam *dfp = new DisplayFontParam(new GooString(fontName), kind);
- dfp->setFileName(fontPath);
- displayFonts->add(dfp->name, dfp);
+void SysFontList::scanWindowsFonts(GooString *winFontDir) {
+ OSVERSIONINFO version;
+ char *path;
+ DWORD idx, valNameLen, dataLen, type;
+ HKEY regKey;
+ char valName[1024], data[1024];
+ int n, fontNum;
+ char *p0, *p1;
+ GooString *fontPath;
+
+ version.dwOSVersionInfoSize = sizeof(version);
+ GetVersionEx(&version);
+ if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\";
+ } else {
+ path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\";
+ }
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0,
+ KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
+ ®Key) == ERROR_SUCCESS) {
+ idx = 0;
+ while (1) {
+ valNameLen = sizeof(valName) - 1;
+ dataLen = sizeof(data) - 1;
+ if (RegEnumValue(regKey, idx, valName, &valNameLen, NULL,
+ &type, (LPBYTE)data, &dataLen) != ERROR_SUCCESS) {
+ break;
+ }
+ if (type == REG_SZ &&
+ valNameLen > 0 && valNameLen < sizeof(valName) &&
+ dataLen > 0 && dataLen < sizeof(data)) {
+ valName[valNameLen] = '\0';
+ data[dataLen] = '\0';
+ n = strlen(data);
+ if (!strcasecmp(data + n - 4, ".ttf") ||
+ !strcasecmp(data + n - 4, ".ttc")) {
+ fontPath = new GooString(data);
+ if (!(dataLen >= 3 && data[1] == ':' && data[2] == '\\')) {
+ fontPath->insert(0, '\\');
+ fontPath->insert(0, winFontDir);
+ fontPath->append('\0');
+ }
+ p0 = valName;
+ fontNum = 0;
+ while (*p0) {
+ p1 = strstr(p0, " & ");
+ if (p1) {
+ *p1 = '\0';
+ p1 = p1 + 3;
+ } else {
+ p1 = p0 + strlen(p0);
+ }
+ fonts->append(makeWindowsFont(p0, fontNum,
+ fontPath->getCString()));
+ p0 = p1;
+ ++fontNum;
+ }
+ delete fontPath;
+ }
+ }
+ ++idx;
+ }
+ RegCloseKey(regKey);
+ }
+}
+
+SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum,
+ char *path) {
+ int n;
+ GBool bold, italic;
+ GooString *s;
+ char c;
+ int i;
+ SysFontType type;
+
+ n = strlen(name);
+ bold = italic = gFalse;
+
+ // remove trailing ' (TrueType)'
+ if (n > 11 && !strncmp(name + n - 11, " (TrueType)", 11)) {
+ n -= 11;
+ }
+
+ // remove trailing ' Italic'
+ if (n > 7 && !strncmp(name + n - 7, " Italic", 7)) {
+ n -= 7;
+ italic = gTrue;
+ }
+
+ // remove trailing ' Bold'
+ if (n > 5 && !strncmp(name + n - 5, " Bold", 5)) {
+ n -= 5;
+ bold = gTrue;
+ }
+
+ // remove trailing ' Regular'
+ if (n > 5 && !strncmp(name + n - 8, " Regular", 8)) {
+ n -= 8;
+ }
+
+ //----- normalize the font name
+ s = new GooString(name, n);
+ i = 0;
+ while (i < s->getLength()) {
+ c = s->getChar(i);
+ if (c == ' ' || c == ',' || c == '-') {
+ s->del(i);
+ } else {
+ ++i;
+ }
+ }
+
+ if (!strcasecmp(path + strlen(path) - 4, ".ttc")) {
+ type = sysFontTTC;
+ } else {
+ type = sysFontTTF;
+ }
+ return new SysFontInfo(s, bold, italic, new GooString(path), type, fontNum);
}
void GlobalParams::setupBaseFonts(char * dir)
@@ -235,14 +348,14 @@ void GlobalParams::setupBaseFonts(char * dir)
GetWindowsFontDir(winFontDir, sizeof(winFontDir));
for (int i = 0; displayFontTab[i].name; ++i) {
- char *fontName = (char *) displayFontTab[i].name;
- if (displayFonts->lookup(fontName))
+ GooString *fontName = new GooString(displayFontTab[i].name);
+ if (fontFiles->lookup(fontName))
continue;
if (dir) {
GooString *fontPath = appendToPath(new GooString(dir), displayFontTab[i].t1FileName);
if (FileExists(fontPath->getCString())) {
- AddFont(displayFonts, fontName, fontPath, displayFontT1);
+ addFontFile(fontName, fontPath);
continue;
}
delete fontPath;
@@ -251,7 +364,7 @@ void GlobalParams::setupBaseFonts(char * dir)
if (winFontDir[0] && displayFontTab[i].ttFileName) {
GooString *fontPath = appendToPath(new GooString(winFontDir), displayFontTab[i].ttFileName);
if (FileExists(fontPath->getCString())) {
- AddFont(displayFonts, fontName, fontPath, displayFontTT);
+ addFontFile(fontName, fontPath);
continue;
}
delete fontPath;
@@ -259,6 +372,9 @@ void GlobalParams::setupBaseFonts(char * dir)
error(errSyntaxError, -1, "No display font for '{0:s}'", fontName);
}
+ if (winFontDir[0]) {
+ sysFonts->scanWindowsFonts(new GooString(winFontDir));
+ }
}
static char *findSubstituteName(const char *origName)
@@ -270,22 +386,28 @@ static char *findSubstituteName(const char *origName)
}
/* Windows implementation of external font matching code */
-DisplayFontParam *GlobalParams::getDisplayFont(GfxFont *font) {
- DisplayFontParam * dfp;
- GooString * fontName = font->getName();
- char * substFontName = NULL;
-
- if (!fontName) return NULL;
- lockGlobalParams;
- setupBaseFonts(NULL);
- dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
- if (!dfp) {
- substFontName = findSubstituteName(fontName->getCString());
- error(errSyntaxError, -1, "Couldn't find a font for '{0:t}', subst is '{0:s}'", fontName, substFontName);
- dfp = (DisplayFontParam *)displayFonts->lookup(substFontName);
- assert(dfp);
+GooString *GlobalParams::findSystemFontFile(GfxFont *font,
+ SysFontType *type,
+ int *fontNum) {
+ SysFontInfo *fi;
+ GooString *path = NULL;
+ GooString *fontName = font->getName();
+ if (!fontName) return NULL;
+ lockGlobalParams;
+ setupBaseFonts(NULL);
+ if ((fi = sysFonts->find(fontName, gFalse))) {
+ path = fi->path->copy();
+ *type = fi->type;
+ *fontNum = fi->fontNum;
+ } else {
+ GooString *substFontName = new GooString(findSubstituteName(fontName->getCString()));
+ error(errSyntaxError, -1, "Couldn't find a font for '{0:t}', subst is '{0:s}'", fontName, substFontName);
+ if ((fi = sysFonts->find(substFontName, gFalse))) {
+ path = fi->path->copy();
+ *type = fi->type;
+ *fontNum = fi->fontNum;
}
- unlockGlobalParams;
- return dfp;
+ }
+ unlockGlobalParams;
+ return path;
}
-
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 4a6537d..cf385be 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -46,6 +46,7 @@
#include <limits.h>
#include "goo/GooString.h"
#include "goo/GooList.h"
+#include "goo/GooHash.h"
#include "poppler-config.h"
#include "GlobalParams.h"
#include "Object.h"
@@ -64,6 +65,7 @@
#include "XRef.h"
#include "PreScanOutputDev.h"
#include "FileSpec.h"
+#include "CharCodeToUnicode.h"
#if HAVE_SPLASH
# include "splash/Splash.h"
# include "splash/SplashBitmap.h"
@@ -805,25 +807,12 @@ struct PSSubstFont {
double mWidth; // width of 'm' character
};
-static const char *psFonts[] = {
- "Courier",
- "Courier-Bold",
- "Courier-Oblique",
- "Courier-BoldOblique",
- "Helvetica",
- "Helvetica-Bold",
- "Helvetica-Oblique",
- "Helvetica-BoldOblique",
- "Symbol",
- "Times-Roman",
- "Times-Bold",
- "Times-Italic",
- "Times-BoldItalic",
- "ZapfDingbats",
- NULL
-};
-
-static const PSSubstFont psSubstFonts[] = {
+// NB: must be in same order as base14SubstFonts in GfxFont.cc
+static PSSubstFont psBase14SubstFonts[14] = {
+ {"Courier", 0.600},
+ {"Courier-Oblique", 0.600},
+ {"Courier-Bold", 0.600},
+ {"Courier-BoldOblique", 0.600},
{"Helvetica", 0.833},
{"Helvetica-Oblique", 0.833},
{"Helvetica-Bold", 0.889},
@@ -832,10 +821,16 @@ static const PSSubstFont psSubstFonts[] = {
{"Times-Italic", 0.722},
{"Times-Bold", 0.833},
{"Times-BoldItalic", 0.778},
- {"Courier", 0.600},
- {"Courier-Oblique", 0.600},
- {"Courier-Bold", 0.600},
- {"Courier-BoldOblique", 0.600}
+ // the last two are never used for substitution
+ {"Symbol", 0},
+ {"ZapfDingbats", 0}
+};
+
+// Mapping from Type 1/1C font file to PS font name.
+struct PST1FontName {
+ Ref fontFileID;
+ GooString *psName; // PostScript font name used for this
+ // embedded font file
};
// Info for 8-bit fonts
@@ -1010,6 +1005,7 @@ PSOutputDev::PSOutputDev(const char *fileName, PDFDoc *doc,
overlayCbkData = NULL;
fontIDs = NULL;
+ fontNames = new GooHash(gTrue);
fontFileIDs = NULL;
fontFileNames = NULL;
font8Info = NULL;
@@ -1073,6 +1069,7 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
overlayCbkData = NULL;
fontIDs = NULL;
+ fontNames = new GooHash(gTrue);
fontFileIDs = NULL;
fontFileNames = NULL;
font8Info = NULL;
@@ -1130,7 +1127,6 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
paperHeight = 1;
}
}
- substFonts = globalParams->getPSSubstFonts();
preload = globalParams->getPSPreload();
if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) {
imgLLX = imgLLY = 0;
@@ -1256,6 +1252,7 @@ PSOutputDev::~PSOutputDev() {
if (fontIDs) {
gfree(fontIDs);
}
+ delete fontNames;
if (fontFileIDs) {
gfree(fontFileIDs);
}
@@ -1656,9 +1653,7 @@ void PSOutputDev::setupFonts(Dict *resDict) {
}
void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
- Ref fontFileID;
- GooString *name;
- PSFontParam *fontParam;
+ GfxFontLoc *fontLoc;
GooString *psName;
char buf[16];
GBool subst;
@@ -1667,9 +1662,7 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
double xs, ys;
int code;
double w1, w2;
- double *fm;
int i, j;
- DisplayFontParam *dfp;
// check if font is already set up
for (i = 0; i < fontIDLen; ++i) {
@@ -1686,205 +1679,162 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
}
fontIDs[fontIDLen++] = *font->getID();
+ psName = NULL;
xs = ys = 1;
subst = gFalse;
- // check for resident 8-bit font
- if (font->getName() &&
- (fontParam = globalParams->getPSFont(font->getName()))) {
- psName = new GooString(fontParam->psFontName->getCString());
-
- // check for embedded Type 1 font
- } else if (globalParams->getPSEmbedType1() &&
- font->getType() == fontType1 &&
- font->getEmbeddedFontID(&fontFileID) &&
- font->getEmbeddedFontName()) {
- psName = font->getEmbeddedFontName()->sanitizedName(gTrue /* ps mode */);
- setupEmbeddedType1Font(&fontFileID, psName);
-
- // check for embedded Type 1C font
- } else if (globalParams->getPSEmbedType1() &&
- font->getType() == fontType1C &&
- font->getEmbeddedFontID(&fontFileID) &&
- font->getName()) {
- // use the PDF font name because the embedded font name might
- // not include the subset prefix
- psName = font->getName()->sanitizedName(gTrue /* ps mode */);
- setupEmbeddedType1CFont(font, &fontFileID, psName);
-
- // check for embedded OpenType - Type 1C font
- } else if (globalParams->getPSEmbedType1() &&
- font->getType() == fontType1COT &&
- font->getEmbeddedFontID(&fontFileID) &&
- font->getName()) {
- // use the PDF font name because the embedded font name might
- // not include the subset prefix
- psName = font->getName()->sanitizedName(gTrue /* ps mode */);
- setupEmbeddedOpenTypeT1CFont(font, &fontFileID, psName);
-
- // check for external Type 1 font file
- } else if (globalParams->getPSEmbedType1() &&
- font->getType() == fontType1 &&
- font->getExtFontFile() &&
- font->getName()) {
- // 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) &&
- font->getEmbeddedFontName()) {
- psName = font->getEmbeddedFontName()->sanitizedName(gTrue /* ps mode */);
- setupEmbeddedTrueTypeFont(font, &fontFileID, psName);
-
- // check for external TrueType font file
- } else if (globalParams->getPSEmbedTrueType() &&
- font->getType() == fontTrueType &&
- font->getExtFontFile()) {
- psName = setupExternalTrueTypeFont(font);
-
- // check for embedded CID PostScript font
- } else if (globalParams->getPSEmbedCIDPostScript() &&
- font->getType() == fontCIDType0C &&
- font->getEmbeddedFontID(&fontFileID) &&
- font->getEmbeddedFontName()) {
- psName = font->getEmbeddedFontName()->sanitizedName(gTrue /* ps mode */);
- setupEmbeddedCIDType0Font(font, &fontFileID, psName);
-
- // check for embedded CID TrueType font
- } else if (globalParams->getPSEmbedCIDTrueType() &&
- (font->getType() == fontCIDType2 ||
- font->getType() == fontCIDType2OT) &&
- font->getEmbeddedFontID(&fontFileID) &&
- font->getEmbeddedFontName()) {
- psName = font->getEmbeddedFontName()->sanitizedName(gTrue /* ps mode */);
- setupEmbeddedCIDTrueTypeFont(font, &fontFileID, psName, gTrue);
-
- // check for embedded OpenType - CID CFF font
- } else if (globalParams->getPSEmbedCIDPostScript() &&
- font->getType() == fontCIDType0COT &&
- font->getEmbeddedFontID(&fontFileID) &&
- font->getEmbeddedFontName()) {
- psName = font->getEmbeddedFontName()->sanitizedName(gTrue /* ps mode */);
- setupEmbeddedOpenTypeCFFFont(font, &fontFileID, psName);
-
- // check for Type 3 font
- } else if (font->getType() == fontType3) {
+ if (font->getType() == fontType3) {
psName = GooString::format("T3_{0:d}_{1:d}",
font->getID()->num, font->getID()->gen);
setupType3Font(font, psName, parentResDict);
-
- // check for external CID TrueType font file
- } else if (globalParams->getPSEmbedCIDTrueType() &&
- font->getType() == fontCIDType2 &&
- font->getExtFontFile()) {
- psName = setupExternalCIDTrueTypeFont(font, font->getExtFontFile());
-
- // 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 GooString(psFonts[i]);
- break;
+ } else {
+ fontLoc = font->locateFont(xref, gTrue);
+ switch (fontLoc->locType) {
+ case gfxFontLocEmbedded:
+ switch (fontLoc->fontType) {
+ case fontType1:
+ // this assumes that the PS font name matches the PDF font name
+ psName = font->getEmbeddedFontName()->copy();
+ setupEmbeddedType1Font(&fontLoc->embFontID, psName);
+ break;
+ case fontType1C:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedType1CFont(font, &fontLoc->embFontID, psName);
+ break;
+ case fontType1COT:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedOpenTypeT1CFont(font, &fontLoc->embFontID, psName);
+ break;
+ case fontTrueType:
+ case fontTrueTypeOT:
+ psName = makePSFontName(font, font->getID());
+ setupEmbeddedTrueTypeFont(font, &fontLoc->embFontID, psName);
+ break;
+ case fontCIDType0C:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedCIDType0Font(font, &fontLoc->embFontID, psName);
+ break;
+ case fontCIDType2:
+ case fontCIDType2OT:
+ psName = makePSFontName(font, font->getID());
+ //~ should check to see if font actually uses vertical mode
+ setupEmbeddedCIDTrueTypeFont(font, &fontLoc->embFontID, psName, gTrue);
+ break;
+ case fontCIDType0COT:
+ psName = makePSFontName(font, &fontLoc->embFontID);
+ setupEmbeddedOpenTypeCFFFont(font, &fontLoc->embFontID, psName);
+ break;
+ default:
+ break;
+ }
+ break;
+ case gfxFontLocExternal:
+ //~ add cases for external 16-bit fonts
+ switch (fontLoc->fontType) {
+ case fontType1:
+ if (font->getName()) {
+ // this assumes that the PS font name matches the PDF font name
+ psName = font->getName()->copy();
+ } else {
+ //~ this won't work -- the PS font name won't match
+ psName = makePSFontName(font, font->getID());
}
+ setupExternalType1Font(fontLoc->path, psName);
+ break;
+ case fontTrueType:
+ case fontTrueTypeOT:
+ psName = makePSFontName(font, font->getID());
+ setupExternalTrueTypeFont(font, fontLoc->path, psName);
+ break;
+ case fontCIDType2:
+ case fontCIDType2OT:
+ psName = makePSFontName(font, font->getID());
+ //~ should check to see if font actually uses vertical mode
+ setupExternalCIDTrueTypeFont(font, fontLoc->path, psName, gTrue);
+ break;
+ default:
+ break;
}
+ break;
+ case gfxFontLocResident:
+ psName = fontLoc->path->copy();
+ break;
}
+
if (!psName) {
- if (substFonts) {
- 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 GooString(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->isCIDFont()) {
+ error(errSyntaxError, -1,
+ "Couldn't find a font to substitute for '{0:s}' ('{1:s}' character collection)",
+ font->getName() ? font->getName()->getCString()
+ : "(unnamed)",
+ ((GfxCIDFont *)font)->getCollection()
+ ? ((GfxCIDFont *)font)->getCollection()->getCString()
+ : "(unknown)");
+ if (font16EncLen >= font16EncSize) {
+ font16EncSize += 16;
+ font16Enc = (PSFont16Enc *)greallocn(font16Enc,
+ font16EncSize,
+ sizeof(PSFont16Enc));
}
+ font16Enc[font16EncLen].fontID = *font->getID();
+ font16Enc[font16EncLen].enc = NULL;
+ ++font16EncLen;
} else {
- psName = new GooString(name);
- xs = 1;
+ error(errSyntaxError, -1,
+ "Couldn't find a font to substitute for '{0:s}'",
+ font->getName() ? font->getName()->getCString()
+ : "(unnamed)");
}
- 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];
+ delete fontLoc;
+ return;
+ }
+
+ // scale substituted 8-bit fonts
+ if (fontLoc->locType == gfxFontLocResident &&
+ fontLoc->substIdx >= 0) {
+ subst = gTrue;
+ 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 {
- ys = 1;
+ w1 = 0;
+ }
+ w2 = psBase14SubstFonts[fontLoc->substIdx].mWidth;
+ xs = w1 / w2;
+ if (xs < 0.1) {
+ xs = 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();
+ // handle encodings for substituted CID fonts
+ if (fontLoc->locType == gfxFontLocResident &&
+ fontLoc->fontType >= fontCIDType0) {
+ subst = gTrue;
+ if (font16EncLen >= font16EncSize) {
+ font16EncSize += 16;
+ font16Enc = (PSFont16Enc *)greallocn(font16Enc,
+ font16EncSize,
+ sizeof(PSFont16Enc));
+ }
+ font16Enc[font16EncLen].fontID = *font->getID();
+ if ((uMap = globalParams->getUnicodeMap(fontLoc->encoding))) {
+ font16Enc[font16EncLen].enc = fontLoc->encoding->copy();
+ uMap->decRefCnt();
+ } else {
+ error(errSyntaxError, -1,
+ "Couldn't find Unicode map for 16-bit font encoding '{0:t}'",
+ fontLoc->encoding);
+ font16Enc[font16EncLen].enc = NULL;
+ }
++font16EncLen;
- } else {
- error(errSyntaxError, -1, "Couldn't find Unicode map for 16-bit font encoding '{0:t}'",
- font16Enc[font16EncLen].enc);
}
- // try the display font for embedding
- } else if (globalParams->getPSEmbedCIDTrueType() &&
- ((GfxCIDFont *)font)->getCollection() &&
- (dfp = globalParams->
- getDisplayFont(font)) &&
- dfp->kind == displayFontTT) {
- psName = setupExternalCIDTrueTypeFont(font, dfp->tt.fileName, dfp->tt.faceIndex);
-
- // give up - can't do anything with this font
- } else {
- error(errSyntaxError, -1, "Couldn't find a font to substitute for '{0:s}' ('{1:s}' character collection)",
- font->getName() ? font->getName()->getCString() : "(unnamed)",
- ((GfxCIDFont *)font)->getCollection()
- ? ((GfxCIDFont *)font)->getCollection()->getCString()
- : "(unknown)");
- return;
+ delete fontLoc;
}
// generate PostScript code to set up the font
@@ -1911,11 +1861,6 @@ void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
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");
@@ -2279,39 +2224,10 @@ void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
writePS("%%EndResource\n");
}
-GooString *PSOutputDev::setupExternalTrueTypeFont(GfxFont *font) {
- GooString *fileName;
- char *fontBuf;
- int fontLen;
+void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GooString *fileName,
+ GooString *psName) {
FoFiTrueType *ffTT;
int *codeToGID;
- GooString *psName;
- int i;
-
- // check if font is already embedded
- fileName = font->getExtFontFile();
- for (i = 0; i < fontFileNameLen; ++i) {
- if (!fontFileNames[i]->cmp(fileName)) {
- return psFileNames[i]->copy();
- }
- }
-
- psName = font->getName()->sanitizedName(gTrue /* ps mode */);
- // add entry to fontFileNames list
- if (i == fontFileNameLen) {
- if (fontFileNameLen >= fontFileNameSize) {
- fontFileNameSize += 64;
- fontFileNames =
- (GooString **)greallocn(fontFileNames,
- fontFileNameSize, sizeof(GooString *));
- psFileNames =
- (GooString **)greallocn(psFileNames,
- fontFileNameSize, sizeof(GooString *));
- }
- fontFileNames[fontFileNameLen] = fileName->copy();
- psFileNames[fontFileNameLen] = psName->copy();
- fontFileNameLen++;
- }
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2320,8 +2236,7 @@ GooString *PSOutputDev::setupExternalTrueTypeFont(GfxFont *font) {
embFontList->append("\n");
// convert it to a Type 42 font
- fontBuf = font->readExtFontFile(&fontLen);
- if ((ffTT = FoFiTrueType::make(fontBuf, fontLen))) {
+ if ((ffTT = FoFiTrueType::load(fileName->getCString()))) {
codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ffTT);
ffTT->convertToType42(psName->getCString(),
((Gfx8BitFont *)font)->getHasEncoding()
@@ -2341,50 +2256,21 @@ GooString *PSOutputDev::setupExternalTrueTypeFont(GfxFont *font) {
}
delete ffTT;
}
- gfree(fontBuf);
// ending comment
writePS("%%EndResource\n");
- return psName;
}
-GooString *PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font, GooString *fileName, int faceIndex) {
+void PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font,
+ GooString *fileName,
+ GooString *psName,
+ GBool needVerticalMetrics) {
FoFiTrueType *ffTT;
int *codeToGID;
- GooString *psName;
- int i;
- GooString *myFileName;
-
- myFileName = fileName->copy();
- if (faceIndex > 0) {
- char tmp[32];
- sprintf(tmp, ",%d", faceIndex);
- myFileName->append(tmp);
- }
- // check if font is already embedded
- for (i = 0; i < fontFileNameLen; ++i) {
- if (!fontFileNames[i]->cmp(myFileName)) {
- delete myFileName;
- return psFileNames[i]->copy();
- }
- }
-
- psName = font->getName()->sanitizedName(gTrue /* ps mode */);
- // add entry to fontFileNames list
- if (i == fontFileNameLen) {
- if (fontFileNameLen >= fontFileNameSize) {
- fontFileNameSize += 64;
- fontFileNames =
- (GooString **)grealloc(fontFileNames,
- fontFileNameSize * sizeof(GooString *));
- psFileNames =
- (GooString **)grealloc(psFileNames,
- fontFileNameSize * sizeof(GooString *));
- }
- }
- fontFileNames[fontFileNameLen] = myFileName;
- psFileNames[fontFileNameLen] = psName->copy();
- fontFileNameLen++;
+ int codeToGIDLen;
+ CharCodeToUnicode *ctu;
+ Unicode *uBuf;
+ int cmap, code;
// beginning comment
writePSFmt("%%BeginResource: font {0:t}\n", psName);
@@ -2392,33 +2278,66 @@ GooString *PSOutputDev::setupExternalCIDTrueTypeFont(GfxFont *font, GooString *f
embFontList->append(psName->getCString());
embFontList->append("\n");
- // convert it to a CID type2 font
- if ((ffTT = FoFiTrueType::load(fileName->getCString(), faceIndex))) {
- int n = ((GfxCIDFont *)font)->getCIDToGIDLen();
- if (n) {
- codeToGID = (int *)gmallocn(n, sizeof(int));
- memcpy(codeToGID, ((GfxCIDFont *)font)->getCIDToGID(), n * sizeof(int));
- } else {
- codeToGID = ((GfxCIDFont *)font)->getCodeToGIDMap(ffTT, &n);
- }
- if (globalParams->getPSLevel() >= psLevel3) {
- // Level 3: use a CID font
- ffTT->convertToCIDType2(psName->getCString(),
- codeToGID, n, gTrue,
- outputFunc, outputStream);
+ // convert it to a Type 0 font
+ //~ this should use fontNum to load the correct font
+ if ((ffTT = FoFiTrueType::load(fileName->getCString()))) {
+
+ // check for embedding permission
+ 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) {
+ if (ctu->mapToUnicode(code, &uBuf) > 0) {
+ codeToGID[code] = ffTT->mapCodeToGID(cmap, uBuf[0]);
+ } else {
+ codeToGID[code] = 0;
+ }
+ }
+ 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 {
- // otherwise: use a non-CID composite font
- ffTT->convertToType0(psName->getCString(),
- codeToGID, n, gTrue,
- outputFunc, outputStream);
+ error(errSyntaxError, -1,
+ "Couldn't find a mapping to Unicode for font '{0:s}'",
+ font->getName() ? font->getName()->getCString() : "(unnamed)");
}
- gfree(codeToGID);
- delete ffTT;
+ } else {
+ error(errSyntaxError, -1,
+ "TrueType font '%s' does not allow embedding",
+ font->getName() ? font->getName()->getCString() : "(unnamed)");
+
+ }
+ delete ffTT;
}
// ending comment
writePS("%%EndResource\n");
- return psName;
}
void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
@@ -2670,6 +2589,41 @@ void PSOutputDev::setupType3Font(GfxFont *font, GooString *psName,
writePS("%%EndResource\n");
}
+// Make a unique PS font name, based on the names given in the PDF
+// font object, and an object ID (font file object for
+GooString *PSOutputDev::makePSFontName(GfxFont *font, Ref *id) {
+ GooString *psName, *s;
+
+ if ((s = font->getEmbeddedFontName())) {
+ psName = filterPSName(s);
+ if (!fontNames->lookupInt(psName)) {
+ fontNames->add(psName->copy(), 1);
+ return psName;
+ }
+ delete psName;
+ }
+ if ((s = font->getName())) {
+ psName = filterPSName(s);
+ if (!fontNames->lookupInt(psName)) {
+ fontNames->add(psName->copy(), 1);
+ return psName;
+ }
+ delete psName;
+ }
+ psName = GooString::format("FF{0:d}_{1:d}", id->num, id->gen);
+ if ((s = font->getEmbeddedFontName())) {
+ s = filterPSName(s);
+ psName->append('_')->append(s);
+ delete s;
+ } else if ((s = font->getName())) {
+ s = filterPSName(s);
+ psName->append('_')->append(s);
+ delete s;
+ }
+ fontNames->add(psName->copy(), 1);
+ return psName;
+}
+
void PSOutputDev::setupImages(Dict *resDict) {
Object xObjDict, xObj, xObjRef, subtypeObj;
int i;
@@ -6909,6 +6863,37 @@ void PSOutputDev::writePSName(const char *s) {
}
}
+GooString *PSOutputDev::filterPSName(GooString *name) {
+ GooString *name2;
+ char buf[8];
+ int i;
+ char c;
+
+ name2 = new GooString();
+
+ // ghostscript chokes on names that begin with out-of-limits
+ // numbers, e.g., 1e4foo is handled correctly (as a name), but
+ // 1e999foo generates a limitcheck error
+ c = name->getChar(0);
+ if (c >= '0' && c <= '9') {
+ name2->append('f');
+ }
+
+ for (i = 0; i < name->getLength(); ++i) {
+ c = name->getChar(i);
+ if (c <= (char)0x20 || c >= (char)0x7f ||
+ c == '(' || c == ')' || c == '<' || c == '>' ||
+ c == '[' || c == ']' || c == '{' || c == '}' ||
+ c == '/' || c == '%') {
+ sprintf(buf, "#%02x", c & 0xff);
+ name2->append(buf);
+ } else {
+ name2->append(c);
+ }
+ }
+ return name2;
+}
+
// Convert GooString to GooString, with appropriate escaping
// of things that can't appear in a label
// This is heavily based on the writePSTextLine() method
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index 69725d4..4666c06 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -297,13 +297,18 @@ private:
void setupEmbeddedType1CFont(GfxFont *font, Ref *id, GooString *psName);
void setupEmbeddedOpenTypeT1CFont(GfxFont *font, Ref *id, GooString *psName);
void setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, GooString *psName);
- GooString *setupExternalTrueTypeFont(GfxFont *font);
+ void setupExternalTrueTypeFont(GfxFont *font, GooString *fileName,
+ GooString *psName);
void setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, GooString *psName);
void setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, GooString *psName,
GBool needVerticalMetrics);
+ void setupExternalCIDTrueTypeFont(GfxFont *font,
+ GooString *fileName,
+ GooString *psName,
+ GBool needVerticalMetrics);
void setupEmbeddedOpenTypeCFFFont(GfxFont *font, Ref *id, GooString *psName);
- GooString *setupExternalCIDTrueTypeFont(GfxFont *font, GooString *fileName, int faceIndex = 0);
void setupType3Font(GfxFont *font, GooString *psName, Dict *parentResDict);
+ GooString *makePSFontName(GfxFont *font, Ref *id);
void setupImages(Dict *resDict);
void setupImage(Ref id, Stream *str);
void setupForms(Dict *resDict);
@@ -353,6 +358,7 @@ private:
double *x1, double *y1);
#endif
void cvtFunction(Function *func);
+ GooString *filterPSName(GooString *name);
// Write the document-level setup.
void writeDocSetup(PDFDoc *doc, Catalog *catalog, int firstPage, int lastPage, GBool duplexA);
@@ -376,7 +382,6 @@ private:
// (only psModePSOrigPageSizes output mode)
int imgLLX, imgLLY, // imageable area, in pts
imgURX, imgURY;
- GBool substFonts; // substitute missing fonts
GBool preload; // load all images into memory, and
// predefine forms
@@ -396,6 +401,7 @@ private:
Ref *fontIDs; // list of object IDs of all used fonts
int fontIDLen; // number of entries in fontIDs array
int fontIDSize; // size of fontIDs array
+ GooHash *fontNames; // all used font names
Ref *fontFileIDs; // list of object IDs of all embedded fonts
int fontFileIDLen; // number of entries in fontFileIDs array
int fontFileIDSize; // size of fontFileIDs array
diff --git a/poppler/PreScanOutputDev.cc b/poppler/PreScanOutputDev.cc
index 7be6abb..d77bb5a 100644
--- a/poppler/PreScanOutputDev.cc
+++ b/poppler/PreScanOutputDev.cc
@@ -108,8 +108,6 @@ void PreScanOutputDev::beginStringOp(GfxState *state) {
int render;
GfxFont *font;
double m11, m12, m21, m22;
- Ref embRef;
- DisplayFontParam *dfp;
GBool simpleTTF;
render = state->getRender();
@@ -124,18 +122,14 @@ void PreScanOutputDev::beginStringOp(GfxState *state) {
font = state->getFont();
state->getFontTransMat(&m11, &m12, &m21, &m22);
+ //~ this should check for external fonts that are non-TrueType
simpleTTF = fabs(m11 + m22) < 0.01 &&
m11 > 0 &&
fabs(m12) < 0.01 &&
fabs(m21) < 0.01 &&
fabs(state->getHorizScaling() - 1) < 0.001 &&
(font->getType() == fontTrueType ||
- font->getType() == fontTrueTypeOT) &&
- (font->getEmbeddedFontID(&embRef) ||
- font->getExtFontFile() ||
- (font->getName() &&
- (dfp = globalParams->getDisplayFont(font)) &&
- dfp->kind == displayFontTT));
+ font->getType() == fontTrueTypeOT);
if (simpleTTF) {
//~ need to create a FoFiTrueType object, and check for a Unicode cmap
}
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index fe99fd4..825c7ad 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -837,7 +837,10 @@ static void setSat(Guchar rIn, Guchar gIn, Guchar bIn, int sat,
static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
- Guchar r0, g0, b0, r1, g1, b1;
+ Guchar r0, g0, b0;
+#ifdef SPLASH_CMYK
+ Guchar r1, g1, b1;
+#endif
switch (cm) {
case splashModeMono1:
@@ -872,7 +875,10 @@ static void splashOutBlendHue(SplashColorPtr src, SplashColorPtr dest,
static void splashOutBlendSaturation(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend,
SplashColorMode cm) {
- Guchar r0, g0, b0, r1, g1, b1;
+ Guchar r0, g0, b0;
+#ifdef SPLASH_CMYK
+ Guchar r1, g1, b1;
+#endif
switch (cm) {
case splashModeMono1:
@@ -1660,18 +1666,17 @@ void SplashOutputDev::updateFont(GfxState * /*state*/) {
void SplashOutputDev::doUpdateFont(GfxState *state) {
GfxFont *gfxFont;
+ GfxFontLoc *fontLoc;
GfxFontType fontType;
SplashOutFontFileID *id;
SplashFontFile *fontFile;
SplashFontSrc *fontsrc = NULL;
FoFiTrueType *ff;
- Ref embRef;
Object refObj, strObj;
GooString *fileName;
char *tmpBuf;
int tmpBufLen;
int *codeToGID;
- DisplayFontParam *dfp;
double *textMat;
double m11, m12, m21, m22, fontSize;
int faceIndex = 0;
@@ -1684,7 +1689,7 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
font = NULL;
fileName = NULL;
tmpBuf = NULL;
- dfp = NULL;
+ fontLoc = NULL;
if (!(gfxFont = state->getFont())) {
goto err1;
@@ -1708,37 +1713,24 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
} else {
- // if there is an embedded font, write it to disk
- if (gfxFont->getEmbeddedFontID(&embRef)) {
+ if (!(fontLoc = gfxFont->locateFont(doc->getXRef(), gFalse))) {
+ error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
+ gfxFont->getName() ? gfxFont->getName()->getCString()
+ : "(unnamed)");
+ goto err2;
+ }
+
+ // embedded font
+ if (fontLoc->locType == gfxFontLocEmbedded) {
+ // if there is an embedded font, read it to memory
tmpBuf = gfxFont->readEmbFontFile(doc->getXRef(), &tmpBufLen);
if (! tmpBuf)
goto err2;
- // if there is an external font file, use it
- } else if (!(fileName = gfxFont->getExtFontFile())) {
-
- // look for a display font mapping or a substitute font
- dfp = NULL;
- if (gfxFont->getName()) {
- dfp = globalParams->getDisplayFont(gfxFont);
- }
- if (!dfp) {
- error(errSyntaxError, -1, "Couldn't find a font for '{0: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;
- faceIndex = dfp->tt.faceIndex;
- break;
- }
+ // external font
+ } else { // gfxFontLocExternal
+ fileName = fontLoc->path;
+ fontType = fontLoc->fontType;
doAdjustFontMatrix = gTrue;
}
@@ -1940,12 +1932,14 @@ void SplashOutputDev::doUpdateFont(GfxState *state) {
font = fontEngine->getFont(fontFile, mat, splash->getMatrix());
}
+ delete fontLoc;
if (fontsrc && !fontsrc->isFile)
fontsrc->unref();
return;
err2:
delete id;
+ delete fontLoc;
err1:
if (fontsrc && !fontsrc->isFile)
fontsrc->unref();
@@ -2959,7 +2953,6 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
#if SPLASH_CMYK
GfxCMYK cmyk;
#endif
- GBool grayIndexed = gFalse;
Guchar pix;
int n, i;
diff --git a/poppler/XRef.cc b/poppler/XRef.cc
index bacd540..c455d6a 100644
--- a/poppler/XRef.cc
+++ b/poppler/XRef.cc
@@ -826,25 +826,25 @@ GBool XRef::constructXRef(GBool *wasReconstructed) {
delete parser;
// look for object
- } else if (isdigit(*p)) {
+ } else if (*p > 0 && isdigit(*p)) {
num = atoi(p);
if (num > 0) {
do {
++p;
- } while (*p && isdigit(*p));
- if (isspace(*p)) {
+ } while (*p > 0 && isdigit(*p));
+ if (*p > 0 && isspace(*p)) {
do {
++p;
- } while (*p && isspace(*p));
- if (isdigit(*p)) {
+ } while (*p > 0 && isspace(*p));
+ if (*p > 0 && isdigit(*p)) {
gen = atoi(p);
do {
++p;
- } while (*p && isdigit(*p));
- if (isspace(*p)) {
+ } while (*p > 0 && isdigit(*p));
+ if (*p > 0 && isspace(*p)) {
do {
++p;
- } while (*p && isspace(*p));
+ } while (*p > 0 && isspace(*p));
if (!strncmp(p, "obj", 3)) {
if (num >= size) {
newSize = (num + 1 + 255) & ~255;
More information about the poppler
mailing list