/src/xpdf-4.04/splash/SplashFontEngine.cc
Line | Count | Source (jump to first uncovered line) |
1 | | //======================================================================== |
2 | | // |
3 | | // SplashFontEngine.cc |
4 | | // |
5 | | // Copyright 2003-2013 Glyph & Cog, LLC |
6 | | // |
7 | | //======================================================================== |
8 | | |
9 | | #include <aconf.h> |
10 | | |
11 | | #ifdef USE_GCC_PRAGMAS |
12 | | #pragma implementation |
13 | | #endif |
14 | | |
15 | | #include <stdlib.h> |
16 | | #include <stdio.h> |
17 | | #ifndef _WIN32 |
18 | | # include <unistd.h> |
19 | | #endif |
20 | | #include "gmem.h" |
21 | | #include "gmempp.h" |
22 | | #include "GString.h" |
23 | | #include "GList.h" |
24 | | #include "SplashMath.h" |
25 | | #include "SplashFTFontEngine.h" |
26 | | #include "SplashFontFile.h" |
27 | | #include "SplashFontFileID.h" |
28 | | #include "SplashFont.h" |
29 | | #include "SplashFontEngine.h" |
30 | | |
31 | | #ifdef VMS |
32 | | #if (__VMS_VER < 70000000) |
33 | | extern "C" int unlink(char *filename); |
34 | | #endif |
35 | | #endif |
36 | | |
37 | | //------------------------------------------------------------------------ |
38 | | // SplashFontEngine |
39 | | //------------------------------------------------------------------------ |
40 | | |
41 | | SplashFontEngine::SplashFontEngine( |
42 | | #if HAVE_FREETYPE_H |
43 | | GBool enableFreeType, |
44 | | Guint freeTypeFlags, |
45 | | #endif |
46 | 0 | GBool aa) { |
47 | 0 | int i; |
48 | |
|
49 | 0 | for (i = 0; i < splashFontCacheSize; ++i) { |
50 | 0 | fontCache[i] = NULL; |
51 | 0 | } |
52 | 0 | badFontFiles = new GList(); |
53 | |
|
54 | 0 | #if HAVE_FREETYPE_H |
55 | 0 | if (enableFreeType) { |
56 | 0 | ftEngine = SplashFTFontEngine::init(aa, freeTypeFlags); |
57 | 0 | } else { |
58 | 0 | ftEngine = NULL; |
59 | 0 | } |
60 | 0 | #endif |
61 | 0 | } |
62 | | |
63 | 0 | SplashFontEngine::~SplashFontEngine() { |
64 | 0 | int i; |
65 | |
|
66 | 0 | for (i = 0; i < splashFontCacheSize; ++i) { |
67 | 0 | if (fontCache[i]) { |
68 | 0 | delete fontCache[i]; |
69 | 0 | } |
70 | 0 | } |
71 | 0 | deleteGList(badFontFiles, SplashFontFileID); |
72 | |
|
73 | 0 | #if HAVE_FREETYPE_H |
74 | 0 | if (ftEngine) { |
75 | 0 | delete ftEngine; |
76 | 0 | } |
77 | 0 | #endif |
78 | 0 | } |
79 | | |
80 | 0 | SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) { |
81 | 0 | SplashFontFile *fontFile; |
82 | 0 | int i; |
83 | |
|
84 | 0 | for (i = 0; i < splashFontCacheSize; ++i) { |
85 | 0 | if (fontCache[i]) { |
86 | 0 | fontFile = fontCache[i]->getFontFile(); |
87 | 0 | if (fontFile && fontFile->getID()->matches(id)) { |
88 | 0 | return fontFile; |
89 | 0 | } |
90 | 0 | } |
91 | 0 | } |
92 | 0 | return NULL; |
93 | 0 | } |
94 | | |
95 | 0 | GBool SplashFontEngine::checkForBadFontFile(SplashFontFileID *id) { |
96 | 0 | for (int i = 0; i < badFontFiles->getLength(); ++i) { |
97 | 0 | if (((SplashFontFileID *)badFontFiles->get(i))->matches(id)) { |
98 | 0 | return gTrue; |
99 | 0 | } |
100 | 0 | } |
101 | 0 | return gFalse; |
102 | 0 | } |
103 | | |
104 | | SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA, |
105 | | #if LOAD_FONTS_FROM_MEM |
106 | | GString *fontBuf, |
107 | | #else |
108 | | char *fileName, |
109 | | GBool deleteFile, |
110 | | #endif |
111 | 0 | const char **enc) { |
112 | 0 | SplashFontFile *fontFile; |
113 | |
|
114 | 0 | fontFile = NULL; |
115 | 0 | #if HAVE_FREETYPE_H |
116 | 0 | if (!fontFile && ftEngine) { |
117 | 0 | fontFile = ftEngine->loadType1Font(idA, |
118 | | #if LOAD_FONTS_FROM_MEM |
119 | | fontBuf, |
120 | | #else |
121 | 0 | fileName, deleteFile, |
122 | 0 | #endif |
123 | 0 | enc); |
124 | 0 | } |
125 | 0 | #endif |
126 | |
|
127 | 0 | #if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__) |
128 | | // delete the (temporary) font file -- with Unix hard link |
129 | | // semantics, this will remove the last link; otherwise it will |
130 | | // return an error, leaving the file to be deleted later (if |
131 | | // loadXYZFont failed, the file will always be deleted) |
132 | 0 | if (deleteFile) { |
133 | 0 | unlink(fontFile ? fontFile->fileName->getCString() : fileName); |
134 | 0 | } |
135 | 0 | #endif |
136 | |
|
137 | 0 | if (!fontFile) { |
138 | 0 | badFontFiles->append(idA); |
139 | 0 | } |
140 | |
|
141 | 0 | return fontFile; |
142 | 0 | } |
143 | | |
144 | | SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA, |
145 | | #if LOAD_FONTS_FROM_MEM |
146 | | GString *fontBuf, |
147 | | #else |
148 | | char *fileName, |
149 | | GBool deleteFile, |
150 | | #endif |
151 | | int *codeToGID, |
152 | 0 | const char **enc) { |
153 | 0 | SplashFontFile *fontFile; |
154 | |
|
155 | 0 | fontFile = NULL; |
156 | 0 | if (!fontFile) { |
157 | 0 | gfree(codeToGID); |
158 | 0 | } |
159 | 0 | #if HAVE_FREETYPE_H |
160 | 0 | if (!fontFile && ftEngine) { |
161 | 0 | fontFile = ftEngine->loadType1CFont(idA, |
162 | | #if LOAD_FONTS_FROM_MEM |
163 | | fontBuf, |
164 | | #else |
165 | 0 | fileName, deleteFile, |
166 | 0 | #endif |
167 | 0 | enc); |
168 | 0 | } |
169 | 0 | #endif |
170 | |
|
171 | 0 | #if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__) |
172 | | // delete the (temporary) font file -- with Unix hard link |
173 | | // semantics, this will remove the last link; otherwise it will |
174 | | // return an error, leaving the file to be deleted later (if |
175 | | // loadXYZFont failed, the file will always be deleted) |
176 | 0 | if (deleteFile) { |
177 | 0 | unlink(fontFile ? fontFile->fileName->getCString() : fileName); |
178 | 0 | } |
179 | 0 | #endif |
180 | |
|
181 | 0 | if (!fontFile) { |
182 | 0 | badFontFiles->append(idA); |
183 | 0 | } |
184 | |
|
185 | 0 | return fontFile; |
186 | 0 | } |
187 | | |
188 | | SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, |
189 | | #if LOAD_FONTS_FROM_MEM |
190 | | GString *fontBuf, |
191 | | #else |
192 | | char *fileName, |
193 | | GBool deleteFile, |
194 | | #endif |
195 | | int *codeToGID, |
196 | 0 | const char **enc) { |
197 | 0 | SplashFontFile *fontFile; |
198 | |
|
199 | 0 | fontFile = NULL; |
200 | 0 | if (!fontFile) { |
201 | 0 | gfree(codeToGID); |
202 | 0 | } |
203 | 0 | #if HAVE_FREETYPE_H |
204 | 0 | if (!fontFile && ftEngine) { |
205 | 0 | fontFile = ftEngine->loadOpenTypeT1CFont(idA, |
206 | | #if LOAD_FONTS_FROM_MEM |
207 | | fontBuf, |
208 | | #else |
209 | 0 | fileName, deleteFile, |
210 | 0 | #endif |
211 | 0 | enc); |
212 | 0 | } |
213 | 0 | #endif |
214 | |
|
215 | 0 | #if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__) |
216 | | // delete the (temporary) font file -- with Unix hard link |
217 | | // semantics, this will remove the last link; otherwise it will |
218 | | // return an error, leaving the file to be deleted later (if |
219 | | // loadXYZFont failed, the file will always be deleted) |
220 | 0 | if (deleteFile) { |
221 | 0 | unlink(fontFile ? fontFile->fileName->getCString() : fileName); |
222 | 0 | } |
223 | 0 | #endif |
224 | |
|
225 | 0 | if (!fontFile) { |
226 | 0 | badFontFiles->append(idA); |
227 | 0 | } |
228 | |
|
229 | 0 | return fontFile; |
230 | 0 | } |
231 | | |
232 | | SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA, |
233 | | #if LOAD_FONTS_FROM_MEM |
234 | | GString *fontBuf, |
235 | | #else |
236 | | char *fileName, |
237 | | GBool deleteFile, |
238 | | #endif |
239 | | int *codeToGID, |
240 | 0 | int codeToGIDLen) { |
241 | 0 | SplashFontFile *fontFile; |
242 | |
|
243 | 0 | fontFile = NULL; |
244 | 0 | #if HAVE_FREETYPE_H |
245 | 0 | if (!fontFile && ftEngine) { |
246 | 0 | fontFile = ftEngine->loadCIDFont(idA, |
247 | | #if LOAD_FONTS_FROM_MEM |
248 | | fontBuf, |
249 | | #else |
250 | 0 | fileName, deleteFile, |
251 | 0 | #endif |
252 | 0 | codeToGID, codeToGIDLen); |
253 | 0 | } |
254 | 0 | #endif |
255 | |
|
256 | 0 | if (!fontFile) { |
257 | 0 | gfree(codeToGID); |
258 | 0 | } |
259 | |
|
260 | 0 | #if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__) |
261 | | // delete the (temporary) font file -- with Unix hard link |
262 | | // semantics, this will remove the last link; otherwise it will |
263 | | // return an error, leaving the file to be deleted later (if |
264 | | // loadXYZFont failed, the file will always be deleted) |
265 | 0 | if (deleteFile) { |
266 | 0 | unlink(fontFile ? fontFile->fileName->getCString() : fileName); |
267 | 0 | } |
268 | 0 | #endif |
269 | |
|
270 | 0 | if (!fontFile) { |
271 | 0 | badFontFiles->append(idA); |
272 | 0 | } |
273 | |
|
274 | 0 | return fontFile; |
275 | 0 | } |
276 | | |
277 | | SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, |
278 | | #if LOAD_FONTS_FROM_MEM |
279 | | GString *fontBuf, |
280 | | #else |
281 | | char *fileName, |
282 | | GBool deleteFile, |
283 | | #endif |
284 | | int *codeToGID, |
285 | 0 | int codeToGIDLen) { |
286 | 0 | SplashFontFile *fontFile; |
287 | |
|
288 | 0 | fontFile = NULL; |
289 | 0 | #if HAVE_FREETYPE_H |
290 | 0 | if (!fontFile && ftEngine) { |
291 | 0 | fontFile = ftEngine->loadOpenTypeCFFFont(idA, |
292 | | #if LOAD_FONTS_FROM_MEM |
293 | | fontBuf, |
294 | | #else |
295 | 0 | fileName, deleteFile, |
296 | 0 | #endif |
297 | 0 | codeToGID, codeToGIDLen); |
298 | 0 | } |
299 | 0 | #endif |
300 | |
|
301 | 0 | if (!fontFile) { |
302 | 0 | gfree(codeToGID); |
303 | 0 | } |
304 | |
|
305 | 0 | #if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__) |
306 | | // delete the (temporary) font file -- with Unix hard link |
307 | | // semantics, this will remove the last link; otherwise it will |
308 | | // return an error, leaving the file to be deleted later (if |
309 | | // loadXYZFont failed, the file will always be deleted) |
310 | 0 | if (deleteFile) { |
311 | 0 | unlink(fontFile ? fontFile->fileName->getCString() : fileName); |
312 | 0 | } |
313 | 0 | #endif |
314 | |
|
315 | 0 | if (!fontFile) { |
316 | 0 | badFontFiles->append(idA); |
317 | 0 | } |
318 | |
|
319 | 0 | return fontFile; |
320 | 0 | } |
321 | | |
322 | | SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA, |
323 | | #if LOAD_FONTS_FROM_MEM |
324 | | GString *fontBuf, |
325 | | #else |
326 | | char *fileName, |
327 | | GBool deleteFile, |
328 | | #endif |
329 | | int fontNum, |
330 | | int *codeToGID, |
331 | | int codeToGIDLen, |
332 | 0 | char *fontName) { |
333 | 0 | SplashFontFile *fontFile; |
334 | |
|
335 | 0 | fontFile = NULL; |
336 | 0 | #if HAVE_FREETYPE_H |
337 | 0 | if (!fontFile && ftEngine) { |
338 | 0 | fontFile = ftEngine->loadTrueTypeFont(idA, |
339 | | #if LOAD_FONTS_FROM_MEM |
340 | | fontBuf, |
341 | | #else |
342 | 0 | fileName, deleteFile, |
343 | 0 | #endif |
344 | 0 | fontNum, codeToGID, codeToGIDLen); |
345 | 0 | } |
346 | 0 | #endif |
347 | |
|
348 | 0 | if (!fontFile) { |
349 | 0 | gfree(codeToGID); |
350 | 0 | } |
351 | |
|
352 | 0 | #if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__) |
353 | | // delete the (temporary) font file -- with Unix hard link |
354 | | // semantics, this will remove the last link; otherwise it will |
355 | | // return an error, leaving the file to be deleted later (if |
356 | | // loadXYZFont failed, the file will always be deleted) |
357 | 0 | if (deleteFile) { |
358 | 0 | unlink(fontFile ? fontFile->fileName->getCString() : fileName); |
359 | 0 | } |
360 | 0 | #endif |
361 | |
|
362 | 0 | if (!fontFile) { |
363 | 0 | badFontFiles->append(idA); |
364 | 0 | } |
365 | |
|
366 | 0 | return fontFile; |
367 | 0 | } |
368 | | |
369 | | SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile, |
370 | | SplashCoord *textMat, |
371 | 0 | SplashCoord *ctm) { |
372 | 0 | SplashCoord mat[4]; |
373 | 0 | SplashFont *font; |
374 | 0 | int i, j; |
375 | |
|
376 | 0 | mat[0] = textMat[0] * ctm[0] + textMat[1] * ctm[2]; |
377 | 0 | mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]); |
378 | 0 | mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2]; |
379 | 0 | mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]); |
380 | 0 | if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.01)) { |
381 | | // avoid a singular (or close-to-singular) matrix |
382 | 0 | mat[0] = 0.01; mat[1] = 0; |
383 | 0 | mat[2] = 0; mat[3] = 0.01; |
384 | 0 | } |
385 | |
|
386 | 0 | font = fontCache[0]; |
387 | 0 | if (font && font->matches(fontFile, mat, textMat)) { |
388 | 0 | return font; |
389 | 0 | } |
390 | 0 | for (i = 1; i < splashFontCacheSize; ++i) { |
391 | 0 | font = fontCache[i]; |
392 | 0 | if (font && font->matches(fontFile, mat, textMat)) { |
393 | 0 | for (j = i; j > 0; --j) { |
394 | 0 | fontCache[j] = fontCache[j-1]; |
395 | 0 | } |
396 | 0 | fontCache[0] = font; |
397 | 0 | return font; |
398 | 0 | } |
399 | 0 | } |
400 | 0 | font = fontFile->makeFont(mat, textMat); |
401 | 0 | if (fontCache[splashFontCacheSize - 1]) { |
402 | 0 | delete fontCache[splashFontCacheSize - 1]; |
403 | 0 | } |
404 | 0 | for (j = splashFontCacheSize - 1; j > 0; --j) { |
405 | 0 | fontCache[j] = fontCache[j-1]; |
406 | 0 | } |
407 | 0 | fontCache[0] = font; |
408 | 0 | return font; |
409 | 0 | } |