GfxFont.cc (xpdf-4.03) | : | GfxFont.cc (xpdf-4.04) | ||
---|---|---|---|---|
skipping to change at line 201 | skipping to change at line 201 | |||
font = new Gfx8BitFont(xref, tagA, idA, nameA, typeA, embFontIDA, | font = new Gfx8BitFont(xref, tagA, idA, nameA, typeA, embFontIDA, | |||
fontDict); | fontDict); | |||
} else { | } else { | |||
font = new GfxCIDFont(xref, tagA, idA, nameA, typeA, embFontIDA, | font = new GfxCIDFont(xref, tagA, idA, nameA, typeA, embFontIDA, | |||
fontDict); | fontDict); | |||
} | } | |||
return font; | return font; | |||
} | } | |||
GfxFont *GfxFont::makeDefaultFont(XRef *xref) { | ||||
Object type, subtype, baseFont; | ||||
type.initName("Font"); | ||||
subtype.initName("Type1"); | ||||
baseFont.initName("Helvetica"); | ||||
Object fontDict; | ||||
fontDict.initDict(xref); | ||||
fontDict.dictAdd(copyString("Type"), &type); | ||||
fontDict.dictAdd(copyString("Subtype"), &subtype); | ||||
fontDict.dictAdd(copyString("BaseFont"), &baseFont); | ||||
Ref r; | ||||
r.gen = 100000; | ||||
r.num = GfxFontDict::hashFontObject(&fontDict); | ||||
GfxFont *font = makeFont(xref, "undef", r, fontDict.getDict()); | ||||
fontDict.free(); | ||||
return font; | ||||
} | ||||
GfxFont::GfxFont(const char *tagA, Ref idA, GString *nameA, | GfxFont::GfxFont(const char *tagA, Ref idA, GString *nameA, | |||
GfxFontType typeA, Ref embFontIDA) { | GfxFontType typeA, Ref embFontIDA) { | |||
ok = gFalse; | ok = gFalse; | |||
tag = new GString(tagA); | tag = new GString(tagA); | |||
id = idA; | id = idA; | |||
name = nameA; | name = nameA; | |||
type = typeA; | type = typeA; | |||
embFontID = embFontIDA; | embFontID = embFontIDA; | |||
embFontName = NULL; | embFontName = NULL; | |||
hasToUnicode = gFalse; | hasToUnicode = gFalse; | |||
skipping to change at line 1704 | skipping to change at line 1725 | |||
if (!obj2.isString() || !obj3.isString()) { | if (!obj2.isString() || !obj3.isString()) { | |||
error(errSyntaxError, -1, | error(errSyntaxError, -1, | |||
"Invalid CIDSystemInfo dictionary in Type 0 descendant font"); | "Invalid CIDSystemInfo dictionary in Type 0 descendant font"); | |||
goto err3; | goto err3; | |||
} | } | |||
collection = obj2.getString()->copy()->append('-')->append(obj3.getString()); | collection = obj2.getString()->copy()->append('-')->append(obj3.getString()); | |||
obj3.free(); | obj3.free(); | |||
obj2.free(); | obj2.free(); | |||
obj1.free(); | obj1.free(); | |||
// encoding (i.e., CMap) | ||||
if (fontDict->lookup("Encoding", &obj1)->isNull()) { | ||||
error(errSyntaxError, -1, "Missing Encoding entry in Type 0 font"); | ||||
goto err2; | ||||
} | ||||
if (!(cMap = CMap::parse(NULL, collection, &obj1))) { | ||||
goto err2; | ||||
} | ||||
// check for fonts that use the Identity-H encoding (cmap), and the | ||||
// Adobe-Identity character collection | ||||
identityEnc = obj1.isName("Identity-H") && | ||||
!collection->cmp("Adobe-Identity"); | ||||
obj1.free(); | ||||
// CIDToGIDMap | ||||
// (the PDF 1.7 spec only allows these for TrueType fonts, but | ||||
// Acrobat apparently also allows them for OpenType CFF fonts -- and | ||||
// the PDF 2.0 spec has removed the prohibition) | ||||
hasIdentityCIDToGID = gFalse; | ||||
desFontDict->lookup("CIDToGIDMap", &obj1); | ||||
if (obj1.isStream()) { | ||||
cidToGIDLen = 0; | ||||
i = 64; | ||||
cidToGID = (int *)gmallocn(i, sizeof(int)); | ||||
obj1.streamReset(); | ||||
while ((c1 = obj1.streamGetChar()) != EOF && | ||||
(c2 = obj1.streamGetChar()) != EOF) { | ||||
if (cidToGIDLen == i) { | ||||
i *= 2; | ||||
cidToGID = (int *)greallocn(cidToGID, i, sizeof(int)); | ||||
} | ||||
cidToGID[cidToGIDLen++] = (c1 << 8) + c2; | ||||
} | ||||
obj1.streamClose(); | ||||
identityEnc = gFalse; | ||||
} else if (obj1.isName("Identity")) { | ||||
hasIdentityCIDToGID = gTrue; | ||||
} else if (!obj1.isNull()) { | ||||
error(errSyntaxError, -1, "Invalid CIDToGIDMap entry in CID font"); | ||||
} | ||||
obj1.free(); | ||||
// look for a ToUnicode CMap | // look for a ToUnicode CMap | |||
hasKnownCollection = gFalse; | hasKnownCollection = gFalse; | |||
if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) { | if (globalParams->getUseTrueTypeUnicodeMapping()) { | |||
readTrueTypeUnicodeMapping(xref); | ||||
} | ||||
if (!ctu) { | ||||
ctu = readToUnicodeCMap(fontDict, 16, NULL); | ||||
} | ||||
if (!ctu) { | ||||
ctuUsesCharCode = gFalse; | ctuUsesCharCode = gFalse; | |||
// use an identity mapping for the "Adobe-Identity" and | // use an identity mapping for the "Adobe-Identity" and | |||
// "Adobe-UCS" collections | // "Adobe-UCS" collections | |||
if (!collection->cmp("Adobe-Identity") || | if (!collection->cmp("Adobe-Identity") || | |||
!collection->cmp("Adobe-UCS")) { | !collection->cmp("Adobe-UCS")) { | |||
ctu = CharCodeToUnicode::makeIdentityMapping(); | ctu = CharCodeToUnicode::makeIdentityMapping(); | |||
// look for a user-supplied .cidToUnicode file | // look for a user-supplied .cidToUnicode file | |||
} else if ((ctu = globalParams->getCIDToUnicode(collection))) { | } else if ((ctu = globalParams->getCIDToUnicode(collection))) { | |||
skipping to change at line 1751 | skipping to change at line 1822 | |||
} | } | |||
} | } | |||
} | } | |||
utu->decRefCnt(); | utu->decRefCnt(); | |||
} | } | |||
} else { | } else { | |||
ctu = utu; | ctu = utu; | |||
} | } | |||
} | } | |||
// encoding (i.e., CMap) | ||||
if (fontDict->lookup("Encoding", &obj1)->isNull()) { | ||||
error(errSyntaxError, -1, "Missing Encoding entry in Type 0 font"); | ||||
goto err2; | ||||
} | ||||
if (!(cMap = CMap::parse(NULL, collection, &obj1))) { | ||||
goto err2; | ||||
} | ||||
// check for fonts that use the Identity-H encoding (cmap), and the | ||||
// Adobe-Identity character collection | ||||
identityEnc = obj1.isName("Identity-H") && | ||||
!collection->cmp("Adobe-Identity"); | ||||
obj1.free(); | ||||
// CIDToGIDMap | ||||
// (the PDF 1.7 spec only allows these for TrueType fonts, but | ||||
// Acrobat apparently also allows them for OpenType CFF fonts -- and | ||||
// the PDF 2.0 spec has removed the prohibition) | ||||
hasIdentityCIDToGID = gFalse; | ||||
desFontDict->lookup("CIDToGIDMap", &obj1); | ||||
if (obj1.isStream()) { | ||||
cidToGIDLen = 0; | ||||
i = 64; | ||||
cidToGID = (int *)gmallocn(i, sizeof(int)); | ||||
obj1.streamReset(); | ||||
while ((c1 = obj1.streamGetChar()) != EOF && | ||||
(c2 = obj1.streamGetChar()) != EOF) { | ||||
if (cidToGIDLen == i) { | ||||
i *= 2; | ||||
cidToGID = (int *)greallocn(cidToGID, i, sizeof(int)); | ||||
} | ||||
cidToGID[cidToGIDLen++] = (c1 << 8) + c2; | ||||
} | ||||
obj1.streamClose(); | ||||
identityEnc = gFalse; | ||||
} else if (obj1.isName("Identity")) { | ||||
hasIdentityCIDToGID = gTrue; | ||||
} else if (!obj1.isNull()) { | ||||
error(errSyntaxError, -1, "Invalid CIDToGIDMap entry in CID font"); | ||||
} | ||||
obj1.free(); | ||||
//----- character metrics ----- | //----- character metrics ----- | |||
// default char width | // default char width | |||
if (desFontDict->lookup("DW", &obj1)->isInt()) { | if (desFontDict->lookup("DW", &obj1)->isNum()) { | |||
widths.defWidth = obj1.getInt() * 0.001; | widths.defWidth = obj1.getNum() * 0.001; | |||
} | } | |||
obj1.free(); | obj1.free(); | |||
// char width exceptions | // char width exceptions | |||
if (desFontDict->lookup("W", &obj1)->isArray()) { | if (desFontDict->lookup("W", &obj1)->isArray()) { | |||
excepsSize = 0; | excepsSize = 0; | |||
i = 0; | i = 0; | |||
while (i + 1 < obj1.arrayGetLength()) { | while (i + 1 < obj1.arrayGetLength()) { | |||
obj1.arrayGet(i, &obj2); | obj1.arrayGet(i, &obj2); | |||
obj1.arrayGet(i + 1, &obj3); | obj1.arrayGet(i + 1, &obj3); | |||
skipping to change at line 1971 | skipping to change at line 1998 | |||
if (ctu) { | if (ctu) { | |||
ctu->decRefCnt(); | ctu->decRefCnt(); | |||
} | } | |||
gfree(widths.exceps); | gfree(widths.exceps); | |||
gfree(widths.excepsV); | gfree(widths.excepsV); | |||
if (cidToGID) { | if (cidToGID) { | |||
gfree(cidToGID); | gfree(cidToGID); | |||
} | } | |||
} | } | |||
// Construct a code-to-Unicode mapping, based on the TrueType Unicode | ||||
// cmap (if present). Constructs ctu if succesful; leaves ctu = null | ||||
// otherwise. Always leaves ctu = null for non-TrueType fonts. | ||||
void GfxCIDFont::readTrueTypeUnicodeMapping(XRef *xref) { | ||||
char *buf; | ||||
FoFiTrueType *ff; | ||||
Unicode *gidToUnicode, *codeToUnicode; | ||||
Unicode u; | ||||
int bufLen, cmapPlatform, cmapEncoding, unicodeCmap; | ||||
int nGlyphs, nMappings, gid, i; | ||||
// must be an embedded TrueType font, with an unknown char collection | ||||
if ((type != fontCIDType2 && type == fontCIDType2OT) || | ||||
embFontID.num < 0 || | ||||
hasKnownCollection) { | ||||
goto err0; | ||||
} | ||||
// read the embedded font and construct a FoFiTrueType | ||||
if (!(buf = readEmbFontFile(xref, &bufLen))) { | ||||
goto err0; | ||||
} | ||||
if (!(ff = FoFiTrueType::make(buf, bufLen, 0))) { | ||||
goto err1; | ||||
} | ||||
// find the TrueType Unicode cmap | ||||
unicodeCmap = -1; | ||||
for (i = 0; i < ff->getNumCmaps(); ++i) { | ||||
cmapPlatform = ff->getCmapPlatform(i); | ||||
cmapEncoding = ff->getCmapEncoding(i); | ||||
if ((cmapPlatform == 3 && cmapEncoding == 1) || | ||||
(cmapPlatform == 0 && cmapEncoding <= 4)) { | ||||
unicodeCmap = i; | ||||
break; | ||||
} | ||||
} | ||||
if (unicodeCmap < 0) { | ||||
goto err2; | ||||
} | ||||
// construct reverse GID-to-Unicode map | ||||
nGlyphs = ff->getNumGlyphs(); | ||||
gidToUnicode = (Unicode *)gmallocn(nGlyphs, sizeof(Unicode)); | ||||
memset(gidToUnicode, 0, nGlyphs * sizeof(Unicode)); | ||||
nMappings = 0; | ||||
for (u = 1; u <= 0xffff; ++u) { | ||||
gid = ff->mapCodeToGID(unicodeCmap, (int)u); | ||||
if (gid > 0 && gid < nGlyphs) { | ||||
gidToUnicode[gid] = u; | ||||
++nMappings; | ||||
} | ||||
} | ||||
// bail out if the Unicode cmap was completely empty | ||||
if (nMappings == 0) { | ||||
goto err3; | ||||
} | ||||
// construct code-to-Unicode map | ||||
codeToUnicode = (Unicode *)gmallocn(65536, sizeof(Unicode)); | ||||
memset(codeToUnicode, 0, 65536 * sizeof(Unicode)); | ||||
for (i = 0; i <= 0xffff; ++i) { | ||||
// we've already checked for an identity encoding, so CID = i | ||||
if (cidToGID && i < cidToGIDLen) { | ||||
gid = cidToGID[i]; | ||||
} else { | ||||
gid = i; | ||||
} | ||||
if (gid < nGlyphs && gidToUnicode[gid] > 0) { | ||||
codeToUnicode[i] = gidToUnicode[gid]; | ||||
} | ||||
} | ||||
ctu = CharCodeToUnicode::make16BitToUnicode(codeToUnicode); | ||||
gfree(codeToUnicode); | ||||
err3: | ||||
gfree(gidToUnicode); | ||||
err2: | ||||
delete ff; | ||||
err1: | ||||
gfree(buf); | ||||
err0: | ||||
return; | ||||
} | ||||
int GfxCIDFont::getNextChar(char *s, int len, CharCode *code, | int GfxCIDFont::getNextChar(char *s, int len, CharCode *code, | |||
Unicode *u, int uSize, int *uLen, | Unicode *u, int uSize, int *uLen, | |||
double *dx, double *dy, double *ox, double *oy) { | double *dx, double *dy, double *ox, double *oy) { | |||
CID cid; | CID cid; | |||
CharCode c; | CharCode c; | |||
int n; | int n; | |||
if (!cMap) { | if (!cMap) { | |||
*code = 0; | *code = 0; | |||
*uLen = 0; | *uLen = 0; | |||
End of changes. 6 change blocks. | ||||
47 lines changed or deleted | 159 lines changed or added |