Fix bad truetype loca tables.
Some fonts have loca tables that aren't sorted or use 0 as an offset to signal a missing glyph. This fixes the bad loca tables by sorting them and then rewriting the loca table and potentially re-ordering the glyf table to match. Fixes #11131 and bug 1650302.
This commit is contained in:
parent
8c162f57f7
commit
f6dff81223
@ -2050,35 +2050,48 @@ var Font = (function FontClosure() {
|
||||
var oldGlyfData = glyf.data;
|
||||
var oldGlyfDataLength = oldGlyfData.length;
|
||||
var newGlyfData = new Uint8Array(oldGlyfDataLength);
|
||||
var startOffset = itemDecode(locaData, 0);
|
||||
var writeOffset = 0;
|
||||
var missingGlyphs = Object.create(null);
|
||||
itemEncode(locaData, 0, writeOffset);
|
||||
var i, j;
|
||||
for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
|
||||
var endOffset = itemDecode(locaData, j);
|
||||
// The spec says the offsets should be in ascending order, however
|
||||
// some fonts use the offset of 0 to mark a glyph as missing.
|
||||
if (endOffset === 0) {
|
||||
endOffset = startOffset;
|
||||
}
|
||||
if (
|
||||
endOffset > oldGlyfDataLength &&
|
||||
((oldGlyfDataLength + 3) & ~3) === endOffset
|
||||
) {
|
||||
// Aspose breaks fonts by aligning the glyphs to the qword, but not
|
||||
// the glyf table size, which makes last glyph out of range.
|
||||
endOffset = oldGlyfDataLength;
|
||||
}
|
||||
if (endOffset > oldGlyfDataLength) {
|
||||
// glyph end offset points outside glyf data, rejecting the glyph
|
||||
startOffset = endOffset;
|
||||
}
|
||||
|
||||
// The spec says the offsets should be in ascending order, however
|
||||
// this is not true for some fonts or they use the offset of 0 to mark a
|
||||
// glyph as missing. OTS requires the offsets to be in order and not to
|
||||
// be zero, so we must sort and rebuild the loca table and potentially
|
||||
// re-arrange the glyf data.
|
||||
var i, j;
|
||||
const locaEntries = [];
|
||||
// There are numGlyphs + 1 loca table entries.
|
||||
for (i = 0, j = 0; i < numGlyphs + 1; i++, j += itemSize) {
|
||||
let offset = itemDecode(locaData, j);
|
||||
if (offset > oldGlyfDataLength) {
|
||||
offset = oldGlyfDataLength;
|
||||
}
|
||||
locaEntries.push({
|
||||
index: i,
|
||||
offset,
|
||||
endOffset: 0,
|
||||
});
|
||||
}
|
||||
locaEntries.sort((a, b) => {
|
||||
return a.offset - b.offset;
|
||||
});
|
||||
// Now the offsets are sorted, calculate the end offset of each glyph.
|
||||
// The last loca entry's endOffset is not calculated since it's the end
|
||||
// of the data and will be stored on the previous entry's endOffset.
|
||||
for (i = 0; i < numGlyphs; i++) {
|
||||
locaEntries[i].endOffset = locaEntries[i + 1].offset;
|
||||
}
|
||||
// Re-sort so glyphs aren't out of order.
|
||||
locaEntries.sort((a, b) => {
|
||||
return a.index - b.index;
|
||||
});
|
||||
|
||||
var missingGlyphs = Object.create(null);
|
||||
var writeOffset = 0;
|
||||
itemEncode(locaData, 0, writeOffset);
|
||||
for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
|
||||
var glyphProfile = sanitizeGlyph(
|
||||
oldGlyfData,
|
||||
startOffset,
|
||||
endOffset,
|
||||
locaEntries[i].offset,
|
||||
locaEntries[i].endOffset,
|
||||
newGlyfData,
|
||||
writeOffset,
|
||||
hintsValid
|
||||
@ -2092,7 +2105,6 @@ var Font = (function FontClosure() {
|
||||
}
|
||||
writeOffset += newLength;
|
||||
itemEncode(locaData, j, writeOffset);
|
||||
startOffset = endOffset;
|
||||
}
|
||||
|
||||
if (writeOffset === 0) {
|
||||
|
2
test/pdfs/.gitignore
vendored
2
test/pdfs/.gitignore
vendored
@ -63,6 +63,7 @@
|
||||
!issue8372.pdf
|
||||
!issue8424.pdf
|
||||
!issue8480.pdf
|
||||
!bug1650302_reduced.pdf
|
||||
!issue8570.pdf
|
||||
!issue8697.pdf
|
||||
!issue8702.pdf
|
||||
@ -121,6 +122,7 @@
|
||||
!bug1132849.pdf
|
||||
!issue6894.pdf
|
||||
!issue5804.pdf
|
||||
!issue11131_reduced.pdf
|
||||
!Pages-tree-refs.pdf
|
||||
!ShowText-ShadingPattern.pdf
|
||||
!complex_ttf_font.pdf
|
||||
|
BIN
test/pdfs/bug1650302_reduced.pdf
Normal file
BIN
test/pdfs/bug1650302_reduced.pdf
Normal file
Binary file not shown.
BIN
test/pdfs/issue11131_reduced.pdf
Normal file
BIN
test/pdfs/issue11131_reduced.pdf
Normal file
Binary file not shown.
@ -3268,6 +3268,12 @@
|
||||
"link": true,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "issue11131_reduced",
|
||||
"file": "pdfs/issue11131_reduced.pdf",
|
||||
"md5": "004b7e7d2b133a8dc4fe64aaf3dc9533",
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "issue818",
|
||||
"file": "pdfs/issue818.pdf",
|
||||
"md5": "dd2f8a5bd65164ad74da2b45a6ca90cc",
|
||||
@ -3365,6 +3371,12 @@
|
||||
"link": false,
|
||||
"type": "load"
|
||||
},
|
||||
{ "id": "bug1650302_reduced",
|
||||
"file": "pdfs/bug1650302_reduced.pdf",
|
||||
"md5": "d918c9ec936486e8b6656e10dd909014",
|
||||
"rounds": 1,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "blendmode",
|
||||
"file": "pdfs/blendmode.pdf",
|
||||
"md5": "5a86e7e9333e93c58abc3f382e1e6ea2",
|
||||
|
Loading…
Reference in New Issue
Block a user