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