Implement TrueType character map "format 2" (fixes #14117)

If a PDF included an embedded TrueType font whose preferred character
map (cmap) was in "format 2", the code would select that character map
and then refuse to read it because of an unsupported format, thus
causing the characters not to be rendered. This commit implements
support for format 2 as described at the link below.

https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html
This commit is contained in:
Jay Berkenbilt 2021-10-12 18:24:18 -04:00
parent 3945965605
commit 586295fad6
4 changed files with 56 additions and 0 deletions

View File

@ -1497,6 +1497,55 @@ class Font {
});
}
hasShortCmap = true;
} else if (format === 2) {
const subHeaderKeys = [];
let maxSubHeaderKey = 0;
// Read subHeaderKeys. If subHeaderKeys[i] === 0, then i is a
// single-byte character. Otherwise, i is the first byte of a
// multi-byte character, and the value is 8*index into
// subHeaders.
for (let i = 0; i < 256; i++) {
const subHeaderKey = file.getUint16() >> 3;
subHeaderKeys.push(subHeaderKey);
maxSubHeaderKey = Math.max(subHeaderKey, maxSubHeaderKey);
}
// Read subHeaders. The number of entries is determined
// dynamically based on the subHeaderKeys found above.
const subHeaders = [];
for (let i = 0; i <= maxSubHeaderKey; i++) {
subHeaders.push({
firstCode: file.getUint16(),
entryCount: file.getUint16(),
idDelta: signedInt16(file.getByte(), file.getByte()),
idRangePos: file.pos + file.getUint16(),
});
}
for (let i = 0; i < 256; i++) {
if (subHeaderKeys[i] === 0) {
// i is a single-byte code.
file.pos = subHeaders[0].idRangePos + 2 * i;
glyphId = file.getUint16();
mappings.push({
charCode: i,
glyphId,
});
} else {
// i is the first byte of a two-byte code.
const s = subHeaders[subHeaderKeys[i]];
for (j = 0; j < s.entryCount; j++) {
const charCode = (i << 8) + j + s.firstCode;
file.pos = s.idRangePos + 2 * j;
glyphId = file.getUint16();
if (glyphId !== 0) {
glyphId = (glyphId + s.idDelta) % 65536;
}
mappings.push({
charCode,
glyphId,
});
}
}
}
} else if (format === 4) {
// re-creating the table in format 4 since the encoding
// might be changed

View File

@ -288,6 +288,7 @@
!PDFJS-7562-reduced.pdf
!issue11768_reduced.pdf
!issue5039.pdf
!issue14117.pdf
!issue5070.pdf
!issue5238.pdf
!issue5244.pdf

BIN
test/pdfs/issue14117.pdf Normal file

Binary file not shown.

View File

@ -5589,6 +5589,12 @@
"type": "eq",
"annotations": true
},
{ "id": "issue14117",
"file": "pdfs/issue14117.pdf",
"md5": "9b1c33ad2f59f4e723c258e863149abf",
"rounds": 1,
"type": "eq"
},
{ "id": "annotation-text-widget-annotations",
"file": "pdfs/annotation-text-widget.pdf",
"md5": "b7b8923a12998fca8603fae53f73f19b",