Coverage Report

Created: 2023-09-25 06:41

/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