diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 10cd2a963..3b8a4c9b2 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -1827,7 +1827,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { extractDataStructures: function PartialEvaluator_extractDataStructures(dict, baseDict, properties) { - var xref = this.xref; + let xref = this.xref, cidToGidBytes; // 9.10.2 var toUnicode = (dict.get('ToUnicode') || baseDict.get('ToUnicode')); var toUnicodePromise = toUnicode ? @@ -1846,7 +1846,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { var cidToGidMap = dict.get('CIDToGIDMap'); if (isStream(cidToGidMap)) { - properties.cidToGidMap = this.readCidToGidMap(cidToGidMap); + cidToGidBytes = cidToGidMap.getBytes(); } } @@ -1929,8 +1929,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { return toUnicodePromise.then((toUnicode) => { properties.toUnicode = toUnicode; return this.buildToUnicode(properties); - }).then(function (toUnicode) { + }).then((toUnicode) => { properties.toUnicode = toUnicode; + if (cidToGidBytes) { + properties.cidToGidMap = this.readCidToGidMap(cidToGidBytes, + toUnicode); + } return properties; }); }, @@ -2146,18 +2150,17 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { return Promise.resolve(null); }, - readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) { + readCidToGidMap(glyphsData, toUnicode) { // Extract the encoding from the CIDToGIDMap - var glyphsData = cidToGidStream.getBytes(); // Set encoding 0 to later verify the font has an encoding var result = []; for (var j = 0, jj = glyphsData.length; j < jj; j++) { var glyphID = (glyphsData[j++] << 8) | glyphsData[j]; - if (glyphID === 0) { + const code = j >> 1; + if (glyphID === 0 && !toUnicode.has(code)) { continue; } - var code = j >> 1; result[code] = glyphID; } return result; diff --git a/src/core/fonts.js b/src/core/fonts.js index f4d00ae8d..c519dd75d 100644 --- a/src/core/fonts.js +++ b/src/core/fonts.js @@ -1606,7 +1606,8 @@ var Font = (function FontClosure() { }; } - function sanitizeMetrics(font, header, metrics, numGlyphs) { + function sanitizeMetrics(font, header, metrics, numGlyphs, + dupFirstEntry) { if (!header) { if (metrics) { metrics.data = null; @@ -1649,6 +1650,11 @@ var Font = (function FontClosure() { // the use of |numMissing * 2| when initializing the typed array. var entries = new Uint8Array(metrics.length + numMissing * 2); entries.set(metrics.data); + if (dupFirstEntry) { + // Set the sidebearing value of the duplicated glyph. + entries[metrics.length] = metrics.data[2]; + entries[metrics.length + 1] = metrics.data[3]; + } metrics.data = entries; } } @@ -2366,7 +2372,8 @@ var Font = (function FontClosure() { // Ensure the hmtx table contains the advance width and // sidebearings information for numGlyphs in the maxp table - sanitizeMetrics(font, tables['hhea'], tables['hmtx'], numGlyphsOut); + sanitizeMetrics(font, tables['hhea'], tables['hmtx'], numGlyphsOut, + dupFirstEntry); if (!tables['head']) { throw new FormatError('Required "head" table is not found'); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 343eeef41..b704c9682 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -293,6 +293,7 @@ !issue5540.pdf !issue5549.pdf !issue5475.pdf +!issue10519_reduced.pdf !annotation-border-styles.pdf !IdentityToUnicodeMap_charCodeOf.pdf !PDFJS-9279-reduced.pdf diff --git a/test/pdfs/issue10519_reduced.pdf b/test/pdfs/issue10519_reduced.pdf new file mode 100644 index 000000000..a80ff5e2c Binary files /dev/null and b/test/pdfs/issue10519_reduced.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 20605a9b2..ecf7234d5 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -3126,6 +3126,12 @@ "lastPage": 4, "type": "load" }, + { "id": "issue10519", + "file": "pdfs/issue10519_reduced.pdf", + "md5": "8a2dae43c0ef47b0734bedaaa24f8c09", + "rounds": 1, + "type": "eq" + }, { "id": "issue3061", "file": "pdfs/issue3061.pdf", "md5": "696a7cb1b194d095ca3f7861779a606b",