//======================================================================== // // SplashFontEngine.cc // //======================================================================== //======================================================================== // // Modified under the Poppler project - http://poppler.freedesktop.org // // All changes made under the Poppler project to this file are licensed // under GPL version 2 or later // // Copyright (C) 2006 Takashi Iwai // Copyright (C) 2009 Petr Gajdos // Copyright (C) 2009 Kovid Goyal // Copyright (C) 2009 Albert Astals Cid // Copyright (C) 2011 Andreas Hartmetz // Copyright (C) 2013 Thomas Freitag // Copyright (C) 2015 Dmytro Morgun // Copyright (C) 2017 Adrian Johnson // Copyright (C) 2018 Oliver Sander // Copyright (C) 2019 Christian Persch // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git // //======================================================================== #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include #include "goo/gmem.h" #include "goo/GooString.h" #include "SplashMath.h" #include "SplashFTFontEngine.h" #include "SplashFontFile.h" #include "SplashFontFileID.h" #include "SplashFont.h" #include "SplashFontEngine.h" //------------------------------------------------------------------------ // SplashFontEngine //------------------------------------------------------------------------ SplashFontEngine::SplashFontEngine(bool enableFreeType, bool enableFreeTypeHinting, bool enableSlightHinting, bool aa) { std::fill(fontCache.begin(), fontCache.end(), nullptr); if (enableFreeType) { ftEngine = SplashFTFontEngine::init(aa, enableFreeTypeHinting, enableSlightHinting); } else { ftEngine = nullptr; } } SplashFontEngine::~SplashFontEngine() { for (auto font : fontCache) { delete font; } if (ftEngine) { delete ftEngine; } } SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) { for (auto font : fontCache) { if (font) { SplashFontFile *fontFile = font->getFontFile(); if (fontFile && fontFile->getID()->matches(id)) { return fontFile; } } } return nullptr; } SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA, SplashFontSrc *src, const char **enc) { SplashFontFile *fontFile = nullptr; if (ftEngine) { fontFile = ftEngine->loadType1Font(idA, src, enc); } // 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 // loadXYZFont failed, the file will always be deleted) if (src->isFile) { src->unref(); } return fontFile; } SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA, SplashFontSrc *src, const char **enc) { SplashFontFile *fontFile = nullptr; if (ftEngine) { fontFile = ftEngine->loadType1CFont(idA, src, enc); } // 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 // loadXYZFont failed, the file will always be deleted) if (src->isFile) { src->unref(); } return fontFile; } SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, SplashFontSrc *src, const char **enc) { SplashFontFile *fontFile = nullptr; if (ftEngine) { fontFile = ftEngine->loadOpenTypeT1CFont(idA, src, enc); } // 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 // loadXYZFont failed, the file will always be deleted) if (src->isFile) { src->unref(); } return fontFile; } SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA, SplashFontSrc *src) { SplashFontFile *fontFile = nullptr; if (ftEngine) { fontFile = ftEngine->loadCIDFont(idA, src); } // 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 // loadXYZFont failed, the file will always be deleted) if (src->isFile) { src->unref(); } return fontFile; } SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, SplashFontSrc *src, int *codeToGID, int codeToGIDLen) { SplashFontFile *fontFile = nullptr; if (ftEngine) { fontFile = ftEngine->loadOpenTypeCFFFont(idA, src, codeToGID, codeToGIDLen); } // 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 // loadXYZFont failed, the file will always be deleted) if (src->isFile) { src->unref(); } return fontFile; } SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA, SplashFontSrc *src, int *codeToGID, int codeToGIDLen, int faceIndex) { SplashFontFile *fontFile = nullptr; if (ftEngine) { fontFile = ftEngine->loadTrueTypeFont(idA, src, codeToGID, codeToGIDLen, faceIndex); } if (!fontFile) { gfree(codeToGID); } // 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 // loadXYZFont failed, the file will always be deleted) if (src->isFile) { src->unref(); } return fontFile; } bool SplashFontEngine::getAA() { return (ftEngine == nullptr) ? false : ftEngine->getAA(); } void SplashFontEngine::setAA(bool aa) { if (ftEngine != nullptr) { ftEngine->setAA(aa); } } SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile, const SplashCoord *textMat, const SplashCoord *ctm) { SplashCoord mat[4]; mat[0] = textMat[0] * ctm[0] + textMat[1] * ctm[2]; mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]); mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2]; mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]); if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.01)) { // avoid a singular (or close-to-singular) matrix mat[0] = 0.01; mat[1] = 0; mat[2] = 0; mat[3] = 0.01; } // Try to find the font in the cache auto fontIt = std::find_if(fontCache.begin(), fontCache.end(), [&](const SplashFont *font) { return font && font->matches(fontFile, mat, textMat); }); // The requested font has been found in the cache if (fontIt != fontCache.end()) { std::rotate(fontCache.begin(), fontIt, fontIt + 1); return fontCache[0]; } // The requested font has not been found in the cache auto newFont = fontFile->makeFont(mat, textMat); if (fontCache.back()) { delete fontCache.back(); } std::rotate(fontCache.begin(), fontCache.end() - 1, fontCache.end()); fontCache[0] = newFont; return fontCache[0]; }