Convert BaseFontLoader.bind to be async, and only utilize BaseFontLoader._queueLoadingCallback when actually necessary

Currently all fonts are using the `_queueLoadingCallback` method to determine when they have been loaded[1]. However in most cases this is just adding unnecessary overhead, especially with `BaseFontLoader.bind` now being asynchronous, given how fonts are loaded:
 - For fonts loaded using the Font Loading API, it's already possible to easily tell when a font has been loaded simply by checking the `loaded` promise on the FontFace object itself.
 - For browsers, e.g. Firefox, which support synchronous font loading it's already assumed that fonts are immediately available.

Hence the `_queueLoadingCallback` method is moved into the `GenericFontLoader`, such that it's only utilized for fonts which are loaded using CSS.

---
[1] In the "fonts loaded using CSS" case, this is already a hack anyway as outlined in the comments.
This commit is contained in:
Jonas Jenwald 2019-02-10 14:01:49 +01:00
parent dfe7d9bc26
commit af3fcca88d
2 changed files with 38 additions and 34 deletions

View File

@ -1944,11 +1944,10 @@ class WorkerTransport {
onUnsupportedFeature: this._onUnsupportedFeature.bind(this),
fontRegistry,
});
const fontReady = (fontObjs) => {
this.commonObjs.resolve(id, font);
};
this.fontLoader.bind([font], fontReady);
this.fontLoader.bind([font]).then(() => {
this.commonObjs.resolve(id, font);
});
break;
case 'FontPath':
this.commonObjs.resolve(id, exportedData);

View File

@ -27,10 +27,6 @@ class BaseFontLoader {
this.nativeFontFaces = [];
this.styleElement = null;
this.loadingContext = {
requests: [],
nextRequestId: 0,
};
}
addNativeFontFace(nativeFontFace) {
@ -64,7 +60,7 @@ class BaseFontLoader {
}
}
bind(fonts, callback) {
async bind(fonts) {
const rules = [];
const fontsToLoad = [];
const fontLoadPromises = [];
@ -99,37 +95,19 @@ class BaseFontLoader {
}
}
const request = this._queueLoadingCallback(callback);
if (this.isFontLoadingAPISupported) {
Promise.all(fontLoadPromises).then(request.complete);
return Promise.all(fontLoadPromises);
} else if (rules.length > 0 && !this.isSyncFontLoadingSupported) {
this._prepareFontLoadEvent(rules, fontsToLoad, request);
} else {
request.complete();
return new Promise((resolve) => {
const request = this._queueLoadingCallback(resolve);
this._prepareFontLoadEvent(rules, fontsToLoad, request);
});
}
return; // Synchronous font loading supported.
}
_queueLoadingCallback(callback) {
function completeRequest() {
assert(!request.done, 'completeRequest() cannot be called twice.');
request.done = true;
// Sending all completed requests in order of how they were queued.
while (context.requests.length > 0 && context.requests[0].done) {
const otherRequest = context.requests.shift();
setTimeout(otherRequest.callback, 0);
}
}
const context = this.loadingContext;
const request = {
id: `pdfjs-font-loading-${context.nextRequestId++}`,
done: false,
complete: completeRequest,
callback,
};
context.requests.push(request);
return request;
unreachable('Abstract method `_queueLoadingCallback`.');
}
get isFontLoadingAPISupported() {
@ -168,6 +146,10 @@ FontLoader = class MozcentralFontLoader extends BaseFontLoader {
FontLoader = class GenericFontLoader extends BaseFontLoader {
constructor(docId) {
super(docId);
this.loadingContext = {
requests: [],
nextRequestId: 0,
};
this.loadTestFontId = 0;
}
@ -205,6 +187,29 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
return shadow(this, 'isSyncFontLoadingSupported', supported);
}
_queueLoadingCallback(callback) {
function completeRequest() {
assert(!request.done, 'completeRequest() cannot be called twice.');
request.done = true;
// Sending all completed requests in order of how they were queued.
while (context.requests.length > 0 && context.requests[0].done) {
const otherRequest = context.requests.shift();
setTimeout(otherRequest.callback, 0);
}
}
const context = this.loadingContext;
const request = {
id: `pdfjs-font-loading-${context.nextRequestId++}`,
done: false,
complete: completeRequest,
callback,
};
context.requests.push(request);
return request;
}
get _loadTestFont() {
const getLoadTestFont = function() {
// This is a CFF font with 1 glyph for '.' that fills its entire width and