From c6d400ed06fb22b97e879ce60b9a24c64df5d520 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 28 Aug 2021 18:09:39 +0200 Subject: [PATCH] Export the XFA/StructTree-layers in the viewer components While e.g. the `simpleviewer` and `singlepageviewer` examples work, since they're based on the `BaseViewer`-class, the standalone `pageviewer` example currently doesn't support either XFA- or StructTree-layers. This seems like an obvious oversight, which can be easily addressed simply by exporting the necessary functionality through `pdf_viewer.component.js`, similar to the existing Text/Annotation-layers. While working on, and testing, these changes I happened to notice a number of smaller things that's also fixed in this patch: - Ensure that `XfaLayerBuilder.render` always have a *consistent* return type, to prevent possible run-time failures in `PDFPageView`; PR 13908 follow-up. - Change the order of the options in the `XfaLayerBuilder`-constructor to agree with the parameter order in the `DefaultXfaLayerFactory.createXfaLayerBuilder`-method. - Add a missing `textHighlighterFactory`-option, in the JSDocs for the `PDFPageView`-class. - A couple of small tweaks in the `TextLayerBuilder.render`-method: Re-use an existing Array rather than creating a new one, and replace an `if` with optional chaining instead. *Please note:* For now XFA-support is currently disabled by default, similar to the regular viewer. --- examples/components/pageviewer.js | 6 ++++-- web/annotation_layer_builder.js | 5 +---- web/pdf_page_view.js | 1 + web/pdf_viewer.component.js | 12 ++++++++++++ web/text_layer_builder.js | 7 +++---- web/xfa_layer_builder.js | 15 ++++++++------- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/examples/components/pageviewer.js b/examples/components/pageviewer.js index dfd82dacc..bdfce5086 100644 --- a/examples/components/pageviewer.js +++ b/examples/components/pageviewer.js @@ -54,11 +54,13 @@ loadingTask.promise.then(function (pdfDocument) { scale: SCALE, defaultViewport: pdfPage.getViewport({ scale: SCALE }), eventBus, - // We can enable text/annotations layers, if needed + // We can enable text/annotation/xfa/struct-layers, as needed. textLayerFactory: new pdfjsViewer.DefaultTextLayerFactory(), annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory(), + xfaLayerFactory: new pdfjsViewer.DefaultXfaLayerFactory(), + structTreeLayerFactory: new pdfjsViewer.DefaultStructTreeLayerFactory(), }); - // Associates the actual page with the view, and drawing it + // Associate the actual page with the view, and draw it. pdfPageView.setPdfPage(pdfPage); return pdfPageView.draw(); }); diff --git a/web/annotation_layer_builder.js b/web/annotation_layer_builder.js index 8579e5f86..b191c53f2 100644 --- a/web/annotation_layer_builder.js +++ b/web/annotation_layer_builder.js @@ -80,10 +80,7 @@ class AnnotationLayerBuilder { this.pdfPage.getAnnotations({ intent }), this._hasJSActionsPromise, ]).then(([annotations, hasJSActions = false]) => { - if (this._cancelled) { - return; - } - if (annotations.length === 0) { + if (this._cancelled || annotations.length === 0) { return; } diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index 05e9ea449..3cbe8e872 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -58,6 +58,7 @@ import { RenderingStates } from "./pdf_rendering_queue.js"; * @property {IPDFAnnotationLayerFactory} annotationLayerFactory * @property {IPDFXfaLayerFactory} xfaLayerFactory * @property {IPDFStructTreeLayerFactory} structTreeLayerFactory + * @property {Object} [textHighlighterFactory] * @property {string} [imageResourcesPath] - Path for image resources, mainly * for annotation icons. Include trailing slash. * @property {string} renderer - 'canvas' or 'svg'. The default is 'canvas'. diff --git a/web/pdf_viewer.component.js b/web/pdf_viewer.component.js index 09e7b0c3e..38d21ed4f 100644 --- a/web/pdf_viewer.component.js +++ b/web/pdf_viewer.component.js @@ -17,10 +17,18 @@ import { AnnotationLayerBuilder, DefaultAnnotationLayerFactory, } from "./annotation_layer_builder.js"; +import { + DefaultStructTreeLayerFactory, + StructTreeLayerBuilder, +} from "./struct_tree_layer_builder.js"; import { DefaultTextLayerFactory, TextLayerBuilder, } from "./text_layer_builder.js"; +import { + DefaultXfaLayerFactory, + XfaLayerBuilder, +} from "./xfa_layer_builder.js"; import { EventBus, ProgressBar } from "./ui_utils.js"; import { PDFLinkService, SimpleLinkService } from "./pdf_link_service.js"; import { DownloadManager } from "./download_manager.js"; @@ -41,7 +49,9 @@ const pdfjsBuild = PDFJSDev.eval("BUNDLE_BUILD"); export { AnnotationLayerBuilder, DefaultAnnotationLayerFactory, + DefaultStructTreeLayerFactory, DefaultTextLayerFactory, + DefaultXfaLayerFactory, DownloadManager, EventBus, GenericL10n, @@ -55,5 +65,7 @@ export { PDFViewer, ProgressBar, SimpleLinkService, + StructTreeLayerBuilder, TextLayerBuilder, + XfaLayerBuilder, }; diff --git a/web/text_layer_builder.js b/web/text_layer_builder.js index 765b88419..f33bcf9f9 100644 --- a/web/text_layer_builder.js +++ b/web/text_layer_builder.js @@ -93,10 +93,9 @@ class TextLayerBuilder { } this.cancel(); - this.textDivs = []; - if (this.highlighter) { - this.highlighter.setTextMapping(this.textDivs, this.textContentItemsStr); - } + this.textDivs.length = 0; + this.highlighter?.setTextMapping(this.textDivs, this.textContentItemsStr); + const textLayerFrag = document.createDocumentFragment(); this.textLayerRenderTask = renderTextLayer({ textContent: this.textContent, diff --git a/web/xfa_layer_builder.js b/web/xfa_layer_builder.js index 0a53d6ba7..b08c4e3b4 100644 --- a/web/xfa_layer_builder.js +++ b/web/xfa_layer_builder.js @@ -21,19 +21,19 @@ import { XfaLayer } from "pdfjs-lib"; * @typedef {Object} XfaLayerBuilderOptions * @property {HTMLDivElement} pageDiv * @property {PDFPage} pdfPage - * @property {Object} [xfaHtml] * @property {AnnotationStorage} [annotationStorage] + * @property {Object} [xfaHtml] */ class XfaLayerBuilder { /** * @param {XfaLayerBuilderOptions} options */ - constructor({ pageDiv, pdfPage, xfaHtml, annotationStorage }) { + constructor({ pageDiv, pdfPage, annotationStorage, xfaHtml }) { this.pageDiv = pageDiv; this.pdfPage = pdfPage; - this.xfaHtml = xfaHtml; this.annotationStorage = annotationStorage; + this.xfaHtml = xfaHtml; this.div = null; this._cancelled = false; @@ -62,17 +62,18 @@ class XfaLayerBuilder { this.pageDiv.appendChild(div); parameters.div = div; - XfaLayer.render(parameters); - return Promise.resolve(); + const result = XfaLayer.render(parameters); + return Promise.resolve(result); } // intent === "display" return this.pdfPage .getXfa() .then(xfa => { - if (this._cancelled) { - return Promise.resolve(); + if (this._cancelled || !xfa) { + return { textDivs: [] }; } + const parameters = { viewport: viewport.clone({ dontFlip: true }), div: this.div,