Improve handling of mismatching /BaseFont and /FontName entries for non-embedded fonts (issue 7454)

This patch is the result of me going through some old issues regarding non-embedded Wingdings support.

There's a few different things wrong in the referenced PDF document:
 - The /BaseFont and /FontName entries don't agree on the name of the fonts, with one font using `/BaseFont /Wingdings-Regular` and `/FontName /wg09np` which obviously makes no sense.
   To address this we'll compare the font-names against our lists of known ones and ignore /FontName entries that don't make sense iff the /BaseFont entry is a known font-name.
 - The non-embedded Wingdings font also set an incorrect /Encoding, in this case /MacRomanEncoding, which should have been fixed by PR 16465. However this doesn't work since the font has *bogus* font-flags, that fail to categorize the font as Symbolic.
   To address this we'll also compare the font-name against the list of known symbol fonts.
This commit is contained in:
Jonas Jenwald 2023-06-02 12:33:36 +02:00
parent 0023c4a511
commit 459d26edec
5 changed files with 45 additions and 20 deletions

View File

@ -49,6 +49,7 @@ import {
getStandardFontName, getStandardFontName,
getStdFontMap, getStdFontMap,
getSymbolsFonts, getSymbolsFonts,
isKnownFontName,
} from "./standard_fonts.js"; } from "./standard_fonts.js";
import { getTilingPatternIR, Pattern } from "./pattern.js"; import { getTilingPatternIR, Pattern } from "./pattern.js";
import { getXfaFontDict, getXfaFontName } from "./xfa_fonts.js"; import { getXfaFontDict, getXfaFontName } from "./xfa_fonts.js";
@ -3487,14 +3488,11 @@ class PartialEvaluator {
} }
} }
const nonEmbeddedFont = !properties.file || properties.isInternalFont; const nonEmbeddedFont = !properties.file || properties.isInternalFont,
isSymbolsFontName = getSymbolsFonts()[properties.name];
// Ignore an incorrectly specified named encoding for non-embedded // Ignore an incorrectly specified named encoding for non-embedded
// symbol fonts (fixes issue16464.pdf). // symbol fonts (fixes issue16464.pdf).
if ( if (baseEncodingName && nonEmbeddedFont && isSymbolsFontName) {
baseEncodingName &&
nonEmbeddedFont &&
getSymbolsFonts()[properties.name]
) {
baseEncodingName = null; baseEncodingName = null;
} }
@ -3512,7 +3510,7 @@ class PartialEvaluator {
} }
// The Symbolic attribute can be misused for regular fonts // The Symbolic attribute can be misused for regular fonts
// Heuristic: we have to check if the font is a standard one also // Heuristic: we have to check if the font is a standard one also
if (isSymbolicFont) { if (isSymbolicFont || isSymbolsFontName) {
encoding = MacRomanEncoding; encoding = MacRomanEncoding;
if (nonEmbeddedFont) { if (nonEmbeddedFont) {
if (/Symbol/i.test(properties.name)) { if (/Symbol/i.test(properties.name)) {
@ -4249,19 +4247,25 @@ class PartialEvaluator {
baseFont = Name.get(baseFont); baseFont = Name.get(baseFont);
} }
if (!isType3Font) {
const fontNameStr = fontName?.name; const fontNameStr = fontName?.name;
const baseFontStr = baseFont?.name; const baseFontStr = baseFont?.name;
if (fontNameStr !== baseFontStr) { if (!isType3Font && fontNameStr !== baseFontStr) {
info( info(
`The FontDescriptor's FontName is "${fontNameStr}" but ` + `The FontDescriptor's FontName is "${fontNameStr}" but ` +
`should be the same as the Font's BaseFont "${baseFontStr}".` `should be the same as the Font's BaseFont "${baseFontStr}".`
); );
// Workaround for cases where e.g. fontNameStr = 'Arial' and // - Workaround for cases where e.g. fontNameStr = 'Arial' and
// baseFontStr = 'Arial,Bold' (needed when no font file is embedded). // baseFontStr = 'Arial,Bold' (needed when no font file is embedded).
if (fontNameStr && baseFontStr?.startsWith(fontNameStr)) { //
fontName = baseFont; // - Workaround for cases where e.g. fontNameStr = 'wg09np' and
} // baseFontStr = 'Wingdings-Regular' (fixes issue7454.pdf).
if (
fontNameStr &&
baseFontStr &&
(baseFontStr.startsWith(fontNameStr) ||
(!isKnownFontName(fontNameStr) && isKnownFontName(baseFontStr)))
) {
fontName = null;
} }
} }
fontName ||= baseFont; fontName ||= baseFont;

View File

@ -309,6 +309,9 @@ const getSymbolsFonts = getLookupTableFactory(function (t) {
t.Dingbats = true; t.Dingbats = true;
t.Symbol = true; t.Symbol = true;
t.ZapfDingbats = true; t.ZapfDingbats = true;
t.Wingdings = true;
t["Wingdings-Bold"] = true;
t["Wingdings-Regular"] = true;
}); });
// Glyph map for well-known standard fonts. Sometimes Ghostscript uses CID // Glyph map for well-known standard fonts. Sometimes Ghostscript uses CID
@ -888,6 +891,16 @@ function getStandardFontName(name) {
return stdFontMap[fontName]; return stdFontMap[fontName];
} }
function isKnownFontName(name) {
const fontName = normalizeFontName(name);
return !!(
getStdFontMap()[fontName] ||
getNonStdFontMap()[fontName] ||
getSerifFonts()[fontName] ||
getSymbolsFonts()[fontName]
);
}
export { export {
getFontNameToFileMap, getFontNameToFileMap,
getGlyphMapForStandardFonts, getGlyphMapForStandardFonts,
@ -898,4 +911,5 @@ export {
getSupplementalGlyphMapForArialBlack, getSupplementalGlyphMapForArialBlack,
getSupplementalGlyphMapForCalibri, getSupplementalGlyphMapForCalibri,
getSymbolsFonts, getSymbolsFonts,
isKnownFontName,
}; };

View File

@ -490,6 +490,7 @@
!issue11656.pdf !issue11656.pdf
!annotation-fileattachment.pdf !annotation-fileattachment.pdf
!annotation-text-widget.pdf !annotation-text-widget.pdf
!issue7454.pdf
!issue15443.pdf !issue15443.pdf
!annotation-choice-widget.pdf !annotation-choice-widget.pdf
!issue10900.pdf !issue10900.pdf

BIN
test/pdfs/issue7454.pdf Normal file

Binary file not shown.

View File

@ -5042,6 +5042,12 @@
"link": true, "link": true,
"type": "load" "type": "load"
}, },
{ "id": "issue7454",
"file": "pdfs/issue7454.pdf",
"md5": "45889bf6a9d3e2eccd01dc48668b21e5",
"rounds": 1,
"type": "eq"
},
{ "id": "bigboundingbox", { "id": "bigboundingbox",
"file": "pdfs/bigboundingbox.pdf", "file": "pdfs/bigboundingbox.pdf",
"md5": "e5c5e2cb80826d6ebf535413865270cd", "md5": "e5c5e2cb80826d6ebf535413865270cd",