Commit 4fcd42cf authored by Albert Astals Cid's avatar Albert Astals Cid
Browse files

[xpdf303] More merges from Thomas (with minor fixes from me)

Basically fonts related and some other small stuff
parent 9c092e17
......@@ -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;
......
......@@ -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();
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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;
......
This diff is collapsed.
This diff is collapsed.
......@@ -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)
......
......@@ -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;