Add a cache to avoid to load several times a local font
On my computer, it takes few tenths of a second to load a local font. Since a font can be used several times in a document, the cache will improve performances.
This commit is contained in:
parent
2d2f7b315e
commit
cfb908c999
@ -81,6 +81,7 @@ class Catalog {
|
|||||||
this.pageKidsCountCache = new RefSetCache();
|
this.pageKidsCountCache = new RefSetCache();
|
||||||
this.pageIndexCache = new RefSetCache();
|
this.pageIndexCache = new RefSetCache();
|
||||||
this.nonBlendModesSet = new RefSet();
|
this.nonBlendModesSet = new RefSet();
|
||||||
|
this.systemFontCache = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
get version() {
|
get version() {
|
||||||
@ -1062,6 +1063,7 @@ class Catalog {
|
|||||||
this.fontCache.clear();
|
this.fontCache.clear();
|
||||||
this.builtInCMapCache.clear();
|
this.builtInCMapCache.clear();
|
||||||
this.standardFontDataCache.clear();
|
this.standardFontDataCache.clear();
|
||||||
|
this.systemFontCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPageDict(pageIndex) {
|
async getPageDict(pageIndex) {
|
||||||
|
@ -74,6 +74,7 @@ class Page {
|
|||||||
builtInCMapCache,
|
builtInCMapCache,
|
||||||
standardFontDataCache,
|
standardFontDataCache,
|
||||||
globalImageCache,
|
globalImageCache,
|
||||||
|
systemFontCache,
|
||||||
nonBlendModesSet,
|
nonBlendModesSet,
|
||||||
xfaFactory,
|
xfaFactory,
|
||||||
}) {
|
}) {
|
||||||
@ -86,6 +87,7 @@ class Page {
|
|||||||
this.builtInCMapCache = builtInCMapCache;
|
this.builtInCMapCache = builtInCMapCache;
|
||||||
this.standardFontDataCache = standardFontDataCache;
|
this.standardFontDataCache = standardFontDataCache;
|
||||||
this.globalImageCache = globalImageCache;
|
this.globalImageCache = globalImageCache;
|
||||||
|
this.systemFontCache = systemFontCache;
|
||||||
this.nonBlendModesSet = nonBlendModesSet;
|
this.nonBlendModesSet = nonBlendModesSet;
|
||||||
this.evaluatorOptions = pdfManager.evaluatorOptions;
|
this.evaluatorOptions = pdfManager.evaluatorOptions;
|
||||||
this.resourcesPromise = null;
|
this.resourcesPromise = null;
|
||||||
@ -270,6 +272,7 @@ class Page {
|
|||||||
builtInCMapCache: this.builtInCMapCache,
|
builtInCMapCache: this.builtInCMapCache,
|
||||||
standardFontDataCache: this.standardFontDataCache,
|
standardFontDataCache: this.standardFontDataCache,
|
||||||
globalImageCache: this.globalImageCache,
|
globalImageCache: this.globalImageCache,
|
||||||
|
systemFontCache: this.systemFontCache,
|
||||||
options: this.evaluatorOptions,
|
options: this.evaluatorOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -321,6 +324,7 @@ class Page {
|
|||||||
builtInCMapCache: this.builtInCMapCache,
|
builtInCMapCache: this.builtInCMapCache,
|
||||||
standardFontDataCache: this.standardFontDataCache,
|
standardFontDataCache: this.standardFontDataCache,
|
||||||
globalImageCache: this.globalImageCache,
|
globalImageCache: this.globalImageCache,
|
||||||
|
systemFontCache: this.systemFontCache,
|
||||||
options: this.evaluatorOptions,
|
options: this.evaluatorOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -390,6 +394,7 @@ class Page {
|
|||||||
builtInCMapCache: this.builtInCMapCache,
|
builtInCMapCache: this.builtInCMapCache,
|
||||||
standardFontDataCache: this.standardFontDataCache,
|
standardFontDataCache: this.standardFontDataCache,
|
||||||
globalImageCache: this.globalImageCache,
|
globalImageCache: this.globalImageCache,
|
||||||
|
systemFontCache: this.systemFontCache,
|
||||||
options: this.evaluatorOptions,
|
options: this.evaluatorOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -533,6 +538,7 @@ class Page {
|
|||||||
builtInCMapCache: this.builtInCMapCache,
|
builtInCMapCache: this.builtInCMapCache,
|
||||||
standardFontDataCache: this.standardFontDataCache,
|
standardFontDataCache: this.standardFontDataCache,
|
||||||
globalImageCache: this.globalImageCache,
|
globalImageCache: this.globalImageCache,
|
||||||
|
systemFontCache: this.systemFontCache,
|
||||||
options: this.evaluatorOptions,
|
options: this.evaluatorOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -602,6 +608,7 @@ class Page {
|
|||||||
builtInCMapCache: this.builtInCMapCache,
|
builtInCMapCache: this.builtInCMapCache,
|
||||||
standardFontDataCache: this.standardFontDataCache,
|
standardFontDataCache: this.standardFontDataCache,
|
||||||
globalImageCache: this.globalImageCache,
|
globalImageCache: this.globalImageCache,
|
||||||
|
systemFontCache: this.systemFontCache,
|
||||||
options: this.evaluatorOptions,
|
options: this.evaluatorOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1476,6 +1483,7 @@ class PDFDocument {
|
|||||||
builtInCMapCache: catalog.builtInCMapCache,
|
builtInCMapCache: catalog.builtInCMapCache,
|
||||||
standardFontDataCache: catalog.standardFontDataCache,
|
standardFontDataCache: catalog.standardFontDataCache,
|
||||||
globalImageCache: catalog.globalImageCache,
|
globalImageCache: catalog.globalImageCache,
|
||||||
|
systemFontCache: catalog.systemFontCache,
|
||||||
nonBlendModesSet: catalog.nonBlendModesSet,
|
nonBlendModesSet: catalog.nonBlendModesSet,
|
||||||
xfaFactory,
|
xfaFactory,
|
||||||
});
|
});
|
||||||
@ -1574,6 +1582,7 @@ class PDFDocument {
|
|||||||
builtInCMapCache: catalog.builtInCMapCache,
|
builtInCMapCache: catalog.builtInCMapCache,
|
||||||
standardFontDataCache: catalog.standardFontDataCache,
|
standardFontDataCache: catalog.standardFontDataCache,
|
||||||
globalImageCache: catalog.globalImageCache,
|
globalImageCache: catalog.globalImageCache,
|
||||||
|
systemFontCache: catalog.systemFontCache,
|
||||||
nonBlendModesSet: catalog.nonBlendModesSet,
|
nonBlendModesSet: catalog.nonBlendModesSet,
|
||||||
xfaFactory: null,
|
xfaFactory: null,
|
||||||
})
|
})
|
||||||
|
@ -215,6 +215,7 @@ class PartialEvaluator {
|
|||||||
builtInCMapCache,
|
builtInCMapCache,
|
||||||
standardFontDataCache,
|
standardFontDataCache,
|
||||||
globalImageCache,
|
globalImageCache,
|
||||||
|
systemFontCache,
|
||||||
options = null,
|
options = null,
|
||||||
}) {
|
}) {
|
||||||
this.xref = xref;
|
this.xref = xref;
|
||||||
@ -225,6 +226,7 @@ class PartialEvaluator {
|
|||||||
this.builtInCMapCache = builtInCMapCache;
|
this.builtInCMapCache = builtInCMapCache;
|
||||||
this.standardFontDataCache = standardFontDataCache;
|
this.standardFontDataCache = standardFontDataCache;
|
||||||
this.globalImageCache = globalImageCache;
|
this.globalImageCache = globalImageCache;
|
||||||
|
this.systemFontCache = systemFontCache;
|
||||||
this.options = options || DefaultPartialEvaluatorOptions;
|
this.options = options || DefaultPartialEvaluatorOptions;
|
||||||
this.parsingType3Font = false;
|
this.parsingType3Font = false;
|
||||||
|
|
||||||
@ -4197,6 +4199,7 @@ class PartialEvaluator {
|
|||||||
properties.isInternalFont = !!file;
|
properties.isInternalFont = !!file;
|
||||||
if (!properties.isInternalFont && this.options.useSystemFonts) {
|
if (!properties.isInternalFont && this.options.useSystemFonts) {
|
||||||
properties.systemFontInfo = getFontSubstitution(
|
properties.systemFontInfo = getFontSubstitution(
|
||||||
|
this.systemFontCache,
|
||||||
this.idFactory,
|
this.idFactory,
|
||||||
this.options.standardFontDataUrl,
|
this.options.standardFontDataUrl,
|
||||||
baseFontName,
|
baseFontName,
|
||||||
@ -4309,6 +4312,7 @@ class PartialEvaluator {
|
|||||||
isInternalFont = !!fontFile;
|
isInternalFont = !!fontFile;
|
||||||
if (!isInternalFont && this.options.useSystemFonts) {
|
if (!isInternalFont && this.options.useSystemFonts) {
|
||||||
systemFontInfo = getFontSubstitution(
|
systemFontInfo = getFontSubstitution(
|
||||||
|
this.systemFontCache,
|
||||||
this.idFactory,
|
this.idFactory,
|
||||||
this.options.standardFontDataUrl,
|
this.options.standardFontDataUrl,
|
||||||
fontName.name,
|
fontName.name,
|
||||||
|
@ -374,6 +374,7 @@ function makeLocal(prepend, local) {
|
|||||||
* }
|
* }
|
||||||
* or use the FontFace API.
|
* or use the FontFace API.
|
||||||
*
|
*
|
||||||
|
* @param {Map} systemFontCache The cache of local fonts.
|
||||||
* @param {Object} idFactory The ids factory.
|
* @param {Object} idFactory The ids factory.
|
||||||
* @param {String} localFontPath Path to the fonts directory.
|
* @param {String} localFontPath Path to the fonts directory.
|
||||||
* @param {String} baseFontName The font name to be substituted.
|
* @param {String} baseFontName The font name to be substituted.
|
||||||
@ -382,6 +383,7 @@ function makeLocal(prepend, local) {
|
|||||||
* @returns an Object with the CSS, the loaded name, the src and the style.
|
* @returns an Object with the CSS, the loaded name, the src and the style.
|
||||||
*/
|
*/
|
||||||
function getFontSubstitution(
|
function getFontSubstitution(
|
||||||
|
systemFontCache,
|
||||||
idFactory,
|
idFactory,
|
||||||
localFontPath,
|
localFontPath,
|
||||||
baseFontName,
|
baseFontName,
|
||||||
@ -393,6 +395,12 @@ function getFontSubstitution(
|
|||||||
// just replace them by a dash.
|
// just replace them by a dash.
|
||||||
baseFontName = normalizeFontName(baseFontName);
|
baseFontName = normalizeFontName(baseFontName);
|
||||||
|
|
||||||
|
const key = baseFontName;
|
||||||
|
let substitutionInfo = systemFontCache.get(key);
|
||||||
|
if (substitutionInfo) {
|
||||||
|
return substitutionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
// First, check if we've a substitution for the base font.
|
// First, check if we've a substitution for the base font.
|
||||||
let substitution = substitutionMap.get(baseFontName);
|
let substitution = substitutionMap.get(baseFontName);
|
||||||
if (!substitution) {
|
if (!substitution) {
|
||||||
@ -416,6 +424,7 @@ function getFontSubstitution(
|
|||||||
const loadedName = `${idFactory.getDocId()}_sf_${idFactory.createFontId()}`;
|
const loadedName = `${idFactory.getDocId()}_sf_${idFactory.createFontId()}`;
|
||||||
if (!substitution) {
|
if (!substitution) {
|
||||||
if (!validateFontName(baseFontName)) {
|
if (!validateFontName(baseFontName)) {
|
||||||
|
systemFontCache.set(key, null);
|
||||||
// If the baseFontName is not valid we don't want to use it.
|
// If the baseFontName is not valid we don't want to use it.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -427,12 +436,14 @@ function getFontSubstitution(
|
|||||||
(bold && BOLD) ||
|
(bold && BOLD) ||
|
||||||
(italic && ITALIC) ||
|
(italic && ITALIC) ||
|
||||||
NORMAL;
|
NORMAL;
|
||||||
return {
|
substitutionInfo = {
|
||||||
css: `${loadedName},sans-serif`,
|
css: `${loadedName},sans-serif`,
|
||||||
loadedName,
|
loadedName,
|
||||||
src: `local(${baseFontName})`,
|
src: `local(${baseFontName})`,
|
||||||
style,
|
style,
|
||||||
};
|
};
|
||||||
|
systemFontCache.set(key, substitutionInfo);
|
||||||
|
return substitutionInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (substitution.alias) {
|
while (substitution.alias) {
|
||||||
@ -467,12 +478,14 @@ function getFontSubstitution(
|
|||||||
src = `local(${baseFontName}),${src}`;
|
src = `local(${baseFontName}),${src}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
substitutionInfo = {
|
||||||
css: `${loadedName},${ultimate}`,
|
css: `${loadedName},${ultimate}`,
|
||||||
loadedName,
|
loadedName,
|
||||||
src,
|
src,
|
||||||
style,
|
style,
|
||||||
};
|
};
|
||||||
|
systemFontCache.set(key, substitutionInfo);
|
||||||
|
return substitutionInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getFontSubstitution };
|
export { getFontSubstitution };
|
||||||
|
@ -25,6 +25,8 @@ import {
|
|||||||
import { isNodeJS } from "../shared/is_node.js";
|
import { isNodeJS } from "../shared/is_node.js";
|
||||||
|
|
||||||
class FontLoader {
|
class FontLoader {
|
||||||
|
#systemFonts = new Set();
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
ownerDocument = globalThis.document,
|
ownerDocument = globalThis.document,
|
||||||
styleElement = null, // For testing only.
|
styleElement = null, // For testing only.
|
||||||
@ -69,6 +71,7 @@ class FontLoader {
|
|||||||
this._document.fonts.delete(nativeFontFace);
|
this._document.fonts.delete(nativeFontFace);
|
||||||
}
|
}
|
||||||
this.nativeFontFaces.clear();
|
this.nativeFontFaces.clear();
|
||||||
|
this.#systemFonts.clear();
|
||||||
|
|
||||||
if (this.styleElement) {
|
if (this.styleElement) {
|
||||||
// Note: ChildNode.remove doesn't throw if the parentNode is undefined.
|
// Note: ChildNode.remove doesn't throw if the parentNode is undefined.
|
||||||
@ -78,6 +81,9 @@ class FontLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadSystemFont(info) {
|
async loadSystemFont(info) {
|
||||||
|
if (!info || this.#systemFonts.has(info.loadedName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
assert(
|
assert(
|
||||||
!this.disableFontFace,
|
!this.disableFontFace,
|
||||||
"loadSystemFont shouldn't be called when `disableFontFace` is set."
|
"loadSystemFont shouldn't be called when `disableFontFace` is set."
|
||||||
@ -89,6 +95,7 @@ class FontLoader {
|
|||||||
this.addNativeFontFace(fontFace);
|
this.addNativeFontFace(fontFace);
|
||||||
try {
|
try {
|
||||||
await fontFace.load();
|
await fontFace.load();
|
||||||
|
this.#systemFonts.add(loadedName);
|
||||||
} catch {
|
} catch {
|
||||||
warn(
|
warn(
|
||||||
`Cannot load system font: ${loadedName} for style ${style.style} and weight ${style.weight}.`
|
`Cannot load system font: ${loadedName} for style ${style.style} and weight ${style.weight}.`
|
||||||
|
@ -130,6 +130,7 @@ describe("annotation", function () {
|
|||||||
fontCache: new RefSetCache(),
|
fontCache: new RefSetCache(),
|
||||||
builtInCMapCache,
|
builtInCMapCache,
|
||||||
standardFontDataCache: new Map(),
|
standardFontDataCache: new Map(),
|
||||||
|
systemFontCache: new Map(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user