Merge pull request #5651 from Snuffleupagus/missing-glyphs

Try to skip mapping of missing TrueType and CIDFontType2 glyphs
This commit is contained in:
Brendan Dahl 2015-02-11 19:31:22 -08:00
commit 394b38b22f
7 changed files with 77 additions and 21 deletions

View File

@ -2203,6 +2203,10 @@ var ToUnicodeMap = (function ToUnicodeMapClosure() {
} }
}, },
has: function(i) {
return this._map[i] !== undefined;
},
get: function(i) { get: function(i) {
return this._map[i]; return this._map[i];
}, },
@ -2232,6 +2236,10 @@ var IdentityToUnicodeMap = (function IdentityToUnicodeMapClosure() {
} }
}, },
has: function (i) {
return this.firstChar <= i && i <= this.lastChar;
},
get: function (i) { get: function (i) {
if (this.firstChar <= i && i <= this.lastChar) { if (this.firstChar <= i && i <= this.lastChar) {
return String.fromCharCode(i); return String.fromCharCode(i);
@ -2664,7 +2672,6 @@ var Font = (function FontClosure() {
var isSymbolic = !!(properties.flags & FontFlags.Symbolic); var isSymbolic = !!(properties.flags & FontFlags.Symbolic);
var isIdentityUnicode = var isIdentityUnicode =
properties.toUnicode instanceof IdentityToUnicodeMap; properties.toUnicode instanceof IdentityToUnicodeMap;
var isCidFontType2 = (properties.type === 'CIDFontType2');
var newMap = Object.create(null); var newMap = Object.create(null);
var toFontChar = []; var toFontChar = [];
var usedFontCharCodes = []; var usedFontCharCodes = [];
@ -2675,17 +2682,11 @@ var Font = (function FontClosure() {
var fontCharCode = originalCharCode; var fontCharCode = originalCharCode;
// First try to map the value to a unicode position if a non identity map // First try to map the value to a unicode position if a non identity map
// was created. // was created.
if (!isIdentityUnicode) { if (!isIdentityUnicode && toUnicode.has(originalCharCode)) {
if (toUnicode.get(originalCharCode) !== undefined) { var unicode = toUnicode.get(fontCharCode);
var unicode = toUnicode.get(fontCharCode); // TODO: Try to map ligatures to the correct spot.
// TODO: Try to map ligatures to the correct spot. if (unicode.length === 1) {
if (unicode.length === 1) { fontCharCode = unicode.charCodeAt(0);
fontCharCode = unicode.charCodeAt(0);
}
} else if (isCidFontType2) {
// For CIDFontType2, move characters not present in toUnicode
// to the private use area (fixes bug 1028735 and issue 4881).
fontCharCode = nextAvailableFontCharCode;
} }
} }
// Try to move control characters, special characters and already mapped // Try to move control characters, special characters and already mapped
@ -3530,6 +3531,7 @@ var Font = (function FontClosure() {
var newGlyfData = new Uint8Array(oldGlyfDataLength); var newGlyfData = new Uint8Array(oldGlyfDataLength);
var startOffset = itemDecode(locaData, 0); var startOffset = itemDecode(locaData, 0);
var writeOffset = 0; var writeOffset = 0;
var missingGlyphData = {};
itemEncode(locaData, 0, writeOffset); itemEncode(locaData, 0, writeOffset);
var i, j; var i, j;
for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
@ -3547,6 +3549,10 @@ var Font = (function FontClosure() {
continue; continue;
} }
if (startOffset === endOffset) {
missingGlyphData[i] = true;
}
var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset, var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
newGlyfData, writeOffset, hintsValid); newGlyfData, writeOffset, hintsValid);
writeOffset += newLength; writeOffset += newLength;
@ -3563,7 +3569,7 @@ var Font = (function FontClosure() {
itemEncode(locaData, j, simpleGlyph.length); itemEncode(locaData, j, simpleGlyph.length);
} }
glyf.data = simpleGlyph; glyf.data = simpleGlyph;
return; return missingGlyphData;
} }
if (dupFirstEntry) { if (dupFirstEntry) {
@ -3580,6 +3586,7 @@ var Font = (function FontClosure() {
} else { } else {
glyf.data = newGlyfData.subarray(0, writeOffset); glyf.data = newGlyfData.subarray(0, writeOffset);
} }
return missingGlyphData;
} }
function readPostScriptTable(post, properties, maxpNumGlyphs) { function readPostScriptTable(post, properties, maxpNumGlyphs) {
@ -4039,11 +4046,13 @@ var Font = (function FontClosure() {
sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0); sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0);
var missingGlyphs = {};
if (isTrueType) { if (isTrueType) {
var isGlyphLocationsLong = int16(tables.head.data[50], var isGlyphLocationsLong = int16(tables.head.data[50],
tables.head.data[51]); tables.head.data[51]);
sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs, missingGlyphs = sanitizeGlyphLocations(tables.loca, tables.glyf,
isGlyphLocationsLong, hintsValid, dupFirstEntry); numGlyphs, isGlyphLocationsLong,
hintsValid, dupFirstEntry);
} }
if (!tables.hhea) { if (!tables.hhea) {
@ -4065,19 +4074,33 @@ var Font = (function FontClosure() {
} }
} }
var charCodeToGlyphId = [], charCode; var charCodeToGlyphId = [], charCode, toUnicode = properties.toUnicode;
function hasGlyph(glyphId, charCode) {
if (!missingGlyphs[glyphId]) {
return true;
}
if (charCode >= 0 && toUnicode.has(charCode)) {
return true;
}
return false;
}
if (properties.type === 'CIDFontType2') { if (properties.type === 'CIDFontType2') {
var cidToGidMap = properties.cidToGidMap || []; var cidToGidMap = properties.cidToGidMap || [];
var cidToGidMapLength = cidToGidMap.length; var isCidToGidMapEmpty = cidToGidMap.length === 0;
properties.cMap.forEach(function(charCode, cid) { properties.cMap.forEach(function(charCode, cid) {
assert(cid <= 0xffff, 'Max size of CID is 65,535'); assert(cid <= 0xffff, 'Max size of CID is 65,535');
var glyphId = -1; var glyphId = -1;
if (cidToGidMapLength === 0) { if (isCidToGidMapEmpty) {
glyphId = charCode; glyphId = charCode;
} else if (cidToGidMap[cid] !== undefined) { } else if (cidToGidMap[cid] !== undefined) {
glyphId = cidToGidMap[cid]; glyphId = cidToGidMap[cid];
} }
if (glyphId >= 0 && glyphId < numGlyphs) {
if (glyphId >= 0 && glyphId < numGlyphs &&
hasGlyph(glyphId, charCode)) {
charCodeToGlyphId[charCode] = glyphId; charCodeToGlyphId[charCode] = glyphId;
} }
}); });
@ -4137,7 +4160,8 @@ var Font = (function FontClosure() {
var found = false; var found = false;
for (i = 0; i < cmapMappingsLength; ++i) { for (i = 0; i < cmapMappingsLength; ++i) {
if (cmapMappings[i].charCode === unicodeOrCharCode) { if (cmapMappings[i].charCode === unicodeOrCharCode &&
hasGlyph(cmapMappings[i].glyphId, unicodeOrCharCode)) {
charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
found = true; found = true;
break; break;
@ -4147,7 +4171,7 @@ var Font = (function FontClosure() {
// Try to map using the post table. There are currently no known // Try to map using the post table. There are currently no known
// pdfs that this fixes. // pdfs that this fixes.
var glyphId = properties.glyphNames.indexOf(glyphName); var glyphId = properties.glyphNames.indexOf(glyphName);
if (glyphId > 0) { if (glyphId > 0 && hasGlyph(glyphId, -1)) {
charCodeToGlyphId[charCode] = glyphId; charCodeToGlyphId[charCode] = glyphId;
} }
} }

View File

@ -18,6 +18,7 @@
!sizes.pdf !sizes.pdf
!close-path-bug.pdf !close-path-bug.pdf
!issue4630.pdf !issue4630.pdf
!issue5202.pdf
!issue5280.pdf !issue5280.pdf
!alphatrans.pdf !alphatrans.pdf
!devicen.pdf !devicen.pdf
@ -58,10 +59,13 @@
!zerowidthline.pdf !zerowidthline.pdf
!bug868745.pdf !bug868745.pdf
!mmtype1.pdf !mmtype1.pdf
!issue5704.pdf
!bug893730.pdf
!bug864847.pdf !bug864847.pdf
!issue1002.pdf !issue1002.pdf
!issue925.pdf !issue925.pdf
!issue2840.pdf !issue2840.pdf
!issue4061.pdf
!issue4668.pdf !issue4668.pdf
!issue5039.pdf !issue5039.pdf
!issue5070.pdf !issue5070.pdf

BIN
test/pdfs/bug893730.pdf Normal file

Binary file not shown.

BIN
test/pdfs/issue4061.pdf Normal file

Binary file not shown.

BIN
test/pdfs/issue5202.pdf Normal file

Binary file not shown.

BIN
test/pdfs/issue5704.pdf Normal file

Binary file not shown.

View File

@ -485,6 +485,20 @@
"lastPage": 1, "lastPage": 1,
"type": "eq" "type": "eq"
}, },
{ "id": "issue4061",
"file": "pdfs/issue4061.pdf",
"md5": "236aaa8840a47c3c061f8e3034549764",
"rounds": 1,
"link": false,
"type": "eq"
},
{ "id": "issue5202",
"file": "pdfs/issue5202.pdf",
"md5": "bb9cc69211112e66aab40828086a4e5a",
"rounds": 1,
"link": false,
"type": "eq"
},
{ "id": "issue5238", { "id": "issue5238",
"file": "pdfs/issue5238.pdf", "file": "pdfs/issue5238.pdf",
"md5": "6ddecda00893be1793de20a70c83a3c2", "md5": "6ddecda00893be1793de20a70c83a3c2",
@ -1015,6 +1029,20 @@
"link": true, "link": true,
"type": "eq" "type": "eq"
}, },
{ "id": "issue5704",
"file": "pdfs/issue5704.pdf",
"md5": "6e0b62585feef24dff2d7e7687cd8128",
"rounds": 1,
"link": false,
"type": "eq"
},
{ "id": "bug893730",
"file": "pdfs/bug893730.pdf",
"md5": "2587379fb1b3bbff89c14f0863e78383",
"rounds": 1,
"link": false,
"type": "eq"
},
{ "id": "pdfkit_compressed", { "id": "pdfkit_compressed",
"file": "pdfs/pdfkit_compressed.pdf", "file": "pdfs/pdfkit_compressed.pdf",
"md5": "ffe9c571d0a1572e234253e6c7cdee6c", "md5": "ffe9c571d0a1572e234253e6c7cdee6c",