From 858d941ff8aaa94f8126cb133b72a80c9698d3f5 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 11 Oct 2022 20:08:36 +0200 Subject: [PATCH] Take the /CIDToGIDMap into account when getting the glyph mapping for CFF fonts (issue 15559) *Please note:* I don't really know what I'm doing here, however the patch appears to fix the referenced issue when comparing the rendering with Adobe Reader (with the caveat that I don't speak the language in question). --- src/core/cff_font.js | 27 +++++++++++++++++++++++++-- test/pdfs/issue15559.pdf.link | 1 + test/test_manifest.json | 8 ++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 test/pdfs/issue15559.pdf.link diff --git a/src/core/cff_font.js b/src/core/cff_font.js index 33805586a..ac4534252 100644 --- a/src/core/cff_font.js +++ b/src/core/cff_font.js @@ -48,11 +48,23 @@ class CFFFont { getGlyphMapping() { const cff = this.cff; const properties = this.properties; + const { cidToGidMap, cMap } = properties; const charsets = cff.charset.charset; let charCodeToGlyphId; let glyphId; if (properties.composite) { + let invCidToGidMap; + if (cidToGidMap && cidToGidMap.length > 0) { + invCidToGidMap = Object.create(null); + for (let i = 0, ii = cidToGidMap.length; i < ii; i++) { + const gid = cidToGidMap[i]; + if (gid !== undefined) { + invCidToGidMap[gid] = i; + } + } + } + charCodeToGlyphId = Object.create(null); let charCode; if (cff.isCIDFont) { @@ -60,14 +72,25 @@ class CFFFont { // to map CIDs to GIDs. for (glyphId = 0; glyphId < charsets.length; glyphId++) { const cid = charsets[glyphId]; - charCode = properties.cMap.charCodeOf(cid); + charCode = cMap.charCodeOf(cid); + + if (invCidToGidMap && invCidToGidMap[charCode] !== undefined) { + // According to the PDF specification, see Table 117, it's not clear + // that a /CIDToGIDMap should be used with any non-TrueType fonts, + // however it's necessary to do so in order to fix issue 15559. + // + // It seems, in the CFF-case, that the /CIDToGIDMap needs to be used + // "inverted" compared to the TrueType-case. Here it thus seem to be + // a charCode mapping, rather than the normal CID to GID mapping. + charCode = invCidToGidMap[charCode]; + } charCodeToGlyphId[charCode] = glyphId; } } else { // If it is NOT actually a CID font then CIDs should be mapped // directly to GIDs. for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) { - charCode = properties.cMap.charCodeOf(glyphId); + charCode = cMap.charCodeOf(glyphId); charCodeToGlyphId[charCode] = glyphId; } } diff --git a/test/pdfs/issue15559.pdf.link b/test/pdfs/issue15559.pdf.link new file mode 100644 index 000000000..edf7a057c --- /dev/null +++ b/test/pdfs/issue15559.pdf.link @@ -0,0 +1 @@ +https://github.com/mozilla/pdf.js/files/9745330/FutureABC.L3.-1.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 534cdaf2d..2d2215b39 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -653,6 +653,14 @@ "type": "eq", "annotations": true }, + { "id": "issue15559", + "file": "pdfs/issue15559.pdf", + "md5": "b937f2e32925aef8c1740f357f2a6282", + "link": true, + "rounds": 1, + "lastPage": 1, + "type": "eq" + }, { "id": "hmm-pdf", "file": "pdfs/hmm.pdf", "md5": "e08467e60101ee5f4a59716e86db6dc9",