Don't re-create the structTreeLayer
on zooming and rotation
Compared to the recent PR 15722 for the `textLayer` this one should be a (comparatively) much a smaller win overall, since most documents don't have any structTree-data and the required parsing should be cheaper. However, it seems to me that it cannot hurt to improve this nonetheless. Note that by moving the `structTreeLayer` initialization we remove the need for the "textlayerrendered" event listener, which thus simplifies the code a little bit. Also, removes the API-caching of the structTree-data since this was basically done to offset the lack of caching in the viewer.
This commit is contained in:
parent
cd72818438
commit
da0e6bc590
@ -1623,9 +1623,7 @@ class PDFPageProxy {
|
||||
* or `null` when no structure tree is present for the current page.
|
||||
*/
|
||||
getStructTree() {
|
||||
return (this._structTreePromise ||= this._transport.getStructTree(
|
||||
this._pageIndex
|
||||
));
|
||||
return this._transport.getStructTree(this._pageIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1659,7 +1657,6 @@ class PDFPageProxy {
|
||||
this._bitmaps.clear();
|
||||
this._annotationPromises.clear();
|
||||
this._jsActionsPromise = null;
|
||||
this._structTreePromise = null;
|
||||
this.pendingCleanup = false;
|
||||
return Promise.all(waitOn);
|
||||
}
|
||||
@ -1694,7 +1691,6 @@ class PDFPageProxy {
|
||||
this.objs.clear();
|
||||
this._annotationPromises.clear();
|
||||
this._jsActionsPromise = null;
|
||||
this._structTreePromise = null;
|
||||
if (resetStats && this._stats) {
|
||||
this._stats = new StatTimer();
|
||||
}
|
||||
|
@ -318,6 +318,33 @@ class PDFPageView {
|
||||
numTextDivs: textLayer.numTextDivs,
|
||||
error,
|
||||
});
|
||||
|
||||
if (this.structTreeLayerFactory) {
|
||||
this.#renderStructTreeLayer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The structure tree is currently only supported when the text layer is
|
||||
* enabled and a canvas is used for rendering.
|
||||
*
|
||||
* The structure tree must be generated after the text layer for the
|
||||
* aria-owns to work.
|
||||
*/
|
||||
async #renderStructTreeLayer() {
|
||||
if (!this.textLayer) {
|
||||
return;
|
||||
}
|
||||
this.structTreeLayer ||=
|
||||
this.structTreeLayerFactory.createStructTreeLayerBuilder();
|
||||
|
||||
const tree = await (!this.structTreeLayer.renderingDone
|
||||
? this.pdfPage.getStructTree()
|
||||
: null);
|
||||
const treeDom = this.structTreeLayer?.render(tree);
|
||||
if (treeDom) {
|
||||
this.canvas?.append(treeDom);
|
||||
}
|
||||
}
|
||||
|
||||
async _buildXfaTextContentItems(textDivs) {
|
||||
@ -578,6 +605,9 @@ class PDFPageView {
|
||||
this.textLayer.cancel();
|
||||
this.textLayer = null;
|
||||
}
|
||||
if (this.structTreeLayer && !this.textLayer) {
|
||||
this.structTreeLayer = null;
|
||||
}
|
||||
if (
|
||||
this.annotationLayer &&
|
||||
(!keepAnnotationLayer || !this.annotationLayer.div)
|
||||
@ -598,10 +628,6 @@ class PDFPageView {
|
||||
this.xfaLayer = null;
|
||||
this.textHighlighter?.disable();
|
||||
}
|
||||
if (this._onTextLayerRendered) {
|
||||
this.eventBus._off("textlayerrendered", this._onTextLayerRendered);
|
||||
this._onTextLayerRendered = null;
|
||||
}
|
||||
}
|
||||
|
||||
cssTransform({
|
||||
@ -844,38 +870,6 @@ class PDFPageView {
|
||||
this._renderXfaLayer();
|
||||
}
|
||||
|
||||
// The structure tree is currently only supported when the text layer is
|
||||
// enabled and a canvas is used for rendering.
|
||||
if (this.structTreeLayerFactory && this.textLayer && this.canvas) {
|
||||
// The structure tree must be generated after the text layer for the
|
||||
// aria-owns to work.
|
||||
this._onTextLayerRendered = event => {
|
||||
if (event.pageNumber !== this.id) {
|
||||
return;
|
||||
}
|
||||
this.eventBus._off("textlayerrendered", this._onTextLayerRendered);
|
||||
this._onTextLayerRendered = null;
|
||||
|
||||
if (!this.canvas) {
|
||||
return; // The canvas was removed, prevent errors below.
|
||||
}
|
||||
this.pdfPage.getStructTree().then(tree => {
|
||||
if (!tree) {
|
||||
return;
|
||||
}
|
||||
if (!this.canvas) {
|
||||
return; // The canvas was removed, prevent errors below.
|
||||
}
|
||||
const treeDom = this.structTreeLayer.render(tree);
|
||||
treeDom.classList.add("structTree");
|
||||
this.canvas.append(treeDom);
|
||||
});
|
||||
};
|
||||
this.eventBus._on("textlayerrendered", this._onTextLayerRendered);
|
||||
this.structTreeLayer =
|
||||
this.structTreeLayerFactory.createStructTreeLayerBuilder();
|
||||
}
|
||||
|
||||
div.setAttribute("data-loaded", true);
|
||||
|
||||
this.eventBus.dispatch("pagerender", {
|
||||
|
@ -72,8 +72,19 @@ const PDF_ROLE_TO_HTML_ROLE = {
|
||||
const HEADING_PATTERN = /^H(\d+)$/;
|
||||
|
||||
class StructTreeLayerBuilder {
|
||||
#treeDom = undefined;
|
||||
|
||||
get renderingDone() {
|
||||
return this.#treeDom !== undefined;
|
||||
}
|
||||
|
||||
render(structTree) {
|
||||
return this.#walk(structTree);
|
||||
if (this.#treeDom !== undefined) {
|
||||
return this.#treeDom;
|
||||
}
|
||||
const treeDom = this.#walk(structTree);
|
||||
treeDom?.classList.add("structTree");
|
||||
return (this.#treeDom = treeDom);
|
||||
}
|
||||
|
||||
#setAttributes(structElement, htmlElement) {
|
||||
|
Loading…
Reference in New Issue
Block a user