+#if HAVE_T1LIB_H
+XOutputFont *XOutputFontCache::tryGetT1Font(XRef *xref,
+ GfxFont *gfxFont,
+ double m11, double m12,
+ double m21, double m22) {
+ Ref *id;
+ XOutputT1FontFile *xFontFile;
+ XOutputFont *font;
+ Ref embRef;
+ GString *fileName;
+ FILE *f;
+ char *fontBuf;
+ int fontLen;
+ Type1CFontFile *ff;
+ Object refObj, strObj;
+ int c;
+ int i;
+
+ // check the already available font files
+ id = gfxFont->getID();
+ for (i = 0; i < t1FontFiles->getLength(); ++i) {
+ xFontFile = (XOutputT1FontFile *)t1FontFiles->get(i);
+ if (xFontFile->num == id->num && xFontFile->gen == id->gen &&
+ !xFontFile->subst) {
+ font = new XOutputT1Font(id, xFontFile->fontFile,
+ m11, m12, m21, m22,
+ m11, m12, m21, m22, display, xOut);
+ if (!font->isOk()) {
+ delete font;
+ return NULL;
+ }
+ return font;
+ }
+ }
+
+ // check for an embedded font
+ if (gfxFont->getEmbeddedFontID(&embRef)) {
+
+ // create the font file
+ fileName = NULL;
+ if (!openTempFile(&fileName, &f, "wb", NULL)) {
+ error(-1, "Couldn't create temporary Type 1 font file");
+ return NULL;
+ }
+ if (gfxFont->getType() == fontType1C) {
+ if (!(fontBuf = gfxFont->readEmbFontFile(xref, &fontLen))) {
+ fclose(f);
+ return NULL;
+ }
+ ff = new Type1CFontFile(fontBuf, fontLen);
+ if (!ff->isOk()) {
+ delete ff;
+ gfree(fontBuf);
+ return NULL;
+ }
+ ff->convertToType1(outputToFile, f);
+ delete ff;
+ gfree(fontBuf);
+ } else { // fontType1
+ refObj.initRef(embRef.num, embRef.gen);
+ refObj.fetch(xref, &strObj);
+ refObj.free();
+ strObj.streamReset();
+ while ((c = strObj.streamGetChar()) != EOF) {
+ fputc(c, f);
+ }
+ strObj.streamClose();
+ strObj.free();
+ }
+ fclose(f);
+
+ // create the Font
+ font = tryGetT1FontFromFile(xref, fileName, gTrue, gfxFont,
+ m11, m12, m21, m22,
+ m11, m12, m21, m22, gFalse);
+
+ // on systems with Unix hard link semantics, this will remove the
+ // last link to the temp file
+ unlink(fileName->getCString());
+
+ delete fileName;
+
+ // check for an external font file
+ } else if ((fileName = gfxFont->getExtFontFile())) {
+ font = tryGetT1FontFromFile(xref, fileName, gFalse, gfxFont,
+ m11, m12, m21, m22,
+ m11, m12, m21, m22, gFalse);
+
+ } else {
+ font = NULL;
+ }
+
+ return font;
+}
+
+XOutputFont *XOutputFontCache::tryGetT1FontFromFile(XRef *xref,
+ GString *fileName,
+ GBool deleteFile,
+ GfxFont *gfxFont,
+ double m11Orig,
+ double m12Orig,
+ double m21Orig,
+ double m22Orig,
+ double m11, double m12,
+ double m21, double m22,
+ GBool subst) {
+ Ref *id;
+ T1FontFile *fontFile;
+ XOutputFont *font;
+
+ // create the t1lib font file
+ fontFile = new T1FontFile(t1Engine, fileName->getCString(),
+ ((Gfx8BitFont *)gfxFont)->getEncoding(),
+ gfxFont->getFontBBox());
+ if (!fontFile->isOk()) {
+ error(-1, "Couldn't create t1lib font from '%s'",
+ fileName->getCString());
+ delete fontFile;
+ if (deleteFile) {
+ unlink(fileName->getCString());
+ }
+ return NULL;
+ }
+
+ // add to list
+ id = gfxFont->getID();
+ t1FontFiles->append(new XOutputT1FontFile(id->num, id->gen,
+ subst, fontFile,
+ deleteFile ? fileName->copy()
+ : (GString *)NULL));
+
+ // create the Font
+ font = new XOutputT1Font(gfxFont->getID(), fontFile,
+ m11Orig, m12Orig, m21Orig, m22Orig,
+ m11, m12, m21, m22, display, xOut);
+ if (!font->isOk()) {
+ delete font;
+ return NULL;
+ }
+ return font;
+}
+#endif // HAVE_T1LIB_H
+
+#if FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
+XOutputFont *XOutputFontCache::tryGetFTFont(XRef *xref,
+ GfxFont *gfxFont,
+ double m11, double m12,
+ double m21, double m22) {
+ Ref *id;
+ XOutputFTFontFile *xFontFile;
+ XOutputFont *font;
+ Ref embRef;
+ GString *fileName;
+ FILE *f;
+#if 1 //~ need this until FT can handle fonts with missing tables
+ char *fontBuf;
+ int fontLen;
+ TrueTypeFontFile *ff;
+#endif
+ Object refObj, strObj;
+ int c;
+ int i;
+
+ // check the already available font files
+ id = gfxFont->getID();
+ for (i = 0; i < ftFontFiles->getLength(); ++i) {
+ xFontFile = (XOutputFTFontFile *)ftFontFiles->get(i);
+ if (xFontFile->num == id->num && xFontFile->gen == id->gen &&
+ !xFontFile->subst) {
+ font = new XOutputFTFont(id, xFontFile->fontFile,
+ m11, m12, m21, m22,
+ m11, m12, m21, m22, display, xOut);
+ if (!font->isOk()) {
+ delete font;
+ return NULL;
+ }
+ return font;
+ }
+ }
+
+ // check for an embedded font
+ if (gfxFont->getEmbeddedFontID(&embRef)) {
+
+ // create the font file
+ fileName = NULL;
+ if (!openTempFile(&fileName, &f, "wb", NULL)) {
+ error(-1, "Couldn't create temporary TrueType font file");
+ return NULL;
+ }
+#if 1 //~ need this until FT can handle fonts with missing tables
+ if (gfxFont->getType() == fontTrueType ||
+ gfxFont->getType() == fontCIDType2) {
+ if (!(fontBuf = gfxFont->readEmbFontFile(xref, &fontLen))) {
+ fclose(f);
+ return NULL;
+ }
+ ff = new TrueTypeFontFile(fontBuf, fontLen);
+ ff->writeTTF(f);
+ delete ff;
+ gfree(fontBuf);
+ } else {
+ refObj.initRef(embRef.num, embRef.gen);
+ refObj.fetch(xref, &strObj);
+ refObj.free();
+ strObj.streamReset();
+ while ((c = strObj.streamGetChar()) != EOF) {
+ fputc(c, f);
+ }
+ strObj.streamClose();
+ strObj.free();
+ }
+#else
+ refObj.initRef(embRef.num, embRef.gen);
+ refObj.fetch(xref, &strObj);
+ refObj.free();
+ strObj.streamReset();
+ while ((c = strObj.streamGetChar()) != EOF) {
+ fputc(c, f);
+ }
+ strObj.streamClose();
+ strObj.free();
+#endif
+ fclose(f);
+
+ // create the Font
+ font = tryGetFTFontFromFile(xref, fileName, gTrue, gfxFont,
+ m11, m12, m21, m22,
+ m11, m12, m21, m22, gTrue, gFalse);
+
+ // on systems with Unix hard link semantics, this will remove the
+ // last link to the temp file
+ unlink(fileName->getCString());
+
+ delete fileName;
+
+ // check for an external font file
+ } else if ((fileName = gfxFont->getExtFontFile())) {
+ font = tryGetFTFontFromFile(xref, fileName, gFalse, gfxFont,
+ m11, m12, m21, m22,
+ m11, m12, m21, m22, gFalse, gFalse);
+
+ } else {
+ font = NULL;
+ }
+
+ return font;
+}
+
+XOutputFont *XOutputFontCache::tryGetFTFontFromFile(XRef *xref,
+ GString *fileName,
+ GBool deleteFile,
+ GfxFont *gfxFont,
+ double m11Orig,
+ double m12Orig,
+ double m21Orig,
+ double m22Orig,
+ double m11, double m12,
+ double m21, double m22,
+ GBool embedded,
+ GBool subst) {
+ Ref *id;
+ FTFontFile *fontFile;
+ XOutputFont *font;
+
+ // create the FreeType font file
+ if (gfxFont->isCIDFont()) {
+ if (gfxFont->getType() == fontCIDType2) {
+ fontFile = new FTFontFile(ftEngine, fileName->getCString(),
+ ((GfxCIDFont *)gfxFont)->getCIDToGID(),
+ ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(),
+ embedded);
+ } else { // fontCIDType0, fontCIDType0C
+ fontFile = new FTFontFile(ftEngine, fileName->getCString(), embedded);
+ }
+ } else {
+ fontFile = new FTFontFile(ftEngine, fileName->getCString(),
+ ((Gfx8BitFont *)gfxFont)->getEncoding(),
+ ((Gfx8BitFont *)gfxFont)->getHasEncoding(),
+ ((Gfx8BitFont *)gfxFont)->isSymbolic());
+ }
+ if (!fontFile->isOk()) {
+ error(-1, "Couldn't create FreeType font from '%s'",
+ fileName->getCString());
+ delete fontFile;
+ if (deleteFile) {
+ unlink(fileName->getCString());
+ }
+ return NULL;
+ }
+
+ // add to list
+ id = gfxFont->getID();
+ ftFontFiles->append(new XOutputFTFontFile(id->num, id->gen,
+ subst, fontFile,
+ deleteFile ? fileName->copy()
+ : (GString *)NULL));
+
+ // create the Font
+ font = new XOutputFTFont(gfxFont->getID(), fontFile,
+ m11Orig, m12Orig, m21Orig, m22Orig,
+ m11, m12, m21, m22, display, xOut);
+ if (!font->isOk()) {
+ delete font;
+ return NULL;
+ }
+ return font;
+}
+#endif // FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
+
+#if !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
+XOutputFont *XOutputFontCache::tryGetTTFont(XRef *xref,
+ GfxFont *gfxFont,
+ double m11, double m12,
+ double m21, double m22) {
+ Ref *id;
+ XOutputTTFontFile *xFontFile;
+ XOutputFont *font;
+ Ref embRef;
+ GString *fileName;
+ FILE *f;
+ Object refObj, strObj;
+ int c;
+ int i;
+
+ // check the already available font files
+ id = gfxFont->getID();
+ xFontFile = NULL;
+ for (i = 0; i < ttFontFiles->getLength(); ++i) {
+ xFontFile = (XOutputTTFontFile *)ttFontFiles->get(i);
+ if (xFontFile->num == id->num && xFontFile->gen == id->gen &&
+ !xFontFile->subst) {
+ font = new XOutputTTFont(id, xFontFile->fontFile,
+ m11, m12, m21, m22,
+ m11, m12, m21, m22, display, xOut);
+ if (!font->isOk()) {
+ delete font;
+ return NULL;
+ }
+ return font;
+ }
+ }
+
+ // check for an embedded font
+ if (gfxFont->getEmbeddedFontID(&embRef)) {
+
+ // create the font file
+ fileName = NULL;
+ if (!openTempFile(&fileName, &f, "wb", NULL)) {
+ error(-1, "Couldn't create temporary TrueType font file");
+ return NULL;
+ }
+ refObj.initRef(embRef.num, embRef.gen);
+ refObj.fetch(xref, &strObj);
+ refObj.free();
+ strObj.streamReset();
+ while ((c = strObj.streamGetChar()) != EOF) {
+ fputc(c, f);
+ }
+ strObj.streamClose();
+ strObj.free();
+ fclose(f);
+
+ // create the Font
+ font = tryGetTTFontFromFile(xref, fileName, gTrue, gfxFont,
+ m11, m12, m21, m22,
+ m11, m12, m21, m22, gFalse);
+
+ // on systems with Unix hard link semantics, this will remove the
+ // last link to the temp file
+ unlink(fileName->getCString());
+
+ delete fileName;
+
+ } else if ((fileName = gfxFont->getExtFontFile())) {
+ font = tryGetTTFontFromFile(xref, fileName, gFalse, gfxFont,
+ m11, m12, m21, m22,
+ m11, m12, m21, m22, gFalse);
+
+ } else {
+ font = NULL;
+ }
+
+ return font;
+}
+
+XOutputFont *XOutputFontCache::tryGetTTFontFromFile(XRef *xref,
+ GString *fileName,
+ GBool deleteFile,
+ GfxFont *gfxFont,
+ double m11Orig,
+ double m12Orig,
+ double m21Orig,
+ double m22Orig,
+ double m11, double m12,
+ double m21, double m22,
+ GBool subst) {
+ Ref *id;
+ TTFontFile *fontFile;
+ XOutputFont *font;
+
+ // create the FreeType font file
+ if (gfxFont->isCIDFont()) {
+ // fontCIDType2
+ fontFile = new TTFontFile(ttEngine, fileName->getCString(),
+ ((GfxCIDFont *)gfxFont)->getCIDToGID(),
+ ((GfxCIDFont *)gfxFont)->getCIDToGIDLen());
+ } else {
+ fontFile = new TTFontFile(ttEngine, fileName->getCString(),
+ ((Gfx8BitFont *)gfxFont)->getEncoding(),
+ ((Gfx8BitFont *)gfxFont)->getHasEncoding());
+ }
+ if (!fontFile->isOk()) {
+ error(-1, "Couldn't create FreeType font from '%s'",
+ fileName->getCString());
+ delete fontFile;
+ if (deleteFile) {
+ unlink(fileName->getCString());
+ }
+ return NULL;
+ }
+
+ // add to list
+ id = gfxFont->getID();
+ ttFontFiles->append(new XOutputTTFontFile(id->num, id->gen,
+ subst, fontFile,
+ deleteFile ? fileName->copy()
+ : (GString *)NULL));
+
+ // create the Font
+ font = new XOutputTTFont(gfxFont->getID(), fontFile,
+ m11Orig, m12Orig, m21Orig, m22Orig,
+ m11, m12, m21, m22, display, xOut);
+ if (!font->isOk()) {
+ delete font;
+ return NULL;
+ }
+ return font;
+}
+#endif // !FREETYPE2 && (HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H)
+
+XOutputFont *XOutputFontCache::tryGetServerFont(GString *xlfd,
+ GString *encodingName,
+ GfxFont *gfxFont,
+ double m11Orig, double m12Orig,
+ double m21Orig, double m22Orig,
+ double m11, double m12,
+ double m21, double m22) {
+ XOutputFont *font;
+ UnicodeMap *uMap;
+ CharCodeToUnicode *ctu;
+
+ uMap = globalParams->getUnicodeMap(encodingName);
+ if (gfxFont->isCIDFont()) {
+ ctu = ((GfxCIDFont *)gfxFont)->getToUnicode();
+ font = new XOutputServer16BitFont(gfxFont->getID(), xlfd, uMap, ctu,
+ m11Orig, m12Orig, m21Orig, m22Orig,
+ m11, m12, m21, m22,
+ display, xOut);
+ ctu->decRefCnt();
+ } else {
+ ctu = ((Gfx8BitFont *)gfxFont)->getToUnicode();
+ font = new XOutputServer8BitFont(gfxFont->getID(), xlfd, uMap, ctu,
+ m11Orig, m12Orig, m21Orig, m22Orig,
+ m11, m12, m21, m22,
+ display, xOut);
+ ctu->decRefCnt();
+ }
+ uMap->decRefCnt();
+ if (!font->isOk()) {
+ delete font;
+ return NULL;
+ }
+ return font;
+}
+
+//------------------------------------------------------------------------
+// T3FontCache
+//------------------------------------------------------------------------
+
+struct T3FontCacheTag {
+ Gushort code;
+ Gushort mru; // valid bit (0x8000) and MRU index
+ double wx, wy; // untransformed glyph metrics
+};
+
+class T3FontCache {
+public:
+
+ T3FontCache(Ref *fontID, double m11A, double m12A,
+ double m21A, double m22A,
+ int glyphXA, int glyphYA, int glyphWA, int glyphHA,
+ Display *displayA, Visual *visual, Guint depth,
+ Pixmap origPixmap);
+ ~T3FontCache();
+ GBool matches(Ref *idA, double m11A, double m12A,
+ double m21A, double m22A)
+ { return fontID.num == idA->num && fontID.gen == idA->gen &&
+ m11 == m11A && m12 == m12A && m21 == m21A && m22 == m22A; }
+
+ Ref fontID; // PDF font ID
+ double m11, m12, m21, m22; // transform matrix
+ int glyphX, glyphY; // pixel offset of glyph pixmaps
+ int glyphW, glyphH; // size of glyph pixmaps, in pixels
+ int glyphSize; // size of glyph pixmaps, in bytes
+ int cacheSets; // number of sets in cache
+ int cacheAssoc; // cache associativity (glyphs per set)
+ Guchar *cacheData; // glyph pixmap cache
+ T3FontCacheTag *cacheTags; // cache tags, i.e., char codes
+ Display *display;
+ Pixmap pixmap;
+ XImage *image;
+};
+
+T3FontCache::T3FontCache(Ref *fontIDA, double m11A, double m12A,
+ double m21A, double m22A,
+ int glyphXA, int glyphYA, int glyphWA, int glyphHA,
+ Display *displayA, Visual *visual, Guint depth,
+ Pixmap origPixmap) {
+ int i;
+
+ fontID = *fontIDA;
+ m11 = m11A;
+ m12 = m12A;
+ m21 = m21A;
+ m22 = m22A;
+ glyphX = glyphXA;
+ glyphY = glyphYA;
+ glyphW = glyphWA;
+ glyphH = glyphHA;
+ glyphSize = glyphW * glyphH;
+ cacheAssoc = 8;
+ if (glyphSize <= 256) {
+ cacheSets = 8;
+ } else if (glyphSize <= 512) {
+ cacheSets = 4;
+ } else if (glyphSize <= 1024) {
+ cacheSets = 2;
+ } else {
+ cacheSets = 1;
+ }
+ cacheData = (Guchar *)gmalloc(cacheSets * cacheAssoc * glyphSize);
+ cacheTags = (T3FontCacheTag *)gmalloc(cacheSets * cacheAssoc *
+ sizeof(T3FontCacheTag));
+ for (i = 0; i < cacheSets * cacheAssoc; ++i) {
+ cacheTags[i].mru = i & (cacheAssoc - 1);
+ }
+ display = displayA;
+ pixmap = XCreatePixmap(display, origPixmap, glyphW, glyphH, depth);
+ image = XCreateImage(display, visual, depth, ZPixmap, 0, NULL,
+ glyphW, glyphH, 8, 0);
+ image->data = (char *)gmalloc(glyphH * image->bytes_per_line);
+}
+
+T3FontCache::~T3FontCache() {
+ gfree(cacheData);
+ gfree(cacheTags);
+ XFreePixmap(display, pixmap);
+ gfree(image->data);
+ image->data = NULL;
+ XDestroyImage(image);
+}
+
+struct T3GlyphStack {
+ GBool cacheable;
+ Gushort code;
+ T3FontCache *cache;
+ int cacheIdx;
+ T3FontCacheTag *cacheTag;
+ Guchar *cacheData;
+ double x, y;
+ Unicode *u;
+ int uLen;
+ GfxRGB color;
+ int origPixmapW, origPixmapH;
+ Pixmap origPixmap;
+ GC origStrokeGC;
+ GC origFillGC;
+ Region origClipRegion;
+ double origCTM4, origCTM5;
+ double wx, wy; // untransformed glyph metrics
+ T3GlyphStack *next;
+};
+