Allocate fewer objects when parsing 2 and 4 byte chunks.
This is achieved by adding getBytes2() and getBytes4() to streams, and by changing int16() and int32() to take multiple scalar args instead of an array arg.
This commit is contained in:
parent
e5cd75083f
commit
6a75e45309
@ -140,6 +140,20 @@ var ChunkedStream = (function ChunkedStreamClosure() {
|
||||
return this.bytes[this.pos++];
|
||||
},
|
||||
|
||||
getUint16: function ChunkedStream_getUint16() {
|
||||
var b0 = this.getByte();
|
||||
var b1 = this.getByte();
|
||||
return (b0 << 8) + b1;
|
||||
},
|
||||
|
||||
getUint32: function ChunkedStream_getUint32() {
|
||||
var b0 = this.getByte();
|
||||
var b1 = this.getByte();
|
||||
var b2 = this.getByte();
|
||||
var b3 = this.getByte();
|
||||
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
|
||||
},
|
||||
|
||||
// returns subarray of original buffer
|
||||
// should only be read
|
||||
getBytes: function ChunkedStream_getBytes(length) {
|
||||
|
@ -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() {
|
||||
// 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() {
|
||||
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
// 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() {
|
||||
}
|
||||
|
||||
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() {
|
||||
} 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() {
|
||||
|
||||
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() {
|
||||
// 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() {
|
||||
|
||||
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() {
|
||||
|
||||
// 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() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
|
||||
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() {
|
||||
// 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() {
|
||||
}
|
||||
|
||||
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() {
|
||||
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() {
|
||||
// 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'] = {
|
||||
|
@ -40,6 +40,18 @@ var Stream = (function StreamClosure() {
|
||||
return -1;
|
||||
return this.bytes[this.pos++];
|
||||
},
|
||||
getUint16: function Stream_getUint16() {
|
||||
var b0 = this.getByte();
|
||||
var b1 = this.getByte();
|
||||
return (b0 << 8) + b1;
|
||||
},
|
||||
getUint32: function Stream_getUint32() {
|
||||
var b0 = this.getByte();
|
||||
var b1 = this.getByte();
|
||||
var b2 = this.getByte();
|
||||
var b3 = this.getByte();
|
||||
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
|
||||
},
|
||||
// returns subarray of original buffer
|
||||
// should only be read
|
||||
getBytes: function Stream_getBytes(length) {
|
||||
@ -143,6 +155,18 @@ var DecodeStream = (function DecodeStreamClosure() {
|
||||
}
|
||||
return this.buffer[this.pos++];
|
||||
},
|
||||
getUint16: function DecodeStream_getUint16() {
|
||||
var b0 = this.getByte();
|
||||
var b1 = this.getByte();
|
||||
return (b0 << 8) + b1;
|
||||
},
|
||||
getUint32: function DecodeStream_getUint32() {
|
||||
var b0 = this.getByte();
|
||||
var b1 = this.getByte();
|
||||
var b2 = this.getByte();
|
||||
var b3 = this.getByte();
|
||||
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
|
||||
},
|
||||
getBytes: function DecodeStream_getBytes(length) {
|
||||
var end, pos = this.pos;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user