Merge pull request #8955 from brendandahl/issue7507
Overwrite maxSizeOfInstructions in maxp with computed value.
This commit is contained in:
commit
b837187094
@ -1568,16 +1568,21 @@ var Font = (function FontClosure() {
|
|||||||
|
|
||||||
function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart,
|
function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart,
|
||||||
hintsValid) {
|
hintsValid) {
|
||||||
|
var glyphProfile = {
|
||||||
|
length: 0,
|
||||||
|
sizeOfInstructions: 0,
|
||||||
|
};
|
||||||
if (sourceEnd - sourceStart <= 12) {
|
if (sourceEnd - sourceStart <= 12) {
|
||||||
// glyph with data less than 12 is invalid one
|
// glyph with data less than 12 is invalid one
|
||||||
return 0;
|
return glyphProfile;
|
||||||
}
|
}
|
||||||
var glyf = source.subarray(sourceStart, sourceEnd);
|
var glyf = source.subarray(sourceStart, sourceEnd);
|
||||||
var contoursCount = (glyf[0] << 8) | glyf[1];
|
var contoursCount = (glyf[0] << 8) | glyf[1];
|
||||||
if (contoursCount & 0x8000) {
|
if (contoursCount & 0x8000) {
|
||||||
// complex glyph, writing as is
|
// complex glyph, writing as is
|
||||||
dest.set(glyf, destStart);
|
dest.set(glyf, destStart);
|
||||||
return glyf.length;
|
glyphProfile.length = glyf.length;
|
||||||
|
return glyphProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
var i, j = 10, flagsCount = 0;
|
var i, j = 10, flagsCount = 0;
|
||||||
@ -1589,6 +1594,7 @@ var Font = (function FontClosure() {
|
|||||||
// skipping instructions
|
// skipping instructions
|
||||||
var instructionsStart = j;
|
var instructionsStart = j;
|
||||||
var instructionsLength = (glyf[j] << 8) | glyf[j + 1];
|
var instructionsLength = (glyf[j] << 8) | glyf[j + 1];
|
||||||
|
glyphProfile.sizeOfInstructions = instructionsLength;
|
||||||
j += 2 + instructionsLength;
|
j += 2 + instructionsLength;
|
||||||
var instructionsEnd = j;
|
var instructionsEnd = j;
|
||||||
// validating flags
|
// validating flags
|
||||||
@ -1610,12 +1616,12 @@ var Font = (function FontClosure() {
|
|||||||
}
|
}
|
||||||
// glyph without coordinates will be rejected
|
// glyph without coordinates will be rejected
|
||||||
if (coordinatesLength === 0) {
|
if (coordinatesLength === 0) {
|
||||||
return 0;
|
return glyphProfile;
|
||||||
}
|
}
|
||||||
var glyphDataLength = j + coordinatesLength;
|
var glyphDataLength = j + coordinatesLength;
|
||||||
if (glyphDataLength > glyf.length) {
|
if (glyphDataLength > glyf.length) {
|
||||||
// not enough data for coordinates
|
// not enough data for coordinates
|
||||||
return 0;
|
return glyphProfile;
|
||||||
}
|
}
|
||||||
if (!hintsValid && instructionsLength > 0) {
|
if (!hintsValid && instructionsLength > 0) {
|
||||||
dest.set(glyf.subarray(0, instructionsStart), destStart);
|
dest.set(glyf.subarray(0, instructionsStart), destStart);
|
||||||
@ -1626,17 +1632,20 @@ var Font = (function FontClosure() {
|
|||||||
if (glyf.length - glyphDataLength > 3) {
|
if (glyf.length - glyphDataLength > 3) {
|
||||||
glyphDataLength = (glyphDataLength + 3) & ~3;
|
glyphDataLength = (glyphDataLength + 3) & ~3;
|
||||||
}
|
}
|
||||||
return glyphDataLength;
|
glyphProfile.length = glyphDataLength;
|
||||||
|
return glyphProfile;
|
||||||
}
|
}
|
||||||
if (glyf.length - glyphDataLength > 3) {
|
if (glyf.length - glyphDataLength > 3) {
|
||||||
// truncating and aligning to 4 bytes the long glyph data
|
// truncating and aligning to 4 bytes the long glyph data
|
||||||
glyphDataLength = (glyphDataLength + 3) & ~3;
|
glyphDataLength = (glyphDataLength + 3) & ~3;
|
||||||
dest.set(glyf.subarray(0, glyphDataLength), destStart);
|
dest.set(glyf.subarray(0, glyphDataLength), destStart);
|
||||||
return glyphDataLength;
|
glyphProfile.length = glyphDataLength;
|
||||||
|
return glyphProfile;
|
||||||
}
|
}
|
||||||
// glyph data is fine
|
// glyph data is fine
|
||||||
dest.set(glyf, destStart);
|
dest.set(glyf, destStart);
|
||||||
return glyf.length;
|
glyphProfile.length = glyf.length;
|
||||||
|
return glyphProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sanitizeHead(head, numGlyphs, locaLength) {
|
function sanitizeHead(head, numGlyphs, locaLength) {
|
||||||
@ -1686,7 +1695,7 @@ var Font = (function FontClosure() {
|
|||||||
|
|
||||||
function sanitizeGlyphLocations(loca, glyf, numGlyphs,
|
function sanitizeGlyphLocations(loca, glyf, numGlyphs,
|
||||||
isGlyphLocationsLong, hintsValid,
|
isGlyphLocationsLong, hintsValid,
|
||||||
dupFirstEntry) {
|
dupFirstEntry, maxSizeOfInstructions) {
|
||||||
var itemSize, itemDecode, itemEncode;
|
var itemSize, itemDecode, itemEncode;
|
||||||
if (isGlyphLocationsLong) {
|
if (isGlyphLocationsLong) {
|
||||||
itemSize = 4;
|
itemSize = 4;
|
||||||
@ -1724,7 +1733,7 @@ var Font = (function FontClosure() {
|
|||||||
var newGlyfData = new Uint8Array(oldGlyfDataLength);
|
var newGlyfData = new Uint8Array(oldGlyfDataLength);
|
||||||
var startOffset = itemDecode(locaData, 0);
|
var startOffset = itemDecode(locaData, 0);
|
||||||
var writeOffset = 0;
|
var writeOffset = 0;
|
||||||
var missingGlyphData = Object.create(null);
|
var missingGlyphs = Object.create(null);
|
||||||
itemEncode(locaData, 0, writeOffset);
|
itemEncode(locaData, 0, writeOffset);
|
||||||
var i, j;
|
var i, j;
|
||||||
// When called with dupFirstEntry the number of glyphs has already been
|
// When called with dupFirstEntry the number of glyphs has already been
|
||||||
@ -1743,10 +1752,15 @@ var Font = (function FontClosure() {
|
|||||||
startOffset = endOffset;
|
startOffset = endOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
|
var glyphProfile = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
|
||||||
newGlyfData, writeOffset, hintsValid);
|
newGlyfData, writeOffset,
|
||||||
|
hintsValid);
|
||||||
|
var newLength = glyphProfile.length;
|
||||||
if (newLength === 0) {
|
if (newLength === 0) {
|
||||||
missingGlyphData[i] = true;
|
missingGlyphs[i] = true;
|
||||||
|
}
|
||||||
|
if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) {
|
||||||
|
maxSizeOfInstructions = glyphProfile.sizeOfInstructions;
|
||||||
}
|
}
|
||||||
writeOffset += newLength;
|
writeOffset += newLength;
|
||||||
itemEncode(locaData, j, writeOffset);
|
itemEncode(locaData, j, writeOffset);
|
||||||
@ -1762,10 +1776,7 @@ var Font = (function FontClosure() {
|
|||||||
itemEncode(locaData, j, simpleGlyph.length);
|
itemEncode(locaData, j, simpleGlyph.length);
|
||||||
}
|
}
|
||||||
glyf.data = simpleGlyph;
|
glyf.data = simpleGlyph;
|
||||||
return missingGlyphData;
|
} else if (dupFirstEntry) {
|
||||||
}
|
|
||||||
|
|
||||||
if (dupFirstEntry) {
|
|
||||||
var firstEntryLength = itemDecode(locaData, itemSize);
|
var firstEntryLength = itemDecode(locaData, itemSize);
|
||||||
if (newGlyfData.length > firstEntryLength + writeOffset) {
|
if (newGlyfData.length > firstEntryLength + writeOffset) {
|
||||||
glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
|
glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
|
||||||
@ -1779,7 +1790,10 @@ var Font = (function FontClosure() {
|
|||||||
} else {
|
} else {
|
||||||
glyf.data = newGlyfData.subarray(0, writeOffset);
|
glyf.data = newGlyfData.subarray(0, writeOffset);
|
||||||
}
|
}
|
||||||
return missingGlyphData;
|
return {
|
||||||
|
missingGlyphs,
|
||||||
|
maxSizeOfInstructions,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function readPostScriptTable(post, properties, maxpNumGlyphs) {
|
function readPostScriptTable(post, properties, maxpNumGlyphs) {
|
||||||
@ -2226,6 +2240,7 @@ var Font = (function FontClosure() {
|
|||||||
var version = font.getInt32();
|
var version = font.getInt32();
|
||||||
var numGlyphs = font.getUint16();
|
var numGlyphs = font.getUint16();
|
||||||
var maxFunctionDefs = 0;
|
var maxFunctionDefs = 0;
|
||||||
|
var maxSizeOfInstructions = 0;
|
||||||
if (version >= 0x00010000 && tables['maxp'].length >= 22) {
|
if (version >= 0x00010000 && tables['maxp'].length >= 22) {
|
||||||
// maxZones can be invalid
|
// maxZones can be invalid
|
||||||
font.pos += 8;
|
font.pos += 8;
|
||||||
@ -2236,6 +2251,8 @@ var Font = (function FontClosure() {
|
|||||||
}
|
}
|
||||||
font.pos += 4;
|
font.pos += 4;
|
||||||
maxFunctionDefs = font.getUint16();
|
maxFunctionDefs = font.getUint16();
|
||||||
|
font.pos += 6;
|
||||||
|
maxSizeOfInstructions = font.getUint16();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dupFirstEntry = false;
|
var dupFirstEntry = false;
|
||||||
@ -2271,11 +2288,19 @@ var Font = (function FontClosure() {
|
|||||||
if (isTrueType) {
|
if (isTrueType) {
|
||||||
var isGlyphLocationsLong = int16(tables['head'].data[50],
|
var isGlyphLocationsLong = int16(tables['head'].data[50],
|
||||||
tables['head'].data[51]);
|
tables['head'].data[51]);
|
||||||
missingGlyphs = sanitizeGlyphLocations(tables['loca'], tables['glyf'],
|
var glyphsInfo = sanitizeGlyphLocations(tables['loca'], tables['glyf'],
|
||||||
numGlyphs, isGlyphLocationsLong,
|
numGlyphs, isGlyphLocationsLong,
|
||||||
hintsValid, dupFirstEntry);
|
hintsValid, dupFirstEntry,
|
||||||
}
|
maxSizeOfInstructions);
|
||||||
|
missingGlyphs = glyphsInfo.missingGlyphs;
|
||||||
|
|
||||||
|
// Some fonts have incorrect maxSizeOfInstructions values, so we use
|
||||||
|
// the computed value instead.
|
||||||
|
if (version >= 0x00010000 && tables['maxp'].length >= 22) {
|
||||||
|
tables['maxp'].data[26] = glyphsInfo.maxSizeOfInstructions >> 8;
|
||||||
|
tables['maxp'].data[27] = glyphsInfo.maxSizeOfInstructions & 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!tables['hhea']) {
|
if (!tables['hhea']) {
|
||||||
throw new FormatError('Required "hhea" table is not found');
|
throw new FormatError('Required "hhea" table is not found');
|
||||||
}
|
}
|
||||||
|
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -40,6 +40,7 @@
|
|||||||
!issue7446.pdf
|
!issue7446.pdf
|
||||||
!issue7492.pdf
|
!issue7492.pdf
|
||||||
!issue7544.pdf
|
!issue7544.pdf
|
||||||
|
!issue7507.pdf
|
||||||
!issue7580.pdf
|
!issue7580.pdf
|
||||||
!issue7598.pdf
|
!issue7598.pdf
|
||||||
!issue7665.pdf
|
!issue7665.pdf
|
||||||
|
BIN
test/pdfs/issue7507.pdf
Normal file
BIN
test/pdfs/issue7507.pdf
Normal file
Binary file not shown.
@ -684,6 +684,13 @@
|
|||||||
"link": false,
|
"link": false,
|
||||||
"type": "load"
|
"type": "load"
|
||||||
},
|
},
|
||||||
|
{ "id": "issue7507",
|
||||||
|
"file": "pdfs/issue7507.pdf",
|
||||||
|
"md5": "f7aeaafe0c89b94436e94eaa63307303",
|
||||||
|
"rounds": 1,
|
||||||
|
"link": false,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue5501",
|
{ "id": "issue5501",
|
||||||
"file": "pdfs/issue5501.pdf",
|
"file": "pdfs/issue5501.pdf",
|
||||||
"md5": "55a60699728fc92f491a2d7d490474e4",
|
"md5": "55a60699728fc92f491a2d7d490474e4",
|
||||||
|
Loading…
Reference in New Issue
Block a user