From 7aac8dc8533347e21311b15186e0af82f1b22fd6 Mon Sep 17 00:00:00 2001 From: Martin Kretzschmar Date: Wed, 18 Sep 2002 20:32:18 +0000 Subject: Synched with Xpdf 0.92 this adds "decryption" support testing this code after six weeks immediately gives me segfaults (image drawing) :-O must have fixed that later without knowing :-O --- (limited to 'pdf/xpdf/GfxFont.cc') diff --git a/pdf/xpdf/GfxFont.cc b/pdf/xpdf/GfxFont.cc index d93a81f..16b311b 100644 --- a/pdf/xpdf/GfxFont.cc +++ b/pdf/xpdf/GfxFont.cc @@ -29,7 +29,13 @@ #include "FontInfo.h" #if JAPANESE_SUPPORT -#include "CMapInfo.h" +#include "Japan12CMapInfo.h" +#endif +#if CHINESE_GB_SUPPORT +#include "GB12CMapInfo.h" +#endif +#if CHINESE_CNS_SUPPORT +#include "CNS13CMapInfo.h" #endif //------------------------------------------------------------------------ @@ -61,12 +67,30 @@ static Gushort *defCharWidths[12] = { GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) { BuiltinFont *builtinFont; Object obj1, obj2, obj3, obj4; + int missingWidth; + char *name2, *p; int i; // get font tag and ID tag = new GString(tag1); id = id1; + // get font type + type = fontUnknownType; + fontDict->lookup("Subtype", &obj1); + if (obj1.isName("Type1")) + type = fontType1; + else if (obj1.isName("Type1C")) + type = fontType1C; + else if (obj1.isName("Type3")) + type = fontType3; + else if (obj1.isName("TrueType")) + type = fontTrueType; + else if (obj1.isName("Type0")) + type = fontType0; + obj1.free(); + is16 = gFalse; + // get base font name name = NULL; fontDict->lookup("BaseFont", &obj1); @@ -74,6 +98,50 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) { name = new GString(obj1.getName()); obj1.free(); + // Newer Adobe tools are using Base14-compatible TrueType fonts + // without embedding them, so munge the names into the equivalent + // PostScript names. This is a kludge -- it would be nice if Adobe + // followed their own spec. + if (type == fontTrueType) { + p = name->getCString(); + name2 = NULL; + if (!strncmp(p, "Arial", 5)) { + if (!strcmp(p+5, ",Bold")) { + name2 = "Helvetica-Bold"; + } else if (!strcmp(p+5, ",Italic")) { + name2 = "Helvetica-Oblique"; + } else if (!strcmp(p+5, ",BoldItalic")) { + name2 = "Helvetica-BoldOblique"; + } else { + name2 = "Helvetica"; + } + } else if (!strncmp(p, "TimesNewRoman", 13)) { + if (!strcmp(p+13, ",Bold")) { + name2 = "Times-Bold"; + } else if (!strcmp(p+13, ",Italic")) { + name2 = "Times-Italic"; + } else if (!strcmp(p+13, ",BoldItalic")) { + name2 = "Times-BoldItalic"; + } else { + name2 = "Times-Roman"; + } + } else if (!strncmp(p, "CourierNew", 10)) { + if (!strcmp(p+10, ",Bold")) { + name2 = "Courier-Bold"; + } else if (!strcmp(p+10, ",Italic")) { + name2 = "Courier-Oblique"; + } else if (!strcmp(p+10, ",BoldItalic")) { + name2 = "Courier-BoldOblique"; + } else { + name2 = "Courier"; + } + } + if (name2) { + delete name; + name = new GString(name2); + } + } + // is it a built-in font? builtinFont = NULL; if (name) { @@ -85,35 +153,14 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) { } } - // get font type - type = fontUnknownType; - fontDict->lookup("Subtype", &obj1); - if (obj1.isName("Type1")) - type = fontType1; - else if (obj1.isName("Type1C")) - type = fontType1C; - else if (obj1.isName("Type3")) - type = fontType3; - else if (obj1.isName("TrueType")) - type = fontTrueType; - else if (obj1.isName("Type0")) - type = fontType0; - obj1.free(); - is16 = gFalse; - - // assume Times-Roman (or TimesNewRoman), but explicitly check for - // Arial and CourierNew -- certain PDF generators apparently don't - // include FontDescriptors for Arial, TimesNewRoman, and CourierNew - flags = fontSerif; // assume Times-Roman by default - if (type == fontTrueType && !name->cmp("Arial")) - flags = 0; - else if (type == fontTrueType && !name->cmp("CourierNew")) - flags = fontFixedWidth; + // assume Times-Roman by default (for substitution purposes) + flags = fontSerif; // get info from font descriptor embFontName = NULL; embFontID.num = -1; embFontID.gen = -1; + missingWidth = 0; fontDict->lookup("FontDescriptor", &obj1); if (obj1.isDict()) { @@ -165,9 +212,25 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) { } obj2.free(); } + + // look for MissingWidth + obj1.dictLookup("MissingWidth", &obj2); + if (obj2.isInt()) { + missingWidth = obj2.getInt(); + } + obj2.free(); } obj1.free(); + // get Type3 font definition + if (type == fontType3) { + fontDict->lookup("CharProcs", &charProcs); + if (!charProcs.isDict()) { + error(-1, "Missing or invalid CharProcs dictionary in Type 3 font"); + charProcs.free(); + } + } + // look for an external font file extFontFile = NULL; if (type == fontType1 && name) @@ -186,22 +249,30 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) { obj1.free(); // get encoding and character widths - if (type == fontType0) + if (type == fontType0) { getType0EncAndWidths(fontDict); - else - getEncAndWidths(fontDict, builtinFont); + } else { + getEncAndWidths(fontDict, builtinFont, missingWidth); + } } GfxFont::~GfxFont() { delete tag; - if (name) + if (name) { delete name; - if (!is16 && encoding) + } + if (!is16 && encoding) { delete encoding; - if (embFontName) + } + if (embFontName) { delete embFontName; - if (extFontFile) + } + if (extFontFile) { delete extFontFile; + } + if (charProcs.isDict()) { + charProcs.free(); + } if (is16) { gfree(widths16.exceps); gfree(widths16.excepsV); @@ -306,7 +377,17 @@ double GfxFont::getOriginY16(int c) { return vy; } -void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont) { +Object *GfxFont::getCharProc(int code, Object *proc) { + if (charProcs.isDict()) { + charProcs.dictLookup(encoding->getCharName(code), proc); + } else { + proc->initNull(); + } + return proc; +} + +void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont, + int missingWidth) { Object obj1, obj2, obj3; char *buf; int len; @@ -408,9 +489,10 @@ void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont) { // get character widths if (builtinFont) - makeWidths(fontDict, builtinFont->encoding, builtinFont->widths); + makeWidths(fontDict, builtinFont->encoding, builtinFont->widths, + missingWidth); else - makeWidths(fontDict, NULL, NULL); + makeWidths(fontDict, NULL, NULL, missingWidth); } void GfxFont::findExtFontFile() { @@ -469,6 +551,7 @@ char *GfxFont::readEmbFontFile(int *len) { error(-1, "Embedded font file is not a stream"); obj2.free(); obj1.free(); + embFontID.num = -1; return NULL; } str = obj2.getStream(); @@ -484,6 +567,7 @@ char *GfxFont::readEmbFontFile(int *len) { buf[i++] = c; } *len = i; + str->close(); obj2.free(); obj1.free(); @@ -492,7 +576,7 @@ char *GfxFont::readEmbFontFile(int *len) { } void GfxFont::makeWidths(Dict *fontDict, FontEncoding *builtinEncoding, - Gushort *builtinWidths) { + Gushort *builtinWidths, int missingWidth) { Object obj1, obj2; int firstChar, lastChar; int code, code2; @@ -501,9 +585,10 @@ void GfxFont::makeWidths(Dict *fontDict, FontEncoding *builtinEncoding, int index; double mult; - // initialize all widths to zero - for (code = 0; code < 256; ++code) - widths[code] = 0; + // initialize all widths + for (code = 0; code < 256; ++code) { + widths[code] = missingWidth * 0.001; + } // use widths from built-in font if (builtinEncoding) { @@ -580,7 +665,7 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) { goto err1; } obj1.arrayGet(0, &obj2); - if (!obj2.isDict("Font")) { + if (!obj2.isDict()) { error(-1, "Bad descendant font of Type 0 font"); goto err2; } @@ -603,6 +688,24 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) { error(-1, "Xpdf was compiled without Japanese font support"); goto err4; #endif + } else if (obj4.getString()->cmp("Adobe") == 0 && + obj5.getString()->cmp("GB1") == 0) { +#if CHINESE_GB_SUPPORT + is16 = gTrue; + enc16.charSet = font16AdobeGB12; +#else + error(-1, "Xpdf was compiled without Chinese GB font support"); + goto err4; +#endif + } else if (obj4.getString()->cmp("Adobe") == 0 && + obj5.getString()->cmp("CNS1") == 0) { +#if CHINESE_CNS_SUPPORT + is16 = gTrue; + enc16.charSet = font16AdobeCNS13; +#else + error(-1, "Xpdf was compiled without Chinese CNS font support"); + goto err4; +#endif } else { error(-1, "Uknown Type 0 character set: %s-%s", obj4.getString()->getCString(), obj5.getString()->getCString()); @@ -805,16 +908,44 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) { } #if JAPANESE_SUPPORT if (enc16.charSet == font16AdobeJapan12) { - for (i = 0; gfxFontEnc16Tab[i].name; ++i) { - if (!strcmp(obj1.getName(), gfxFontEnc16Tab[i].name)) + for (i = 0; gfxJapan12Tab[i].name; ++i) { + if (!strcmp(obj1.getName(), gfxJapan12Tab[i].name)) break; } - if (!gfxFontEnc16Tab[i].name) { + if (!gfxJapan12Tab[i].name) { error(-1, "Unknown encoding '%s' for Adobe-Japan1-2 font", obj1.getName()); goto err1; } - enc16.enc = gfxFontEnc16Tab[i].enc; + enc16.enc = gfxJapan12Tab[i].enc; + } +#endif +#if CHINESE_GB_SUPPORT + if (enc16.charSet == font16AdobeGB12) { + for (i = 0; gfxGB12Tab[i].name; ++i) { + if (!strcmp(obj1.getName(), gfxGB12Tab[i].name)) + break; + } + if (!gfxGB12Tab[i].name) { + error(-1, "Unknown encoding '%s' for Adobe-GB1-2 font", + obj1.getName()); + goto err1; + } + enc16.enc = gfxGB12Tab[i].enc; + } +#endif +#if CHINESE_CNS_SUPPORT + if (enc16.charSet == font16AdobeCNS13) { + for (i = 0; gfxCNS13Tab[i].name; ++i) { + if (!strcmp(obj1.getName(), gfxCNS13Tab[i].name)) + break; + } + if (!gfxCNS13Tab[i].name) { + error(-1, "Unknown encoding '%s' for Adobe-CNS1-3 font", + obj1.getName()); + goto err1; + } + enc16.enc = gfxCNS13Tab[i].enc; } #endif obj1.free(); @@ -832,7 +963,7 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) { obj1.free(); //~ fix this --> add 16-bit font support to FontFile encoding = new FontEncoding(); - makeWidths(fontDict, NULL, NULL); + makeWidths(fontDict, NULL, NULL, 0); } static int CDECL cmpWidthExcep(const void *w1, const void *w2) { @@ -856,7 +987,7 @@ GfxFontDict::GfxFontDict(Dict *fontDict) { for (i = 0; i < numFonts; ++i) { fontDict->getValNF(i, &obj1); obj1.fetch(&obj2); - if (obj1.isRef() && obj2.isDict("Font")) { + if (obj1.isRef() && obj2.isDict()) { fonts[i] = new GfxFont(fontDict->getKey(i), obj1.getRef(), obj2.getDict()); } else { -- cgit v0.9.1