|
|
|
@ -2312,13 +2312,12 @@ var Font = (function FontClosure() {
@@ -2312,13 +2312,12 @@ var Font = (function FontClosure() {
|
|
|
|
|
return strBuf.join(''); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function int16(bytes) { |
|
|
|
|
return (bytes[0] << 8) + (bytes[1] & 0xff); |
|
|
|
|
function int16(b0, b1) { |
|
|
|
|
return (b0 << 8) + b1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function int32(bytes) { |
|
|
|
|
return (bytes[0] << 24) + (bytes[1] << 16) + |
|
|
|
|
(bytes[2] << 8) + (bytes[3] & 0xff); |
|
|
|
|
function int32(b0, b1, b2, b3) { |
|
|
|
|
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getMaxPower2(number) { |
|
|
|
@ -2397,8 +2396,8 @@ var Font = (function FontClosure() {
@@ -2397,8 +2396,8 @@ var Font = (function FontClosure() {
|
|
|
|
|
// checksum
|
|
|
|
|
var checksum = 0, n = data.length; |
|
|
|
|
for (var i = 0; i < n; i += 4) |
|
|
|
|
checksum = (checksum + int32([data[i], data[i + 1], data[i + 2], |
|
|
|
|
data[i + 3]])) | 0; |
|
|
|
|
checksum = (checksum + int32(data[i], data[i + 1], data[i + 2], |
|
|
|
|
data[i + 3])) | 0; |
|
|
|
|
|
|
|
|
|
var tableEntry = (tag + string32(checksum) + |
|
|
|
|
string32(offset) + string32(length)); |
|
|
|
@ -2626,21 +2625,21 @@ var Font = (function FontClosure() {
@@ -2626,21 +2625,21 @@ var Font = (function FontClosure() {
|
|
|
|
|
|
|
|
|
|
function validateOS2Table(os2) { |
|
|
|
|
var stream = new Stream(os2.data); |
|
|
|
|
var version = int16(stream.getBytes(2)); |
|
|
|
|
var version = stream.getUint16(); |
|
|
|
|
// TODO verify all OS/2 tables fields, but currently we validate only those
|
|
|
|
|
// that give us issues
|
|
|
|
|
stream.getBytes(60); // skipping type, misc sizes, panose, unicode ranges
|
|
|
|
|
var selection = int16(stream.getBytes(2)); |
|
|
|
|
var selection = stream.getUint16(); |
|
|
|
|
if (version < 4 && (selection & 0x0300)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
var firstChar = int16(stream.getBytes(2)); |
|
|
|
|
var lastChar = int16(stream.getBytes(2)); |
|
|
|
|
var firstChar = stream.getUint16(); |
|
|
|
|
var lastChar = stream.getUint16(); |
|
|
|
|
if (firstChar > lastChar) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
stream.getBytes(6); // skipping sTypoAscender/Descender/LineGap
|
|
|
|
|
var usWinAscent = int16(stream.getBytes(2)); |
|
|
|
|
var usWinAscent = stream.getUint16(); |
|
|
|
|
if (usWinAscent === 0) { // makes font unreadable by windows
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
@ -2859,9 +2858,9 @@ var Font = (function FontClosure() {
@@ -2859,9 +2858,9 @@ var Font = (function FontClosure() {
|
|
|
|
|
String.fromCharCode(tag[2]) + |
|
|
|
|
String.fromCharCode(tag[3]); |
|
|
|
|
|
|
|
|
|
var checksum = int32(file.getBytes(4)); |
|
|
|
|
var offset = int32(file.getBytes(4)); |
|
|
|
|
var length = int32(file.getBytes(4)); |
|
|
|
|
var checksum = file.getUint32(); |
|
|
|
|
var offset = file.getUint32(); |
|
|
|
|
var length = file.getUint32(); |
|
|
|
|
|
|
|
|
|
// Read the table associated data
|
|
|
|
|
var previousPosition = file.pos; |
|
|
|
@ -2888,10 +2887,10 @@ var Font = (function FontClosure() {
@@ -2888,10 +2887,10 @@ var Font = (function FontClosure() {
|
|
|
|
|
function readOpenTypeHeader(ttf) { |
|
|
|
|
return { |
|
|
|
|
version: arrayToString(ttf.getBytes(4)), |
|
|
|
|
numTables: int16(ttf.getBytes(2)), |
|
|
|
|
searchRange: int16(ttf.getBytes(2)), |
|
|
|
|
entrySelector: int16(ttf.getBytes(2)), |
|
|
|
|
rangeShift: int16(ttf.getBytes(2)) |
|
|
|
|
numTables: ttf.getUint16(), |
|
|
|
|
searchRange: ttf.getUint16(), |
|
|
|
|
entrySelector: ttf.getUint16(), |
|
|
|
|
rangeShift: ttf.getUint16() |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2903,8 +2902,8 @@ var Font = (function FontClosure() {
@@ -2903,8 +2902,8 @@ var Font = (function FontClosure() {
|
|
|
|
|
var start = (font.start ? font.start : 0) + cmap.offset; |
|
|
|
|
font.pos = start; |
|
|
|
|
|
|
|
|
|
var version = int16(font.getBytes(2)); |
|
|
|
|
var numTables = int16(font.getBytes(2)); |
|
|
|
|
var version = font.getUint16(); |
|
|
|
|
var numTables = font.getUint16(); |
|
|
|
|
|
|
|
|
|
var potentialTable; |
|
|
|
|
var canBreak = false; |
|
|
|
@ -2915,9 +2914,9 @@ var Font = (function FontClosure() {
@@ -2915,9 +2914,9 @@ var Font = (function FontClosure() {
|
|
|
|
|
// The following takes advantage of the fact that the tables are sorted
|
|
|
|
|
// to work.
|
|
|
|
|
for (var i = 0; i < numTables; i++) { |
|
|
|
|
var platformId = int16(font.getBytes(2)); |
|
|
|
|
var encodingId = int16(font.getBytes(2)); |
|
|
|
|
var offset = int32(font.getBytes(4)); |
|
|
|
|
var platformId = font.getUint16(); |
|
|
|
|
var encodingId = font.getUint16(); |
|
|
|
|
var offset = font.getUint32(); |
|
|
|
|
var useTable = false; |
|
|
|
|
|
|
|
|
|
if (platformId == 1 && encodingId === 0) { |
|
|
|
@ -2950,9 +2949,9 @@ var Font = (function FontClosure() {
@@ -2950,9 +2949,9 @@ var Font = (function FontClosure() {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
font.pos = start + potentialTable.offset; |
|
|
|
|
var format = int16(font.getBytes(2)); |
|
|
|
|
var length = int16(font.getBytes(2)); |
|
|
|
|
var language = int16(font.getBytes(2)); |
|
|
|
|
var format = font.getUint16(); |
|
|
|
|
var length = font.getUint16(); |
|
|
|
|
var language = font.getUint16(); |
|
|
|
|
|
|
|
|
|
var hasShortCmap = false; |
|
|
|
|
var mappings = []; |
|
|
|
@ -2973,25 +2972,25 @@ var Font = (function FontClosure() {
@@ -2973,25 +2972,25 @@ var Font = (function FontClosure() {
|
|
|
|
|
} else if (format === 4) { |
|
|
|
|
// re-creating the table in format 4 since the encoding
|
|
|
|
|
// might be changed
|
|
|
|
|
var segCount = (int16(font.getBytes(2)) >> 1); |
|
|
|
|
var segCount = (font.getUint16() >> 1); |
|
|
|
|
font.getBytes(6); // skipping range fields
|
|
|
|
|
var segIndex, segments = []; |
|
|
|
|
for (segIndex = 0; segIndex < segCount; segIndex++) { |
|
|
|
|
segments.push({ end: int16(font.getBytes(2)) }); |
|
|
|
|
segments.push({ end: font.getUint16() }); |
|
|
|
|
} |
|
|
|
|
font.getBytes(2); |
|
|
|
|
font.getUint16(); |
|
|
|
|
for (segIndex = 0; segIndex < segCount; segIndex++) { |
|
|
|
|
segments[segIndex].start = int16(font.getBytes(2)); |
|
|
|
|
segments[segIndex].start = font.getUint16(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (segIndex = 0; segIndex < segCount; segIndex++) { |
|
|
|
|
segments[segIndex].delta = int16(font.getBytes(2)); |
|
|
|
|
segments[segIndex].delta = font.getUint16(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var offsetsCount = 0; |
|
|
|
|
for (segIndex = 0; segIndex < segCount; segIndex++) { |
|
|
|
|
var segment = segments[segIndex]; |
|
|
|
|
var rangeOffset = int16(font.getBytes(2)); |
|
|
|
|
var rangeOffset = font.getUint16(); |
|
|
|
|
if (!rangeOffset) { |
|
|
|
|
segment.offsetIndex = -1; |
|
|
|
|
continue; |
|
|
|
@ -3005,7 +3004,7 @@ var Font = (function FontClosure() {
@@ -3005,7 +3004,7 @@ var Font = (function FontClosure() {
|
|
|
|
|
|
|
|
|
|
var offsets = []; |
|
|
|
|
for (var j = 0; j < offsetsCount; j++) { |
|
|
|
|
offsets.push(int16(font.getBytes(2))); |
|
|
|
|
offsets.push(font.getUint16()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (segIndex = 0; segIndex < segCount; segIndex++) { |
|
|
|
@ -3036,13 +3035,13 @@ var Font = (function FontClosure() {
@@ -3036,13 +3035,13 @@ var Font = (function FontClosure() {
|
|
|
|
|
// table. (This looks weird, so I can have missed something), this
|
|
|
|
|
// works on Linux but seems to fails on Mac so let's rewrite the
|
|
|
|
|
// cmap table to a 3-1-4 style
|
|
|
|
|
var firstCode = int16(font.getBytes(2)); |
|
|
|
|
var entryCount = int16(font.getBytes(2)); |
|
|
|
|
var firstCode = font.getUint16(); |
|
|
|
|
var entryCount = font.getUint16(); |
|
|
|
|
|
|
|
|
|
var glyphs = []; |
|
|
|
|
var ids = []; |
|
|
|
|
for (var j = 0; j < entryCount; j++) { |
|
|
|
|
var glyphId = int16(font.getBytes(2)); |
|
|
|
|
var glyphId = font.getUint16(); |
|
|
|
|
var charCode = firstCode + j; |
|
|
|
|
|
|
|
|
|
mappings.push({ |
|
|
|
@ -3083,7 +3082,7 @@ var Font = (function FontClosure() {
@@ -3083,7 +3082,7 @@ var Font = (function FontClosure() {
|
|
|
|
|
|
|
|
|
|
font.pos = (font.start ? font.start : 0) + header.offset; |
|
|
|
|
font.pos += header.length - 2; |
|
|
|
|
var numOfMetrics = int16(font.getBytes(2)); |
|
|
|
|
var numOfMetrics = font.getUint16(); |
|
|
|
|
|
|
|
|
|
if (numOfMetrics > numGlyphs) { |
|
|
|
|
info('The numOfMetrics (' + numOfMetrics + ') should not be ' + |
|
|
|
@ -3187,7 +3186,7 @@ var Font = (function FontClosure() {
@@ -3187,7 +3186,7 @@ var Font = (function FontClosure() {
|
|
|
|
|
|
|
|
|
|
// Validate version:
|
|
|
|
|
// 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) { |
|
|
|
|
info('Attempting to fix invalid version in head table: ' + version); |
|
|
|
|
data[0] = 0; |
|
|
|
@ -3196,7 +3195,7 @@ var Font = (function FontClosure() {
@@ -3196,7 +3195,7 @@ var Font = (function FontClosure() {
|
|
|
|
|
data[3] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var indexToLocFormat = int16([data[50], data[51]]); |
|
|
|
|
var indexToLocFormat = int16(data[50], data[51]); |
|
|
|
|
if (indexToLocFormat < 0 || indexToLocFormat > 1) { |
|
|
|
|
info('Attempting to fix invalid indexToLocFormat in head table: ' + |
|
|
|
|
indexToLocFormat); |
|
|
|
@ -3321,7 +3320,7 @@ var Font = (function FontClosure() {
@@ -3321,7 +3320,7 @@ var Font = (function FontClosure() {
|
|
|
|
|
font.pos = start; |
|
|
|
|
|
|
|
|
|
var length = post.length, end = start + length; |
|
|
|
|
var version = int32(font.getBytes(4)); |
|
|
|
|
var version = font.getUint32(); |
|
|
|
|
// skip rest to the tables
|
|
|
|
|
font.getBytes(28); |
|
|
|
|
|
|
|
|
@ -3332,14 +3331,14 @@ var Font = (function FontClosure() {
@@ -3332,14 +3331,14 @@ var Font = (function FontClosure() {
|
|
|
|
|
glyphNames = MacStandardGlyphOrdering; |
|
|
|
|
break; |
|
|
|
|
case 0x00020000: |
|
|
|
|
var numGlyphs = int16(font.getBytes(2)); |
|
|
|
|
var numGlyphs = font.getUint16(); |
|
|
|
|
if (numGlyphs != maxpNumGlyphs) { |
|
|
|
|
valid = false; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
var glyphNameIndexes = []; |
|
|
|
|
for (var i = 0; i < numGlyphs; ++i) { |
|
|
|
|
var index = int16(font.getBytes(2)); |
|
|
|
|
var index = font.getUint16(); |
|
|
|
|
if (index >= 32768) { |
|
|
|
|
valid = false; |
|
|
|
|
break; |
|
|
|
@ -3385,25 +3384,25 @@ var Font = (function FontClosure() {
@@ -3385,25 +3384,25 @@ var Font = (function FontClosure() {
|
|
|
|
|
|
|
|
|
|
var names = [[], []]; |
|
|
|
|
var length = nameTable.length, end = start + length; |
|
|
|
|
var format = int16(font.getBytes(2)); |
|
|
|
|
var format = font.getUint16(); |
|
|
|
|
var FORMAT_0_HEADER_LENGTH = 6; |
|
|
|
|
if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) { |
|
|
|
|
// unsupported name table format or table "too" small
|
|
|
|
|
return names; |
|
|
|
|
} |
|
|
|
|
var numRecords = int16(font.getBytes(2)); |
|
|
|
|
var stringsStart = int16(font.getBytes(2)); |
|
|
|
|
var numRecords = font.getUint16(); |
|
|
|
|
var stringsStart = font.getUint16(); |
|
|
|
|
var records = []; |
|
|
|
|
var NAME_RECORD_LENGTH = 12; |
|
|
|
|
for (var i = 0; i < numRecords && |
|
|
|
|
font.pos + NAME_RECORD_LENGTH <= end; i++) { |
|
|
|
|
var r = { |
|
|
|
|
platform: int16(font.getBytes(2)), |
|
|
|
|
encoding: int16(font.getBytes(2)), |
|
|
|
|
language: int16(font.getBytes(2)), |
|
|
|
|
name: int16(font.getBytes(2)), |
|
|
|
|
length: int16(font.getBytes(2)), |
|
|
|
|
offset: int16(font.getBytes(2)) |
|
|
|
|
platform: font.getUint16(), |
|
|
|
|
encoding: font.getUint16(), |
|
|
|
|
language: font.getUint16(), |
|
|
|
|
name: font.getUint16(), |
|
|
|
|
length: font.getUint16(), |
|
|
|
|
offset: font.getUint16() |
|
|
|
|
}; |
|
|
|
|
// using only Macintosh and Windows platform/encoding names
|
|
|
|
|
if ((r.platform == 1 && r.encoding === 0 && r.language === 0) || |
|
|
|
@ -3424,7 +3423,7 @@ var Font = (function FontClosure() {
@@ -3424,7 +3423,7 @@ var Font = (function FontClosure() {
|
|
|
|
|
// unicode
|
|
|
|
|
var str = ''; |
|
|
|
|
for (var j = 0, jj = record.length; j < jj; j += 2) { |
|
|
|
|
str += String.fromCharCode(int16(font.getBytes(2))); |
|
|
|
|
str += String.fromCharCode(font.getUint16()); |
|
|
|
|
} |
|
|
|
|
names[1][nameIndex] = str; |
|
|
|
|
} else { |
|
|
|
@ -3719,19 +3718,19 @@ var Font = (function FontClosure() {
@@ -3719,19 +3718,19 @@ var Font = (function FontClosure() {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
font.pos = (font.start || 0) + tables.maxp.offset; |
|
|
|
|
var version = int32(font.getBytes(4)); |
|
|
|
|
var numGlyphs = int16(font.getBytes(2)); |
|
|
|
|
var version = font.getUint32(); |
|
|
|
|
var numGlyphs = font.getUint16(); |
|
|
|
|
var maxFunctionDefs = 0; |
|
|
|
|
if (version >= 0x00010000 && tables.maxp.length >= 22) { |
|
|
|
|
// maxZones can be invalid
|
|
|
|
|
font.pos += 8; |
|
|
|
|
var maxZones = int16(font.getBytes(2)); |
|
|
|
|
var maxZones = font.getUint16(); |
|
|
|
|
if (maxZones > 2) { // reset to 2 if font has invalid maxZones
|
|
|
|
|
tables.maxp.data[14] = 0; |
|
|
|
|
tables.maxp.data[15] = 2; |
|
|
|
|
} |
|
|
|
|
font.pos += 4; |
|
|
|
|
maxFunctionDefs = int16(font.getBytes(2)); |
|
|
|
|
maxFunctionDefs = font.getUint16(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var dupFirstEntry = false; |
|
|
|
@ -3781,8 +3780,8 @@ var Font = (function FontClosure() {
@@ -3781,8 +3780,8 @@ var Font = (function FontClosure() {
|
|
|
|
|
sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0); |
|
|
|
|
|
|
|
|
|
if (isTrueType) { |
|
|
|
|
var isGlyphLocationsLong = int16([tables.head.data[50], |
|
|
|
|
tables.head.data[51]]); |
|
|
|
|
var isGlyphLocationsLong = int16(tables.head.data[50], |
|
|
|
|
tables.head.data[51]); |
|
|
|
|
sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs, |
|
|
|
|
isGlyphLocationsLong, hintsValid, dupFirstEntry); |
|
|
|
|
} |
|
|
|
@ -3926,11 +3925,11 @@ var Font = (function FontClosure() {
@@ -3926,11 +3925,11 @@ var Font = (function FontClosure() {
|
|
|
|
|
// extract some more font properties from the OpenType head and
|
|
|
|
|
// hhea tables; yMin and descent value are always negative
|
|
|
|
|
var override = { |
|
|
|
|
unitsPerEm: int16([tables.head.data[18], tables.head.data[19]]), |
|
|
|
|
yMax: int16([tables.head.data[42], tables.head.data[43]]), |
|
|
|
|
yMin: int16([tables.head.data[38], tables.head.data[39]]) - 0x10000, |
|
|
|
|
ascent: int16([tables.hhea.data[4], tables.hhea.data[5]]), |
|
|
|
|
descent: int16([tables.hhea.data[6], tables.hhea.data[7]]) - 0x10000 |
|
|
|
|
unitsPerEm: int16(tables.head.data[18], tables.head.data[19]), |
|
|
|
|
yMax: int16(tables.head.data[42], tables.head.data[43]), |
|
|
|
|
yMin: int16(tables.head.data[38], tables.head.data[39]) - 0x10000, |
|
|
|
|
ascent: int16(tables.hhea.data[4], tables.hhea.data[5]), |
|
|
|
|
descent: int16(tables.hhea.data[6], tables.hhea.data[7]) - 0x10000 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
tables['OS/2'] = { |
|
|
|
@ -4781,7 +4780,7 @@ var Type1CharString = (function Type1CharStringClosure() {
@@ -4781,7 +4780,7 @@ var Type1CharString = (function Type1CharStringClosure() {
|
|
|
|
|
if (keepStack) { |
|
|
|
|
this.stack.splice(start, howManyArgs); |
|
|
|
|
} else { |
|
|
|
|
this.stack = []; |
|
|
|
|
this.stack.length = 0; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|