Don't attempt to re-create the annotationLayer, for pages without any annotations, on zooming and rotation

For pages without any annotations, applies e.g. to the `tracemonkey.pdf` document, we'll repeatedly try to re-create the `annotationLayer` on every zoom and rotation operation.
The reason that this happens is because we don't insert the `annotationLayer`-div into the DOM unless there's annotations present on the page, which thus means that we miss the existing `annotationLayer`-caching present in the `PDFPageView` implementation.

This is a very old issue, and the easiest solution is to simply always insert an *empty* (and hidden) `annotationLayer`-div such that the existing code/caching starts working for the "no annotations" case as well.
Note that this is consistent with other layers, since e.g. the `textLayer` and/or `annotationEditorLayer` may be empty. Given that only a limited, by default ten, number of pages are ever active at once the additional DOM-elements shouldn't effect things negatively here.
This commit is contained in:
Jonas Jenwald 2022-12-11 14:51:28 +01:00
parent d9f13558d6
commit 8e56f072e0

View File

@ -47,6 +47,8 @@ import { PresentationModeState } from "./ui_utils.js";
*/
class AnnotationLayerBuilder {
#numAnnotations = 0;
#onPresentationModeChanged = null;
/**
@ -77,8 +79,8 @@ class AnnotationLayerBuilder {
this.l10n = l10n;
this.annotationStorage = annotationStorage;
this.enableScripting = enableScripting;
this._hasJSActionsPromise = hasJSActionsPromise;
this._fieldObjectsPromise = fieldObjectsPromise;
this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
this._mouseState = mouseState;
this._annotationCanvasMap = annotationCanvasMap;
this._accessibilityManager = accessibilityManager;
@ -95,18 +97,41 @@ class AnnotationLayerBuilder {
* annotations is complete.
*/
async render(viewport, intent = "display") {
const [annotations, hasJSActions = false, fieldObjects = null] =
await Promise.all([
if (this.div) {
if (this._cancelled || this.#numAnnotations === 0) {
return;
}
// If an annotationLayer already exists, refresh its children's
// transformation matrices.
AnnotationLayer.update({
viewport: viewport.clone({ dontFlip: true }),
div: this.div,
annotationCanvasMap: this._annotationCanvasMap,
});
return;
}
const [annotations, hasJSActions, fieldObjects] = await Promise.all([
this.pdfPage.getAnnotations({ intent }),
this._hasJSActionsPromise,
this._fieldObjectsPromise,
]);
if (this._cancelled || annotations.length === 0) {
if (this._cancelled) {
return;
}
this.#numAnnotations = annotations.length;
const parameters = {
// Create an annotation layer div and render the annotations
// if there is at least one annotation.
this.div = document.createElement("div");
this.div.className = "annotationLayer";
this.pageDiv.append(this.div);
if (this.#numAnnotations === 0) {
this.hide();
return;
}
AnnotationLayer.render({
viewport: viewport.clone({ dontFlip: true }),
div: this.div,
annotations,
@ -122,20 +147,7 @@ class AnnotationLayerBuilder {
mouseState: this._mouseState,
annotationCanvasMap: this._annotationCanvasMap,
accessibilityManager: this._accessibilityManager,
};
if (this.div) {
// If an annotationLayer already exists, refresh its children's
// transformation matrices.
AnnotationLayer.update(parameters);
} else {
// Create an annotation layer div and render the annotations
// if there is at least one annotation.
this.div = parameters.div = document.createElement("div");
this.div.className = "annotationLayer";
this.pageDiv.append(this.div);
AnnotationLayer.render(parameters);
});
this.l10n.translate(this.div);
// Ensure that interactive form elements in the annotationLayer are
@ -153,7 +165,6 @@ class AnnotationLayerBuilder {
);
}
}
}
cancel() {
this._cancelled = true;