Spaces:
Running
Running
//======================================================================== | |
// | |
// 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 <[email protected]> | |
// Copyright (C) 2009 Petr Gajdos <[email protected]> | |
// Copyright (C) 2009 Kovid Goyal <[email protected]> | |
// Copyright (C) 2009 Albert Astals Cid <[email protected]> | |
// Copyright (C) 2011 Andreas Hartmetz <[email protected]> | |
// Copyright (C) 2013 Thomas Freitag <[email protected]> | |
// Copyright (C) 2015 Dmytro Morgun <[email protected]> | |
// Copyright (C) 2017 Adrian Johnson <[email protected]> | |
// Copyright (C) 2018 Oliver Sander <[email protected]> | |
// Copyright (C) 2019 Christian Persch <[email protected]> | |
// | |
// 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 | |
// | |
//======================================================================== | |
//------------------------------------------------------------------------ | |
// 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]; | |
} | |