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 | |
52 | SplashFontEngine::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 | |
63 | SplashFontEngine::~SplashFontEngine() |
64 | { |
65 | for (auto font : fontCache) { |
66 | delete font; |
67 | } |
68 | |
69 | if (ftEngine) { |
70 | delete ftEngine; |
71 | } |
72 | } |
73 | |
74 | SplashFontFile *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 | |
87 | SplashFontFile *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 | |
106 | SplashFontFile *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 | |
125 | SplashFontFile *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 | |
144 | SplashFontFile *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 | |
163 | SplashFontFile *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 | |
182 | SplashFontFile *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 | |
205 | bool SplashFontEngine::getAA() |
206 | { |
207 | return (ftEngine == nullptr) ? false : ftEngine->getAA(); |
208 | } |
209 | |
210 | void SplashFontEngine::setAA(bool aa) |
211 | { |
212 | if (ftEngine != nullptr) { |
213 | ftEngine->setAA(aa); |
214 | } |
215 | } |
216 | |
217 | SplashFont *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 | |