Coverage Report

Created: 2026-02-26 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xpdf-4.06/splash/SplashFontEngine.cc
Line
Count
Source
1
//========================================================================
2
//
3
// SplashFontEngine.cc
4
//
5
// Copyright 2003-2013 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
#include <aconf.h>
10
11
#include <stdlib.h>
12
#include <stdio.h>
13
#ifndef _WIN32
14
#  include <unistd.h>
15
#endif
16
#include "gmem.h"
17
#include "gmempp.h"
18
#include "GString.h"
19
#include "GList.h"
20
#include "SplashMath.h"
21
#include "SplashFTFontEngine.h"
22
#include "SplashFontFile.h"
23
#include "SplashFontFileID.h"
24
#include "SplashFont.h"
25
#include "SplashFontEngine.h"
26
27
#ifdef VMS
28
#if (__VMS_VER < 70000000)
29
extern "C" int unlink(char *filename);
30
#endif
31
#endif
32
33
//------------------------------------------------------------------------
34
// SplashFontEngine
35
//------------------------------------------------------------------------
36
37
SplashFontEngine::SplashFontEngine(
38
#if HAVE_FREETYPE_H
39
           GBool enableFreeType,
40
           Guint freeTypeFlags,
41
#endif
42
13.4k
           GBool aa) {
43
13.4k
  int i;
44
45
228k
  for (i = 0; i < splashFontCacheSize; ++i) {
46
215k
    fontCache[i] = NULL;
47
215k
  }
48
13.4k
  badFontFiles = new GList();
49
50
13.4k
#if HAVE_FREETYPE_H
51
13.4k
  if (enableFreeType) {
52
13.4k
    ftEngine = SplashFTFontEngine::init(aa, freeTypeFlags);
53
13.4k
  } else {
54
0
    ftEngine = NULL;
55
0
  }
56
13.4k
#endif
57
13.4k
}
58
59
13.4k
SplashFontEngine::~SplashFontEngine() {
60
13.4k
  int i;
61
62
228k
  for (i = 0; i < splashFontCacheSize; ++i) {
63
214k
    if (fontCache[i]) {
64
4.66k
      delete fontCache[i];
65
4.66k
    }
66
214k
  }
67
13.4k
  deleteGList(badFontFiles, SplashFontFileID);
68
69
13.4k
#if HAVE_FREETYPE_H
70
13.4k
  if (ftEngine) {
71
13.4k
    delete ftEngine;
72
13.4k
  }
73
13.4k
#endif
74
13.4k
}
75
76
46.2k
SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) {
77
46.2k
  SplashFontFile *fontFile;
78
46.2k
  int i;
79
80
434k
  for (i = 0; i < splashFontCacheSize; ++i) {
81
410k
    if (fontCache[i]) {
82
23.3k
      fontFile = fontCache[i]->getFontFile();
83
23.3k
      if (fontFile && fontFile->getID()->matches(id)) {
84
21.9k
  return fontFile;
85
21.9k
      }
86
23.3k
    }
87
410k
  }
88
24.2k
  return NULL;
89
46.2k
}
90
91
49.0k
GBool SplashFontEngine::checkForBadFontFile(SplashFontFileID *id) {
92
54.0k
  for (int i = 0; i < badFontFiles->getLength(); ++i) {
93
7.80k
    if (((SplashFontFileID *)badFontFiles->get(i))->matches(id)) {
94
2.82k
      return gTrue;
95
2.82k
    }
96
7.80k
  }
97
46.2k
  return gFalse;
98
49.0k
}
99
100
SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA,
101
#if LOAD_FONTS_FROM_MEM
102
            GString *fontBuf,
103
#else
104
            char *fileName,
105
            GBool deleteFile,
106
#endif
107
1.19k
            const char **enc) {
108
1.19k
  SplashFontFile *fontFile;
109
110
1.19k
  fontFile = NULL;
111
1.19k
#if HAVE_FREETYPE_H
112
1.19k
  if (!fontFile && ftEngine) {
113
1.19k
    fontFile = ftEngine->loadType1Font(idA,
114
#if LOAD_FONTS_FROM_MEM
115
               fontBuf,
116
#else
117
1.19k
               fileName, deleteFile,
118
1.19k
#endif
119
1.19k
               enc);
120
1.19k
  }
121
1.19k
#endif
122
123
1.19k
#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
124
  // delete the (temporary) font file -- with Unix hard link
125
  // semantics, this will remove the last link; otherwise it will
126
  // return an error, leaving the file to be deleted later (if
127
  // loadXYZFont failed, the file will always be deleted)
128
1.19k
  if (deleteFile) {
129
1.19k
    unlink(fontFile ? fontFile->fileName->getCString() : fileName);
130
1.19k
  }
131
1.19k
#endif
132
133
1.19k
  if (!fontFile) {
134
1.09k
    badFontFiles->append(idA);
135
1.09k
  }
136
137
1.19k
  return fontFile;
138
1.19k
}
139
140
SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA,
141
#if LOAD_FONTS_FROM_MEM
142
             GString *fontBuf,
