Coverage Report

Created: 2026-05-30 06:25

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