diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 59791cb90..79591b4ac 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -825,7 +825,7 @@ class PartialEvaluator { loadedName: "g_font_error", font: new ErrorFont(`Type3 font load error: ${reason}`), dict: translated.font, - extraProperties: this.options.fontExtraProperties, + evaluatorOptions: this.options, }); }); }) @@ -850,7 +850,12 @@ class PartialEvaluator { font.disableFontFace || this.options.disableFontFace ) { - PartialEvaluator.buildFontPaths(font, glyphs, this.handler); + PartialEvaluator.buildFontPaths( + font, + glyphs, + this.handler, + this.options + ); } } return glyphs; @@ -1002,7 +1007,7 @@ class PartialEvaluator { loadedName: "g_font_error", font: new ErrorFont(`Font "${fontName}" is not available.`), dict: font, - extraProperties: this.options.fontExtraProperties, + evaluatorOptions: this.options, }); }; @@ -1147,7 +1152,7 @@ class PartialEvaluator { loadedName: font.loadedName, font: translatedFont, dict: font, - extraProperties: this.options.fontExtraProperties, + evaluatorOptions: this.options, }) ); }) @@ -1178,7 +1183,7 @@ class PartialEvaluator { reason instanceof Error ? reason.message : reason ), dict: font, - extraProperties: this.options.fontExtraProperties, + evaluatorOptions: this.options, }) ); }); @@ -3667,10 +3672,11 @@ class PartialEvaluator { toUnicode, cssFontInfo, }) { + const isType3Font = type === "Type3"; let properties; if (!descriptor) { - if (type === "Type3") { + if (isType3Font) { // FontDescriptor is only required for Type3 fonts when the document // is a tagged pdf. Create a barbebones one to get by. descriptor = new Dict(null); @@ -3707,6 +3713,7 @@ class PartialEvaluator { firstChar, lastChar, toUnicode, + isType3Font, }; const widths = dict.get("Widths"); return this.extractDataStructures(dict, dict, properties).then( @@ -3746,7 +3753,7 @@ class PartialEvaluator { baseFont = Name.get(baseFont); } - if (type !== "Type3") { + if (!isType3Font) { const fontNameStr = fontName && fontName.name; const baseFontStr = baseFont && baseFont.name; if (fontNameStr !== baseFontStr) { @@ -3811,7 +3818,7 @@ class PartialEvaluator { capHeight: descriptor.get("CapHeight"), flags: descriptor.get("Flags"), italicAngle: descriptor.get("ItalicAngle"), - isType3Font: false, + isType3Font, cssFontInfo, }; @@ -3833,24 +3840,35 @@ class PartialEvaluator { newProperties => { this.extractWidths(dict, descriptor, newProperties); - if (type === "Type3") { - newProperties.isType3Font = true; - } return new Font(fontName.name, fontFile, newProperties); } ); } - static buildFontPaths(font, glyphs, handler) { + static buildFontPaths(font, glyphs, handler, evaluatorOptions) { function buildPath(fontChar) { - if (font.renderer.hasBuiltPath(fontChar)) { - return; + const glyphName = `${font.loadedName}_path_${fontChar}`; + 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) { @@ -3877,11 +3895,11 @@ class PartialEvaluator { } class TranslatedFont { - constructor({ loadedName, font, dict, extraProperties = false }) { + constructor({ loadedName, font, dict, evaluatorOptions }) { this.loadedName = loadedName; this.font = font; this.dict = dict; - this._extraProperties = extraProperties; + this._evaluatorOptions = evaluatorOptions || DefaultPartialEvaluatorOptions; this.type3Loaded = null; this.type3Dependencies = font.isType3Font ? new Set() : null; this.sent = false; @@ -3896,7 +3914,7 @@ class TranslatedFont { handler.send("commonobj", [ this.loadedName, "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. // To ensure that all 'FontPath's are available on the main-thread, when // font loading failed, attempt to resend *all* previously parsed glyphs. - const glyphs = this.font.glyphCacheValues; - PartialEvaluator.buildFontPaths(this.font, glyphs, handler); + PartialEvaluator.buildFontPaths( + this.font, + /* glyphs = */ this.font.glyphCacheValues, + handler, + this._evaluatorOptions + ); } loadType3Data(evaluator, resources, task) { diff --git a/src/core/font_renderer.js b/src/core/font_renderer.js index 02c0d5023..9849c8f2a 100644 --- a/src/core/font_renderer.js +++ b/src/core/font_renderer.js @@ -734,14 +734,24 @@ class CompiledFont { } getPathJs(unicode) { - const cmap = lookupCmap(this.cmap, unicode); - let fn = this.compiledGlyphs[cmap.glyphId]; + const { charCode, glyphId } = lookupCmap(this.cmap, unicode); + let fn = this.compiledGlyphs[glyphId]; if (!fn) { - fn = this.compileGlyph(this.glyphs[cmap.glyphId], cmap.glyphId); - this.compiledGlyphs[cmap.glyphId] = fn; + try { + 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) { - this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId; + if (this.compiledCharCodeToGlyphId[charCode] === undefined) { + this.compiledCharCodeToGlyphId[charCode] = glyphId; } return fn; } @@ -781,10 +791,10 @@ class CompiledFont { } hasBuiltPath(unicode) { - const cmap = lookupCmap(this.cmap, unicode); + const { charCode, glyphId } = lookupCmap(this.cmap, unicode); return ( - this.compiledGlyphs[cmap.glyphId] !== undefined && - this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined + this.compiledGlyphs[glyphId] !== undefined && + this.compiledCharCodeToGlyphId[charCode] !== undefined ); } } diff --git a/src/shared/util.js b/src/shared/util.js index 21d507c0c..319ed09a0 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -331,6 +331,7 @@ const UNSUPPORTED_FEATURES = { errorOperatorList: "errorOperatorList", errorFontToUnicode: "errorFontToUnicode", errorFontLoadNative: "errorFontLoadNative", + errorFontBuildPath: "errorFontBuildPath", errorFontGetPath: "errorFontGetPath", errorMarkedContent: "errorMarkedContent", };