143
#else
144
             char *fileName,
145
             GBool deleteFile,
146
#endif
147
             int *codeToGID,
148
1.66k
             const char **enc) {
149
1.66k
  SplashFontFile *fontFile;
150
151
1.66k
  fontFile = NULL;
152
1.66k
  if (!fontFile) {
153
1.66k
    gfree(codeToGID);
154
1.66k
  }
155
1.66k
#if HAVE_FREETYPE_H
156
1.66k
  if (!fontFile && ftEngine) {
157
1.66k
    fontFile = ftEngine->loadType1CFont(idA,
158
#if LOAD_FONTS_FROM_MEM
159
          fontBuf,
160
#else
161
1.66k
          fileName, deleteFile,
162
1.66k
#endif
163
1.66k
          enc);
164
1.66k
  }
165
1.66k
#endif
166
167
1.66k
#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
168
  // delete the (temporary) font file -- with Unix hard link
169
  // semantics, this will remove the last link; otherwise it will
170
  // return an error, leaving the file to be deleted later (if
171
  // loadXYZFont failed, the file will always be deleted)
172
1.66k
  if (deleteFile) {
173
1.66k
    unlink(fontFile ? fontFile->fileName->getCString() : fileName);
174
1.66k
  }
175
1.66k
#endif
176
177
1.66k
  if (!fontFile) {
178
344
    badFontFiles->append(idA);
179
344
  }
180
181
1.66k
  return fontFile;
182
1.66k
}
183
184
SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(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
0
                  const char **enc) {
193
0
  SplashFontFile *fontFile;
194
195
0
  fontFile = NULL;
196
0
  if (!fontFile) {
197
0
    gfree(codeToGID);
198
0
  }
199
0
#if HAVE_FREETYPE_H
200
0
  if (!fontFile && ftEngine) {
201
0
    fontFile = ftEngine->loadOpenTypeT1CFont(idA,
202
#if LOAD_FONTS_FROM_MEM
203
               fontBuf,
204
#else
205
0
               fileName, deleteFile,
206
0
#endif
207
0
               enc);
208
0
  }
209
0
#endif
210
211
0
#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
212
  // delete the (temporary) font file -- with Unix hard link
213
  // semantics, this will remove the last link; otherwise it will
214
  // return an error, leaving the file to be deleted later (if
215
  // loadXYZFont failed, the file will always be deleted)
216
0
  if (deleteFile) {
217
0
    unlink(fontFile ? fontFile->fileName->getCString() : fileName);
218
0
  }
219
0
#endif
220
221
0
  if (!fontFile) {
222
0
    badFontFiles->append(idA);
223
0
  }
224
225
0
  return fontFile;
226
0
}
227
228
SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA,
229
#if LOAD_FONTS_FROM_MEM
230
                GString *fontBuf,
231
#else
232
                char *fileName,
233
                GBool deleteFile,
234
#endif
235
                int *codeToGID,
236
48
                int codeToGIDLen) {
237
48
  SplashFontFile *fontFile;
238
239
48
  fontFile = NULL;
240
48
#if HAVE_FREETYPE_H
241
48
  if (!fontFile && ftEngine) {
242
48
    fontFile = ftEngine->loadCIDFont(idA,
243
#if LOAD_FONTS_FROM_MEM
244
             fontBuf,
245
#else
246
48
             fileName, deleteFile,
247
48
#endif
248
48
             codeToGID, codeToGIDLen);
249
48
  }
250
48
#endif
251
252
48
  if (!fontFile) {
253
11
    gfree(codeToGID);
254
11
  }
255
256
48
#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
257
  // delete the (temporary) font file -- with Unix hard link
258
  // semantics, this will remove the last link; otherwise it will
259
  // return an error, leaving the file to be deleted later (if
260
  // loadXYZFont failed, the file will always be deleted)
261
48
  if (deleteFile) {
262
48
    unlink(fontFile ? fontFile->fileName->getCString() : fileName);
263
48
  }
264
48
#endif
265
266
48
  if (!fontFile) {
267
11
    badFontFiles->append(idA);
268
11
  }
269
270
48
  return fontFile;
271
48
}
272
273
SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
274
#if LOAD_FONTS_FROM_MEM
275
                  GString *fontBuf,
276
#else
277
                  char *fileName,
278
                  GBool deleteFile,
279
#endif
280
                  int *codeToGID,
