1 //========================================================================
5 // Copyright 2001-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
21 #include <fontconfig/fontconfig.h>
28 #include "NameToCharCode.h"
29 #include "CharCodeToUnicode.h"
30 #include "UnicodeMap.h"
32 #include "BuiltinFontTables.h"
33 #include "FontEncodingTables.h"
34 #include "GlobalParams.h"
37 # define lockGlobalParams gLockMutex(&mutex)
38 # define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex)
39 # define lockCMapCache gLockMutex(&cMapCacheMutex)
40 # define unlockGlobalParams gUnlockMutex(&mutex)
41 # define unlockUnicodeMapCache gUnlockMutex(&unicodeMapCacheMutex)
42 # define unlockCMapCache gUnlockMutex(&cMapCacheMutex)
44 # define lockGlobalParams
45 # define lockUnicodeMapCache
46 # define lockCMapCache
47 # define unlockGlobalParams
48 # define unlockUnicodeMapCache
49 # define unlockCMapCache
52 #include "NameToUnicodeTable.h"
53 #include "UnicodeMapTables.h"
56 //------------------------------------------------------------------------
58 #define cidToUnicodeCacheSize 4
59 #define unicodeToUnicodeCacheSize 4
61 //------------------------------------------------------------------------
66 } displayFontTab[] = {
67 {"Courier", "n022003l.pfb"},
68 {"Courier-Bold", "n022004l.pfb"},
69 {"Courier-BoldOblique", "n022024l.pfb"},
70 {"Courier-Oblique", "n022023l.pfb"},
71 {"Helvetica", "n019003l.pfb"},
72 {"Helvetica-Bold", "n019004l.pfb"},
73 {"Helvetica-BoldOblique", "n019024l.pfb"},
74 {"Helvetica-Oblique", "n019023l.pfb"},
75 {"Symbol", "s050000l.pfb"},
76 {"Times-Bold", "n021004l.pfb"},
77 {"Times-BoldItalic", "n021024l.pfb"},
78 {"Times-Italic", "n021023l.pfb"},
79 {"Times-Roman", "n021003l.pfb"},
80 {"ZapfDingbats", "d050000l.pfb"},
84 static char *displayFontDirs[] = {
85 "/usr/share/ghostscript/fonts",
86 "/usr/local/share/ghostscript/fonts",
87 "/usr/share/fonts/default/Type1",
91 /* patterns originally from mupdf; added agfa fonts*/
95 } displayFontTabFc[] = {
96 /* FIXME Adobe fonts should be here, but that breaks down if
97 fontconfig returns pcf fonts */
98 {"Courier", "Nimbus Mono L,Courier New,Cumberland AMT,Cumberland:style=Regular,Roman"},
99 {"Courier-Bold", "Nimbus Mono L,Courier New,Cumberland AMT,Cumberland:style=Bold"},
100 {"Courier-BoldOblique", "Nimbus Mono L,Courier New,Cumberland AMT,Cumberland:style=Oblique,Italic"},
101 {"Courier-Oblique", "Nimbus Mono L,Courier New,Cumberland AMT,Cumberland:style=BoldOblique,BoldItalic"},
102 {"Helvetica", "Nimbus Sans L,Arial,Albany AMT,Albany:style=Regular,Roman"},
103 {"Helvetica-Bold", "Nimbus Sans L,Arial,Albany AMT,Albany:style=Bold"},
104 {"Helvetica-BoldOblique", "Nimbus Sans L,Arial,Albany AMT,Albany:style=Oblique,Italic"},
105 {"Helvetica-Oblique", "Nimbus Sans L,Arial,Albany AMT,Albany:style=BoldOblique,BoldItalic"},
106 /* FIXME Symbol should be first,
107 but that matches windows ttf which gets wrong encoding */
108 {"Symbol", "Standard Symbols L,Symbol"},
109 {"Times-Bold", "Nimbus Roman No9 L,Times New Roman,Thorndale AMT,Thorndale:style=Bold,Medium"},
110 {"Times-BoldItalic", "Nimbus Roman No9 L,Times New Roman,Thorndale AMT,Thorndale:style=BoldItalic,Medium Italic"},
111 {"Times-Italic", "Nimbus Roman No9 L,Times New Roman,Thorndale AMT,Thorndale:style=Italic,Regular Italic"},
112 {"Times-Roman", "Nimbus Roman No9 L,Times New Roman,Thorndale AMT,Thorndale:style=Regular,Roman"},
113 {"ZapfDingbats", "Dingbats:outline=true"},
117 //------------------------------------------------------------------------
119 GlobalParams *globalParams = NULL;
121 //------------------------------------------------------------------------
123 //------------------------------------------------------------------------
125 DisplayFontParam::DisplayFontParam(GString *nameA,
126 DisplayFontParamKind kindA) {
139 DisplayFontParam::~DisplayFontParam() {
155 //------------------------------------------------------------------------
157 //------------------------------------------------------------------------
159 PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA,
160 GString *psFontNameA, GString *encodingA) {
161 pdfFontName = pdfFontNameA;
163 psFontName = psFontNameA;
164 encoding = encodingA;
167 PSFontParam::~PSFontParam() {
175 //------------------------------------------------------------------------
177 //------------------------------------------------------------------------
179 GlobalParams::GlobalParams(char *cfgFileName) {
187 gInitMutex(&unicodeMapCacheMutex);
188 gInitMutex(&cMapCacheMutex);
191 initBuiltinFontTables();
193 // scan the encoding in reverse because we want the lowest-numbered
194 // index for each char name ('space' is encoded twice)
195 macRomanReverseMap = new NameToCharCode();
196 for (i = 255; i >= 0; --i) {
197 if (macRomanEncoding[i]) {
198 macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i);
202 nameToUnicode = new NameToCharCode();
203 cidToUnicodes = new GHash(gTrue);
204 unicodeToUnicodes = new GHash(gTrue);
205 residentUnicodeMaps = new GHash();
206 unicodeMaps = new GHash(gTrue);
207 cMapDirs = new GHash(gTrue);
208 toUnicodeDirs = new GList();
209 displayFonts = new GHash();
210 displayCIDFonts = new GHash();
211 displayNamedCIDFonts = new GHash();
214 const struct paper *paperType;
216 if ((paperName = systempapername())) {
217 paperType = paperinfo(paperName);
218 psPaperWidth = (int)paperpswidth(paperType);
219 psPaperHeight = (int)paperpsheight(paperType);
221 error(-1, "No paper information available - using defaults");
222 psPaperWidth = defPaperWidth;
223 psPaperHeight = defPaperHeight;
227 psPaperWidth = defPaperWidth;
228 psPaperHeight = defPaperHeight;
230 psImageableLLX = psImageableLLY = 0;
231 psImageableURX = psPaperWidth;
232 psImageableURY = psPaperHeight;
234 psExpandSmaller = gFalse;
235 psShrinkLarger = gTrue;
240 psFonts = new GHash();
241 psNamedFonts16 = new GList();
242 psFonts16 = new GList();
243 psEmbedType1 = gTrue;
244 psEmbedTrueType = gTrue;
245 psEmbedCIDPostScript = gTrue;
246 psEmbedCIDTrueType = gTrue;
249 textEncoding = new GString("Latin1");
257 textPageBreaks = gTrue;
258 textKeepTinyChars = gFalse;
259 fontDirs = new GList();
260 initialZoom = new GString("125");
262 enableFreeType = gTrue;
266 mapNumericCharNames = gTrue;
267 printCommands = gFalse;
270 cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize);
271 unicodeToUnicodeCache =
272 new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize);
273 unicodeMapCache = new UnicodeMapCache();
274 cMapCache = new CMapCache();
276 // set up the initial nameToUnicode table
277 for (i = 0; nameToUnicodeTab[i].name; ++i) {
278 nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
281 // set up the residentUnicodeMaps table
282 map = new UnicodeMap("Latin1", gFalse,
283 latin1UnicodeMapRanges, latin1UnicodeMapLen);
284 residentUnicodeMaps->add(map->getEncodingName(), map);
285 map = new UnicodeMap("ASCII7", gFalse,
286 ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
287 residentUnicodeMaps->add(map->getEncodingName(), map);
288 map = new UnicodeMap("Symbol", gFalse,
289 symbolUnicodeMapRanges, symbolUnicodeMapLen);
290 residentUnicodeMaps->add(map->getEncodingName(), map);
291 map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges,
292 zapfDingbatsUnicodeMapLen);
293 residentUnicodeMaps->add(map->getEncodingName(), map);
294 map = new UnicodeMap("UTF-8", gTrue, &mapUTF8);
295 residentUnicodeMaps->add(map->getEncodingName(), map);
296 map = new UnicodeMap("UCS-2", gTrue, &mapUCS2);
297 residentUnicodeMaps->add(map->getEncodingName(), map);
299 // look for a user config file, then a system-wide config file
302 if (cfgFileName && cfgFileName[0]) {
303 fileName = new GString(cfgFileName);
304 if (!(f = fopen(fileName->getCString(), "r"))) {
309 fileName = appendToPath(getHomeDir(), xpdfUserConfigFile);
310 if (!(f = fopen(fileName->getCString(), "r"))) {
315 #if defined(WIN32) && !defined(__CYGWIN32__)
317 i = GetModuleFileName(NULL, buf, sizeof(buf));
318 if (i <= 0 || i >= sizeof(buf)) {
319 // error or path too long for buffer - just use the current dir
322 fileName = grabPath(buf);
323 appendToPath(fileName, xpdfSysConfigFile);
325 fileName = new GString(xpdfSysConfigFile);
327 if (!(f = fopen(fileName->getCString(), "r"))) {
332 parseFile(fileName, f);
338 void GlobalParams::parseFile(GString *fileName, FILE *f) {
341 GString *cmd, *incFile;
347 while (getLine(buf, sizeof(buf) - 1, f)) {
349 // break the line into tokens
350 tokens = new GList();
353 for (; *p1 && isspace(*p1); ++p1) ;
357 if (*p1 == '"' || *p1 == '\'') {
358 for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
361 for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
363 tokens->append(new GString(p1, p2 - p1));
364 p1 = *p2 ? p2 + 1 : p2;
367 if (tokens->getLength() > 0 &&
368 ((GString *)tokens->get(0))->getChar(0) != '#') {
369 cmd = (GString *)tokens->get(0);
370 if (!cmd->cmp("include")) {
371 if (tokens->getLength() == 2) {
372 incFile = (GString *)tokens->get(1);
373 if ((f2 = fopen(incFile->getCString(), "r"))) {
374 parseFile(incFile, f2);
377 error(-1, "Couldn't find included config file: '%s' (%s:%d)",
378 incFile->getCString(), fileName->getCString(), line);
381 error(-1, "Bad 'include' config file command (%s:%d)",
382 fileName->getCString(), line);
384 } else if (!cmd->cmp("nameToUnicode")) {
385 parseNameToUnicode(tokens, fileName, line);
386 } else if (!cmd->cmp("cidToUnicode")) {
387 parseCIDToUnicode(tokens, fileName, line);
388 } else if (!cmd->cmp("unicodeToUnicode")) {
389 parseUnicodeToUnicode(tokens, fileName, line);
390 } else if (!cmd->cmp("unicodeMap")) {
391 parseUnicodeMap(tokens, fileName, line);
392 } else if (!cmd->cmp("cMapDir")) {
393 parseCMapDir(tokens, fileName, line);
394 } else if (!cmd->cmp("toUnicodeDir")) {
395 parseToUnicodeDir(tokens, fileName, line);
396 } else if (!cmd->cmp("displayFontT1")) {
397 parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
398 } else if (!cmd->cmp("displayFontTT")) {
399 parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
400 } else if (!cmd->cmp("displayNamedCIDFontT1")) {
401 parseDisplayFont(tokens, displayNamedCIDFonts,
402 displayFontT1, fileName, line);
403 } else if (!cmd->cmp("displayCIDFontT1")) {
404 parseDisplayFont(tokens, displayCIDFonts,
405 displayFontT1, fileName, line);
406 } else if (!cmd->cmp("displayNamedCIDFontTT")) {
407 parseDisplayFont(tokens, displayNamedCIDFonts,
408 displayFontTT, fileName, line);
409 } else if (!cmd->cmp("displayCIDFontTT")) {
410 parseDisplayFont(tokens, displayCIDFonts,
411 displayFontTT, fileName, line);
412 } else if (!cmd->cmp("psFile")) {
413 parsePSFile(tokens, fileName, line);
414 } else if (!cmd->cmp("psFont")) {
415 parsePSFont(tokens, fileName, line);
416 } else if (!cmd->cmp("psNamedFont16")) {
417 parsePSFont16("psNamedFont16", psNamedFonts16,
418 tokens, fileName, line);
419 } else if (!cmd->cmp("psFont16")) {
420 parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
421 } else if (!cmd->cmp("psPaperSize")) {
422 parsePSPaperSize(tokens, fileName, line);
423 } else if (!cmd->cmp("psImageableArea")) {
424 parsePSImageableArea(tokens, fileName, line);
425 } else if (!cmd->cmp("psCrop")) {
426 parseYesNo("psCrop", &psCrop, tokens, fileName, line);
427 } else if (!cmd->cmp("psExpandSmaller")) {
428 parseYesNo("psExpandSmaller", &psExpandSmaller,
429 tokens, fileName, line);
430 } else if (!cmd->cmp("psShrinkLarger")) {
431 parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line);
432 } else if (!cmd->cmp("psCenter")) {
433 parseYesNo("psCenter", &psCenter, tokens, fileName, line);
434 } else if (!cmd->cmp("psDuplex")) {
435 parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
436 } else if (!cmd->cmp("psLevel")) {
437 parsePSLevel(tokens, fileName, line);
438 } else if (!cmd->cmp("psEmbedType1Fonts")) {
439 parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
440 } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
441 parseYesNo("psEmbedTrueType", &psEmbedTrueType,
442 tokens, fileName, line);
443 } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
444 parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
445 tokens, fileName, line);
446 } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
447 parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
448 tokens, fileName, line);
449 } else if (!cmd->cmp("psOPI")) {
450 parseYesNo("psOPI", &psOPI, tokens, fileName, line);
451 } else if (!cmd->cmp("psASCIIHex")) {
452 parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
453 } else if (!cmd->cmp("textEncoding")) {
454 parseTextEncoding(tokens, fileName, line);
455 } else if (!cmd->cmp("textEOL")) {
456 parseTextEOL(tokens, fileName, line);
457 } else if (!cmd->cmp("textPageBreaks")) {
458 parseYesNo("textPageBreaks", &textPageBreaks,
459 tokens, fileName, line);
460 } else if (!cmd->cmp("textKeepTinyChars")) {
461 parseYesNo("textKeepTinyChars", &textKeepTinyChars,
462 tokens, fileName, line);
463 } else if (!cmd->cmp("fontDir")) {
464 parseFontDir(tokens, fileName, line);
465 } else if (!cmd->cmp("initialZoom")) {
466 parseInitialZoom(tokens, fileName, line);
467 } else if (!cmd->cmp("enableT1lib")) {
468 parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line);
469 } else if (!cmd->cmp("enableFreeType")) {
470 parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line);
471 } else if (!cmd->cmp("antialias")) {
472 parseYesNo("antialias", &antialias, tokens, fileName, line);
473 } else if (!cmd->cmp("urlCommand")) {
474 parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
475 } else if (!cmd->cmp("movieCommand")) {
476 parseCommand("movieCommand", &movieCommand, tokens, fileName, line);
477 } else if (!cmd->cmp("mapNumericCharNames")) {
478 parseYesNo("mapNumericCharNames", &mapNumericCharNames,
479 tokens, fileName, line);
480 } else if (!cmd->cmp("printCommands")) {
481 parseYesNo("printCommands", &printCommands, tokens, fileName, line);
482 } else if (!cmd->cmp("errQuiet")) {
483 parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
485 error(-1, "Unknown config file command '%s' (%s:%d)",
486 cmd->getCString(), fileName->getCString(), line);
487 if (!cmd->cmp("displayFontX") ||
488 !cmd->cmp("displayNamedCIDFontX") ||
489 !cmd->cmp("displayCIDFontX")) {
490 error(-1, "-- Xpdf no longer supports X fonts");
491 } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) {
492 error(-1, "-- The t1libControl and freetypeControl options have been replaced");
493 error(-1, " by the enableT1lib, enableFreeType, and antialias options");
494 } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
495 error(-1, "-- the config file format has changed since Xpdf 0.9x");
500 deleteGList(tokens, GString);
505 void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
514 if (tokens->getLength() != 2) {
515 error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
516 fileName->getCString(), line);
519 name = (GString *)tokens->get(1);
520 if (!(f = fopen(name->getCString(), "r"))) {
521 error(-1, "Couldn't open 'nameToUnicode' file '%s'",
526 while (getLine(buf, sizeof(buf), f)) {
527 tok1 = strtok(buf, " \t\r\n");
528 tok2 = strtok(NULL, " \t\r\n");
530 sscanf(tok1, "%x", &u);
531 nameToUnicode->add(tok2, u);
533 error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
540 void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
542 GString *collection, *name, *old;
544 if (tokens->getLength() != 3) {
545 error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
546 fileName->getCString(), line);
549 collection = (GString *)tokens->get(1);
550 name = (GString *)tokens->get(2);
551 if ((old = (GString *)cidToUnicodes->remove(collection))) {
554 cidToUnicodes->add(collection->copy(), name->copy());
557 void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
559 GString *font, *file, *old;
561 if (tokens->getLength() != 3) {
562 error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)",
563 fileName->getCString(), line);
566 font = (GString *)tokens->get(1);
567 file = (GString *)tokens->get(2);
568 if ((old = (GString *)unicodeToUnicodes->remove(font))) {
571 unicodeToUnicodes->add(font->copy(), file->copy());
574 void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
576 GString *encodingName, *name, *old;
578 if (tokens->getLength() != 3) {
579 error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
580 fileName->getCString(), line);
583 encodingName = (GString *)tokens->get(1);
584 name = (GString *)tokens->get(2);
585 if ((old = (GString *)unicodeMaps->remove(encodingName))) {
588 unicodeMaps->add(encodingName->copy(), name->copy());
591 void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
592 GString *collection, *dir;
595 if (tokens->getLength() != 3) {
596 error(-1, "Bad 'cMapDir' config file command (%s:%d)",
597 fileName->getCString(), line);
600 collection = (GString *)tokens->get(1);
601 dir = (GString *)tokens->get(2);
602 if (!(list = (GList *)cMapDirs->lookup(collection))) {
604 cMapDirs->add(collection->copy(), list);
606 list->append(dir->copy());
609 void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
611 if (tokens->getLength() != 2) {
612 error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
613 fileName->getCString(), line);
616 toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
619 void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
620 DisplayFontParamKind kind,
621 GString *fileName, int line) {
622 DisplayFontParam *param, *old;
624 if (tokens->getLength() < 2) {
627 param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
631 if (tokens->getLength() != 3) {
634 param->t1.fileName = ((GString *)tokens->get(2))->copy();
637 if (tokens->getLength() != 3) {
640 param->tt.fileName = ((GString *)tokens->get(2))->copy();
644 if ((old = (DisplayFontParam *)fontHash->remove(param->name))) {
647 fontHash->add(param->name, param);
653 error(-1, "Bad 'display*Font*' config file command (%s:%d)",
654 fileName->getCString(), line);
657 void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
661 if (tokens->getLength() == 2) {
662 tok = (GString *)tokens->get(1);
663 if (!setPSPaperSize(tok->getCString())) {
664 error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
665 fileName->getCString(), line);
667 } else if (tokens->getLength() == 3) {
668 tok = (GString *)tokens->get(1);
669 psPaperWidth = atoi(tok->getCString());
670 tok = (GString *)tokens->get(2);
671 psPaperHeight = atoi(tok->getCString());
672 psImageableLLX = psImageableLLY = 0;
673 psImageableURX = psPaperWidth;
674 psImageableURY = psPaperHeight;
676 error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
677 fileName->getCString(), line);
681 void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName,
683 if (tokens->getLength() != 5) {
684 error(-1, "Bad 'psImageableArea' config file command (%s:%d)",
685 fileName->getCString(), line);
688 psImageableLLX = atoi(((GString *)tokens->get(1))->getCString());
689 psImageableLLY = atoi(((GString *)tokens->get(2))->getCString());
690 psImageableURX = atoi(((GString *)tokens->get(3))->getCString());
691 psImageableURY = atoi(((GString *)tokens->get(4))->getCString());
694 void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
697 if (tokens->getLength() != 2) {
698 error(-1, "Bad 'psLevel' config file command (%s:%d)",
699 fileName->getCString(), line);
702 tok = (GString *)tokens->get(1);
703 if (!tok->cmp("level1")) {
705 } else if (!tok->cmp("level1sep")) {
706 psLevel = psLevel1Sep;
707 } else if (!tok->cmp("level2")) {
709 } else if (!tok->cmp("level2sep")) {
710 psLevel = psLevel2Sep;
711 } else if (!tok->cmp("level3")) {
713 } else if (!tok->cmp("level3Sep")) {
714 psLevel = psLevel3Sep;
716 error(-1, "Bad 'psLevel' config file command (%s:%d)",
717 fileName->getCString(), line);
721 void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
722 if (tokens->getLength() != 2) {
723 error(-1, "Bad 'psFile' config file command (%s:%d)",
724 fileName->getCString(), line);
730 psFile = ((GString *)tokens->get(1))->copy();
733 void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
736 if (tokens->getLength() != 3) {
737 error(-1, "Bad 'psFont' config file command (%s:%d)",
738 fileName->getCString(), line);
741 param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0,
742 ((GString *)tokens->get(2))->copy(), NULL);
743 psFonts->add(param->pdfFontName, param);
746 void GlobalParams::parsePSFont16(char *cmdName, GList *fontList,
747 GList *tokens, GString *fileName, int line) {
752 if (tokens->getLength() != 5) {
753 error(-1, "Bad '%s' config file command (%s:%d)",
754 cmdName, fileName->getCString(), line);
757 tok = (GString *)tokens->get(2);
758 if (!tok->cmp("H")) {
760 } else if (!tok->cmp("V")) {
763 error(-1, "Bad '%s' config file command (%s:%d)",
764 cmdName, fileName->getCString(), line);
767 param = new PSFontParam(((GString *)tokens->get(1))->copy(),
769 ((GString *)tokens->get(3))->copy(),
770 ((GString *)tokens->get(4))->copy());
771 fontList->append(param);
774 void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
776 if (tokens->getLength() != 2) {
777 error(-1, "Bad 'textEncoding' config file command (%s:%d)",
778 fileName->getCString(), line);
782 textEncoding = ((GString *)tokens->get(1))->copy();
785 void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
788 if (tokens->getLength() != 2) {
789 error(-1, "Bad 'textEOL' config file command (%s:%d)",
790 fileName->getCString(), line);
793 tok = (GString *)tokens->get(1);
794 if (!tok->cmp("unix")) {
796 } else if (!tok->cmp("dos")) {
798 } else if (!tok->cmp("mac")) {
801 error(-1, "Bad 'textEOL' config file command (%s:%d)",
802 fileName->getCString(), line);
806 void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
807 if (tokens->getLength() != 2) {
808 error(-1, "Bad 'fontDir' config file command (%s:%d)",
809 fileName->getCString(), line);
812 fontDirs->append(((GString *)tokens->get(1))->copy());
815 void GlobalParams::parseInitialZoom(GList *tokens,
816 GString *fileName, int line) {
817 if (tokens->getLength() != 2) {
818 error(-1, "Bad 'initialZoom' config file command (%s:%d)",
819 fileName->getCString(), line);
823 initialZoom = ((GString *)tokens->get(1))->copy();
826 void GlobalParams::parseCommand(char *cmdName, GString **val,
827 GList *tokens, GString *fileName, int line) {
828 if (tokens->getLength() != 2) {
829 error(-1, "Bad '%s' config file command (%s:%d)",
830 cmdName, fileName->getCString(), line);
836 *val = ((GString *)tokens->get(1))->copy();
839 void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
840 GList *tokens, GString *fileName, int line) {
843 if (tokens->getLength() != 2) {
844 error(-1, "Bad '%s' config file command (%s:%d)",
845 cmdName, fileName->getCString(), line);
848 tok = (GString *)tokens->get(1);
849 if (!parseYesNo2(tok->getCString(), flag)) {
850 error(-1, "Bad '%s' config file command (%s:%d)",
851 cmdName, fileName->getCString(), line);
855 GBool GlobalParams::parseYesNo2(char *token, GBool *flag) {
856 if (!strcmp(token, "yes")) {
858 } else if (!strcmp(token, "no")) {
866 GlobalParams::~GlobalParams() {
871 freeBuiltinFontTables();
873 delete macRomanReverseMap;
875 delete nameToUnicode;
876 deleteGHash(cidToUnicodes, GString);
877 deleteGHash(unicodeToUnicodes, GString);
878 deleteGHash(residentUnicodeMaps, UnicodeMap);
879 deleteGHash(unicodeMaps, GString);
880 deleteGList(toUnicodeDirs, GString);
881 deleteGHash(displayFonts, DisplayFontParam);
882 deleteGHash(displayCIDFonts, DisplayFontParam);
883 deleteGHash(displayNamedCIDFonts, DisplayFontParam);
887 deleteGHash(psFonts, PSFontParam);
888 deleteGList(psNamedFonts16, PSFontParam);
889 deleteGList(psFonts16, PSFontParam);
891 deleteGList(fontDirs, GString);
900 cMapDirs->startIter(&iter);
901 while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
902 deleteGList(list, GString);
906 delete cidToUnicodeCache;
907 delete unicodeToUnicodeCache;
908 delete unicodeMapCache;
912 gDestroyMutex(&mutex);
913 gDestroyMutex(&unicodeMapCacheMutex);
914 gDestroyMutex(&cMapCacheMutex);
918 //------------------------------------------------------------------------
920 void GlobalParams::setupBaseFonts(char *dir) {
924 DisplayFontParam *dfp;
927 for (i = 0; displayFontTab[i].name; ++i) {
928 fontName = new GString(displayFontTab[i].name);
929 if (getDisplayFont(fontName)) {
935 fileName = appendToPath(new GString(dir), displayFontTab[i].fileName);
936 if ((f = fopen(fileName->getCString(), "rb"))) {
944 for (j = 0; !fileName && displayFontDirs[j]; ++j) {
945 fileName = appendToPath(new GString(displayFontDirs[j]),
946 displayFontTab[i].fileName);
947 if ((f = fopen(fileName->getCString(), "rb"))) {
956 error(-1, "No display font for '%s'", displayFontTab[i].name);
960 dfp = new DisplayFontParam(fontName, displayFontT1);
961 dfp->t1.fileName = fileName;
962 globalParams->addDisplayFont(dfp);
966 //------------------------------------------------------------------------
968 void GlobalParams::setupBaseFontsFc(FcConfig *fcConfig) {
971 DisplayFontParam *dfp;
972 FcPattern *namePat, *matchPat;
976 DisplayFontParamKind kind;
978 for (i = 0; displayFontTabFc[i].name; ++i) {
979 fontName = new GString(displayFontTabFc[i].name);
980 if (getDisplayFont(fontName)) {
985 result = FcResultMatch;
986 namePat = FcNameParse((const FcChar8 *)displayFontTabFc[i].pattern);
987 FcConfigSubstitute(fcConfig, namePat, FcMatchPattern);
988 FcDefaultSubstitute(namePat);
989 matchPat = FcFontMatch(fcConfig, namePat, &result);
991 if (result == FcResultMatch) {
992 result = FcPatternGetString(matchPat, "file", 0, &fcFileName);
993 if (result == FcResultMatch)
994 fileName = new GString((const char *)fcFileName);
997 FcPatternDestroy(matchPat);
998 FcPatternDestroy(namePat);
1004 ext = strrchr(fileName->getCString(), '.');
1006 if (strcasecmp (ext, ".pfb") == 0)
1007 kind = displayFontT1;
1008 else if (strcasecmp (ext, ".pfa") == 0)
1009 kind = displayFontT1;
1010 else if (strcasecmp (ext, ".ttf") == 0)
1011 kind = displayFontTT;
1012 else if (strcasecmp (ext, ".ttc") == 0)
1013 kind = displayFontTT;
1025 error(-1, "No display font for '%s'", displayFontTabFc[i].name);
1030 dfp = new DisplayFontParam(fontName, kind);
1033 dfp->t1.fileName = fileName;
1036 dfp->tt.fileName = fileName;
1039 globalParams->addDisplayFont(dfp);
1043 //------------------------------------------------------------------------
1045 //------------------------------------------------------------------------
1047 CharCode GlobalParams::getMacRomanCharCode(char *charName) {
1048 // no need to lock - macRomanReverseMap is constant
1049 return macRomanReverseMap->lookup(charName);
1052 Unicode GlobalParams::mapNameToUnicode(char *charName) {
1053 // no need to lock - nameToUnicode is constant
1054 return nameToUnicode->lookup(charName);
1057 UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
1061 map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
1069 FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
1074 if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) {
1075 f = fopen(fileName->getCString(), "r");
1083 FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
1091 if (!(list = (GList *)cMapDirs->lookup(collection))) {
1095 for (i = 0; i < list->getLength(); ++i) {
1096 dir = (GString *)list->get(i);
1097 fileName = appendToPath(dir->copy(), cMapName->getCString());
1098 f = fopen(fileName->getCString(), "r");
1109 FILE *GlobalParams::findToUnicodeFile(GString *name) {
1110 GString *dir, *fileName;
1115 for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
1116 dir = (GString *)toUnicodeDirs->get(i);
1117 fileName = appendToPath(dir->copy(), name->getCString());
1118 f = fopen(fileName->getCString(), "r");
1129 DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
1130 DisplayFontParam *dfp;
1133 dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
1138 DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
1139 GString *collection) {
1140 DisplayFontParam *dfp;
1144 !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
1145 dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
1151 GString *GlobalParams::getPSFile() {
1155 s = psFile ? psFile->copy() : (GString *)NULL;
1160 int GlobalParams::getPSPaperWidth() {
1169 int GlobalParams::getPSPaperHeight() {
1178 void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) {
1180 *llx = psImageableLLX;
1181 *lly = psImageableLLY;
1182 *urx = psImageableURX;
1183 *ury = psImageableURY;
1187 GBool GlobalParams::getPSCrop() {
1196 GBool GlobalParams::getPSExpandSmaller() {
1200 f = psExpandSmaller;
1205 GBool GlobalParams::getPSShrinkLarger() {
1214 GBool GlobalParams::getPSCenter() {
1223 GBool GlobalParams::getPSDuplex() {
1232 PSLevel GlobalParams::getPSLevel() {
1241 PSFontParam *GlobalParams::getPSFont(GString *fontName) {
1245 p = (PSFontParam *)psFonts->lookup(fontName);
1250 PSFontParam *GlobalParams::getPSFont16(GString *fontName,
1251 GString *collection, int wMode) {
1258 for (i = 0; i < psNamedFonts16->getLength(); ++i) {
1259 p = (PSFontParam *)psNamedFonts16->get(i);
1260 if (!p->pdfFontName->cmp(fontName) &&
1261 p->wMode == wMode) {
1267 if (!p && collection) {
1268 for (i = 0; i < psFonts16->getLength(); ++i) {
1269 p = (PSFontParam *)psFonts16->get(i);
1270 if (!p->pdfFontName->cmp(collection) &&
1271 p->wMode == wMode) {
1281 GBool GlobalParams::getPSEmbedType1() {
1290 GBool GlobalParams::getPSEmbedTrueType() {
1294 e = psEmbedTrueType;
1299 GBool GlobalParams::getPSEmbedCIDPostScript() {
1303 e = psEmbedCIDPostScript;
1308 GBool GlobalParams::getPSEmbedCIDTrueType() {
1312 e = psEmbedCIDTrueType;
1317 GBool GlobalParams::getPSOPI() {
1326 GBool GlobalParams::getPSASCIIHex() {
1335 GString *GlobalParams::getTextEncodingName() {
1339 s = textEncoding->copy();
1344 EndOfLineKind GlobalParams::getTextEOL() {
1353 GBool GlobalParams::getTextPageBreaks() {
1357 pageBreaks = textPageBreaks;
1362 GBool GlobalParams::getTextKeepTinyChars() {
1366 tiny = textKeepTinyChars;
1371 GString *GlobalParams::findFontFile(GString *fontName, char **exts) {
1372 GString *dir, *fileName;
1378 for (i = 0; i < fontDirs->getLength(); ++i) {
1379 dir = (GString *)fontDirs->get(i);
1380 for (ext = exts; *ext; ++ext) {
1381 fileName = appendToPath(dir->copy(), fontName->getCString());
1382 fileName->append(*ext);
1383 if ((f = fopen(fileName->getCString(), "rb"))) {
1395 GString *GlobalParams::getInitialZoom() {
1399 s = initialZoom->copy();
1404 GBool GlobalParams::getEnableT1lib() {
1413 GBool GlobalParams::getEnableFreeType() {
1423 GBool GlobalParams::getAntialias() {
1432 GBool GlobalParams::getMapNumericCharNames() {
1436 map = mapNumericCharNames;
1441 GBool GlobalParams::getPrintCommands() {
1450 GBool GlobalParams::getErrQuiet() {
1459 CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
1461 CharCodeToUnicode *ctu;
1464 if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) {
1465 if ((fileName = (GString *)cidToUnicodes->lookup(collection)) &&
1466 (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) {
1467 cidToUnicodeCache->add(ctu);
1474 CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) {
1475 CharCodeToUnicode *ctu;
1477 GString *fontPattern, *fileName;
1481 unicodeToUnicodes->startIter(&iter);
1482 while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) {
1483 if (strstr(fontName->getCString(), fontPattern->getCString())) {
1484 unicodeToUnicodes->killIter(&iter);
1490 if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) {
1491 if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) {
1492 unicodeToUnicodeCache->add(ctu);
1502 UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
1503 return getUnicodeMap2(encodingName);
1506 UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) {
1509 if (!(map = getResidentUnicodeMap(encodingName))) {
1510 lockUnicodeMapCache;
1511 map = unicodeMapCache->getUnicodeMap(encodingName);
1512 unlockUnicodeMapCache;
1517 CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
1521 cMap = cMapCache->getCMap(collection, cMapName);
1526 UnicodeMap *GlobalParams::getTextEncoding() {
1527 return getUnicodeMap2(textEncoding);
1530 //------------------------------------------------------------------------
1531 // functions to set parameters
1532 //------------------------------------------------------------------------
1534 void GlobalParams::addDisplayFont(DisplayFontParam *param) {
1535 DisplayFontParam *old;
1538 if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
1541 displayFonts->add(param->name, param);
1545 void GlobalParams::setPSFile(char *file) {
1550 psFile = new GString(file);
1554 GBool GlobalParams::setPSPaperSize(char *size) {
1556 if (!strcmp(size, "match")) {
1557 psPaperWidth = psPaperHeight = -1;
1558 } else if (!strcmp(size, "letter")) {
1560 psPaperHeight = 792;
1561 } else if (!strcmp(size, "legal")) {
1563 psPaperHeight = 1008;
1564 } else if (!strcmp(size, "A4")) {
1566 psPaperHeight = 842;
1567 } else if (!strcmp(size, "A3")) {
1569 psPaperHeight = 1190;
1574 psImageableLLX = psImageableLLY = 0;
1575 psImageableURX = psPaperWidth;
1576 psImageableURY = psPaperHeight;
1581 void GlobalParams::setPSPaperWidth(int width) {
1583 psPaperWidth = width;
1585 psImageableURX = psPaperWidth;
1589 void GlobalParams::setPSPaperHeight(int height) {
1591 psPaperHeight = height;
1593 psImageableURY = psPaperHeight;
1597 void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) {
1599 psImageableLLX = llx;
1600 psImageableLLY = lly;
1601 psImageableURX = urx;
1602 psImageableURY = ury;
1606 void GlobalParams::setPSCrop(GBool crop) {
1612 void GlobalParams::setPSExpandSmaller(GBool expand) {
1614 psExpandSmaller = expand;
1618 void GlobalParams::setPSShrinkLarger(GBool shrink) {
1620 psShrinkLarger = shrink;
1624 void GlobalParams::setPSCenter(GBool center) {
1630 void GlobalParams::setPSDuplex(GBool duplex) {
1636 void GlobalParams::setPSLevel(PSLevel level) {
1642 void GlobalParams::setPSEmbedType1(GBool embed) {
1644 psEmbedType1 = embed;
1648 void GlobalParams::setPSEmbedTrueType(GBool embed) {
1650 psEmbedTrueType = embed;
1654 void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
1656 psEmbedCIDPostScript = embed;
1660 void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
1662 psEmbedCIDTrueType = embed;
1666 void GlobalParams::setPSOPI(GBool opi) {
1672 void GlobalParams::setPSASCIIHex(GBool hex) {
1678 void GlobalParams::setTextEncoding(char *encodingName) {
1680 delete textEncoding;
1681 textEncoding = new GString(encodingName);
1685 GBool GlobalParams::setTextEOL(char *s) {
1687 if (!strcmp(s, "unix")) {
1689 } else if (!strcmp(s, "dos")) {
1691 } else if (!strcmp(s, "mac")) {
1701 void GlobalParams::setTextPageBreaks(GBool pageBreaks) {
1703 textPageBreaks = pageBreaks;
1707 void GlobalParams::setTextKeepTinyChars(GBool keep) {
1709 textKeepTinyChars = keep;
1713 void GlobalParams::setInitialZoom(char *s) {
1716 initialZoom = new GString(s);
1720 GBool GlobalParams::setEnableT1lib(char *s) {
1724 ok = parseYesNo2(s, &enableT1lib);
1729 GBool GlobalParams::setEnableFreeType(char *s) {
1733 ok = parseYesNo2(s, &enableFreeType);
1739 GBool GlobalParams::setAntialias(char *s) {
1743 ok = parseYesNo2(s, &antialias);
1748 void GlobalParams::setMapNumericCharNames(GBool map) {
1750 mapNumericCharNames = map;
1754 void GlobalParams::setPrintCommands(GBool printCommandsA) {
1756 printCommands = printCommandsA;
1760 void GlobalParams::setErrQuiet(GBool errQuietA) {
1762 errQuiet = errQuietA;