[api-minor] XFA - Remove the xfaLayer from the DOM when resetting pages (bug 1721977, PR 13427 follow-up)

Originally the `xfaLayer` wasn't implemented in such a way that it supported being removed from the DOM when pages were evicted from the cache, however this limitation was lifted in PR 13427 and the `xfaLayer` should thus be handled similar to e.g. the `annotationLayer`.

In addition to removing the `xfaLayer` from the DOM, this patch *also* implements proper rendering/hiding-handling for it (mirroring the `annotationLayer`-code).

*Please note:* This patch is tagged API-minor just in case[1], since it changes the signatures of a couple of `PDFPageView`-methods to improve readability of the code.

---
[1] Although users are *hopefully* not directly accessing any of the affected methods, and are rather using e.g. `PDFViewer` in which case none of these changes will matter.
This commit is contained in:
Jonas Jenwald 2021-07-23 11:37:38 +02:00
parent 51f0a81085
commit d22ffbbc0a

View File

@ -207,33 +207,36 @@ class PDFPageView {
this.zoomLayer = null; this.zoomLayer = null;
} }
reset(keepZoomLayer = false, keepAnnotations = false) { reset({
this.cancelRendering(keepAnnotations); keepZoomLayer = false,
keepAnnotationLayer = false,
keepXfaLayer = false,
} = {}) {
this.cancelRendering({ keepAnnotationLayer, keepXfaLayer });
this.renderingState = RenderingStates.INITIAL; this.renderingState = RenderingStates.INITIAL;
const div = this.div; const div = this.div;
div.style.width = Math.floor(this.viewport.width) + "px"; div.style.width = Math.floor(this.viewport.width) + "px";
div.style.height = Math.floor(this.viewport.height) + "px"; div.style.height = Math.floor(this.viewport.height) + "px";
const childNodes = div.childNodes; const childNodes = div.childNodes,
const currentZoomLayerNode = (keepZoomLayer && this.zoomLayer) || null; zoomLayerNode = (keepZoomLayer && this.zoomLayer) || null,
const currentAnnotationNode = annotationLayerNode =
(keepAnnotations && this.annotationLayer?.div) || null; (keepAnnotationLayer && this.annotationLayer?.div) || null,
const currentXfaLayerNode = this.xfaLayer?.div || null; xfaLayerNode = (keepXfaLayer && this.xfaLayer?.div) || null;
for (let i = childNodes.length - 1; i >= 0; i--) { for (let i = childNodes.length - 1; i >= 0; i--) {
const node = childNodes[i]; const node = childNodes[i];
if ( switch (node) {
currentZoomLayerNode === node || case zoomLayerNode:
currentAnnotationNode === node || case annotationLayerNode:
currentXfaLayerNode === node case xfaLayerNode:
) { continue;
continue;
} }
div.removeChild(node); div.removeChild(node);
} }
div.removeAttribute("data-loaded"); div.removeAttribute("data-loaded");
if (currentAnnotationNode) { if (annotationLayerNode) {
// Hide the annotation layer until all elements are resized // Hide the annotation layer until all elements are resized
// so they are not displayed on the already resized page. // so they are not displayed on the already resized page.
this.annotationLayer.hide(); this.annotationLayer.hide();
@ -242,7 +245,16 @@ class PDFPageView {
this.annotationLayer = null; this.annotationLayer = null;
} }
if (!currentZoomLayerNode) { if (xfaLayerNode) {
// Hide the XFA layer until all elements are resized
// so they are not displayed on the already resized page.
this.xfaLayer.hide();
} else if (this.xfaLayer) {
this.xfaLayer.cancel();
this.xfaLayer = null;
}
if (!zoomLayerNode) {
if (this.canvas) { if (this.canvas) {
this.paintedViewportMap.delete(this.canvas); this.paintedViewportMap.delete(this.canvas);
// Zeroing the width and height causes Firefox to release graphics // Zeroing the width and height causes Firefox to release graphics
@ -284,7 +296,11 @@ class PDFPageView {
}); });
if (this.svg) { if (this.svg) {
this.cssTransform(this.svg, true); this.cssTransform({
target: this.svg,
redrawAnnotationLayer: true,
redrawXfaLayer: true,
});
this.eventBus.dispatch("pagerendered", { this.eventBus.dispatch("pagerendered", {
source: this, source: this,
@ -313,7 +329,11 @@ class PDFPageView {
this.useOnlyCssZoom || this.useOnlyCssZoom ||
(this.hasRestrictedScaling && isScalingRestricted) (this.hasRestrictedScaling && isScalingRestricted)
) { ) {
this.cssTransform(this.canvas, true); this.cssTransform({
target: this.canvas,
redrawAnnotationLayer: true,
redrawXfaLayer: true,
});
this.eventBus.dispatch("pagerendered", { this.eventBus.dispatch("pagerendered", {
source: this, source: this,
@ -330,16 +350,20 @@ class PDFPageView {
} }
} }
if (this.zoomLayer) { if (this.zoomLayer) {
this.cssTransform(this.zoomLayer.firstChild); this.cssTransform({ target: this.zoomLayer.firstChild });
} }
this.reset(/* keepZoomLayer = */ true, /* keepAnnotations = */ true); this.reset({
keepZoomLayer: true,
keepAnnotationLayer: true,
keepXfaLayer: true,
});
} }
/** /**
* PLEASE NOTE: Most likely you want to use the `this.reset()` method, * PLEASE NOTE: Most likely you want to use the `this.reset()` method,
* rather than calling this one directly. * rather than calling this one directly.
*/ */
cancelRendering(keepAnnotations = false) { cancelRendering({ keepAnnotationLayer = false, keepXfaLayer = false } = {}) {
if (this.paintTask) { if (this.paintTask) {
this.paintTask.cancel(); this.paintTask.cancel();
this.paintTask = null; this.paintTask = null;
@ -350,17 +374,25 @@ class PDFPageView {
this.textLayer.cancel(); this.textLayer.cancel();
this.textLayer = null; this.textLayer = null;
} }
if (!keepAnnotations && this.annotationLayer) { if (!keepAnnotationLayer && this.annotationLayer) {
this.annotationLayer.cancel(); this.annotationLayer.cancel();
this.annotationLayer = null; this.annotationLayer = null;
} }
if (!keepXfaLayer && this.xfaLayer) {
this.xfaLayer.cancel();
this.xfaLayer = null;
}
if (this._onTextLayerRendered) { if (this._onTextLayerRendered) {
this.eventBus._off("textlayerrendered", this._onTextLayerRendered); this.eventBus._off("textlayerrendered", this._onTextLayerRendered);
this._onTextLayerRendered = null; this._onTextLayerRendered = null;
} }
} }
cssTransform(target, redrawAnnotations = false) { cssTransform({
target,
redrawAnnotationLayer = false,
redrawXfaLayer = false,
}) {
// Scale target (canvas or svg), its wrapper and page container. // Scale target (canvas or svg), its wrapper and page container.
const width = this.viewport.width; const width = this.viewport.width;
const height = this.viewport.height; const height = this.viewport.height;
@ -429,11 +461,10 @@ class PDFPageView {
textLayerDiv.style.transformOrigin = "0% 0%"; textLayerDiv.style.transformOrigin = "0% 0%";
} }
if (redrawAnnotations && this.annotationLayer) { if (redrawAnnotationLayer && this.annotationLayer) {
this._renderAnnotationLayer(); this._renderAnnotationLayer();
} }
if (redrawXfaLayer && this.xfaLayer) {
if (this.xfaLayer) {
this._renderXfaLayer(); this._renderXfaLayer();
} }
} }