|
|
@ -801,7 +801,7 @@ var Font = (function FontClosure() { |
|
|
|
* font that we build |
|
|
|
* font that we build |
|
|
|
* 'charCodeToGlyphId' - maps the new font char codes to glyph ids |
|
|
|
* 'charCodeToGlyphId' - maps the new font char codes to glyph ids |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
function adjustMapping(charCodeToGlyphId, properties) { |
|
|
|
function adjustMapping(charCodeToGlyphId, properties, missingGlyphs) { |
|
|
|
var toUnicode = properties.toUnicode; |
|
|
|
var toUnicode = properties.toUnicode; |
|
|
|
var isSymbolic = !!(properties.flags & FontFlags.Symbolic); |
|
|
|
var isSymbolic = !!(properties.flags & FontFlags.Symbolic); |
|
|
|
var isIdentityUnicode = |
|
|
|
var isIdentityUnicode = |
|
|
@ -831,7 +831,8 @@ var Font = (function FontClosure() { |
|
|
|
// font was symbolic and there is only an identity unicode map since the
|
|
|
|
// font was symbolic and there is only an identity unicode map since the
|
|
|
|
// characters probably aren't in the correct position (fixes an issue
|
|
|
|
// characters probably aren't in the correct position (fixes an issue
|
|
|
|
// with firefox and thuluthfont).
|
|
|
|
// with firefox and thuluthfont).
|
|
|
|
if ((usedFontCharCodes[fontCharCode] !== undefined || |
|
|
|
if (!missingGlyphs[glyphId] && |
|
|
|
|
|
|
|
(usedFontCharCodes[fontCharCode] !== undefined || |
|
|
|
isProblematicUnicodeLocation(fontCharCode) || |
|
|
|
isProblematicUnicodeLocation(fontCharCode) || |
|
|
|
(isSymbolic && !hasUnicodeValue)) && |
|
|
|
(isSymbolic && !hasUnicodeValue)) && |
|
|
|
nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END) { // Room left.
|
|
|
|
nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END) { // Room left.
|
|
|
@ -1686,9 +1687,15 @@ var Font = (function FontClosure() { |
|
|
|
var startOffset = itemDecode(locaData, 0); |
|
|
|
var startOffset = itemDecode(locaData, 0); |
|
|
|
var writeOffset = 0; |
|
|
|
var writeOffset = 0; |
|
|
|
var missingGlyphData = Object.create(null); |
|
|
|
var missingGlyphData = Object.create(null); |
|
|
|
|
|
|
|
// Glyph zero should be notdef which isn't drawn. Sometimes this is a
|
|
|
|
|
|
|
|
// valid glyph but, then it is duplicated.
|
|
|
|
|
|
|
|
missingGlyphData[0] = true; |
|
|
|
itemEncode(locaData, 0, writeOffset); |
|
|
|
itemEncode(locaData, 0, writeOffset); |
|
|
|
var i, j; |
|
|
|
var i, j; |
|
|
|
for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { |
|
|
|
// When called with dupFirstEntry the number of glyphs has already been
|
|
|
|
|
|
|
|
// increased but there isn't data yet for the duplicated glyph.
|
|
|
|
|
|
|
|
var locaCount = dupFirstEntry ? numGlyphs - 1 : numGlyphs; |
|
|
|
|
|
|
|
for (i = 0, j = itemSize; i < locaCount; i++, j += itemSize) { |
|
|
|
var endOffset = itemDecode(locaData, j); |
|
|
|
var endOffset = itemDecode(locaData, j); |
|
|
|
if (endOffset > oldGlyfDataLength && |
|
|
|
if (endOffset > oldGlyfDataLength && |
|
|
|
((oldGlyfDataLength + 3) & ~3) === endOffset) { |
|
|
|
((oldGlyfDataLength + 3) & ~3) === endOffset) { |
|
|
@ -1698,17 +1705,14 @@ var Font = (function FontClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
if (endOffset > oldGlyfDataLength) { |
|
|
|
if (endOffset > oldGlyfDataLength) { |
|
|
|
// glyph end offset points outside glyf data, rejecting the glyph
|
|
|
|
// glyph end offset points outside glyf data, rejecting the glyph
|
|
|
|
itemEncode(locaData, j, writeOffset); |
|
|
|
|
|
|
|
startOffset = endOffset; |
|
|
|
startOffset = endOffset; |
|
|
|
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); |
|
|
|
|
|
|
|
if (newLength === 0) { |
|
|
|
|
|
|
|
missingGlyphData[i] = true; |
|
|
|
|
|
|
|
} |
|
|
|
writeOffset += newLength; |
|
|
|
writeOffset += newLength; |
|
|
|
itemEncode(locaData, j, writeOffset); |
|
|
|
itemEncode(locaData, j, writeOffset); |
|
|
|
startOffset = endOffset; |
|
|
|
startOffset = endOffset; |
|
|
@ -2271,24 +2275,10 @@ var Font = (function FontClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var charCodeToGlyphId = [], charCode; |
|
|
|
var charCodeToGlyphId = [], charCode; |
|
|
|
var toUnicode = properties.toUnicode, widths = properties.widths; |
|
|
|
|
|
|
|
var skipToUnicode = (toUnicode instanceof IdentityToUnicodeMap || |
|
|
|
|
|
|
|
toUnicode.length === 0x10000); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Helper function to try to skip mapping of empty glyphs.
|
|
|
|
// Helper function to try to skip mapping of empty glyphs.
|
|
|
|
// Note: In some cases, just relying on the glyph data doesn't work,
|
|
|
|
function hasGlyph(glyphId) { |
|
|
|
// hence we also use a few heuristics to fix various PDF files.
|
|
|
|
return !missingGlyphs[glyphId]; |
|
|
|
function hasGlyph(glyphId, charCode, widthCode) { |
|
|
|
|
|
|
|
if (!missingGlyphs[glyphId]) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!skipToUnicode && charCode >= 0 && toUnicode.has(charCode)) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (widths && widthCode >= 0 && isNum(widths[widthCode])) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (properties.composite) { |
|
|
|
if (properties.composite) { |
|
|
@ -2304,8 +2294,7 @@ var Font = (function FontClosure() { |
|
|
|
glyphId = cidToGidMap[cid]; |
|
|
|
glyphId = cidToGidMap[cid]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (glyphId >= 0 && glyphId < numGlyphs && |
|
|
|
if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId)) { |
|
|
|
hasGlyph(glyphId, charCode, cid)) { |
|
|
|
|
|
|
|
charCodeToGlyphId[charCode] = glyphId; |
|
|
|
charCodeToGlyphId[charCode] = glyphId; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
@ -2361,10 +2350,9 @@ var Font = (function FontClosure() { |
|
|
|
// Ensure that non-standard glyph names are resolved to valid ones.
|
|
|
|
// Ensure that non-standard glyph names are resolved to valid ones.
|
|
|
|
standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap); |
|
|
|
standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap); |
|
|
|
|
|
|
|
|
|
|
|
var unicodeOrCharCode, isUnicode = false; |
|
|
|
var unicodeOrCharCode; |
|
|
|
if (cmapPlatformId === 3 && cmapEncodingId === 1) { |
|
|
|
if (cmapPlatformId === 3 && cmapEncodingId === 1) { |
|
|
|
unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName]; |
|
|
|
unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName]; |
|
|
|
isUnicode = true; |
|
|
|
|
|
|
|
} else if (cmapPlatformId === 1 && cmapEncodingId === 0) { |
|
|
|
} else if (cmapPlatformId === 1 && cmapEncodingId === 0) { |
|
|
|
// TODO: the encoding needs to be updated with mac os table.
|
|
|
|
// TODO: the encoding needs to be updated with mac os table.
|
|
|
|
unicodeOrCharCode = MacRomanEncoding.indexOf(standardGlyphName); |
|
|
|
unicodeOrCharCode = MacRomanEncoding.indexOf(standardGlyphName); |
|
|
@ -2375,8 +2363,7 @@ var Font = (function FontClosure() { |
|
|
|
if (cmapMappings[i].charCode !== unicodeOrCharCode) { |
|
|
|
if (cmapMappings[i].charCode !== unicodeOrCharCode) { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
var code = isUnicode ? charCode : unicodeOrCharCode; |
|
|
|
if (hasGlyph(cmapMappings[i].glyphId)) { |
|
|
|
if (hasGlyph(cmapMappings[i].glyphId, code, -1)) { |
|
|
|
|
|
|
|
charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; |
|
|
|
charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; |
|
|
|
found = true; |
|
|
|
found = true; |
|
|
|
break; |
|
|
|
break; |
|
|
@ -2390,7 +2377,7 @@ var Font = (function FontClosure() { |
|
|
|
if (glyphId === -1 && standardGlyphName !== glyphName) { |
|
|
|
if (glyphId === -1 && standardGlyphName !== glyphName) { |
|
|
|
glyphId = properties.glyphNames.indexOf(standardGlyphName); |
|
|
|
glyphId = properties.glyphNames.indexOf(standardGlyphName); |
|
|
|
} |
|
|
|
} |
|
|
|
if (glyphId > 0 && hasGlyph(glyphId, -1, -1)) { |
|
|
|
if (glyphId > 0 && hasGlyph(glyphId)) { |
|
|
|
charCodeToGlyphId[charCode] = glyphId; |
|
|
|
charCodeToGlyphId[charCode] = glyphId; |
|
|
|
found = true; |
|
|
|
found = true; |
|
|
|
} |
|
|
|
} |
|
|
@ -2432,7 +2419,8 @@ var Font = (function FontClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Converting glyphs and ids into font's cmap table
|
|
|
|
// Converting glyphs and ids into font's cmap table
|
|
|
|
var newMapping = adjustMapping(charCodeToGlyphId, properties); |
|
|
|
var newMapping = adjustMapping(charCodeToGlyphId, properties, |
|
|
|
|
|
|
|
missingGlyphs); |
|
|
|
this.toFontChar = newMapping.toFontChar; |
|
|
|
this.toFontChar = newMapping.toFontChar; |
|
|
|
tables['cmap'] = { |
|
|
|
tables['cmap'] = { |
|
|
|
tag: 'cmap', |
|
|
|
tag: 'cmap', |
|
|
@ -2499,7 +2487,7 @@ var Font = (function FontClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var mapping = font.getGlyphMapping(properties); |
|
|
|
var mapping = font.getGlyphMapping(properties); |
|
|
|
var newMapping = adjustMapping(mapping, properties); |
|
|
|
var newMapping = adjustMapping(mapping, properties, Object.create(null)); |
|
|
|
this.toFontChar = newMapping.toFontChar; |
|
|
|
this.toFontChar = newMapping.toFontChar; |
|
|
|
var numGlyphs = font.numGlyphs; |
|
|
|
var numGlyphs = font.numGlyphs; |
|
|
|
|
|
|
|
|
|
|
|