summaryrefslogtreecommitdiff
path: root/noncore/unsupported/qpdf/xpdf/GfxFont.cc
Side-by-side diff
Diffstat (limited to 'noncore/unsupported/qpdf/xpdf/GfxFont.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/qpdf/xpdf/GfxFont.cc62
1 files changed, 51 insertions, 11 deletions
diff --git a/noncore/unsupported/qpdf/xpdf/GfxFont.cc b/noncore/unsupported/qpdf/xpdf/GfxFont.cc
index 518f97b..8d722d6 100644
--- a/noncore/unsupported/qpdf/xpdf/GfxFont.cc
+++ b/noncore/unsupported/qpdf/xpdf/GfxFont.cc
@@ -1,17 +1,17 @@
//========================================================================
//
// GfxFont.cc
//
-// Copyright 1996-2001 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@@ -445,31 +445,42 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
fontMat[0] = fontMat[3] = 1;
fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
if (fontDict->lookup("FontMatrix", &obj1)->isArray()) {
for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
if (obj1.arrayGet(i, &obj2)->isNum()) {
fontMat[i] = obj2.getNum();
}
obj2.free();
}
}
obj1.free();
- // get Type3 font definition
+ // get Type 3 bounding box, font definition, and resources
if (type == fontType3) {
- fontDict->lookup("CharProcs", &charProcs);
- if (!charProcs.isDict()) {
+ if (fontDict->lookup("FontBBox", &obj1)->isArray()) {
+ for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ fontBBox[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+ if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) {
error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
charProcs.free();
}
+ if (!fontDict->lookup("Resources", &resources)->isDict()) {
+ resources.free();
+ }
}
//----- build the font encoding -----
// Encodings start with a base encoding, which can come from
// (in order of priority):
// 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
// - MacRoman / MacExpert / WinAnsi / Standard
// 2. embedded or external font file
// 3. default:
// - builtin --> builtin encoding
// - TrueType --> MacRomanEncoding
@@ -504,41 +515,46 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
} else if (obj1.isName("MacExpertEncoding")) {
hasEncoding = gTrue;
baseEnc = macExpertEncoding;
} else if (obj1.isName("WinAnsiEncoding")) {
hasEncoding = gTrue;
baseEnc = winAnsiEncoding;
} else if (obj1.isName("StandardEncoding")) {
hasEncoding = gTrue;
baseEnc = standardEncoding;
}
// check embedded or external font file for base encoding
+ // (only for Type 1 fonts - trying to get an encoding out of a
+ // TrueType font is a losing proposition)
fontFile = NULL;
buf = NULL;
- if ((type == fontType1 || type == fontType1C || type == fontTrueType) &&
+ if ((type == fontType1 || type == fontType1C) &&
(extFontFile || embFontID.num >= 0)) {
if (extFontFile) {
buf = readExtFontFile(&len);
} else {
buf = readEmbFontFile(xref, &len);
}
if (buf) {
#if 0
+ if (type == fontType1C && !strncmp(buf, "%!", 2)) {
+ // various tools (including Adobe's) occasionally embed Type 1
+ // fonts but label them Type 1C
+ type = fontType1;
+ }
if (type == fontType1) {
fontFile = new Type1FontFile(buf, len);
- } else if (type == fontType1C) {
- fontFile = new Type1CFontFile(buf, len);
} else {
- fontFile = new TrueTypeFontFile(buf, len);
+ fontFile = new Type1CFontFile(buf, len);
}
if (fontFile->getName()) {
if (embFontName) {
delete embFontName;
}
embFontName = new GString(fontFile->getName());
}
if (!baseEnc) {
baseEnc = fontFile->getEncoding();
baseEncFromFontFile = gTrue;
}
#endif
@@ -560,24 +576,25 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
// copy the base encoding
for (i = 0; i < 256; ++i) {
enc[i] = baseEnc[i];
if ((encFree[i] = baseEncFromFontFile) && enc[i]) {
enc[i] = copyString(baseEnc[i]);
}
}
// merge differences into encoding
if (obj1.isDict()) {
obj1.dictLookup("Differences", &obj2);
if (obj2.isArray()) {
+ hasEncoding = gTrue;
code = 0;
for (i = 0; i < obj2.arrayGetLength(); ++i) {
obj2.arrayGet(i, &obj3);
if (obj3.isInt()) {
code = obj3.getInt();
} else if (obj3.isName()) {
if (code < 256) {
if (encFree[code]) {
gfree(enc[code]);
}
enc[code] = copyString(obj3.getName());
encFree[code] = gTrue;
@@ -627,44 +644,48 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
(charName[1] >= 'a' && charName[1] <= 'f') ||
(charName[1] >= 'A' && charName[1] <= 'F')))) {
hex = gTrue;
}
missing = gTrue;
}
} else {
toUnicode[code] = 0;
}
}
// pass 2: try to fill in the missing chars, looking for names of
- // the form 'Axx', 'xx', 'Ann', or 'nn', where 'A' is any letter,
- // 'xx' is two hex digits, and 'nn' is 2-4 decimal digits
+ // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B'
+ // are any letters, 'xx' is two hex digits, and 'nn' is 2-4
+ // decimal digits
if (missing && globalParams->getMapNumericCharNames()) {
for (code = 0; code < 256; ++code) {
if ((charName = enc[code]) && !toUnicode[code] &&
strcmp(charName, ".notdef")) {
n = strlen(charName);
code2 = -1;
if (hex && n == 3 && isalpha(charName[0]) &&
isxdigit(charName[1]) && isxdigit(charName[2])) {
sscanf(charName+1, "%x", &code2);
} else if (hex && n == 2 &&
isxdigit(charName[0]) && isxdigit(charName[1])) {
sscanf(charName, "%x", &code2);
} else if (!hex && n >= 2 && n <= 4 &&
isdigit(charName[0]) && isdigit(charName[1])) {
code2 = atoi(charName);
} else if (n >= 3 && n <= 5 &&
isdigit(charName[1]) && isdigit(charName[2])) {
code2 = atoi(charName+1);
+ } else if (n >= 4 && n <= 6 &&
+ isdigit(charName[2]) && isdigit(charName[3])) {
+ code2 = atoi(charName+2);
}
if (code2 >= 0 && code2 <= 0xff) {
toUnicode[code] = (Unicode)code2;
}
}
}
}
ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
}
//----- get the character widths -----
@@ -675,28 +696,32 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
}
// use widths from font dict, if present
fontDict->lookup("FirstChar", &obj1);
firstChar = obj1.isInt() ? obj1.getInt() : 0;
obj1.free();
fontDict->lookup("LastChar", &obj1);
lastChar = obj1.isInt() ? obj1.getInt() : 255;
obj1.free();
mul = (type == fontType3) ? fontMat[0] : fouble(0.001);
fontDict->lookup("Widths", &obj1);
if (obj1.isArray()) {
+ flags |= fontFixedWidth;
for (code = firstChar; code <= lastChar; ++code) {
obj1.arrayGet(code - firstChar, &obj2);
if (obj2.isNum()) {
widths[code] = obj2.getNum() * mul;
+ if (widths[code] != widths[firstChar]) {
+ flags &= ~fontFixedWidth;
+ }
}
obj2.free();
}
// use widths from built-in font
} else if (builtinFont) {
// this is a kludge for broken PDF files that encode char 32
// as .notdef
if (builtinFont->widths->getWidth("space", &w)) {
widths[32] = 0.001 * w;
}
for (code = 0; code < 256; ++code) {
@@ -743,52 +768,63 @@ Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
Gfx8BitFont::~Gfx8BitFont() {
int i;
for (i = 0; i < 256; ++i) {
if (encFree[i] && enc[i]) {
gfree(enc[i]);
}
}
ctu->decRefCnt();
if (charProcs.isDict()) {
charProcs.free();
}
+ if (resources.isDict()) {
+ resources.free();
+ }
}
int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code,
Unicode *u, int uSize, int *uLen,
fouble *dx, fouble *dy, fouble *ox, fouble *oy) {
CharCode c;
*code = c = (CharCode)(*s & 0xff);
*uLen = ctu->mapToUnicode(c, u, uSize);
*dx = widths[c];
*dy = *ox = *oy = 0;
return 1;
}
CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
ctu->incRefCnt();
return ctu;
}
+Dict *Gfx8BitFont::getCharProcs() {
+ return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
+}
+
Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
if (charProcs.isDict()) {
charProcs.dictLookup(enc[code], proc);
} else {
proc->initNull();
}
return proc;
}
+Dict *Gfx8BitFont::getResources() {
+ return resources.isDict() ? resources.getDict() : (Dict *)NULL;
+}
+
//------------------------------------------------------------------------
// GfxCIDFont
//------------------------------------------------------------------------
static int cmpWidthExcep(const void *w1, const void *w2) {
return ((GfxFontCIDWidthExcep *)w1)->first -
((GfxFontCIDWidthExcep *)w2)->first;
}
static int cmpWidthExcepV(const void *w1, const void *w2) {
return ((GfxFontCIDWidthExcepV *)w1)->first -
((GfxFontCIDWidthExcepV *)w2)->first;
@@ -1177,24 +1213,28 @@ int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
}
}
}
*dx = w;
*dy = h;
*ox = vx;
*oy = vy;
return n;
}
+int GfxCIDFont::getWMode() {
+ return cMap ? cMap->getWMode() : 0;
+}
+
CharCodeToUnicode *GfxCIDFont::getToUnicode() {
ctu->incRefCnt();
return ctu;
}
GString *GfxCIDFont::getCollection() {
return cMap ? cMap->getCollection() : (GString *)NULL;
}
//------------------------------------------------------------------------
// GfxFontDict
//------------------------------------------------------------------------
@@ -1207,25 +1247,25 @@ GfxFontDict::GfxFontDict(XRef *xref, Dict *fontDict) {
fonts = (GfxFont **)gmalloc(numFonts * sizeof(GfxFont *));
for (i = 0; i < numFonts; ++i) {
fontDict->getValNF(i, &obj1);
obj1.fetch(xref, &obj2);
if (obj1.isRef() && obj2.isDict()) {
fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
obj1.getRef(), obj2.getDict());
if (fonts[i] && !fonts[i]->isOk()) {
delete fonts[i];
fonts[i] = NULL;
}
} else {
- error(-1, "font resource is not a dictionary");
+ error(-1, "font resource is not a dictionary reference");
fonts[i] = NULL;
}
obj1.free();
obj2.free();
}
}
GfxFontDict::~GfxFontDict() {
int i;
for (i = 0; i < numFonts; ++i) {
if (fonts[i]) {