Merge pull request #12486 from Snuffleupagus/font-Dict-cacheKey

Stop caching the *parsed* Font data on its `Dict` object (PR 7347 follow-up)
This commit is contained in:
Tim van der Meij 2020-10-16 22:30:17 +02:00 committed by GitHub
commit 127bb03e03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 24 deletions

View File

@ -979,15 +979,13 @@ class PartialEvaluator {
} }
loadFont(fontName, font, resources) { loadFont(fontName, font, resources) {
const errorFont = () => { const errorFont = async () => {
return Promise.resolve( return new TranslatedFont({
new TranslatedFont({ 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,
extraProperties: this.options.fontExtraProperties, });
})
);
}; };
var fontRef, var fontRef,
@ -1034,10 +1032,10 @@ class PartialEvaluator {
return errorFont(); return errorFont();
} }
// We are holding `font.translated` references just for `fontRef`s that // We are holding `font.cacheKey` references only for `fontRef`s that
// are not actually `Ref`s, but rather `Dict`s. See explanation below. // are not actually `Ref`s, but rather `Dict`s. See explanation below.
if (font.translated) { if (font.cacheKey && this.fontCache.has(font.cacheKey)) {
return font.translated; return this.fontCache.get(font.cacheKey);
} }
var fontCapability = createPromiseCapability(); var fontCapability = createPromiseCapability();
@ -1077,18 +1075,16 @@ class PartialEvaluator {
// Workaround for bad PDF generators that reference fonts incorrectly, // Workaround for bad PDF generators that reference fonts incorrectly,
// where `fontRef` is a `Dict` rather than a `Ref` (fixes bug946506.pdf). // where `fontRef` is a `Dict` rather than a `Ref` (fixes bug946506.pdf).
// In this case we should not put the font into `this.fontCache` (which is // In this case we cannot put the font into `this.fontCache` (which is
// a `RefSetCache`), since it's not meaningful to use a `Dict` as a key. // a `RefSetCache`), since it's not possible to use a `Dict` as a key.
// //
// However, if we don't cache the font it's not possible to remove it // However, if we don't cache the font it's not possible to remove it
// when `cleanup` is triggered from the API, which causes issues on // when `cleanup` is triggered from the API, which causes issues on
// subsequent rendering operations (see issue7403.pdf). // subsequent rendering operations (see issue7403.pdf) and would force us
// A simple workaround would be to just not hold `font.translated` // to unnecessarily load the same fonts over and over.
// references in this case, but this would force us to unnecessarily load
// the same fonts over and over.
// //
// Instead, we cheat a bit by attempting to use a modified `fontID` as a // Instead, we cheat a bit by using a modified `fontID` as a key in
// key in `this.fontCache`, to allow the font to be cached. // `this.fontCache`, to allow the font to be cached.
// NOTE: This works because `RefSetCache` calls `toString()` on provided // NOTE: This works because `RefSetCache` calls `toString()` on provided
// keys. Also, since `fontRef` is used when getting cached fonts, // keys. Also, since `fontRef` is used when getting cached fonts,
// we'll not accidentally match fonts cached with the `fontID`. // we'll not accidentally match fonts cached with the `fontID`.
@ -1098,7 +1094,8 @@ class PartialEvaluator {
if (!fontID) { if (!fontID) {
fontID = this.idFactory.createFontId(); fontID = this.idFactory.createFontId();
} }
this.fontCache.put(`id_${fontID}`, fontCapability.promise); font.cacheKey = `cacheKey_${fontID}`;
this.fontCache.put(font.cacheKey, fontCapability.promise);
} }
assert( assert(
fontID && fontID.startsWith("f"), fontID && fontID.startsWith("f"),
@ -1109,8 +1106,6 @@ class PartialEvaluator {
// load them asynchronously before calling display on a page. // load them asynchronously before calling display on a page.
font.loadedName = `${this.idFactory.getDocId()}_${fontID}`; font.loadedName = `${this.idFactory.getDocId()}_${fontID}`;
font.translated = fontCapability.promise;
this.translateFont(preEvaluatedFont) this.translateFont(preEvaluatedFont)
.then(translatedFont => { .then(translatedFont => {
if (translatedFont.fontType !== undefined) { if (translatedFont.fontType !== undefined) {

View File

@ -908,7 +908,7 @@ class Catalog {
return Promise.all(promises).then(translatedFonts => { return Promise.all(promises).then(translatedFonts => {
for (const { dict } of translatedFonts) { for (const { dict } of translatedFonts) {
delete dict.translated; delete dict.cacheKey;
} }
this.fontCache.clear(); this.fontCache.clear();
this.builtInCMapCache.clear(); this.builtInCMapCache.clear();