1//========================================================================
2//
3// SplashFontEngine.cc
4//
5//========================================================================
6
7//========================================================================
8//
9// Modified under the Poppler project - http://poppler.freedesktop.org
10//
11// All changes made under the Poppler project to this file are licensed
12// under GPL version 2 or later
13//
14// Copyright (C) 2006 Takashi Iwai <tiwai@suse.de>
15// Copyright (C) 2009 Petr Gajdos <pgajdos@novell.com>
16// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
17// Copyright (C) 2009 Albert Astals Cid <aacid@kde.org>
18// Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com>
19// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
20// Copyright (C) 2015 Dmytro Morgun <lztoad@gmail.com>
21// Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com>
22// Copyright (C) 2018 Oliver Sander <oliver.sander@tu-dresden.de>
23// Copyright (C) 2019 Christian Persch <chpe@src.gnome.org>
24//
25// To see a description of the changes please see the Changelog file that
26// came with your tarball or type make ChangeLog if you are building from git
27//
28//========================================================================
29
30#include <config.h>
31
32#include <cstdlib>
33#include <cstdio>
34#ifdef HAVE_UNISTD_H
35# include <unistd.h>
36#endif
37#include <algorithm>
38
39#include "goo/gmem.h"
40#include "goo/GooString.h"
41#include "SplashMath.h"
42#include "SplashFTFontEngine.h"
43#include "SplashFontFile.h"
44#include "SplashFontFileID.h"
45#include "SplashFont.h"
46#include "SplashFontEngine.h"
47
48//------------------------------------------------------------------------
49// SplashFontEngine
50//------------------------------------------------------------------------
51
52SplashFontEngine::SplashFontEngine(bool enableFreeType, bool enableFreeTypeHinting, bool enableSlightHinting, bool aa)
53{
54 std::fill(first: fontCache.begin(), last: fontCache.end(), value: nullptr);
55
56 if (enableFreeType) {
57 ftEngine = SplashFTFontEngine::init(aaA: aa, enableFreeTypeHintingA: enableFreeTypeHinting, enableSlightHinting);
58 } else {
59 ftEngine = nullptr;
60 }
61}
62
63SplashFontEngine::~SplashFontEngine()
64{
65 for (auto font : fontCache) {
66 delete font;
67 }
68
69 if (ftEngine) {
70 delete ftEngine;
71 }
72}
73
74SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id)
75{
76 for (auto font : fontCache) {
77 if (font) {
78 SplashFontFile *fontFile = font->getFontFile();
79 if (fontFile && fontFile->getID()->matches(id)) {
80 return fontFile;
81 }
82 }
83 }
84 return nullptr;
85}
86
87SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA, SplashFontSrc *src, const char **enc)
88{
89 SplashFontFile *fontFile = nullptr;
90
91 if (ftEngine) {
92 fontFile = ftEngine->loadType1Font(idA, src, enc);
93 }
94
95 // delete the (temporary) font file -- with Unix hard link
96 // semantics, this will remove the last link; otherwise it will
97 // return an error, leaving the file to be deleted later (if
98 // loadXYZFont failed, the file will always be deleted)
99 if (src->isFile) {
100 src->unref();
101 }
102
103 return fontFile;
104}
105
106SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA, SplashFontSrc *src, const char **enc)
107{
108 SplashFontFile *fontFile = nullptr;
109
110 if (ftEngine) {
111 fontFile = ftEngine->loadType1CFont(idA, src, enc);
112 }
113
114 // delete the (temporary) font file -- with Unix hard link
115 // semantics, this will remove the last link; otherwise it will
116 // return an error, leaving the file to be deleted later (if
117 // loadXYZFont failed, the file will always be deleted)
118 if (src->isFile) {
119 src->unref();
120 }
121
122 return fontFile;
123}
124
125SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, SplashFontSrc *src, const char **enc)
126{
127 SplashFontFile *fontFile = nullptr;
128
129 if (ftEngine) {
130 fontFile = ftEngine->loadOpenTypeT1CFont(idA, src, enc);
131 }
132
133 // delete the (temporary) font file -- with Unix hard link
134 // semantics, this will remove the last link; otherwise it will
135 // return an error, leaving the file to be deleted later (if
136 // loadXYZFont failed, the file will always be deleted)
137 if (src->isFile) {
138 src->unref();
139 }
140
141 return fontFile;
142}
143
144SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA, SplashFontSrc *src)
145{
146 SplashFontFile *fontFile = nullptr;
147
148 if (ftEngine) {
149 fontFile = ftEngine->loadCIDFont(idA, src);
150 }
151
152 // delete the (temporary) font file -- with Unix hard link
153 // semantics, this will remove the last link; otherwise it will
154 // return an error, leaving the file to be deleted later (if
155 // loadXYZFont failed, the file will always be deleted)
156 if (src->isFile) {
157 src->unref();
158 }
159
160 return fontFile;
161}
162
163SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, SplashFontSrc *src, int *codeToGID, int codeToGIDLen)
164{
165 SplashFontFile *fontFile = nullptr;
166
167 if (ftEngine) {
168 fontFile = ftEngine->loadOpenTypeCFFFont(idA, src, codeToGID, codeToGIDLen);
169 }
170
171 // delete the (temporary) font file -- with Unix hard link
172 // semantics, this will remove the last link; otherwise it will
173 // return an error, leaving the file to be deleted later (if
174 // loadXYZFont failed, the file will always be deleted)
175 if (src->isFile) {
176 src->unref();
177 }
178
179 return fontFile;
180}
181
182SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA, SplashFontSrc *src, int *codeToGID, int codeToGIDLen, int faceIndex)
183{
184 SplashFontFile *fontFile = nullptr;
185
186 if (ftEngine) {
187 fontFile = ftEngine->loadTrueTypeFont(idA, src, codeToGID, codeToGIDLen, faceIndex);
188 }
189
190 if (!fontFile) {
191 gfree(p: codeToGID);
192 }
193
194 // delete the (temporary) font file -- with Unix hard link
195 // semantics, this will remove the last link; otherwise it will
196 // return an error, leaving the file to be deleted later (if
197 // loadXYZFont failed, the file will always be deleted)
198 if (src->isFile) {
199 src->unref();
200 }
201
202 return fontFile;
203}
204
205bool SplashFontEngine::getAA()
206{
207 return (ftEngine == nullptr) ? false : ftEngine->getAA();
208}
209
210void SplashFontEngine::setAA(bool aa)
211{
212 if (ftEngine != nullptr) {
213 ftEngine->setAA(aa);
214 }
215}
216
217SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile, const SplashCoord *textMat, const SplashCoord *ctm)
218{
219 SplashCoord mat[4];
220
221 mat[0] = textMat[0] * ctm[0] + textMat[1] * ctm[2];
222 mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]);
223 mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2];
224 mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]);
225 if (!splashCheckDet(m11: mat[0], m12: mat[1], m21: mat[2], m22: mat[3], epsilon: 0.01)) {
226 // avoid a singular (or close-to-singular) matrix
227 mat[0] = 0.01;
228 mat[1] = 0;
229 mat[2] = 0;
230 mat[3] = 0.01;
231 }
232
233 // Try to find the font in the cache
234 auto fontIt = std::find_if(first: fontCache.begin(), last: fontCache.end(), pred: [&](const SplashFont *font) { return font && font->matches(fontFileA: fontFile, matA: mat, textMatA: textMat); });
235
236 // The requested font has been found in the cache
237 if (fontIt != fontCache.end()) {
238 std::rotate(first: fontCache.begin(), middle: fontIt, last: fontIt + 1);
239 return fontCache[0];
240 }
241
242 // The requested font has not been found in the cache
243 auto newFont = fontFile->makeFont(mat, textMat);
244 if (fontCache.back()) {
245 delete fontCache.back();
246 }
247 std::rotate(first: fontCache.begin(), middle: fontCache.end() - 1, last: fontCache.end());
248
249 fontCache[0] = newFont;
250 return fontCache[0];
251}
252

source code of poppler/splash/SplashFontEngine.cc