Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/pdf/xpdf/GfxFont.cc
diff options
context:
space:
mode:
authorArturo Espinosa <unammx@src.gnome.org>1999-08-06 00:14:27 (GMT)
committer Arturo Espinosa <unammx@src.gnome.org>1999-08-06 00:14:27 (GMT)
commit50e9d31c05e9ca11ad43cc570556094782c1b956 (patch)
treee8d30241d1f97d7a52ad4486089a74e55160ad78 /pdf/xpdf/GfxFont.cc
parentbd7dce23fec36adeb1713c164d594bbc0436b346 (diff)
Painful merge.
Painful merge. I merged the latest release into the CVS. This version supports the regular xpdf or gpdf if the GNOME libraries are found. Miguel.
Diffstat (limited to 'pdf/xpdf/GfxFont.cc')
-rw-r--r--pdf/xpdf/GfxFont.cc680
1 files changed, 373 insertions, 307 deletions
diff --git a/pdf/xpdf/GfxFont.cc b/pdf/xpdf/GfxFont.cc
index d1148cf..d93a81f 100644
--- a/pdf/xpdf/GfxFont.cc
+++ b/pdf/xpdf/GfxFont.cc
@@ -24,6 +24,7 @@
#include "Dict.h"
#include "Error.h"
#include "Params.h"
+#include "FontFile.h"
#include "GfxFont.h"
#include "FontInfo.h"
@@ -34,6 +35,7 @@
//------------------------------------------------------------------------
static int CDECL cmpWidthExcep(const void *w1, const void *w2);
+static int CDECL cmpWidthExcepV(const void *w1, const void *w2);
//------------------------------------------------------------------------
@@ -53,124 +55,12 @@ static Gushort *defCharWidths[12] = {
};
//------------------------------------------------------------------------
-// GfxFontEncoding
-//------------------------------------------------------------------------
-
-inline int GfxFontEncoding::hash(char *name) {
- int h;
-
- h = name[0];
- if (name[1])
- h = h * 61 + name[1];
- return h % gfxFontEncHashSize;
-}
-
-GfxFontEncoding::GfxFontEncoding() {
- int i;
-
- encoding = (char **)gmalloc(256 * sizeof(char *));
- freeEnc = gTrue;
- for (i = 0; i < 256; ++i)
- encoding[i] = NULL;
- for (i = 0; i < gfxFontEncHashSize; ++i)
- hashTab[i] = -1;
-}
-
-GfxFontEncoding::GfxFontEncoding(char **encoding1, int encSize) {
- int i;
-
- encoding = encoding1;
- freeEnc = gFalse;
- for (i = 0; i < gfxFontEncHashSize; ++i)
- hashTab[i] = -1;
- for (i = 0; i < encSize; ++i) {
- if (encoding[i])
- addChar1(i, encoding[i]);
- }
-}
-
-void GfxFontEncoding::addChar(int code, char *name) {
- int h, i;
-
- // replace character associated with code
- if (encoding[code]) {
- h = hash(encoding[code]);
- for (i = 0; i < gfxFontEncHashSize; ++i) {
- if (hashTab[h] == code) {
- hashTab[h] = -2;
- break;
- }
- if (++h == gfxFontEncHashSize)
- h = 0;
- }
- gfree(encoding[code]);
- }
-
- // associate name with code
- encoding[code] = name;
-
- // insert name in hash table
- addChar1(code, name);
-}
-
-void GfxFontEncoding::addChar1(int code, char *name) {
- int h, i, code2;
-
- // insert name in hash table
- h = hash(name);
- for (i = 0; i < gfxFontEncHashSize; ++i) {
- code2 = hashTab[h];
- if (code2 < 0) {
- hashTab[h] = code;
- break;
- } else if (encoding[code2] && !strcmp(encoding[code2], name)) {
- // keep the highest code for each char -- this is needed because
- // X won't display chars with codes < 32
- if (code > code2)
- hashTab[h] = code;
- break;
- }
- if (++h == gfxFontEncHashSize)
- h = 0;
- }
-}
-
-GfxFontEncoding::~GfxFontEncoding() {
- int i;
-
- if (freeEnc) {
- for (i = 0; i < 256; ++i) {
- if (encoding[i])
- gfree(encoding[i]);
- }
- gfree(encoding);
- }
-}
-
-int GfxFontEncoding::getCharCode(char *name) {
- int h, i, code;
-
- h = hash(name);
- for (i = 0; i < gfxFontEncHashSize; ++i) {
- code = hashTab[h];
- if (code == -1 ||
- (code > 0 && encoding[code] && !strcmp(encoding[code], name)))
- return code;
- if (++h >= gfxFontEncHashSize)
- h = 0;
- }
- return -1;
-}
-
-//------------------------------------------------------------------------
// GfxFont
//------------------------------------------------------------------------
GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) {
BuiltinFont *builtinFont;
- char buf[256];
- Object obj1, obj2, obj3;
- char *p1, *p2;
+ Object obj1, obj2, obj3, obj4;
int i;
// get font tag and ID
@@ -200,6 +90,8 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) {
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"))
@@ -209,75 +101,78 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) {
obj1.free();
is16 = gFalse;
- // get info from font descriptor
- // for flags: 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
+ // 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;
+
+ // get info from font descriptor
+ embFontName = NULL;
embFontID.num = -1;
embFontID.gen = -1;
- embFontName = NULL;
- extFontFile = NULL;
fontDict->lookup("FontDescriptor", &obj1);
if (obj1.isDict()) {
- // flags
+ // get flags
obj1.dictLookup("Flags", &obj2);
if (obj2.isInt())
flags = obj2.getInt();
obj2.free();
- // embedded Type 1 font file and font name
+ // get name
+ obj1.dictLookup("FontName", &obj2);
+ if (obj2.isName())
+ embFontName = new GString(obj2.getName());
+ obj2.free();
+
+ // look for embedded font file
if (type == fontType1) {
obj1.dictLookupNF("FontFile", &obj2);
+ if (obj2.isRef())
+ embFontID = obj2.getRef();
+ obj2.free();
+ }
+ if (embFontID.num == -1 && type == fontTrueType) {
+ obj1.dictLookupNF("FontFile2", &obj2);
+ if (obj2.isRef())
+ embFontID = obj2.getRef();
+ obj2.free();
+ }
+ if (embFontID.num == -1) {
+ obj1.dictLookupNF("FontFile3", &obj2);
if (obj2.isRef()) {
embFontID = obj2.getRef();
-
- // get font name from the font file itself since font subsets
- // sometimes use the 'AAAAAA+foo' name and sometimes use just 'foo'
obj2.fetch(&obj3);
if (obj3.isStream()) {
- obj3.streamReset();
- for (i = 0; i < 64; ++i) {
- obj3.streamGetLine(buf, sizeof(buf));
- if (!strncmp(buf, "/FontName", 9)) {
- if ((p1 = strchr(buf+9, '/'))) {
- ++p1;
- for (p2 = p1; *p2 && !isspace(*p2); ++p2) ;
- embFontName = new GString(p1, p2 - p1);
- }
- break;
- }
- }
+ obj3.streamGetDict()->lookup("Subtype", &obj4);
+ if (obj4.isName("Type1"))
+ type = fontType1;
+ else if (obj4.isName("Type1C"))
+ type = fontType1C;
+ else if (obj4.isName("Type3"))
+ type = fontType3;
+ else if (obj4.isName("TrueType"))
+ type = fontTrueType;
+ else if (obj4.isName("Type0"))
+ type = fontType0;
+ obj4.free();
}
obj3.free();
- obj2.free();
-
- // couldn't find font name so just use the one in the PDF font
- // descriptor
- if (!embFontName) {
- obj1.dictLookup("FontName", &obj2);
- if (obj2.isName())
- embFontName = new GString(obj2.getName());
- }
}
obj2.free();
-
- // embedded TrueType font file
- } else if (type == fontTrueType) {
- obj1.dictLookupNF("FontFile2", &obj2);
- if (obj2.isRef())
- embFontID = obj2.getRef();
- obj2.free();
}
}
obj1.free();
+ // look for an external font file
+ extFontFile = NULL;
+ if (type == fontType1 && name)
+ findExtFontFile();
+
// get font matrix
fontMat[0] = fontMat[3] = 1;
fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
@@ -291,15 +186,10 @@ GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) {
obj1.free();
// get encoding and character widths
- if (type == fontType0) {
+ if (type == fontType0)
getType0EncAndWidths(fontDict);
- } else if (builtinFont) {
- makeEncoding(fontDict, builtinFont->encoding);
- makeWidths(fontDict, builtinFont->encoding, builtinFont->widths);
- } else {
- makeEncoding(fontDict, NULL);
- makeWidths(fontDict, NULL, NULL);
- }
+ else
+ getEncAndWidths(fontDict, builtinFont);
}
GfxFont::~GfxFont() {
@@ -312,8 +202,10 @@ GfxFont::~GfxFont() {
delete embFontName;
if (extFontFile)
delete extFontFile;
- if (is16)
+ if (is16) {
gfree(widths16.exceps);
+ gfree(widths16.excepsV);
+ }
}
double GfxFont::getWidth(GString *s) {
@@ -348,36 +240,150 @@ double GfxFont::getWidth16(int c) {
return w;
}
-double GfxFont::getWidth16(GString *s) {
- double w;
- int c;
- int i;
+double GfxFont::getHeight16(int c) {
+ double h;
+ int a, b, m;
- w = 0;
- for (i = 0; i < s->getLength(); i += 2) {
- c = (s->getChar(i) << 8) + s->getChar(i+1);
- w += getWidth16(c);
+ h = widths16.defHeight;
+ a = -1;
+ b = widths16.numExcepsV;
+ // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (widths16.excepsV[m].last < c) {
+ a = m;
+ } else if (c < widths16.excepsV[m].first) {
+ b = m;
+ } else {
+ h = widths16.excepsV[m].height;
+ break;
+ }
}
- return w;
+ return h;
}
-void GfxFont::makeEncoding(Dict *fontDict, GfxFontEncoding *builtinEncoding) {
- GfxFontEncoding *baseEnc;
+double GfxFont::getOriginX16(int c) {
+ double vx;
+ int a, b, m;
+
+ vx = widths16.defWidth / 2;
+ a = -1;
+ b = widths16.numExcepsV;
+ // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (widths16.excepsV[m].last < c) {
+ a = m;
+ } else if (c < widths16.excepsV[m].first) {
+ b = m;
+ } else {
+ vx = widths16.excepsV[m].vx;
+ break;
+ }
+ }
+ return vx;
+}
+
+double GfxFont::getOriginY16(int c) {
+ double vy;
+ int a, b, m;
+
+ vy = widths16.defVY;
+ a = -1;
+ b = widths16.numExcepsV;
+ // invariant: widths16.excepsV[a].last < c < widths16.excepsV[b].first
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (widths16.excepsV[m].last < c) {
+ a = m;
+ } else if (c < widths16.excepsV[m].first) {
+ b = m;
+ } else {
+ vy = widths16.excepsV[m].vy;
+ break;
+ }
+ }
+ return vy;
+}
+
+void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont) {
Object obj1, obj2, obj3;
- char *charName;
+ char *buf;
+ int len;
+ FontFile *fontFile;
int code, i;
- // start with empty encoding
- encoding = new GfxFontEncoding();
-
- // get encoding from font dict
+ // Encodings start with a base encoding, which can come from
+ // (in order of priority):
+ // 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
+ // - MacRoman / WinAnsi / Standard
+ // 2. embedded font file
+ // 3. default:
+ // - builtin --> builtin encoding
+ // - TrueType --> MacRomanEncoding
+ // - others --> StandardEncoding
+ // and then add a list of differences from
+ // FontDict.Encoding.Differences.
+
+ // check FontDict for base encoding
+ encoding = NULL;
fontDict->lookup("Encoding", &obj1);
-
- // encoding specified by dictionary
if (obj1.isDict()) {
obj1.dictLookup("BaseEncoding", &obj2);
- baseEnc = makeEncoding1(obj2, fontDict, builtinEncoding);
+ if (obj2.isName("MacRomanEncoding")) {
+ encoding = macRomanEncoding.copy();
+ } else if (obj2.isName("WinAnsiEncoding")) {
+ encoding = winAnsiEncoding.copy();
+ } else if (obj2.isName("StandardEncoding")) {
+ encoding = standardEncoding.copy();
+ }
obj2.free();
+ } else if (obj1.isName("MacRomanEncoding")) {
+ encoding = macRomanEncoding.copy();
+ } else if (obj1.isName("WinAnsiEncoding")) {
+ encoding = winAnsiEncoding.copy();
+ } else if (obj1.isName("StandardEncoding")) {
+ encoding = standardEncoding.copy();
+ }
+ obj1.free();
+
+ // check embedded or external font file for base encoding
+ if ((type == fontType1 || type == fontType1C) &&
+ (extFontFile || embFontID.num >= 0)) {
+ if (extFontFile)
+ buf = readExtFontFile(&len);
+ else
+ buf = readEmbFontFile(&len);
+ if (buf) {
+ if (type == fontType1)
+ fontFile = new Type1FontFile(buf, len);
+ else
+ fontFile = new Type1CFontFile(buf, len);
+ if (fontFile->getName()) {
+ if (embFontName)
+ delete embFontName;
+ embFontName = new GString(fontFile->getName());
+ }
+ if (!encoding)
+ encoding = fontFile->getEncoding(gTrue);
+ delete fontFile;
+ gfree(buf);
+ }
+ }
+
+ // get default base encoding
+ if (!encoding) {
+ if (builtinFont)
+ encoding = builtinFont->encoding->copy();
+ else if (type == fontTrueType)
+ encoding = macRomanEncoding.copy();
+ else
+ encoding = standardEncoding.copy();
+ }
+
+ // merge differences into encoding
+ fontDict->lookup("Encoding", &obj1);
+ if (obj1.isDict()) {
obj1.dictLookup("Differences", &obj2);
if (obj2.isArray()) {
code = 0;
@@ -397,149 +403,95 @@ void GfxFont::makeEncoding(Dict *fontDict, GfxFontEncoding *builtinEncoding) {
}
}
obj2.free();
-
- // encoding specified by name or null
- } else {
- baseEnc = makeEncoding1(obj1, fontDict, builtinEncoding);
}
-
- // free the font dict encoding
obj1.free();
- // merge base encoding and differences;
- for (code = 0; code < 256; ++code) {
- if (!encoding->getCharName(code)) {
- if ((charName = baseEnc->getCharName(code)))
- encoding->addChar(code, copyString(charName));
- }
- }
+ // get character widths
+ if (builtinFont)
+ makeWidths(fontDict, builtinFont->encoding, builtinFont->widths);
+ else
+ makeWidths(fontDict, NULL, NULL);
}
-GfxFontEncoding *GfxFont::makeEncoding1(Object obj, Dict *fontDict,
- GfxFontEncoding *builtinEncoding) {
- GfxFontEncoding *enc;
- GBool haveEncoding;
- Object obj1, obj2;
+void GfxFont::findExtFontFile() {
char **path;
FILE *f;
- FileStream *str;
-
- // MacRoman, WinAnsi, or Standard encoding
- if (obj.isName("MacRomanEncoding")) {
- enc = &macRomanEncoding;
- } else if (obj.isName("WinAnsiEncoding")) {
- enc = &winAnsiEncoding;
- } else if (obj.isName("StandardEncoding")) {
- enc = &standardEncoding;
-
- // use the built-in font encoding if possible
- } else if (builtinEncoding) {
- enc = builtinEncoding;
-
- // check font type
- } else {
-
- // Type 1 font: try to get encoding from font file
- if (type == fontType1) {
-
- // default to using standard encoding
- enc = &standardEncoding;
-
- // is there an external font file?
- haveEncoding = gFalse;
- if (name) {
- for (path = fontPath; *path; ++path) {
- extFontFile = appendToPath(new GString(*path), name->getCString());
- f = fopen(extFontFile->getCString(), "rb");
- if (!f) {
- extFontFile->append(".pfb");
- f = fopen(extFontFile->getCString(), "rb");
- }
- if (!f) {
- extFontFile->del(extFontFile->getLength() - 4, 4);
- extFontFile->append(".pfa");
- f = fopen(extFontFile->getCString(), "rb");
- }
- if (f) {
- obj1.initNull();
- str = new FileStream(f, 0, -1, &obj1);
- getType1Encoding(str);
- delete str;
- fclose(f);
- haveEncoding = gTrue;
- break;
- }
- delete extFontFile;
- extFontFile = NULL;
- }
- }
- // is there an embedded font file?
- // (this has to be checked after the external font because
- // XOutputDev needs the encoding from the external font)
- if (!haveEncoding && embFontID.num >= 0) {
- obj1.initRef(embFontID.num, embFontID.gen);
- obj1.fetch(&obj2);
- if (obj2.isStream())
- getType1Encoding(obj2.getStream());
- obj2.free();
- obj1.free();
- }
-
- // TrueType font: use Mac encoding
- } else if (type == fontTrueType) {
- enc = &macRomanEncoding;
-
- // not Type 1 or TrueType: just use the standard encoding
- } else {
- enc = &standardEncoding;
+ for (path = fontPath; *path; ++path) {
+ extFontFile = appendToPath(new GString(*path), name->getCString());
+ f = fopen(extFontFile->getCString(), "rb");
+ if (!f) {
+ extFontFile->append(".pfb");
+ f = fopen(extFontFile->getCString(), "rb");
+ }
+ if (!f) {
+ extFontFile->del(extFontFile->getLength() - 4, 4);
+ extFontFile->append(".pfa");
+ f = fopen(extFontFile->getCString(), "rb");
}
+ if (f) {
+ fclose(f);
+ break;
+ }
+ delete extFontFile;
+ extFontFile = NULL;
}
+}
+
+char *GfxFont::readExtFontFile(int *len) {
+ FILE *f;
+ char *buf;
- return enc;
+ if (!(f = fopen(extFontFile->getCString(), "rb"))) {
+ error(-1, "Internal: external font file '%s' vanished", extFontFile);
+ return NULL;
+ }
+ fseek(f, 0, SEEK_END);
+ *len = (int)ftell(f);
+ fseek(f, 0, SEEK_SET);
+ buf = (char *)gmalloc(*len);
+ if ((int)fread(buf, 1, *len, f) != *len)
+ error(-1, "Error reading external font file '%s'", extFontFile);
+ fclose(f);
+ return buf;
}
-void GfxFont::getType1Encoding(Stream *str) {
- char buf[256];
- char *p;
- GBool found;
- int code, i;
+char *GfxFont::readEmbFontFile(int *len) {
+ char *buf;
+ Object obj1, obj2;
+ Stream *str;
+ int c;
+ int size, i;
- // look for encoding in font file
- str->reset();
- found = gFalse;
- for (i = 0; i < 100; ++i) {
- if (!str->getLine(buf, sizeof(buf)))
- break;
- if (!strncmp(buf, "/Encoding StandardEncoding def", 30))
- break;
- if (!strncmp(buf, "/Encoding 256 array", 19)) {
- found = gTrue;
- break;
- }
+ obj1.initRef(embFontID.num, embFontID.gen);
+ obj1.fetch(&obj2);
+ if (!obj2.isStream()) {
+ error(-1, "Embedded font file is not a stream");
+ obj2.free();
+ obj1.free();
+ return NULL;
}
+ str = obj2.getStream();
- // found the encoding, grab it
- if (found) {
- for (i = 0; i < 300; ++i) {
- if (!str->getLine(buf, sizeof(buf)))
- break;
- p = strtok(buf, " \t");
- if (p && !strcmp(p, "dup")) {
- if ((p = strtok(NULL, " \t"))) {
- code = atoi(p);
- if ((p = strtok(NULL, " \t"))) {
- if (p[0] == '/')
- encoding->addChar(code, copyString(p+1));
- }
- }
- }
+ buf = NULL;
+ i = size = 0;
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ if (i == size) {
+ size += 4096;
+ buf = (char *)grealloc(buf, size);
}
- //~ look for getinterval/putinterval junk
+ buf[i++] = c;
}
+ *len = i;
+
+ obj2.free();
+ obj1.free();
+
+ return buf;
}
-void GfxFont::makeWidths(Dict *fontDict, GfxFontEncoding *builtinEncoding,
+void GfxFont::makeWidths(Dict *fontDict, FontEncoding *builtinEncoding,
Gushort *builtinWidths) {
Object obj1, obj2;
int firstChar, lastChar;
@@ -585,7 +537,7 @@ void GfxFont::makeWidths(Dict *fontDict, GfxFontEncoding *builtinEncoding,
} else {
// couldn't find widths -- use defaults
-#if 0
+#if 0 //~
//~ certain PDF generators apparently don't include widths
//~ for Arial and TimesNewRoman -- and this error message
//~ is a nuisance
@@ -614,10 +566,14 @@ void GfxFont::makeWidths(Dict *fontDict, GfxFontEncoding *builtinEncoding,
}
void GfxFont::getType0EncAndWidths(Dict *fontDict) {
- Object obj1, obj2, obj3, obj4, obj5, obj6;
+ Object obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8;
int excepsSize;
int i, j, k, n;
+ widths16.exceps = NULL;
+ widths16.excepsV = NULL;
+
+ // get the CIDFont
fontDict->lookup("DescendantFonts", &obj1);
if (!obj1.isArray() || obj1.arrayGetLength() != 1) {
error(-1, "Bad DescendantFonts entry for Type 0 font");
@@ -629,6 +585,7 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
goto err2;
}
+ // get font info
obj2.dictLookup("CIDSystemInfo", &obj3);
if (!obj3.isDict()) {
error(-1, "Bad CIDSystemInfo in Type 0 font descendant");
@@ -659,6 +616,7 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
obj4.free();
obj3.free();
+ // get default char width
obj2.dictLookup("DW", &obj3);
if (obj3.isInt())
widths16.defWidth = obj3.getInt() * 0.001;
@@ -666,6 +624,25 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
widths16.defWidth = 1.0;
obj3.free();
+ // get default char metrics for vertical font
+ obj2.dictLookup("DW2", &obj3);
+ widths16.defVY = 0.880;
+ widths16.defHeight = -1;
+ if (obj3.isArray() && obj3.arrayGetLength() == 2) {
+ obj3.arrayGet(0, &obj4);
+ if (obj4.isInt()) {
+ widths16.defVY = obj4.getInt() * 0.001;
+ }
+ obj4.free();
+ obj3.arrayGet(1, &obj4);
+ if (obj4.isInt()) {
+ widths16.defHeight = obj4.getInt() * 0.001;
+ }
+ obj4.free();
+ }
+ obj3.free();
+
+ // get char width exceptions
widths16.exceps = NULL;
widths16.numExceps = 0;
obj2.dictLookup("W", &obj3);
@@ -734,9 +711,93 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
}
obj3.free();
+ // get char metric exceptions for vertical font
+ widths16.excepsV = NULL;
+ widths16.numExcepsV = 0;
+ obj2.dictLookup("W2", &obj3);
+ if (obj3.isArray()) {
+ excepsSize = 0;
+ k = 0;
+ i = 0;
+ while (i+1 < obj3.arrayGetLength()) {
+ obj3.arrayGet(i, &obj4);
+ obj3.arrayGet(i+1, &obj5);
+ if (obj4.isInt() && obj5.isInt()) {
+ obj3.arrayGet(i+2, &obj6);
+ obj3.arrayGet(i+3, &obj7);
+ obj3.arrayGet(i+4, &obj8);
+ if (!obj6.isNum() || !obj7.isNum() || !obj8.isNum()) {
+ error(-1, "Bad widths (W2) array in Type 0 font");
+ obj8.free();
+ obj7.free();
+ obj6.free();
+ obj5.free();
+ obj4.free();
+ break;
+ }
+ if (k == excepsSize) {
+ excepsSize += 16;
+ widths16.excepsV = (GfxFontWidthExcepV *)
+ grealloc(widths16.excepsV,
+ excepsSize * sizeof(GfxFontWidthExcepV));
+ }
+ widths16.excepsV[k].first = obj4.getInt();
+ widths16.excepsV[k].last = obj5.getInt();
+ widths16.excepsV[k].height = obj6.getNum() * 0.001;
+ widths16.excepsV[k].vx = obj7.getNum() * 0.001;
+ widths16.excepsV[k].vy = obj8.getNum() * 0.001;
+ obj8.free();
+ obj7.free();
+ obj6.free();
+ ++k;
+ i += 5;
+ } else if (obj4.isInt() && obj5.isArray()) {
+ if (k + obj5.arrayGetLength() / 3 >= excepsSize) {
+ excepsSize = (k + obj5.arrayGetLength() / 3 + 15) & ~15;
+ widths16.excepsV = (GfxFontWidthExcepV *)
+ grealloc(widths16.excepsV,
+ excepsSize * sizeof(GfxFontWidthExcepV));
+ }
+ n = obj4.getInt();
+ for (j = 0; j < obj5.arrayGetLength(); j += 3) {
+ obj5.arrayGet(j, &obj6);
+ obj5.arrayGet(j+1, &obj7);
+ obj5.arrayGet(j+1, &obj8);
+ if (!obj6.isNum() || !obj7.isNum() || !obj8.isNum()) {
+ error(-1, "Bad widths (W2) array in Type 0 font");
+ obj6.free();
+ break;
+ }
+ widths16.excepsV[k].first = widths16.exceps[k].last = n++;
+ widths16.excepsV[k].height = obj6.getNum() * 0.001;
+ widths16.excepsV[k].vx = obj7.getNum() * 0.001;
+ widths16.excepsV[k].vy = obj8.getNum() * 0.001;
+ obj8.free();
+ obj7.free();
+ obj6.free();
+ ++k;
+ }
+ i += 2;
+ } else {
+ error(-1, "Bad widths array in Type 0 font");
+ obj5.free();
+ obj4.free();
+ break;
+ }
+ obj5.free();
+ obj4.free();
+ }
+ widths16.numExcepsV = k;
+ if (k > 0) {
+ qsort(widths16.excepsV, k, sizeof(GfxFontWidthExcepV), &cmpWidthExcepV);
+ }
+ }
+ obj3.free();
+
obj2.free();
obj1.free();
+ // get encoding (CMap)
fontDict->lookup("Encoding", &obj1);
if (!obj1.isName()) {
error(-1, "Bad encoding for Type 0 font");
@@ -769,7 +830,8 @@ void GfxFont::getType0EncAndWidths(Dict *fontDict) {
obj2.free();
err1:
obj1.free();
- makeEncoding(fontDict, NULL);
+ //~ fix this --> add 16-bit font support to FontFile
+ encoding = new FontEncoding();
makeWidths(fontDict, NULL, NULL);
}
@@ -777,6 +839,10 @@ static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
return ((GfxFontWidthExcep *)w1)->first - ((GfxFontWidthExcep *)w2)->first;
}
+static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
+ return ((GfxFontWidthExcepV *)w1)->first - ((GfxFontWidthExcepV *)w2)->first;
+}
+
//------------------------------------------------------------------------
// GfxFontDict
//------------------------------------------------------------------------