|
|
@ -1656,6 +1656,30 @@ var Font = (function FontClosure() { |
|
|
|
glyf.data = newGlyfData.subarray(0, writeOffset); |
|
|
|
glyf.data = newGlyfData.subarray(0, writeOffset); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function findEmptyGlyphs(locaTable, isGlyphLocationsLong, emptyGlyphIds) { |
|
|
|
|
|
|
|
var itemSize, itemDecode; |
|
|
|
|
|
|
|
if (isGlyphLocationsLong) { |
|
|
|
|
|
|
|
itemSize = 4; |
|
|
|
|
|
|
|
itemDecode = function fontItemDecodeLong(data, offset) { |
|
|
|
|
|
|
|
return (data[offset] << 24) | (data[offset + 1] << 16) | |
|
|
|
|
|
|
|
(data[offset + 2] << 8) | data[offset + 3]; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
itemSize = 2; |
|
|
|
|
|
|
|
itemDecode = function fontItemDecode(data, offset) { |
|
|
|
|
|
|
|
return (data[offset] << 9) | (data[offset + 1] << 1); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var data = locaTable.data, length = data.length; |
|
|
|
|
|
|
|
var lastOffset = itemDecode(data, 0); |
|
|
|
|
|
|
|
for (var i = itemSize, j = 0; i < length; i += itemSize, j++) { |
|
|
|
|
|
|
|
var offset = itemDecode(data, i); |
|
|
|
|
|
|
|
if (offset == lastOffset) |
|
|
|
|
|
|
|
emptyGlyphIds[j] = true; |
|
|
|
|
|
|
|
lastOffset = offset; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function readGlyphNameMap(post, properties) { |
|
|
|
function readGlyphNameMap(post, properties) { |
|
|
|
var start = (font.start ? font.start : 0) + post.offset; |
|
|
|
var start = (font.start ? font.start : 0) + post.offset; |
|
|
|
font.pos = start; |
|
|
|
font.pos = start; |
|
|
@ -1782,11 +1806,15 @@ var Font = (function FontClosure() { |
|
|
|
sanitizeMetrics(font, hhea, hmtx, numGlyphs); |
|
|
|
sanitizeMetrics(font, hhea, hmtx, numGlyphs); |
|
|
|
sanitizeMetrics(font, vhea, vmtx, numGlyphs); |
|
|
|
sanitizeMetrics(font, vhea, vmtx, numGlyphs); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var isGlyphLocationsLong = int16([head.data[50], head.data[51]]); |
|
|
|
if (head && loca && glyf) { |
|
|
|
if (head && loca && glyf) { |
|
|
|
var isGlyphLocationsLong = int16([head.data[50], head.data[51]]); |
|
|
|
|
|
|
|
sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong); |
|
|
|
sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var emptyGlyphIds = []; |
|
|
|
|
|
|
|
if (glyf) |
|
|
|
|
|
|
|
findEmptyGlyphs(loca, isGlyphLocationsLong, emptyGlyphIds); |
|
|
|
|
|
|
|
|
|
|
|
// Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
|
|
|
|
// Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
|
|
|
|
// Sometimes it's 0. That needs to be fixed
|
|
|
|
// Sometimes it's 0. That needs to be fixed
|
|
|
|
if (hhea.data[10] == 0 && hhea.data[11] == 0) { |
|
|
|
if (hhea.data[10] == 0 && hhea.data[11] == 0) { |
|
|
@ -1918,6 +1946,15 @@ var Font = (function FontClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// remove glyph references outside range of avaialable glyphs or empty
|
|
|
|
|
|
|
|
for (var i = ids.length - 1; i >= 0; i--) { |
|
|
|
|
|
|
|
if (ids[i] < numGlyphs && |
|
|
|
|
|
|
|
(!emptyGlyphIds[ids[i]] || this.isSymbolicFont)) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
ids.splice(i, 1); |
|
|
|
|
|
|
|
glyphs.splice(i, 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (hasShortCmap && this.hasEncoding && !this.isSymbolicFont) { |
|
|
|
if (hasShortCmap && this.hasEncoding && !this.isSymbolicFont) { |
|
|
|
// Re-encode short map encoding to unicode -- that simplifies the
|
|
|
|
// Re-encode short map encoding to unicode -- that simplifies the
|
|
|
|
// resolution of MacRoman encoded glyphs logic for TrueType fonts:
|
|
|
|
// resolution of MacRoman encoded glyphs logic for TrueType fonts:
|
|
|
@ -1951,9 +1988,11 @@ var Font = (function FontClosure() { |
|
|
|
// Re-encode cmap encoding to unicode, based on the 'post' table data
|
|
|
|
// Re-encode cmap encoding to unicode, based on the 'post' table data
|
|
|
|
// diffrence array or base encoding
|
|
|
|
// diffrence array or base encoding
|
|
|
|
var reverseMap = []; |
|
|
|
var reverseMap = []; |
|
|
|
for (var i = 0, ii = glyphs.length; i < ii; i++) |
|
|
|
for (var i = 0, ii = glyphs.length; i < ii; i++) { |
|
|
|
reverseMap[glyphs[i].unicode] = i; |
|
|
|
reverseMap[glyphs[i].unicode] = i; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var backtrackReplacements = []; |
|
|
|
for (var i = 0, ii = glyphs.length; i < ii; i++) { |
|
|
|
for (var i = 0, ii = glyphs.length; i < ii; i++) { |
|
|
|
var code = glyphs[i].unicode; |
|
|
|
var code = glyphs[i].unicode; |
|
|
|
var changeCode = false; |
|
|
|
var changeCode = false; |
|
|
@ -1966,13 +2005,36 @@ var Font = (function FontClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
if (glyphName in GlyphsUnicode) { |
|
|
|
if (glyphName in GlyphsUnicode) { |
|
|
|
var unicode = GlyphsUnicode[glyphName]; |
|
|
|
var unicode = GlyphsUnicode[glyphName]; |
|
|
|
if (!unicode || (unicode in reverseMap)) |
|
|
|
if (!unicode || reverseMap[unicode] === i) |
|
|
|
continue; // unknown glyph name or its place is taken
|
|
|
|
continue; // unknown glyph name or in its own place
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (unicode in reverseMap) { |
|
|
|
|
|
|
|
backtrackReplacements[unicode] = { |
|
|
|
|
|
|
|
index: i, |
|
|
|
|
|
|
|
code: code, |
|
|
|
|
|
|
|
changeCode: changeCode |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
continue; // its place is taken
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
glyphs[i].unicode = unicode; |
|
|
|
var index = i; |
|
|
|
reverseMap[unicode] = i; |
|
|
|
while (true) { |
|
|
|
if (changeCode) |
|
|
|
glyphs[index].unicode = unicode; |
|
|
|
toFontChar[code] = unicode; |
|
|
|
reverseMap[unicode] = index; |
|
|
|
|
|
|
|
if (changeCode) |
|
|
|
|
|
|
|
toFontChar[code] = unicode; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// checking if available place can be used by other glyph
|
|
|
|
|
|
|
|
var backtrack = backtrackReplacements[code]; |
|
|
|
|
|
|
|
if (!backtrack) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
delete backtrackReplacements[code]; |
|
|
|
|
|
|
|
index = backtrack.index; |
|
|
|
|
|
|
|
code = backtrack.code; |
|
|
|
|
|
|
|
changeCode = backtrack.changeCode; |
|
|
|
|
|
|
|
unicode = code; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
this.useToFontChar = true; |
|
|
|
this.useToFontChar = true; |
|
|
|
} |
|
|
|
} |
|
|
@ -1988,12 +2050,6 @@ var Font = (function FontClosure() { |
|
|
|
this.useToFontChar = true; |
|
|
|
this.useToFontChar = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// remove glyph references outside range of avaialable glyphs
|
|
|
|
|
|
|
|
for (var i = 0, ii = ids.length; i < ii; i++) { |
|
|
|
|
|
|
|
if (ids[i] >= numGlyphs) |
|
|
|
|
|
|
|
ids[i] = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
createGlyphNameMap(glyphs, ids, properties); |
|
|
|
createGlyphNameMap(glyphs, ids, properties); |
|
|
|
this.glyphNameMap = properties.glyphNameMap; |
|
|
|
this.glyphNameMap = properties.glyphNameMap; |
|
|
|
|
|
|
|
|
|
|
|