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,31 +406,42 @@ 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}".`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
data = await response.arrayBuffer();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Get the data on the main-thread instead.
|
||||||
|
try {
|
||||||
|
data = await this.handler.sendWithPromise("FetchStandardFontData", {
|
||||||
|
filename,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
warn(
|
||||||
|
`fetchStandardFontData: failed to fetch file "${filename}" with "${e}".`
|
||||||
);
|
);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return new Stream(await response.arrayBuffer());
|
|
||||||
}
|
}
|
||||||
// Get the data on the main thread instead.
|
|
||||||
try {
|
if (!data) {
|
||||||
const data = await this.handler.sendWithPromise("FetchStandardFontData", {
|
return null;
|
||||||
filename,
|
|
||||||
});
|
|
||||||
return new Stream(data);
|
|
||||||
} catch (e) {
|
|
||||||
warn(
|
|
||||||
`fetchStandardFontData failed to fetch file "${filename}" with "${e}".`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
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(
|
||||||
|
@ -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