Handle errors gracefully, in PartialEvaluator.buildFontPaths, when glyph path building fails
				
					
				
			The building of glyph paths, in the `FontRendererFactory`, can fail in various ways for corrupt font data. However, we're currently not attempting to handle any such errors in the evaluator, which means that a single broken glyph *can* prevent an entire page from rendering. To address this we simply have to pass along, and check, the existing `ignoreErrors` option in `PartialEvaluator.buildFontPaths` similar to the rest of the `PartialEvaluator` code.
This commit is contained in:
		
							parent
							
								
									b2ffebe978
								
							
						
					
					
						commit
						68350378c0
					
				| @ -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, | ||||||
|           }) |           }) | ||||||
|         ); |         ); | ||||||
|       }); |       }); | ||||||
| @ -3841,16 +3846,30 @@ class PartialEvaluator { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 +3896,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 +3915,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 +3931,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) { | ||||||
|  | |||||||
| @ -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 | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -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", | ||||||
| }; | }; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user