| //======================================================================== |
| // |
| // 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 <tiwai@suse.de> |
| // Copyright (C) 2009 Petr Gajdos <pgajdos@novell.com> |
| // Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net> |
| // Copyright (C) 2009 Albert Astals Cid <aacid@kde.org> |
| // Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com> |
| // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de> |
| // Copyright (C) 2015 Dmytro Morgun <lztoad@gmail.com> |
| // Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com> |
| // Copyright (C) 2018 Oliver Sander <oliver.sander@tu-dresden.de> |
| // Copyright (C) 2019 Christian Persch <chpe@src.gnome.org> |
| // |
| // 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 <config.h> |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #ifdef HAVE_UNISTD_H |
| # include <unistd.h> |
| #endif |
| #include <algorithm> |
| |
| #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]; |
| } |