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 //
21 // To see a description of the changes please see the Changelog file that
22 // came with your tarball or type make ChangeLog if you are building from git
23 //
24 //========================================================================
25
26 #include <config.h>
27
28 #ifdef USE_GCC_PRAGMAS
29 #pragma implementation
30 #endif
31
32 #if HAVE_T1LIB_H
33 #include <t1lib.h>
34 #endif
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #ifdef HAVE_UNISTD_H
39 # include <unistd.h>
40 #endif
41 #include "goo/gmem.h"
42 #include "goo/GooString.h"
43 #include "SplashMath.h"
44 #include "SplashT1FontEngine.h"
45 #include "SplashFTFontEngine.h"
46 #include "SplashFontFile.h"
47 #include "SplashFontFileID.h"
48 #include "SplashFont.h"
49 #include "SplashFontEngine.h"
50
51 #ifdef VMS
52 #if (__VMS_VER < 70000000)
53 extern "C" int unlink(char *filename);
54 #endif
55 #endif
56
57 #ifdef VMS
58 #if (__VMS_VER < 70000000)
59 extern "C" int unlink(char *filename);
60 #endif
61 #endif
62
63 //------------------------------------------------------------------------
64 // SplashFontEngine
65 //------------------------------------------------------------------------
66
SplashFontEngine(GBool enableT1lib,GBool enableFreeType,GBool enableFreeTypeHinting,GBool enableSlightHinting,GBool aa)67 SplashFontEngine::SplashFontEngine(
68 #if HAVE_T1LIB_H
69 GBool enableT1lib,
70 #endif
71 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
72 GBool enableFreeType,
73 GBool enableFreeTypeHinting,
74 GBool enableSlightHinting,
75 #endif
76 GBool aa) {
77 int i;
78
79 for (i = 0; i < splashFontCacheSize; ++i) {
80 fontCache[i] = NULL;
81 }
82
83 #if HAVE_T1LIB_H
84 if (enableT1lib) {
85 t1Engine = SplashT1FontEngine::init(aa);
86 } else {
87 t1Engine = NULL;
88 }
89 #endif
90 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
91 if (enableFreeType) {
92 ftEngine = SplashFTFontEngine::init(aa, enableFreeTypeHinting, enableSlightHinting);
93 } else {
94 ftEngine = NULL;
95 }
96 #endif
97 }
98
~SplashFontEngine()99 SplashFontEngine::~SplashFontEngine() {
100 int i;
101
102 for (i = 0; i < splashFontCacheSize; ++i) {
103 if (fontCache[i]) {
104 delete fontCache[i];
105 }
106 }
107
108 #if HAVE_T1LIB_H
109 if (t1Engine) {
110 delete t1Engine;
111 }
112 #endif
113 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
114 if (ftEngine) {
115 delete ftEngine;
116 }
117 #endif
118 }
119
getFontFile(SplashFontFileID * id)120 SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) {
121 SplashFontFile *fontFile;
122 int i;
123
124 for (i = 0; i < splashFontCacheSize; ++i) {
125 if (fontCache[i]) {
126 fontFile = fontCache[i]->getFontFile();
127 if (fontFile && fontFile->getID()->matches(id)) {
128 return fontFile;
129 }
130 }
131 }
132 return NULL;
133 }
134
loadType1Font(SplashFontFileID * idA,SplashFontSrc * src,const char ** enc)135 SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA,
136 SplashFontSrc *src,
137 const char **enc) {
138 SplashFontFile *fontFile;
139
140 fontFile = NULL;
141 #if HAVE_T1LIB_H
142 if (!fontFile && t1Engine) {
143 fontFile = t1Engine->loadType1Font(idA, src, enc);
144 }
145 #endif
146 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
147 if (!fontFile && ftEngine) {
148 fontFile = ftEngine->loadType1Font(idA, src, enc);
149 }
150 #endif
151
152 #ifndef _WIN32
153 // delete the (temporary) font file -- with Unix hard link
154 // semantics, this will remove the last link; otherwise it will
155 // return an error, leaving the file to be deleted later (if
156 // loadXYZFont failed, the file will always be deleted)
157 if (src->isFile)
158 src->unref();
159 #endif
160
161 return fontFile;
162 }
163
loadType1CFont(SplashFontFileID * idA,SplashFontSrc * src,const char ** enc)164 SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA,
165 SplashFontSrc *src,
166 const char **enc) {
167 SplashFontFile *fontFile;
168
169 fontFile = NULL;
170 #if HAVE_T1LIB_H
171 if (!fontFile && t1Engine) {
172 fontFile = t1Engine->loadType1CFont(idA, src, enc);
173 }
174 #endif
175 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
176 if (!fontFile && ftEngine) {
177 fontFile = ftEngine->loadType1CFont(idA, src, enc);
178 }
179 #endif
180
181 #ifndef _WIN32
182 // delete the (temporary) font file -- with Unix hard link
183 // semantics, this will remove the last link; otherwise it will
184 // return an error, leaving the file to be deleted later (if
185 // loadXYZFont failed, the file will always be deleted)
186 if (src->isFile)
187 src->unref();
188 #endif
189
190 return fontFile;
191 }
192
loadOpenTypeT1CFont(SplashFontFileID * idA,SplashFontSrc * src,const char ** enc)193 SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
194 SplashFontSrc *src,
195 const char **enc) {
196 SplashFontFile *fontFile;
197
198 fontFile = NULL;
199 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
200 if (!fontFile && ftEngine) {
201 fontFile = ftEngine->loadOpenTypeT1CFont(idA, src, enc);
202 }
203 #endif
204
205 // delete the (temporary) font file -- with Unix hard link
206 // semantics, this will remove the last link; otherwise it will
207 // return an error, leaving the file to be deleted later (if
208 // loadXYZFont failed, the file will always be deleted)
209 if (src->isFile)
210 src->unref();
211
212 return fontFile;
213 }
214
loadCIDFont(SplashFontFileID * idA,SplashFontSrc * src)215 SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA,
216 SplashFontSrc *src) {
217 SplashFontFile *fontFile;
218
219 fontFile = NULL;
220 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
221 if (!fontFile && ftEngine) {
222 fontFile = ftEngine->loadCIDFont(idA, src);
223 }
224 #endif
225
226 #ifndef _WIN32
227 // delete the (temporary) font file -- with Unix hard link
228 // semantics, this will remove the last link; otherwise it will
229 // return an error, leaving the file to be deleted later (if
230 // loadXYZFont failed, the file will always be deleted)
231 if (src->isFile)
232 src->unref();
233 #endif
234
235 return fontFile;
236 }
237
loadOpenTypeCFFFont(SplashFontFileID * idA,SplashFontSrc * src,int * codeToGID,int codeToGIDLen)238 SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
239 SplashFontSrc *src,
240 int *codeToGID,
241 int codeToGIDLen) {
242 SplashFontFile *fontFile;
243
244 fontFile = NULL;
245 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
246 if (!fontFile && ftEngine) {
247 fontFile = ftEngine->loadOpenTypeCFFFont(idA, src, codeToGID, codeToGIDLen);
248 }
249 #endif
250
251 // delete the (temporary) font file -- with Unix hard link
252 // semantics, this will remove the last link; otherwise it will
253 // return an error, leaving the file to be deleted later (if
254 // loadXYZFont failed, the file will always be deleted)
255 if (src->isFile)
256 src->unref();
257
258 return fontFile;
259 }
260
loadTrueTypeFont(SplashFontFileID * idA,SplashFontSrc * src,int * codeToGID,int codeToGIDLen,int faceIndex)261 SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
262 SplashFontSrc *src,
263 int *codeToGID,
264 int codeToGIDLen,
265 int faceIndex) {
266 SplashFontFile *fontFile;
267
268 fontFile = NULL;
269 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
270 if (!fontFile && ftEngine) {
271 fontFile = ftEngine->loadTrueTypeFont(idA, src,
272 codeToGID, codeToGIDLen, faceIndex);
273 }
274 #endif
275
276 if (!fontFile) {
277 gfree(codeToGID);
278 }
279
280 #ifndef _WIN32
281 // delete the (temporary) font file -- with Unix hard link
282 // semantics, this will remove the last link; otherwise it will
283 // return an error, leaving the file to be deleted later (if
284 // loadXYZFont failed, the file will always be deleted)
285 if (src->isFile)
286 src->unref();
287 #endif
288
289 return fontFile;
290 }
291
292 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
getAA()293 GBool SplashFontEngine::getAA() {
294 return (ftEngine == NULL) ? gFalse : ftEngine->getAA();
295 }
296
setAA(GBool aa)297 void SplashFontEngine::setAA(GBool aa) {
298 if (ftEngine != NULL) {
299 ftEngine->setAA(aa);
300 }
301 }
302 #endif
303
getFont(SplashFontFile * fontFile,SplashCoord * textMat,SplashCoord * ctm)304 SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile,
305 SplashCoord *textMat,
306 SplashCoord *ctm) {
307 SplashCoord mat[4];
308 SplashFont *font;
309 int i, j;
310
311 mat[0] = textMat[0] * ctm[0] + textMat[1] * ctm[2];
312 mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]);
313 mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2];
314 mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]);
315 if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.01)) {
316 // avoid a singular (or close-to-singular) matrix
317 mat[0] = 0.01; mat[1] = 0;
318 mat[2] = 0; mat[3] = 0.01;
319 }
320
321 font = fontCache[0];
322 if (font && font->matches(fontFile, mat, textMat)) {
323 return font;
324 }
325 for (i = 1; i < splashFontCacheSize; ++i) {
326 font = fontCache[i];
327 if (font && font->matches(fontFile, mat, textMat)) {
328 for (j = i; j > 0; --j) {
329 fontCache[j] = fontCache[j-1];
330 }
331 fontCache[0] = font;
332 return font;
333 }
334 }
335 font = fontFile->makeFont(mat, textMat);
336 if (fontCache[splashFontCacheSize - 1]) {
337 delete fontCache[splashFontCacheSize - 1];
338 }
339 for (j = splashFontCacheSize - 1; j > 0; --j) {
340 fontCache[j] = fontCache[j-1];
341 }
342 fontCache[0] = font;
343 return font;
344 }
345