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