Merge pull request #13381 from Snuffleupagus/buildFontPaths-ignoreErrors

Handle errors gracefully, in PartialEvaluator.buildFontPaths, when glyph path building fails
This commit is contained in:
Tim van der Meij 2021-05-22 13:06:31 +02:00 committed by GitHub
commit de680d7777
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 33 deletions

View File

@ -825,7 +825,7 @@ class PartialEvaluator {
loadedName: "g_font_error", loadedName: "g_font_error",
font: new ErrorFont(`Type3 font load error: ${reason}`), font: new ErrorFont(`Type3 font load error: ${reason}`),
dict: translated.font, dict: translated.font,
extraProperties: this.options.fontExtraProperties, evaluatorOptions: this.options,
}); });
}); });
}) })
@ -850,7 +850,12 @@ class PartialEvaluator {
font.disableFontFace || font.disableFontFace ||
this.options.disableFontFace this.options.disableFontFace
) { ) {
PartialEvaluator.buildFontPaths(font, glyphs, this.handler); PartialEvaluator.buildFontPaths(
font,
glyphs,
this.handler,
this.options
);
} }
} }
return glyphs; return glyphs;
@ -1002,7 +1007,7 @@ class PartialEvaluator {
loadedName: "g_font_error", loadedName: "g_font_error",
font: new ErrorFont(`Font "${fontName}" is not available.`), font: new ErrorFont(`Font "${fontName}" is not available.`),
dict: font, dict: font,
extraProperties: this.options.fontExtraProperties, evaluatorOptions: this.options,
}); });
}; };
@ -1147,7 +1152,7 @@ class PartialEvaluator {
loadedName: font.loadedName, loadedName: font.loadedName,
font: translatedFont, font: translatedFont,
dict: font, dict: font,
extraProperties: this.options.fontExtraProperties, evaluatorOptions: this.options,
}) })
); );
}) })
@ -1178,7 +1183,7 @@ class PartialEvaluator {
reason instanceof Error ? reason.message : reason reason instanceof Error ? reason.message : reason
), ),
dict: font, dict: font,
extraProperties: this.options.fontExtraProperties, evaluatorOptions: this.options,
}) })
); );
}); });
@ -3667,10 +3672,11 @@ class PartialEvaluator {
toUnicode, toUnicode,
cssFontInfo, cssFontInfo,
}) { }) {
const isType3Font = type === "Type3";
let properties; let properties;
if (!descriptor) { if (!descriptor) {
if (type === "Type3") { if (isType3Font) {
// FontDescriptor is only required for Type3 fonts when the document // FontDescriptor is only required for Type3 fonts when the document
// is a tagged pdf. Create a barbebones one to get by. // is a tagged pdf. Create a barbebones one to get by.
descriptor = new Dict(null); descriptor = new Dict(null);
@ -3707,6 +3713,7 @@ class PartialEvaluator {
firstChar, firstChar,
lastChar, lastChar,
toUnicode, toUnicode,
isType3Font,
}; };
const widths = dict.get("Widths"); const widths = dict.get("Widths");
return this.extractDataStructures(dict, dict, properties).then( return this.extractDataStructures(dict, dict, properties).then(
@ -3746,7 +3753,7 @@ class PartialEvaluator {
baseFont = Name.get(baseFont); baseFont = Name.get(baseFont);
} }
if (type !== "Type3") { if (!isType3Font) {
const fontNameStr = fontName && fontName.name; const fontNameStr = fontName && fontName.name;
const baseFontStr = baseFont && baseFont.name; const baseFontStr = baseFont && baseFont.name;
if (fontNameStr !== baseFontStr) { if (fontNameStr !== baseFontStr) {
@ -3811,7 +3818,7 @@ class PartialEvaluator {
capHeight: descriptor.get("CapHeight"), capHeight: descriptor.get("CapHeight"),
flags: descriptor.get("Flags"), flags: descriptor.get("Flags"),
italicAngle: descriptor.get("ItalicAngle"), italicAngle: descriptor.get("ItalicAngle"),
isType3Font: false, isType3Font,
cssFontInfo, cssFontInfo,
}; };
@ -3833,24 +3840,35 @@ class PartialEvaluator {
newProperties => { newProperties => {
this.extractWidths(dict, descriptor, newProperties); this.extractWidths(dict, descriptor, newProperties);
if (type === "Type3") {
newProperties.isType3Font = true;
}
return new Font(fontName.name, fontFile, newProperties); return new Font(fontName.name, fontFile, newProperties);
} }
); );
} }
static buildFontPaths(font, glyphs, handler) { static buildFontPaths(font, glyphs, handler, evaluatorOptions) {
function buildPath(fontChar) { function buildPath(fontChar) {
if (font.renderer.hasBuiltPath(fontChar)) { const glyphName = `${font.loadedName}_path_${fontChar}`;
return; try {
if (font.renderer.hasBuiltPath(fontChar)) {
return;
}
handler.send("commonobj", [
glyphName,
"FontPath",
font.renderer.getPathJs(fontChar),
]);
} catch (reason) {
if (evaluatorOptions.ignoreErrors) {
// Error in the font data -- sending unsupported feature notification
// and allow glyph path building to continue.
handler.send("UnsupportedFeature", {
featureId: UNSUPPORTED_FEATURES.errorFontBuildPath,
});
warn(`buildFontPaths - ignoring ${glyphName} glyph: "${reason}".`);
return;
}
throw reason;
} }
handler.send("commonobj", [
`${font.loadedName}_path_${fontChar}`,
"FontPath",
font.renderer.getPathJs(fontChar),
]);
} }
for (const glyph of glyphs) { for (const glyph of glyphs) {
@ -3877,11 +3895,11 @@ class PartialEvaluator {
} }
class TranslatedFont { class TranslatedFont {
constructor({ loadedName, font, dict, extraProperties = false }) { constructor({ loadedName, font, dict, evaluatorOptions }) {
this.loadedName = loadedName; this.loadedName = loadedName;
this.font = font; this.font = font;
this.dict = dict; this.dict = dict;
this._extraProperties = extraProperties; this._evaluatorOptions = evaluatorOptions || DefaultPartialEvaluatorOptions;
this.type3Loaded = null; this.type3Loaded = null;
this.type3Dependencies = font.isType3Font ? new Set() : null; this.type3Dependencies = font.isType3Font ? new Set() : null;
this.sent = false; this.sent = false;
@ -3896,7 +3914,7 @@ class TranslatedFont {
handler.send("commonobj", [ handler.send("commonobj", [
this.loadedName, this.loadedName,
"Font", "Font",
this.font.exportData(this._extraProperties), this.font.exportData(this._evaluatorOptions.fontExtraProperties),
]); ]);
} }
@ -3912,8 +3930,12 @@ class TranslatedFont {
// message was received on the worker-thread. // message was received on the worker-thread.
// To ensure that all 'FontPath's are available on the main-thread, when // To ensure that all 'FontPath's are available on the main-thread, when
// font loading failed, attempt to resend *all* previously parsed glyphs. // font loading failed, attempt to resend *all* previously parsed glyphs.
const glyphs = this.font.glyphCacheValues; PartialEvaluator.buildFontPaths(
PartialEvaluator.buildFontPaths(this.font, glyphs, handler); this.font,
/* glyphs = */ this.font.glyphCacheValues,
handler,
this._evaluatorOptions
);
} }
loadType3Data(evaluator, resources, task) { loadType3Data(evaluator, resources, task) {

View File

@ -734,14 +734,24 @@ class CompiledFont {
} }
getPathJs(unicode) { getPathJs(unicode) {
const cmap = lookupCmap(this.cmap, unicode); const { charCode, glyphId } = lookupCmap(this.cmap, unicode);
let fn = this.compiledGlyphs[cmap.glyphId]; let fn = this.compiledGlyphs[glyphId];
if (!fn) { if (!fn) {
fn = this.compileGlyph(this.glyphs[cmap.glyphId], cmap.glyphId); try {
this.compiledGlyphs[cmap.glyphId] = fn; fn = this.compileGlyph(this.glyphs[glyphId], glyphId);
this.compiledGlyphs[glyphId] = fn;
} catch (ex) {
// Avoid attempting to re-compile a corrupt glyph.
this.compiledGlyphs[glyphId] = NOOP;
if (this.compiledCharCodeToGlyphId[charCode] === undefined) {
this.compiledCharCodeToGlyphId[charCode] = glyphId;
}
throw ex;
}
} }
if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) { if (this.compiledCharCodeToGlyphId[charCode] === undefined) {
this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId; this.compiledCharCodeToGlyphId[charCode] = glyphId;
} }
return fn; return fn;
} }
@ -781,10 +791,10 @@ class CompiledFont {
} }
hasBuiltPath(unicode) { hasBuiltPath(unicode) {
const cmap = lookupCmap(this.cmap, unicode); const { charCode, glyphId } = lookupCmap(this.cmap, unicode);
return ( return (
this.compiledGlyphs[cmap.glyphId] !== undefined && this.compiledGlyphs[glyphId] !== undefined &&
this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined this.compiledCharCodeToGlyphId[charCode] !== undefined
); );
} }
} }

View File

@ -331,6 +331,7 @@ const UNSUPPORTED_FEATURES = {
errorOperatorList: "errorOperatorList", errorOperatorList: "errorOperatorList",
errorFontToUnicode: "errorFontToUnicode", errorFontToUnicode: "errorFontToUnicode",
errorFontLoadNative: "errorFontLoadNative", errorFontLoadNative: "errorFontLoadNative",
errorFontBuildPath: "errorFontBuildPath",
errorFontGetPath: "errorFontGetPath", errorFontGetPath: "errorFontGetPath",
errorMarkedContent: "errorMarkedContent", errorMarkedContent: "errorMarkedContent",
}; };