|
|
@ -3185,13 +3185,23 @@ var Font = (function FontClosure() { |
|
|
|
font.pos += header.length - 2; |
|
|
|
font.pos += header.length - 2; |
|
|
|
var numOfMetrics = int16(font.getBytes(2)); |
|
|
|
var numOfMetrics = int16(font.getBytes(2)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (numOfMetrics > numGlyphs) { |
|
|
|
|
|
|
|
info('The numOfMetrics (' + numOfMetrics + ') should not be ' + |
|
|
|
|
|
|
|
'greater than the numGlyphs (' + numGlyphs + ')'); |
|
|
|
|
|
|
|
// Reduce numOfMetrics if it is greater than numGlyphs
|
|
|
|
|
|
|
|
numOfMetrics = numGlyphs; |
|
|
|
|
|
|
|
header.data[34] = (numOfMetrics & 0xff00) >> 8; |
|
|
|
|
|
|
|
header.data[35] = numOfMetrics & 0x00ff; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var numOfSidebearings = numGlyphs - numOfMetrics; |
|
|
|
var numOfSidebearings = numGlyphs - numOfMetrics; |
|
|
|
var numMissing = numOfSidebearings - |
|
|
|
var numMissing = numOfSidebearings - |
|
|
|
((hmtx.length - numOfMetrics * 4) >> 1); |
|
|
|
((metrics.length - numOfMetrics * 4) >> 1); |
|
|
|
|
|
|
|
|
|
|
|
if (numMissing > 0) { |
|
|
|
if (numMissing > 0) { |
|
|
|
font.pos = (font.start ? font.start : 0) + metrics.offset; |
|
|
|
font.pos = (font.start ? font.start : 0) + metrics.offset; |
|
|
|
var entries = ''; |
|
|
|
var entries = ''; |
|
|
|
for (var i = 0, ii = hmtx.length; i < ii; i++) |
|
|
|
for (var i = 0, ii = metrics.length; i < ii; i++) |
|
|
|
entries += String.fromCharCode(font.getByte()); |
|
|
|
entries += String.fromCharCode(font.getByte()); |
|
|
|
for (var i = 0; i < numMissing; i++) |
|
|
|
for (var i = 0; i < numMissing; i++) |
|
|
|
entries += '\x00\x00'; |
|
|
|
entries += '\x00\x00'; |
|
|
@ -3254,19 +3264,48 @@ var Font = (function FontClosure() { |
|
|
|
return glyf.length; |
|
|
|
return glyf.length; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function sanitizeHead(head) { |
|
|
|
function sanitizeHead(head, numGlyphs, locaLength) { |
|
|
|
var data = head.data; |
|
|
|
var data = head.data; |
|
|
|
|
|
|
|
|
|
|
|
// Validate version:
|
|
|
|
// Validate version:
|
|
|
|
// Should always be 0x00010000
|
|
|
|
// Should always be 0x00010000
|
|
|
|
var version = int32([data[0], data[1], data[2], data[3]]); |
|
|
|
var version = int32([data[0], data[1], data[2], data[3]]); |
|
|
|
if (version >> 16 !== 1) { |
|
|
|
if (version >> 16 !== 1) { |
|
|
|
info('Invalid version in data type: ' + version); |
|
|
|
info('Attempting to fix invalid version in head table: ' + version); |
|
|
|
data[0] = 0; |
|
|
|
data[0] = 0; |
|
|
|
data[1] = 1; |
|
|
|
data[1] = 1; |
|
|
|
data[2] = 0; |
|
|
|
data[2] = 0; |
|
|
|
data[3] = 0; |
|
|
|
data[3] = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var indexToLocFormat = int16([data[50], data[51]]); |
|
|
|
|
|
|
|
if (indexToLocFormat < 0 || indexToLocFormat > 1) { |
|
|
|
|
|
|
|
info('Attempting to fix invalid indexToLocFormat in head table: ' + |
|
|
|
|
|
|
|
indexToLocFormat); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The value of indexToLocFormat should be 0 if the loca table
|
|
|
|
|
|
|
|
// consists of short offsets, and should be 1 if the loca table
|
|
|
|
|
|
|
|
// consists of long offsets.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// The number of entries in the loca table should be numGlyphs + 1.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Using this information, we can work backwards to deduce if the
|
|
|
|
|
|
|
|
// size of each offset in the loca table, and thus figure out the
|
|
|
|
|
|
|
|
// appropriate value for indexToLocFormat.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var numGlyphsPlusOne = numGlyphs + 1; |
|
|
|
|
|
|
|
if (locaLength === numGlyphsPlusOne << 1) { |
|
|
|
|
|
|
|
// 0x0000 indicates the loca table consists of short offsets
|
|
|
|
|
|
|
|
data[50] = 0; |
|
|
|
|
|
|
|
data[51] = 0; |
|
|
|
|
|
|
|
} else if (locaLength === numGlyphsPlusOne << 2) { |
|
|
|
|
|
|
|
// 0x0001 indicates the loca table consists of long offsets
|
|
|
|
|
|
|
|
data[50] = 0; |
|
|
|
|
|
|
|
data[51] = 1; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
warn('Could not fix indexToLocFormat: ' + indexToLocFormat); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function sanitizeGlyphLocations(loca, glyf, numGlyphs, |
|
|
|
function sanitizeGlyphLocations(loca, glyf, numGlyphs, |
|
|
@ -3694,7 +3733,7 @@ var Font = (function FontClosure() { |
|
|
|
sanitizeTTPrograms(fpgm, prep); |
|
|
|
sanitizeTTPrograms(fpgm, prep); |
|
|
|
|
|
|
|
|
|
|
|
if (head) { |
|
|
|
if (head) { |
|
|
|
sanitizeHead(head); |
|
|
|
sanitizeHead(head, numGlyphs, loca.length); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var isGlyphLocationsLong = int16([head.data[50], head.data[51]]); |
|
|
|
var isGlyphLocationsLong = int16([head.data[50], head.data[51]]); |
|
|
|