diff --git a/src/core/fonts.js b/src/core/fonts.js index 30de218ce..355aca399 100644 --- a/src/core/fonts.js +++ b/src/core/fonts.js @@ -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) { diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 085de126c..8476ef86c 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -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 diff --git a/test/pdfs/bug1650302_reduced.pdf b/test/pdfs/bug1650302_reduced.pdf new file mode 100644 index 000000000..0bd014b75 Binary files /dev/null and b/test/pdfs/bug1650302_reduced.pdf differ diff --git a/test/pdfs/issue11131_reduced.pdf b/test/pdfs/issue11131_reduced.pdf new file mode 100644 index 000000000..4920fdbd0 Binary files /dev/null and b/test/pdfs/issue11131_reduced.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index c13f77c34..193acc406 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -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",