sync with TL 36474
[luatex.git] / source / libs / poppler / poppler-0.32.0 / poppler / GlobalParamsWin.cc
blob084b49bf639e6b13e1498aebdd3f6c8f9ddb11b0
1 /* Written by Krzysztof Kowalczyk (http://blog.kowalczyk.info)
2 but mostly based on xpdf code.
4 // Copyright (C) 2010, 2012 Hib Eris <hib@hiberis.nl>
5 // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
6 // Copyright (C) 2012 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
7 // Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
8 // Copyright (C) 2012 Mark Brand <mabrand@mabrand.nl>
9 // Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
11 TODO: instead of a fixed mapping defined in displayFontTab, it could
12 scan the whole fonts directory, parse TTF files and build font
13 description for all fonts available in Windows. That's how MuPDF works.
16 #ifndef PACKAGE_NAME
17 #include <config.h>
18 #endif
20 #ifdef USE_GCC_PRAGMAS
21 #pragma implementation
22 #endif
24 #include <windows.h>
25 #if !(_WIN32_IE >= 0x0500)
26 #error "_WIN32_IE must be defined >= 0x0500 for SHGFP_TYPE_CURRENT from shlobj.h"
27 #endif
28 #include <shlobj.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <assert.h>
34 #include "goo/gmem.h"
35 #include "goo/GooString.h"
36 #include "goo/GooList.h"
37 #include "goo/GooHash.h"
38 #include "goo/gfile.h"
39 #include "Error.h"
40 #include "NameToCharCode.h"
41 #include "CharCodeToUnicode.h"
42 #include "UnicodeMap.h"
43 #include "CMap.h"
44 #include "BuiltinFontTables.h"
45 #include "FontEncodingTables.h"
46 #include "GlobalParams.h"
47 #include "GfxFont.h"
48 #include <sys/stat.h>
49 #include "Object.h"
50 #include "Stream.h"
51 #include "Lexer.h"
52 #include "Parser.h"
54 #if MULTITHREADED
55 # define lockGlobalParams gLockMutex(&mutex)
56 # define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex)
57 # define lockCMapCache gLockMutex(&cMapCacheMutex)
58 # define unlockGlobalParams gUnlockMutex(&mutex)
59 # define unlockUnicodeMapCache gUnlockMutex(&unicodeMapCacheMutex)
60 # define unlockCMapCache gUnlockMutex(&cMapCacheMutex)
61 #else
62 # define lockGlobalParams
63 # define lockUnicodeMapCache
64 # define lockCMapCache
65 # define unlockGlobalParams
66 # define unlockUnicodeMapCache
67 # define unlockCMapCache
68 #endif
70 #define DEFAULT_SUBSTITUTE_FONT "Helvetica"
71 #define DEFAULT_CID_FONT_AC1_MSWIN "MingLiU" /* Adobe-CNS1 for Taiwan, HongKong */
72 #define DEFAULT_CID_FONT_AG1_MSWIN "SimSun" /* Adobe-GB1 for PRC, Singapore */
73 #define DEFAULT_CID_FONT_AJ1_MSWIN "MS-Mincho" /* Adobe-Japan1 */
74 #define DEFAULT_CID_FONT_AJ2_MSWIN "MS-Mincho" /* Adobe-Japan2 (legacy) */
75 #define DEFAULT_CID_FONT_AK1_MSWIN "Batang" /* Adobe-Korea1 */
76 #define DEFAULT_CID_FONT_MSWIN "ArialUnicode" /* Unknown */
78 static struct {
79 const char *name;
80 const char *t1FileName;
81 const char *ttFileName;
82 GBool warnIfMissing;
83 } displayFontTab[] = {
84 {"Courier", "n022003l.pfb", "cour.ttf", gTrue},
85 {"Courier-Bold", "n022004l.pfb", "courbd.ttf", gTrue},
86 {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf", gTrue},
87 {"Courier-Oblique", "n022023l.pfb", "couri.ttf", gTrue},
88 {"Helvetica", "n019003l.pfb", "arial.ttf", gTrue},
89 {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf", gTrue},
90 {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf", gTrue},
91 {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf", gTrue},
92 // TODO: not sure if "symbol.ttf" is right
93 {"Symbol", "s050000l.pfb", "symbol.ttf", gTrue},
94 {"Times-Bold", "n021004l.pfb", "timesbd.ttf", gTrue},
95 {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf", gTrue},
96 {"Times-Italic", "n021023l.pfb", "timesi.ttf", gTrue},
97 {"Times-Roman", "n021003l.pfb", "times.ttf", gTrue},
98 // TODO: not sure if "wingding.ttf" is right
99 {"ZapfDingbats", "d050000l.pfb", "wingding.ttf", gTrue},
101 // those seem to be frequently accessed by PDF files and I kind of guess
102 // which font file do the refer to
103 {"Palatino", NULL, "pala.ttf", gTrue},
104 {"Palatino-Roman", NULL, "pala.ttf", gTrue},
105 {"Palatino-Bold", NULL, "palab.ttf", gTrue},
106 {"Palatino-Italic", NULL, "palai.ttf", gTrue},
107 {"Palatino,Italic", NULL, "palai.ttf", gTrue},
108 {"Palatino-BoldItalic", NULL, "palabi.ttf", gTrue},
110 {"ArialBlack", NULL, "arialbd.ttf", gTrue},
112 {"ArialNarrow", NULL, "arialn.ttf", gTrue},
113 {"ArialNarrow,Bold", NULL, "arialnb.ttf", gTrue},
114 {"ArialNarrow,Italic", NULL, "arialni.ttf", gTrue},
115 {"ArialNarrow,BoldItalic", NULL, "arialnbi.ttf", gTrue},
116 {"ArialNarrow-Bold", NULL, "arialnb.ttf", gTrue},
117 {"ArialNarrow-Italic", NULL, "arialni.ttf", gTrue},
118 {"ArialNarrow-BoldItalic", NULL, "arialnbi.ttf", gTrue},
120 {"HelveticaNarrow", NULL, "arialn.ttf", gTrue},
121 {"HelveticaNarrow,Bold", NULL, "arialnb.ttf", gTrue},
122 {"HelveticaNarrow,Italic", NULL, "arialni.ttf", gTrue},
123 {"HelveticaNarrow,BoldItalic", NULL, "arialnbi.ttf", gTrue},
124 {"HelveticaNarrow-Bold", NULL, "arialnb.ttf", gTrue},
125 {"HelveticaNarrow-Italic", NULL, "arialni.ttf", gTrue},
126 {"HelveticaNarrow-BoldItalic", NULL, "arialnbi.ttf", gTrue},
128 {"BookAntiqua", NULL, "bkant.ttf", gTrue},
129 {"BookAntiqua,Bold", NULL, "bkant.ttf", gTrue},
130 {"BookAntiqua,Italic", NULL, "bkant.ttf", gTrue},
131 {"BookAntiqua,BoldItalic", NULL, "bkant.ttf", gTrue},
132 {"BookAntiqua-Bold", NULL, "bkant.ttf", gTrue},
133 {"BookAntiqua-Italic", NULL, "bkant.ttf", gTrue},
134 {"BookAntiqua-BoldItalic", NULL, "bkant.ttf", gTrue},
136 {"Verdana", NULL, "verdana.ttf", gTrue},
137 {"Verdana,Bold", NULL, "verdanab.ttf", gTrue},
138 {"Verdana,Italic", NULL, "verdanai.ttf", gTrue},
139 {"Verdana,BoldItalic", NULL, "verdanaz.ttf", gTrue},
140 {"Verdana-Bold", NULL, "verdanab.ttf", gTrue},
141 {"Verdana-Italic", NULL, "verdanai.ttf", gTrue},
142 {"Verdana-BoldItalic", NULL, "verdanaz.ttf", gTrue},
144 {"Tahoma", NULL, "tahoma.ttf", gTrue},
145 {"Tahoma,Bold", NULL, "tahomabd.ttf", gTrue},
146 {"Tahoma,Italic", NULL, "tahoma.ttf", gTrue},
147 {"Tahoma,BoldItalic", NULL, "tahomabd.ttf", gTrue},
148 {"Tahoma-Bold", NULL, "tahomabd.ttf", gTrue},
149 {"Tahoma-Italic", NULL, "tahoma.ttf", gTrue},
150 {"Tahoma-BoldItalic", NULL, "tahomabd.ttf", gTrue},
152 {"CCRIKH+Verdana", NULL, "verdana.ttf", gTrue},
153 {"CCRIKH+Verdana,Bold", NULL, "verdanab.ttf", gTrue},
154 {"CCRIKH+Verdana,Italic", NULL, "verdanai.ttf", gTrue},
155 {"CCRIKH+Verdana,BoldItalic", NULL, "verdanaz.ttf", gTrue},
156 {"CCRIKH+Verdana-Bold", NULL, "verdanab.ttf", gTrue},
157 {"CCRIKH+Verdana-Italic", NULL, "verdanai.ttf", gTrue},
158 {"CCRIKH+Verdana-BoldItalic", NULL, "verdanaz.ttf", gTrue},
160 {"Georgia", NULL, "georgia.ttf", gTrue},
161 {"Georgia,Bold", NULL, "georgiab.ttf", gTrue},
162 {"Georgia,Italic", NULL, "georgiai.ttf", gTrue},
163 {"Georgia,BoldItalic", NULL, "georgiaz.ttf", gTrue},
164 {"Georgia-Bold", NULL, "georgiab.ttf", gTrue},
165 {"Georgia-Italic", NULL, "georgiai.ttf", gTrue},
166 {"Georgia-BoldItalic", NULL, "georgiaz.ttf", gTrue},
168 // fallback for Adobe CID fonts:
169 {"MingLiU", NULL, "mingliu.ttf", gFalse},
170 {"SimSun", NULL, "simsun.ttf", gFalse},
171 {"MS-Mincho", NULL, "msmincho.ttf", gFalse},
172 {"Batang", NULL, "batang.ttf", gFalse},
173 {"ArialUnicode", NULL, "arialuni.ttf", gTrue},
174 {NULL}
177 #define FONTS_SUBDIR "\\fonts"
179 static void GetWindowsFontDir(char *winFontDir, int cbWinFontDirLen)
181 BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner,
182 LPTSTR lpszPath,
183 int nFolder,
184 BOOL fCreate);
185 HRESULT (__stdcall *SHGetFolderPathFunc)(HWND hwndOwner,
186 int nFolder,
187 HANDLE hToken,
188 DWORD dwFlags,
189 LPTSTR pszPath);
191 // SHGetSpecialFolderPath isn't available in older versions of shell32.dll (Win95 and
192 // WinNT4), so do a dynamic load of ANSI versions.
193 winFontDir[0] = '\0';
195 HMODULE hLib = LoadLibrary("shell32.dll");
196 if (hLib) {
197 SHGetFolderPathFunc = (HRESULT (__stdcall *)(HWND, int, HANDLE, DWORD, LPTSTR))
198 GetProcAddress(hLib, "SHGetFolderPathA");
199 if (SHGetFolderPathFunc)
200 (*SHGetFolderPathFunc)(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, winFontDir);
202 if (!winFontDir[0]) {
203 // Try an older function
204 SHGetSpecialFolderPathFunc = (BOOL (__stdcall *)(HWND, LPTSTR, int, BOOL))
205 GetProcAddress(hLib, "SHGetSpecialFolderPathA");
206 if (SHGetSpecialFolderPathFunc)
207 (*SHGetSpecialFolderPathFunc)(NULL, winFontDir, CSIDL_FONTS, FALSE);
209 FreeLibrary(hLib);
211 if (winFontDir[0])
212 return;
214 // Try older DLL
215 hLib = LoadLibrary("SHFolder.dll");
216 if (hLib) {
217 SHGetFolderPathFunc = (HRESULT (__stdcall *)(HWND, int, HANDLE, DWORD, LPTSTR))
218 GetProcAddress(hLib, "SHGetFolderPathA");
219 if (SHGetFolderPathFunc)
220 (*SHGetFolderPathFunc)(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, winFontDir);
221 FreeLibrary(hLib);
223 if (winFontDir[0])
224 return;
226 // Everything else failed so the standard fonts directory.
227 GetWindowsDirectory(winFontDir, cbWinFontDirLen);
228 if (winFontDir[0]) {
229 strncat(winFontDir, FONTS_SUBDIR, cbWinFontDirLen);
230 winFontDir[cbWinFontDirLen-1] = 0;
234 static bool FileExists(const char *path)
236 FILE * f = fopen(path, "rb");
237 if (f) {
238 fclose(f);
239 return true;
241 return false;
244 void SysFontList::scanWindowsFonts(GooString *winFontDir) {
245 OSVERSIONINFO version;
246 const char *path;
247 DWORD idx, valNameLen, dataLen, type;
248 HKEY regKey;
249 char valName[1024], data[1024];
250 int n, fontNum;
251 char *p0, *p1;
252 GooString *fontPath;
254 version.dwOSVersionInfoSize = sizeof(version);
255 GetVersionEx(&version);
256 if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
257 path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\";
258 } else {
259 path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\";
261 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0,
262 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
263 &regKey) == ERROR_SUCCESS) {
264 idx = 0;
265 while (1) {
266 valNameLen = sizeof(valName) - 1;
267 dataLen = sizeof(data) - 1;
268 if (RegEnumValue(regKey, idx, valName, &valNameLen, NULL,
269 &type, (LPBYTE)data, &dataLen) != ERROR_SUCCESS) {
270 break;
272 if (type == REG_SZ &&
273 valNameLen > 0 && valNameLen < sizeof(valName) &&
274 dataLen > 0 && dataLen < sizeof(data)) {
275 valName[valNameLen] = '\0';
276 data[dataLen] = '\0';
277 n = strlen(data);
278 if (!strcasecmp(data + n - 4, ".ttf") ||
279 !strcasecmp(data + n - 4, ".ttc") ||
280 !strcasecmp(data + n - 4, ".otf")) {
281 fontPath = new GooString(data);
282 if (!(dataLen >= 3 && data[1] == ':' && data[2] == '\\')) {
283 fontPath->insert(0, '\\');
284 fontPath->insert(0, winFontDir);
285 fontPath->append('\0');
287 p0 = valName;
288 fontNum = 0;
289 while (*p0) {
290 p1 = strstr(p0, " & ");
291 if (p1) {
292 *p1 = '\0';
293 p1 = p1 + 3;
294 } else {
295 p1 = p0 + strlen(p0);
297 fonts->append(makeWindowsFont(p0, fontNum,
298 fontPath->getCString()));
299 p0 = p1;
300 ++fontNum;
302 delete fontPath;
305 ++idx;
307 RegCloseKey(regKey);
311 SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum,
312 char *path) {
313 int n;
314 GBool bold, italic, oblique, fixedWidth;
315 GooString *s;
316 char c;
317 int i;
318 SysFontType type;
319 GooString substituteName;
321 n = strlen(name);
322 bold = italic = oblique = fixedWidth = gFalse;
324 // remove trailing ' (TrueType)'
325 if (n > 11 && !strncmp(name + n - 11, " (TrueType)", 11)) {
326 n -= 11;
329 // remove trailing ' (OpenType)'
330 if (n > 11 && !strncmp(name + n - 11, " (OpenType)", 11)) {
331 n -= 11;
334 // remove trailing ' Italic'
335 if (n > 7 && !strncmp(name + n - 7, " Italic", 7)) {
336 n -= 7;
337 italic = gTrue;
340 // remove trailing ' Oblique'
341 if (n > 7 && !strncmp(name + n - 8, " Oblique", 8)) {
342 n -= 8;
343 oblique = gTrue;
346 // remove trailing ' Bold'
347 if (n > 5 && !strncmp(name + n - 5, " Bold", 5)) {
348 n -= 5;
349 bold = gTrue;
352 // remove trailing ' Regular'
353 if (n > 5 && !strncmp(name + n - 8, " Regular", 8)) {
354 n -= 8;
357 // the familyname cannot indicate whether a font is fixedWidth or not.
358 // some well-known fixedWidth typeface family names or keyword are checked.
359 if ( strstr(name, "Courier") ||
360 strstr(name, "Fixed") ||
361 (strstr(name, "Mono") && !strstr(name, "Monotype")) ||
362 strstr(name, "Typewriter") )
363 fixedWidth = gTrue;
364 else
365 fixedWidth = gFalse;
368 //----- normalize the font name
369 s = new GooString(name, n);
370 i = 0;
371 while (i < s->getLength()) {
372 c = s->getChar(i);
373 if (c == ' ' || c == ',' || c == '-') {
374 s->del(i);
375 } else {
376 ++i;
380 if (!strcasecmp(path + strlen(path) - 4, ".ttc")) {
381 type = sysFontTTC;
382 } else {
383 type = sysFontTTF;
386 return new SysFontInfo(s, bold, italic, oblique, fixedWidth,
387 new GooString(path), type, fontNum, substituteName.copy());
390 static GooString* replaceSuffix(GooString *path,
391 const char* suffixA, const char* suffixB)
393 int suffLenA = strlen(suffixA);
394 int suffLenB = strlen(suffixB);
395 int baseLenA = path->getLength() - suffLenA;
396 int baseLenB = path->getLength() - suffLenB;
398 if (!strcasecmp(path->getCString()+baseLenA, suffixA)) {
399 path->del(baseLenA,suffLenA)->append(suffixB);
400 } else if (!strcasecmp(path->getCString()+baseLenB, suffixB)) {
401 path->del(baseLenB,suffLenB)->append(suffixA);
404 return path;
408 void GlobalParams::setupBaseFonts(char * dir)
410 const char *dataRoot = popplerDataDir ? popplerDataDir : POPPLER_DATADIR;
411 GooString *fileName = NULL;
412 GooFile *file;
414 if (baseFontsInitialized)
415 return;
416 baseFontsInitialized = true;
418 char winFontDir[MAX_PATH];
419 GetWindowsFontDir(winFontDir, sizeof(winFontDir));
421 for (int i = 0; displayFontTab[i].name; ++i) {
422 GooString *fontName = new GooString(displayFontTab[i].name);
423 if (fontFiles->lookup(fontName))
424 continue;
426 if (dir) {
427 GooString *fontPath = appendToPath(new GooString(dir), displayFontTab[i].t1FileName);
428 if (FileExists(fontPath->getCString()) ||
429 FileExists(replaceSuffix(fontPath, ".pfb", ".pfa")->getCString())) {
430 addFontFile(fontName, fontPath);
431 continue;
433 delete fontPath;
436 if (winFontDir[0] && displayFontTab[i].ttFileName) {
437 GooString *fontPath = appendToPath(new GooString(winFontDir), displayFontTab[i].ttFileName);
438 if (FileExists(fontPath->getCString()) ||
439 FileExists(replaceSuffix(fontPath, ".ttc", ".ttf")->getCString())) {
440 addFontFile(fontName, fontPath);
441 continue;
443 delete fontPath;
446 if (displayFontTab[i].warnIfMissing)
447 error(errSyntaxError, -1, "No display font for '{0:s}'", fontName);
449 if (winFontDir[0]) {
450 sysFonts->scanWindowsFonts(new GooString(winFontDir));
453 fileName = new GooString(dataRoot);
454 fileName->append("/cidfmap");
456 // try to open file
457 file = GooFile::open(fileName);
459 if (file != NULL) {
460 Parser *parser;
461 Object obj1, obj2;
463 obj1.initNull();
464 parser = new Parser(NULL,
465 new Lexer(NULL,
466 new FileStream(file, 0, gFalse, file->size(), &obj1)),
467 gTrue);
468 obj1.free();
469 parser->getObj(&obj1);
470 while (!obj1.isEOF()) {
471 parser->getObj(&obj2);
472 if (obj1.isName()) {
473 // Substitutions
474 if (obj2.isDict()) {
475 Object obj3;
476 obj2.getDict()->lookup("Path", &obj3);
477 if (obj3.isString())
478 addFontFile(new GooString(obj1.getName()), obj3.getString()->copy());
479 obj3.free();
480 // Aliases
481 } else if (obj2.isName()) {
482 substFiles->add(new GooString(obj1.getName()), new GooString(obj2.getName()));
485 obj2.free();
486 obj1.free();
487 parser->getObj(&obj1);
488 // skip trailing ';'
489 while (obj1.isCmd(";")) {
490 obj1.free();
491 parser->getObj(&obj1);
494 delete file;
495 delete parser;
499 static const char *findSubstituteName(GfxFont *font, GooHash *fontFiles,
500 GooHash *substFiles,
501 const char *origName)
503 assert(origName);
504 if (!origName) return NULL;
505 GooString *name2 = new GooString(origName);
506 int n = strlen(origName);
507 // remove trailing "-Identity-H"
508 if (n > 11 && !strcmp(name2->getCString() + n - 11, "-Identity-H")) {
509 name2->del(n - 11, 11);
510 n -= 11;
512 // remove trailing "-Identity-V"
513 if (n > 11 && !strcmp(name2->getCString() + n - 11, "-Identity-V")) {
514 name2->del(n - 11, 11);
515 n -= 11;
517 GooString *substName = (GooString *)substFiles->lookup(name2);
518 if (substName != NULL) {
519 delete name2;
520 return substName->getCString();
523 /* TODO: try to at least guess bold/italic/bolditalic from the name */
524 delete name2;
525 if (font->isCIDFont()) {
526 GooString *collection = ((GfxCIDFont *)font)->getCollection();
528 const char* name3 = NULL;
529 if ( !collection->cmp("Adobe-CNS1") )
530 name3 = DEFAULT_CID_FONT_AC1_MSWIN;
531 else if ( !collection->cmp("Adobe-GB1") )
532 name3 = DEFAULT_CID_FONT_AG1_MSWIN;
533 else if ( !collection->cmp("Adobe-Japan1") )
534 name3 = DEFAULT_CID_FONT_AJ1_MSWIN;
535 else if ( !collection->cmp("Adobe-Japan2") )
536 name3 = DEFAULT_CID_FONT_AJ2_MSWIN;
537 else if ( !collection->cmp("Adobe-Korea1") )
538 name3 = DEFAULT_CID_FONT_AK1_MSWIN;
540 if (name3 && fontFiles->lookup(name3))
541 return name3;
543 if (fontFiles->lookup(DEFAULT_CID_FONT_MSWIN))
544 return DEFAULT_CID_FONT_MSWIN;
546 return DEFAULT_SUBSTITUTE_FONT;
549 /* Windows implementation of external font matching code */
550 GooString *GlobalParams::findSystemFontFile(GfxFont *font,
551 SysFontType *type,
552 int *fontNum, GooString *substituteFontName,
553 GooString *base14Name) {
554 SysFontInfo *fi;
555 GooString *path = NULL;
556 GooString *fontName = font->getName();
557 if (!fontName) return NULL;
558 lockGlobalParams;
559 setupBaseFonts(NULL);
561 // TODO: base14Name should be changed?
562 // In the system using FontConfig, findSystemFontFile() uses
563 // base14Name only for the creation of query pattern.
565 if ((fi = sysFonts->find(fontName, gFalse, gFalse))) {
566 path = fi->path->copy();
567 *type = fi->type;
568 *fontNum = fi->fontNum;
569 if (substituteFontName)
570 substituteFontName->Set(fi->substituteName->getCString());
571 } else {
572 GooString *substFontName = new GooString(findSubstituteName(font, fontFiles,
573 substFiles,
574 fontName->getCString()));
575 GooString *path2 = NULL;
576 error(errSyntaxError, -1, "Couldn't find a font for '{0:t}', subst is '{1:t}'", fontName, substFontName);
577 if ((path2 = (GooString *)fontFiles->lookup(substFontName))) {
578 path = new GooString(path2);
579 if (substituteFontName)
580 substituteFontName->Set(path->getCString());
581 if (!strcasecmp(path->getCString() + path->getLength() - 4, ".ttc")) {
582 *type = sysFontTTC;
583 } else {
584 *type = sysFontTTF;
586 *fontNum = 0;
589 unlockGlobalParams;
590 return path;