281
0
                  int codeToGIDLen) {
282
0
  SplashFontFile *fontFile;
283
284
0
  fontFile = NULL;
285
0
#if HAVE_FREETYPE_H
286
0
  if (!fontFile && ftEngine) {
287
0
    fontFile = ftEngine->loadOpenTypeCFFFont(idA,
288
#if LOAD_FONTS_FROM_MEM
289
               fontBuf,
290
#else
291
0
               fileName, deleteFile,
292
0
#endif
293
0
               codeToGID, codeToGIDLen);
294
0
  }
295
0
#endif
296
297
0
  if (!fontFile) {
298
0
    gfree(codeToGID);
299
0
  }
300
301
0
#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
302
  // delete the (temporary) font file -- with Unix hard link
303
  // semantics, this will remove the last link; otherwise it will
304
  // return an error, leaving the file to be deleted later (if
305
  // loadXYZFont failed, the file will always be deleted)
306
0
  if (deleteFile) {
307
0
    unlink(fontFile ? fontFile->fileName->getCString() : fileName);
308
0
  }
309
0
#endif
310
311
0
  if (!fontFile) {
312
0
    badFontFiles->append(idA);
313
0
  }
314
315
0
  return fontFile;
316
0
}
317
318
SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
319
#if LOAD_FONTS_FROM_MEM
320
               GString *fontBuf,
321
#else
322
               char *fileName,
323
               GBool deleteFile,
324
#endif
325
               int fontNum,
326
               int *codeToGID,
327
               int codeToGIDLen,
328
2.96k
               char *fontName) {
329
2.96k
  SplashFontFile *fontFile;
330
331
2.96k
  fontFile = NULL;
332
2.96k
#if HAVE_FREETYPE_H
333
2.96k
  if (!fontFile && ftEngine) {
334
2.96k
    fontFile = ftEngine->loadTrueTypeFont(idA,
335
#if LOAD_FONTS_FROM_MEM
336
            fontBuf,
337
#else
338
2.96k
            fileName, deleteFile,
339
2.96k
#endif
340
2.96k
            fontNum, codeToGID, codeToGIDLen);
341
2.96k
  }
342
2.96k
#endif
343
344
2.96k
  if (!fontFile) {
345
211
    gfree(codeToGID);
346
211
  }
347
348
2.96k
#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
349
  // delete the (temporary) font file -- with Unix hard link
350
  // semantics, this will remove the last link; otherwise it will
351
  // return an error, leaving the file to be deleted later (if
352
  // loadXYZFont failed, the file will always be deleted)
353
2.96k
  if (deleteFile) {
354
2.96k
    unlink(fontFile ? fontFile->fileName->getCString() : fileName);
355
2.96k
  }
356
2.96k
#endif
357
358
2.96k
  if (!fontFile) {
359
211
    badFontFiles->append(idA);
360
211
  }
361
362
2.96k
  return fontFile;
363
2.96k
}
364
365
SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile,
366
              SplashCoord *textMat,
367
26.2k
              SplashCoord *ctm) {
368
26.2k
  SplashCoord mat[4];
369
26.2k
  SplashFont *font;
370
26.2k
  int i, j;
371
372
26.2k
  mat[0] = textMat[0] * ctm[0] + textMat[1] * ctm[2];
373
26.2k
  mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]);
374
26.2k
  mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2];
375
26.2k
  mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]);
376
26.2k
  if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.01)) {
377
    // avoid a singular (or close-to-singular) matrix
378
26.2k
    mat[0] = 0.01;  mat[1] = 0;
379
26.2k
    mat[2] = 0;     mat[3] = 0.01;
380
26.2k
  }
381
382
26.2k
  font = fontCache[0];
383
26.2k
  if (font && font->matches(fontFile, mat, textMat)) {
384
21.4k
    return font;
385
21.4k
  }
386
74.8k
  for (i = 1; i < splashFontCacheSize; ++i) {
387
70.2k
    font = fontCache[i];
388
70.2k
    if (font && font->matches(fontFile, mat, textMat)) {
389
308
      for (j = i; j > 0; --j) {
390
173
  fontCache[j] = fontCache[j-1];
391
173
      }
392
135
      fontCache[0] = font;
393
135
      return font;
394
135
    }
395
70.2k
  }
396
4.66k
  font = fontFile->makeFont(mat, textMat);
397
4.66k
  if (fontCache[splashFontCacheSize - 1]) {
398
0
    delete fontCache[splashFontCacheSize - 1];
399
0
  }
400
74.7k
  for (j = splashFontCacheSize - 1; j > 0; --j) {
401
70.0k
    fontCache[j] = fontCache[j-1];
402
70.0k
  }
403
4.66k
  fontCache[0] = font;
404
4.66k
  return font;
405
4.80k
}