/src/xpdf-4.04/splash/SplashFTFontEngine.cc
Line | Count | Source (jump to first uncovered line) |
1 | | //======================================================================== |
2 | | // |
3 | | // SplashFTFontEngine.cc |
4 | | // |
5 | | // Copyright 2003-2013 Glyph & Cog, LLC |
6 | | // |
7 | | //======================================================================== |
8 | | |
9 | | #include <aconf.h> |
10 | | |
11 | | #if HAVE_FREETYPE_H |
12 | | |
13 | | #ifdef USE_GCC_PRAGMAS |
14 | | #pragma implementation |
15 | | #endif |
16 | | |
17 | | #include <stdio.h> |
18 | | #ifndef _WIN32 |
19 | | # include <unistd.h> |
20 | | #endif |
21 | | #include "gmem.h" |
22 | | #include "gmempp.h" |
23 | | #include "GString.h" |
24 | | #include "gfile.h" |
25 | | #include "FoFiTrueType.h" |
26 | | #include "FoFiType1C.h" |
27 | | #include "SplashFTFontFile.h" |
28 | | #include "SplashFTFontEngine.h" |
29 | | #include FT_MODULE_H |
30 | | #ifdef FT_CFF_DRIVER_H |
31 | | # include FT_CFF_DRIVER_H |
32 | | #endif |
33 | | |
34 | | #ifdef VMS |
35 | | #if (__VMS_VER < 70000000) |
36 | | extern "C" int unlink(char *filename); |
37 | | #endif |
38 | | #endif |
39 | | |
40 | | //------------------------------------------------------------------------ |
41 | | |
42 | 0 | static void fileWrite(void *stream, const char *data, int len) { |
43 | 0 | fwrite(data, 1, len, (FILE *)stream); |
44 | 0 | } |
45 | | |
46 | | #if LOAD_FONTS_FROM_MEM |
47 | | static void gstringWrite(void *stream, const char *data, int len) { |
48 | | ((GString *)stream)->append(data, len); |
49 | | } |
50 | | #endif |
51 | | |
52 | | //------------------------------------------------------------------------ |
53 | | // SplashFTFontEngine |
54 | | //------------------------------------------------------------------------ |
55 | | |
56 | | SplashFTFontEngine::SplashFTFontEngine(GBool aaA, Guint flagsA, |
57 | 0 | FT_Library libA) { |
58 | 0 | FT_Int major, minor, patch; |
59 | |
|
60 | 0 | aa = aaA; |
61 | 0 | flags = flagsA; |
62 | 0 | lib = libA; |
63 | | |
64 | | // as of FT 2.1.8, CID fonts are indexed by CID instead of GID |
65 | 0 | FT_Library_Version(lib, &major, &minor, &patch); |
66 | 0 | useCIDs = major > 2 || |
67 | 0 | (major == 2 && (minor > 1 || (minor == 1 && patch > 7))); |
68 | 0 | } |
69 | | |
70 | 0 | SplashFTFontEngine *SplashFTFontEngine::init(GBool aaA, Guint flagsA) { |
71 | 0 | FT_Library libA; |
72 | |
|
73 | 0 | if (FT_Init_FreeType(&libA)) { |
74 | 0 | return NULL; |
75 | 0 | } |
76 | 0 | return new SplashFTFontEngine(aaA, flagsA, libA); |
77 | 0 | } |
78 | | |
79 | 0 | SplashFTFontEngine::~SplashFTFontEngine() { |
80 | 0 | FT_Done_FreeType(lib); |
81 | 0 | } |
82 | | |
83 | | SplashFontFile *SplashFTFontEngine::loadType1Font(SplashFontFileID *idA, |
84 | | #if LOAD_FONTS_FROM_MEM |
85 | | GString *fontBuf, |
86 | | #else |
87 | | char *fileName, |
88 | | GBool deleteFile, |
89 | | #endif |
90 | 0 | const char **enc) { |
91 | 0 | return SplashFTFontFile::loadType1Font(this, idA, splashFontType1, |
92 | | #if LOAD_FONTS_FROM_MEM |
93 | | fontBuf, |
94 | | #else |
95 | 0 | fileName, deleteFile, |
96 | 0 | #endif |
97 | 0 | enc); |
98 | 0 | } |
99 | | |
100 | | SplashFontFile *SplashFTFontEngine::loadType1CFont(SplashFontFileID *idA, |
101 | | #if LOAD_FONTS_FROM_MEM |
102 | | GString *fontBuf, |
103 | | #else |
104 | | char *fileName, |
105 | | GBool deleteFile, |
106 | | #endif |
107 | 0 | const char **enc) { |
108 | 0 | return SplashFTFontFile::loadType1Font(this, idA, splashFontType1C, |
109 | | #if LOAD_FONTS_FROM_MEM |
110 | | fontBuf, |
111 | | #else |
112 | 0 | fileName, deleteFile, |
113 | 0 | #endif |
114 | 0 | enc); |
115 | 0 | } |
116 | | |
117 | | SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA, |
118 | | #if LOAD_FONTS_FROM_MEM |
119 | | GString *fontBuf, |
120 | | #else |
121 | | char *fileName, |
122 | | GBool deleteFile, |
123 | | #endif |
124 | 0 | const char **enc) { |
125 | 0 | FoFiTrueType *ff; |
126 | | #if LOAD_FONTS_FROM_MEM |
127 | | GString *fontBuf2; |
128 | | #else |
129 | 0 | GString *tmpFileName; |
130 | 0 | FILE *tmpFile; |
131 | 0 | #endif |
132 | 0 | SplashFontFile *ret; |
133 | |
|
134 | | #if LOAD_FONTS_FROM_MEM |
135 | | if (!(ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(), |
136 | | 0, gTrue))) { |
137 | | #else |
138 | 0 | if (!(ff = FoFiTrueType::load(fileName, 0, gTrue))) { |
139 | 0 | #endif |
140 | 0 | return NULL; |
141 | 0 | } |
142 | 0 | if (ff->isHeadlessCFF()) { |
143 | | #if LOAD_FONTS_FROM_MEM |
144 | | fontBuf2 = new GString(); |
145 | | ff->convertToType1(NULL, enc, gFalse, &gstringWrite, fontBuf2); |
146 | | delete ff; |
147 | | ret = SplashFTFontFile::loadType1Font(this, idA, splashFontType1, |
148 | | fontBuf2, enc); |
149 | | if (ret) { |
150 | | delete fontBuf; |
151 | | } else { |
152 | | delete fontBuf2; |
153 | | } |
154 | | #else |
155 | 0 | tmpFileName = NULL; |
156 | 0 | if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { |
157 | 0 | delete ff; |
158 | 0 | return NULL; |
159 | 0 | } |
160 | 0 | ff->convertToType1(NULL, enc, gFalse, &fileWrite, tmpFile); |
161 | 0 | delete ff; |
162 | 0 | fclose(tmpFile); |
163 | 0 | ret = SplashFTFontFile::loadType1Font(this, idA, splashFontType1, |
164 | 0 | tmpFileName->getCString(), |
165 | 0 | gTrue, enc); |
166 | 0 | if (ret) { |
167 | 0 | if (deleteFile) { |
168 | 0 | unlink(fileName); |
169 | 0 | } |
170 | 0 | } else { |
171 | 0 | unlink(tmpFileName->getCString()); |
172 | 0 | } |
173 | 0 | delete tmpFileName; |
174 | 0 | #endif |
175 | 0 | } else { |
176 | 0 | delete ff; |
177 | 0 | ret = SplashFTFontFile::loadType1Font(this, idA, splashFontOpenTypeT1C, |
178 | | #if LOAD_FONTS_FROM_MEM |
179 | | fontBuf, |
180 | | #else |
181 | 0 | fileName, deleteFile, |
182 | 0 | #endif |
183 | 0 | enc); |
184 | 0 | } |
185 | 0 | return ret; |
186 | 0 | } |
187 | | |
188 | | SplashFontFile *SplashFTFontEngine::loadCIDFont(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 | int codeToGIDLen) { |
197 | 0 | FoFiType1C *ff; |
198 | 0 | int *cidToGIDMap; |
199 | 0 | int nCIDs; |
200 | 0 | SplashFontFile *ret; |
201 | | |
202 | | // check for a CFF font |
203 | 0 | if (codeToGID) { |
204 | 0 | cidToGIDMap = NULL; |
205 | 0 | nCIDs = 0; |
206 | 0 | } else if (useCIDs) { |
207 | 0 | cidToGIDMap = NULL; |
208 | 0 | nCIDs = 0; |
209 | | #if LOAD_FONTS_FROM_MEM |
210 | | } else if ((ff = FoFiType1C::make(fontBuf->getCString(), |
211 | | fontBuf->getLength()))) { |
212 | | #else |
213 | 0 | } else if ((ff = FoFiType1C::load(fileName))) { |
214 | 0 | #endif |
215 | 0 | cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); |
216 | 0 | delete ff; |
217 | 0 | } else { |
218 | 0 | cidToGIDMap = NULL; |
219 | 0 | nCIDs = 0; |
220 | 0 | } |
221 | 0 | ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontCID, |
222 | | #if LOAD_FONTS_FROM_MEM |
223 | | fontBuf, |
224 | | #else |
225 | 0 | fileName, deleteFile, |
226 | 0 | #endif |
227 | 0 | codeToGID ? codeToGID : cidToGIDMap, |
228 | 0 | codeToGID ? codeToGIDLen : nCIDs); |
229 | 0 | if (!ret) { |
230 | 0 | gfree(cidToGIDMap); |
231 | 0 | } |
232 | 0 | return ret; |
233 | 0 | } |
234 | | |
235 | | SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA, |
236 | | #if LOAD_FONTS_FROM_MEM |
237 | | GString *fontBuf, |
238 | | #else |
239 | | char *fileName, |
240 | | GBool deleteFile, |
241 | | #endif |
242 | | int *codeToGID, |
243 | 0 | int codeToGIDLen) { |
244 | 0 | FoFiTrueType *ff; |
245 | | #if LOAD_FONTS_FROM_MEM |
246 | | GString *fontBuf2; |
247 | | #else |
248 | 0 | GString *tmpFileName; |
249 | 0 | FILE *tmpFile; |
250 | 0 | #endif |
251 | 0 | char *cffStart; |
252 | 0 | int cffLength; |
253 | 0 | int *cidToGIDMap; |
254 | 0 | int nCIDs; |
255 | 0 | SplashFontFile *ret; |
256 | |
|
257 | | #if LOAD_FONTS_FROM_MEM |
258 | | if (!(ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(), |
259 | | 0, gTrue))) { |
260 | | #else |
261 | 0 | if (!(ff = FoFiTrueType::load(fileName, 0, gTrue))) { |
262 | 0 | #endif |
263 | 0 | return NULL; |
264 | 0 | } |
265 | 0 | cidToGIDMap = NULL; |
266 | 0 | nCIDs = 0; |
267 | 0 | if (ff->isHeadlessCFF()) { |
268 | 0 | if (!ff->getCFFBlock(&cffStart, &cffLength)) { |
269 | 0 | return NULL; |
270 | 0 | } |
271 | | #if LOAD_FONTS_FROM_MEM |
272 | | fontBuf2 = new GString(cffStart, cffLength); |
273 | | if (!useCIDs) { |
274 | | cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); |
275 | | } |
276 | | ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontOpenTypeCFF, |
277 | | fontBuf2, cidToGIDMap, nCIDs); |
278 | | if (ret) { |
279 | | delete fontBuf; |
280 | | } else { |
281 | | delete fontBuf2; |
282 | | } |
283 | | #else |
284 | 0 | tmpFileName = NULL; |
285 | 0 | if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { |
286 | 0 | delete ff; |
287 | 0 | return NULL; |
288 | 0 | } |
289 | 0 | fwrite(cffStart, 1, cffLength, tmpFile); |
290 | 0 | fclose(tmpFile); |
291 | 0 | if (!useCIDs) { |
292 | 0 | cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); |
293 | 0 | } |
294 | 0 | ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontOpenTypeCFF, |
295 | 0 | tmpFileName->getCString(), gTrue, |
296 | 0 | cidToGIDMap, nCIDs); |
297 | 0 | if (ret) { |
298 | 0 | if (deleteFile) { |
299 | 0 | unlink(fileName); |
300 | 0 | } |
301 | 0 | } else { |
302 | 0 | unlink(tmpFileName->getCString()); |
303 | 0 | } |
304 | 0 | delete tmpFileName; |
305 | 0 | #endif |
306 | 0 | } else { |
307 | 0 | if (!codeToGID && !useCIDs && ff->isOpenTypeCFF()) { |
308 | 0 | cidToGIDMap = ff->getCIDToGIDMap(&nCIDs); |
309 | 0 | } |
310 | 0 | ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontOpenTypeCFF, |
311 | | #if LOAD_FONTS_FROM_MEM |
312 | | fontBuf, |
313 | | #else |
314 | 0 | fileName, deleteFile, |
315 | 0 | #endif |
316 | 0 | codeToGID ? codeToGID : cidToGIDMap, |
317 | 0 | codeToGID ? codeToGIDLen : nCIDs); |
318 | 0 | } |
319 | 0 | delete ff; |
320 | 0 | if (!ret) { |
321 | 0 | gfree(cidToGIDMap); |
322 | 0 | } |
323 | 0 | return ret; |
324 | 0 | } |
325 | | |
326 | | SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA, |
327 | | #if LOAD_FONTS_FROM_MEM |
328 | | GString *fontBuf, |
329 | | #else |
330 | | char *fileName, |
331 | | GBool deleteFile, |
332 | | #endif |
333 | | int fontNum, |
334 | | int *codeToGID, |
335 | 0 | int codeToGIDLen) { |
336 | 0 | FoFiTrueType *ff; |
337 | | #if LOAD_FONTS_FROM_MEM |
338 | | GString *fontBuf2; |
339 | | #else |
340 | 0 | GString *tmpFileName; |
341 | 0 | FILE *tmpFile; |
342 | 0 | #endif |
343 | 0 | SplashFontFile *ret; |
344 | |
|
345 | | #if LOAD_FONTS_FROM_MEM |
346 | | if (!(ff = FoFiTrueType::make(fontBuf->getCString(), fontBuf->getLength(), |
347 | | fontNum))) { |
348 | | #else |
349 | 0 | if (!(ff = FoFiTrueType::load(fileName, fontNum))) { |
350 | 0 | #endif |
351 | 0 | return NULL; |
352 | 0 | } |
353 | | #if LOAD_FONTS_FROM_MEM |
354 | | fontBuf2 = new GString; |
355 | | ff->writeTTF(&gstringWrite, fontBuf2); |
356 | | #else |
357 | 0 | tmpFileName = NULL; |
358 | 0 | if (!openTempFile(&tmpFileName, &tmpFile, "wb", NULL)) { |
359 | 0 | delete ff; |
360 | 0 | return NULL; |
361 | 0 | } |
362 | 0 | ff->writeTTF(&fileWrite, tmpFile); |
363 | 0 | fclose(tmpFile); |
364 | 0 | #endif |
365 | 0 | delete ff; |
366 | 0 | ret = SplashFTFontFile::loadTrueTypeFont(this, idA, splashFontTrueType, |
367 | | #if LOAD_FONTS_FROM_MEM |
368 | | fontBuf2, |
369 | | #else |
370 | 0 | tmpFileName->getCString(), gTrue, |
371 | 0 | #endif |
372 | 0 | 0, codeToGID, codeToGIDLen); |
373 | | #if LOAD_FONTS_FROM_MEM |
374 | | if (ret) { |
375 | | delete fontBuf; |
376 | | } else { |
377 | | delete fontBuf2; |
378 | | } |
379 | | #else |
380 | 0 | if (ret) { |
381 | 0 | if (deleteFile) { |
382 | 0 | unlink(fileName); |
383 | 0 | } |
384 | 0 | } else { |
385 | 0 | unlink(tmpFileName->getCString()); |
386 | 0 | } |
387 | 0 | delete tmpFileName; |
388 | 0 | #endif |
389 | 0 | return ret; |
390 | 0 | } |
391 | | |
392 | | #endif // HAVE_FREETYPE_H |