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