1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-22 16:18:08 +02:00

Hide .notdef glyphs in non-embedded Type1 fonts and don't ignore Widths

Fixes #11403
The PDF uses the non-embedded Type1 font Helvetica. Character codes 194 and 160 (`Â` and `NBSP`) are encoded as `.notdef`. We shouldn't show those glyphs because it seems that Acrobat Reader doesn't draw glyphs that are named `.notdef` in fonts like this.

In addition to testing `glyphName === ".notdef"`, we must test also `glyphName === ""` because the name `""` is used in `core/encodings.js` for undefined glyphs in encodings like `WinAnsiEncoding`.

The solution above hides the `Â` characters but now the replacement character (space) appears to be too wide. I found out that PDF.js ignores font's `Widths` array if the font has no `FontDescriptor` entry. That happens in #11403, so the default widths of Helvetica were used as specified in `core/metrics.js` and `.nodef` got a width of 333. The correct width is 0 as specified by the `Widths` array in the PDF. Thus we must never ignore `Widths`.
This commit is contained in:
Jani Pehkonen 2020-01-21 20:36:41 +02:00
parent 40f531ee87
commit 809b96b40c
5 changed files with 125 additions and 8 deletions

View file

@ -2945,6 +2945,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var type = preEvaluatedFont.type;
var maxCharIndex = composite ? 0xffff : 0xff;
var properties;
const firstChar = dict.get("FirstChar") || 0;
const lastChar = dict.get("LastChar") || maxCharIndex;
if (!descriptor) {
if (type === "Type3") {
@ -2981,15 +2983,25 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
widths: metrics.widths,
defaultWidth: metrics.defaultWidth,
flags,
firstChar: 0,
lastChar: maxCharIndex,
firstChar,
lastChar,
};
const widths = dict.get("Widths");
return this.extractDataStructures(dict, dict, properties).then(
properties => {
properties.widths = this.buildCharCodeToWidth(
metrics.widths,
properties
);
if (widths) {
const glyphWidths = [];
let j = firstChar;
for (let i = 0, ii = widths.length; i < ii; i++) {
glyphWidths[j++] = this.xref.fetchIfRef(widths[i]);
}
properties.widths = glyphWidths;
} else {
properties.widths = this.buildCharCodeToWidth(
metrics.widths,
properties
);
}
return new Font(baseFontName, null, properties);
}
);
@ -3001,8 +3013,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
// to ignore this rule when a variant of a standard font is used.
// TODO Fill the width array depending on which of the base font this is
// a variant.
var firstChar = dict.get("FirstChar") || 0;
var lastChar = dict.get("LastChar") || maxCharIndex;
var fontName = descriptor.get("FontName");
var baseFont = dict.get("BaseFont");

View file

@ -3392,6 +3392,16 @@ var Font = (function FontClosure() {
// back to the char code.
fontCharCode = this.toFontChar[charcode] || charcode;
if (this.missingFile) {
const glyphName =
this.differences[charcode] || this.defaultEncoding[charcode];
if (
(glyphName === ".notdef" || glyphName === "") &&
this.type === "Type1"
) {
// .notdef glyphs should be invisible in non-embedded Type1 fonts, so
// replace them with spaces.
fontCharCode = 0x20;
}
fontCharCode = mapSpecialUnicodeValues(fontCharCode);
}