diff --git a/poppler/CairoFontEngine.cc b/poppler/CairoFontEngine.cc index 6ef5e11..925d073 100644 --- a/poppler/CairoFontEngine.cc +++ b/poppler/CairoFontEngine.cc @@ -165,14 +165,21 @@ _ft_done_face_uncached (void *closure) static GBool _ft_new_face_uncached (FT_Library lib, const char *filename, + char *font_data, + int font_data_len, FT_Face *face_out, cairo_font_face_t **font_face_out) { FT_Face face; cairo_font_face_t *font_face; - if (FT_New_Face (lib, filename, 0, &face)) - return gFalse; + if (font_data == NULL) { + if (FT_New_Face (lib, filename, 0, &face)) + return gFalse; + } else { + if (FT_New_Memory_Face (lib, (unsigned char *)font_data, font_data_len, 0, &face)) + return gFalse; + } font_face = cairo_ft_font_face_create_for_ft_face (face, FT_LOAD_NO_HINTING | @@ -257,6 +264,8 @@ _ft_done_face (void *closure) static GBool _ft_new_face (FT_Library lib, const char *filename, + char *font_data, + int font_data_len, FT_Face *face_out, cairo_font_face_t **font_face_out) { @@ -264,37 +273,46 @@ _ft_new_face (FT_Library lib, struct stat st; struct _ft_face_data tmpl; - /* if we fail to mmap the file, just pass it to FreeType instead */ - tmpl.fd = open (filename, O_RDONLY); - if (tmpl.fd == -1) - return _ft_new_face_uncached (lib, filename, face_out, font_face_out); + tmpl.fd = -1; - if (fstat (tmpl.fd, &st) == -1) { - close (tmpl.fd); - return _ft_new_face_uncached (lib, filename, face_out, font_face_out); - } + if (font_data == NULL) { + /* if we fail to mmap the file, just pass it to FreeType instead */ + tmpl.fd = open (filename, O_RDONLY); + if (tmpl.fd == -1) + return _ft_new_face_uncached (lib, filename, font_data, font_data_len, face_out, font_face_out); + + if (fstat (tmpl.fd, &st) == -1) { + close (tmpl.fd); + return _ft_new_face_uncached (lib, filename, font_data, font_data_len, face_out, font_face_out); + } - tmpl.bytes = (unsigned char *) mmap (NULL, st.st_size, - PROT_READ, MAP_PRIVATE, - tmpl.fd, 0); - if (tmpl.bytes == MAP_FAILED) { - close (tmpl.fd); - return _ft_new_face_uncached (lib, filename, face_out, font_face_out); + tmpl.bytes = (unsigned char *) mmap (NULL, st.st_size, + PROT_READ, MAP_PRIVATE, + tmpl.fd, 0); + if (tmpl.bytes == MAP_FAILED) { + close (tmpl.fd); + return _ft_new_face_uncached (lib, filename, font_data, font_data_len, face_out, font_face_out); + } + tmpl.size = st.st_size; + } else { + tmpl.bytes = (unsigned char*) font_data; + tmpl.size = font_data_len; } /* check to see if this is a duplicate of any of the currently open fonts */ tmpl.lib = lib; - tmpl.size = st.st_size; tmpl.hash = _djb_hash (tmpl.bytes, tmpl.size); for (l = _ft_open_faces; l; l = l->next) { if (_ft_face_data_equal (l, &tmpl)) { + if (tmpl.fd != -1) { #if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4) - munmap ((char*)tmpl.bytes, tmpl.size); + munmap ((char*)tmpl.bytes, tmpl.size); #else - munmap (tmpl.bytes, tmpl.size); + munmap (tmpl.bytes, tmpl.size); #endif - close (tmpl.fd); + close (tmpl.fd); + } *face_out = l->face; *font_face_out = cairo_font_face_reference (l->font_face); return gTrue; @@ -306,13 +324,15 @@ _ft_new_face (FT_Library lib, (FT_Byte *) tmpl.bytes, tmpl.size, 0, &tmpl.face)) { + if (tmpl.fd != -1) { #if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4) - munmap ((char*)tmpl.bytes, tmpl.size); + munmap ((char*)tmpl.bytes, tmpl.size); #else - munmap (tmpl.bytes, tmpl.size); + munmap (tmpl.bytes, tmpl.size); #endif - close (tmpl.fd); + close (tmpl.fd); + } return gFalse; } @@ -364,10 +384,12 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs) { Ref embRef; Object refObj, strObj; - GooString *tmpFileName, *fileName; + GooString *fileName; + char *fileNameC; + char *font_data; + int font_data_len; DisplayFontParam *dfp; - FILE *tmpFile; - int c, i, n; + int i, n; GfxFontType fontType; char **enc; char *name; @@ -379,42 +401,25 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, Gushort *codeToGID; int codeToGIDLen; - + dfp = NULL; codeToGID = NULL; codeToGIDLen = 0; + font_data = NULL; + font_data_len = 0; + fileName = NULL; + fileNameC = NULL; GBool substitute = gFalse; - + ref = *gfxFont->getID(); fontType = gfxFont->getType(); - tmpFileName = NULL; - if (gfxFont->getEmbeddedFontID(&embRef)) { - if (!openTempFile(&tmpFileName, &tmpFile, "wb")) { - error(-1, "Couldn't create temporary font file"); - goto err2; - } - - refObj.initRef(embRef.num, embRef.gen); - refObj.fetch(xref, &strObj); - refObj.free(); - if (!strObj.isStream()) { - error(-1, "Embedded font object is wrong type"); - strObj.free(); - fclose(tmpFile); - goto err2; - } - strObj.streamReset(); - while ((c = strObj.streamGetChar()) != EOF) { - fputc(c, tmpFile); - } - strObj.streamClose(); - strObj.free(); - fclose(tmpFile); - fileName = tmpFileName; - + 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; @@ -440,17 +445,21 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, substitute = gTrue; } + if (fileName != NULL) { + fileNameC = fileName->getCString(); + } + switch (fontType) { case fontType1: case fontType1C: case fontType1COT: - if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) { + if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) { error(-1, "could not create type1 face"); goto err2; } - + enc = ((Gfx8BitFont *)gfxFont)->getEncoding(); - + codeToGID = (Gushort *)gmallocn(256, sizeof(int)); codeToGIDLen = 256; for (i = 0; i < 256; ++i) { @@ -460,7 +469,7 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, } } break; - + case fontCIDType2: codeToGID = NULL; n = 0; @@ -472,7 +481,11 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, n * sizeof(Gushort)); } } else { - ff = FoFiTrueType::load(fileName->getCString()); + if (font_data != NULL) { + ff = FoFiTrueType::make(font_data, font_data_len); + } else { + ff = FoFiTrueType::load(fileNameC); + } if (! ff) goto err2; codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n); @@ -481,22 +494,27 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, codeToGIDLen = n; /* Fall through */ case fontTrueType: - if (!(ff = FoFiTrueType::load(fileName->getCString()))) { - error(-1, "failed to load truetype font\n"); - goto err2; - } + if (font_data != NULL) { + ff = FoFiTrueType::make(font_data, font_data_len); + } else { + ff = FoFiTrueType::load(fileNameC); + } + if (!(ff)) { + error(-1, "failed to load truetype font\n"); + goto err2; + } /* This might be set already for the CIDType2 case */ if (fontType == fontTrueType) { codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff); codeToGIDLen = 256; } delete ff; - if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) { + if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) { error(-1, "could not create truetype face\n"); goto err2; } break; - + case fontCIDType0: case fontCIDType0C: @@ -505,34 +523,31 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, if (!useCIDs) { - if ((ff1c = FoFiType1C::load(fileName->getCString()))) { + if (font_data != NULL) { + ff1c = FoFiType1C::make(font_data, font_data_len); + } else { + ff1c = FoFiType1C::load(fileNameC); + } + if (ff1c) { codeToGID = ff1c->getCIDToGIDMap(&codeToGIDLen); delete ff1c; } } - if (! _ft_new_face (lib, fileName->getCString(), &face, &font_face)) { + if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) { gfree(codeToGID); codeToGID = NULL; error(-1, "could not create cid face\n"); goto err2; } break; - + default: - printf ("font type %d not handled\n", (int)fontType); + fprintf (stderr, "font type %d not handled\n", (int)fontType); goto err2; break; } - // delete the (temporary) font file -- with Unix hard link - // semantics, this will remove the last link; otherwise it will - // return an error, leaving the file to be deleted later - if (fileName == tmpFileName) { - unlink (fileName->getCString()); - delete tmpFileName; - } - return new CairoFreeTypeFont(ref, font_face, face, codeToGID, codeToGIDLen, @@ -540,7 +555,7 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, err2: /* hmm? */ - printf ("some font thing failed\n"); + fprintf (stderr, "some font thing failed\n"); return NULL; } @@ -726,7 +741,7 @@ CairoFontEngine::CairoFontEngine(FT_Library libA) { for (i = 0; i < cairoFontCacheSize; ++i) { fontCache[i] = NULL; } - + FT_Int major, minor, patch; // as of FT 2.1.8, CID fonts are indexed by CID instead of GID FT_Library_Version(lib, &major, &minor, &patch); @@ -736,7 +751,7 @@ CairoFontEngine::CairoFontEngine(FT_Library libA) { CairoFontEngine::~CairoFontEngine() { int i; - + for (i = 0; i < cairoFontCacheSize; ++i) { if (fontCache[i]) delete fontCache[i]; @@ -749,7 +764,7 @@ CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref, Catalog *catalog, GBool p Ref ref; CairoFont *font; GfxFontType fontType; - + ref = *gfxFont->getID(); for (i = 0; i < cairoFontCacheSize; ++i) { @@ -762,7 +777,7 @@ CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref, Catalog *catalog, GBool p return font; } } - + fontType = gfxFont->getType(); if (fontType == fontType3) font = CairoType3Font::create (gfxFont, xref, catalog, this, printing);