Cache the "raw" standard font data in the worker-thread (PR 12726 follow-up)
*This implementation is basically a copy of the pre-existing `builtInCMapCache` implementation.* For some, badly generated, PDF documents it's possible that we'll end up having to fetch the *same* standard font data over and over (which is obviously inefficient). While not common, it's certainly possible that a PDF document uses *custom* font names where the actual font then references one of the standard fonts; see e.g. issue 11399 for one such example. Note that I did suggest adding worker-thread caching of standard font data in PR 12726, however it wasn't deemed necessary at the time. Now that we have a real-world example that benefit from caching, I think that we should simply implement this now.
This commit is contained in:
		
							parent
							
								
									6d88d8cdaa
								
							
						
					
					
						commit
						a01c599247
					
				| @ -71,6 +71,7 @@ class Catalog { | |||||||
| 
 | 
 | ||||||
|     this.fontCache = new RefSetCache(); |     this.fontCache = new RefSetCache(); | ||||||
|     this.builtInCMapCache = new Map(); |     this.builtInCMapCache = new Map(); | ||||||
|  |     this.standardFontDataCache = new Map(); | ||||||
|     this.globalImageCache = new GlobalImageCache(); |     this.globalImageCache = new GlobalImageCache(); | ||||||
|     this.pageKidsCountCache = new RefSetCache(); |     this.pageKidsCountCache = new RefSetCache(); | ||||||
|     this.pageIndexCache = new RefSetCache(); |     this.pageIndexCache = new RefSetCache(); | ||||||
| @ -1020,6 +1021,7 @@ class Catalog { | |||||||
|       } |       } | ||||||
|       this.fontCache.clear(); |       this.fontCache.clear(); | ||||||
|       this.builtInCMapCache.clear(); |       this.builtInCMapCache.clear(); | ||||||
|  |       this.standardFontDataCache.clear(); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -79,6 +79,7 @@ class Page { | |||||||
|     globalIdFactory, |     globalIdFactory, | ||||||
|     fontCache, |     fontCache, | ||||||
|     builtInCMapCache, |     builtInCMapCache, | ||||||
|  |     standardFontDataCache, | ||||||
|     globalImageCache, |     globalImageCache, | ||||||
|     nonBlendModesSet, |     nonBlendModesSet, | ||||||
|     xfaFactory, |     xfaFactory, | ||||||
| @ -90,6 +91,7 @@ class Page { | |||||||
|     this.ref = ref; |     this.ref = ref; | ||||||
|     this.fontCache = fontCache; |     this.fontCache = fontCache; | ||||||
|     this.builtInCMapCache = builtInCMapCache; |     this.builtInCMapCache = builtInCMapCache; | ||||||
|  |     this.standardFontDataCache = standardFontDataCache; | ||||||
|     this.globalImageCache = globalImageCache; |     this.globalImageCache = globalImageCache; | ||||||
|     this.nonBlendModesSet = nonBlendModesSet; |     this.nonBlendModesSet = nonBlendModesSet; | ||||||
|     this.evaluatorOptions = pdfManager.evaluatorOptions; |     this.evaluatorOptions = pdfManager.evaluatorOptions; | ||||||
| @ -255,6 +257,7 @@ class Page { | |||||||
|       idFactory: this._localIdFactory, |       idFactory: this._localIdFactory, | ||||||
|       fontCache: this.fontCache, |       fontCache: this.fontCache, | ||||||
|       builtInCMapCache: this.builtInCMapCache, |       builtInCMapCache: this.builtInCMapCache, | ||||||
|  |       standardFontDataCache: this.standardFontDataCache, | ||||||
|       globalImageCache: this.globalImageCache, |       globalImageCache: this.globalImageCache, | ||||||
|       options: this.evaluatorOptions, |       options: this.evaluatorOptions, | ||||||
|     }); |     }); | ||||||
| @ -321,6 +324,7 @@ class Page { | |||||||
|       idFactory: this._localIdFactory, |       idFactory: this._localIdFactory, | ||||||
|       fontCache: this.fontCache, |       fontCache: this.fontCache, | ||||||
|       builtInCMapCache: this.builtInCMapCache, |       builtInCMapCache: this.builtInCMapCache, | ||||||
|  |       standardFontDataCache: this.standardFontDataCache, | ||||||
|       globalImageCache: this.globalImageCache, |       globalImageCache: this.globalImageCache, | ||||||
|       options: this.evaluatorOptions, |       options: this.evaluatorOptions, | ||||||
|     }); |     }); | ||||||
| @ -425,6 +429,7 @@ class Page { | |||||||
|         idFactory: this._localIdFactory, |         idFactory: this._localIdFactory, | ||||||
|         fontCache: this.fontCache, |         fontCache: this.fontCache, | ||||||
|         builtInCMapCache: this.builtInCMapCache, |         builtInCMapCache: this.builtInCMapCache, | ||||||
|  |         standardFontDataCache: this.standardFontDataCache, | ||||||
|         globalImageCache: this.globalImageCache, |         globalImageCache: this.globalImageCache, | ||||||
|         options: this.evaluatorOptions, |         options: this.evaluatorOptions, | ||||||
|       }); |       }); | ||||||
| @ -889,6 +894,7 @@ class PDFDocument { | |||||||
|       idFactory: this._globalIdFactory, |       idFactory: this._globalIdFactory, | ||||||
|       fontCache: this.catalog.fontCache, |       fontCache: this.catalog.fontCache, | ||||||
|       builtInCMapCache: this.catalog.builtInCMapCache, |       builtInCMapCache: this.catalog.builtInCMapCache, | ||||||
|  |       standardFontDataCache: this.catalog.standardFontDataCache, | ||||||
|       options, |       options, | ||||||
|     }); |     }); | ||||||
|     const operatorList = new OperatorList(); |     const operatorList = new OperatorList(); | ||||||
| @ -1148,6 +1154,7 @@ class PDFDocument { | |||||||
|           globalIdFactory: this._globalIdFactory, |           globalIdFactory: this._globalIdFactory, | ||||||
|           fontCache: catalog.fontCache, |           fontCache: catalog.fontCache, | ||||||
|           builtInCMapCache: catalog.builtInCMapCache, |           builtInCMapCache: catalog.builtInCMapCache, | ||||||
|  |           standardFontDataCache: catalog.standardFontDataCache, | ||||||
|           globalImageCache: catalog.globalImageCache, |           globalImageCache: catalog.globalImageCache, | ||||||
|           nonBlendModesSet: catalog.nonBlendModesSet, |           nonBlendModesSet: catalog.nonBlendModesSet, | ||||||
|           xfaFactory: this.xfaFactory, |           xfaFactory: this.xfaFactory, | ||||||
| @ -1170,6 +1177,7 @@ class PDFDocument { | |||||||
|         globalIdFactory: this._globalIdFactory, |         globalIdFactory: this._globalIdFactory, | ||||||
|         fontCache: catalog.fontCache, |         fontCache: catalog.fontCache, | ||||||
|         builtInCMapCache: catalog.builtInCMapCache, |         builtInCMapCache: catalog.builtInCMapCache, | ||||||
|  |         standardFontDataCache: catalog.standardFontDataCache, | ||||||
|         globalImageCache: catalog.globalImageCache, |         globalImageCache: catalog.globalImageCache, | ||||||
|         nonBlendModesSet: catalog.nonBlendModesSet, |         nonBlendModesSet: catalog.nonBlendModesSet, | ||||||
|         xfaFactory: null, |         xfaFactory: null, | ||||||
|  | |||||||
| @ -207,6 +207,7 @@ class PartialEvaluator { | |||||||
|     idFactory, |     idFactory, | ||||||
|     fontCache, |     fontCache, | ||||||
|     builtInCMapCache, |     builtInCMapCache, | ||||||
|  |     standardFontDataCache, | ||||||
|     globalImageCache, |     globalImageCache, | ||||||
|     options = null, |     options = null, | ||||||
|   }) { |   }) { | ||||||
| @ -216,6 +217,7 @@ class PartialEvaluator { | |||||||
|     this.idFactory = idFactory; |     this.idFactory = idFactory; | ||||||
|     this.fontCache = fontCache; |     this.fontCache = fontCache; | ||||||
|     this.builtInCMapCache = builtInCMapCache; |     this.builtInCMapCache = builtInCMapCache; | ||||||
|  |     this.standardFontDataCache = standardFontDataCache; | ||||||
|     this.globalImageCache = globalImageCache; |     this.globalImageCache = globalImageCache; | ||||||
|     this.options = options || DefaultPartialEvaluatorOptions; |     this.options = options || DefaultPartialEvaluatorOptions; | ||||||
|     this.parsingType3Font = false; |     this.parsingType3Font = false; | ||||||
| @ -390,8 +392,13 @@ class PartialEvaluator { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   async fetchStandardFontData(name) { |   async fetchStandardFontData(name) { | ||||||
|  |     const cachedData = this.standardFontDataCache.get(name); | ||||||
|  |     if (cachedData) { | ||||||
|  |       return new Stream(cachedData); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // The symbol fonts are not consistent across platforms, always load the
 |     // The symbol fonts are not consistent across platforms, always load the
 | ||||||
|     // font data for them.
 |     // standard font data for them.
 | ||||||
|     if ( |     if ( | ||||||
|       this.options.useSystemFonts && |       this.options.useSystemFonts && | ||||||
|       name !== "Symbol" && |       name !== "Symbol" && | ||||||
| @ -399,32 +406,43 @@ class PartialEvaluator { | |||||||
|     ) { |     ) { | ||||||
|       return null; |       return null; | ||||||
|     } |     } | ||||||
|     const standardFontNameToFileName = getFontNameToFileMap(); | 
 | ||||||
|     const filename = standardFontNameToFileName[name]; |     const standardFontNameToFileName = getFontNameToFileMap(), | ||||||
|  |       filename = standardFontNameToFileName[name]; | ||||||
|  |     let data; | ||||||
|  | 
 | ||||||
|     if (this.options.standardFontDataUrl !== null) { |     if (this.options.standardFontDataUrl !== null) { | ||||||
|       const url = `${this.options.standardFontDataUrl}${filename}`; |       const url = `${this.options.standardFontDataUrl}${filename}`; | ||||||
|       const response = await fetch(url); |       const response = await fetch(url); | ||||||
|       if (!response.ok) { |       if (!response.ok) { | ||||||
|         warn( |         warn( | ||||||
|           `fetchStandardFontData failed to fetch file "${url}" with "${response.statusText}".` |           `fetchStandardFontData: failed to fetch file "${url}" with "${response.statusText}".` | ||||||
|         ); |         ); | ||||||
|         return null; |       } else { | ||||||
|  |         data = await response.arrayBuffer(); | ||||||
|       } |       } | ||||||
|       return new Stream(await response.arrayBuffer()); |     } else { | ||||||
|     } |       // Get the data on the main-thread instead.
 | ||||||
|     // Get the data on the main thread instead.
 |  | ||||||
|       try { |       try { | ||||||
|       const data = await this.handler.sendWithPromise("FetchStandardFontData", { |         data = await this.handler.sendWithPromise("FetchStandardFontData", { | ||||||
|           filename, |           filename, | ||||||
|         }); |         }); | ||||||
|       return new Stream(data); |  | ||||||
|       } catch (e) { |       } catch (e) { | ||||||
|         warn( |         warn( | ||||||
|         `fetchStandardFontData failed to fetch file "${filename}" with "${e}".` |           `fetchStandardFontData: failed to fetch file "${filename}" with "${e}".` | ||||||
|         ); |         ); | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!data) { | ||||||
|       return null; |       return null; | ||||||
|     } |     } | ||||||
|  |     // Cache the "raw" standard font data, to avoid fetching it repeateadly
 | ||||||
|  |     // (see e.g. issue 11399).
 | ||||||
|  |     this.standardFontDataCache.set(name, data); | ||||||
|  | 
 | ||||||
|  |     return new Stream(data); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   async buildFormXObject( |   async buildFormXObject( | ||||||
|     resources, |     resources, | ||||||
|  | |||||||
| @ -125,6 +125,7 @@ describe("annotation", function () { | |||||||
|       idFactory: createIdFactory(/* pageIndex = */ 0), |       idFactory: createIdFactory(/* pageIndex = */ 0), | ||||||
|       fontCache: new RefSetCache(), |       fontCache: new RefSetCache(), | ||||||
|       builtInCMapCache, |       builtInCMapCache, | ||||||
|  |       standardFontDataCache: new Map(), | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user