From a989b5a87942ff728463af7a6a1dae3df691d095 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 21 Nov 2022 18:48:37 +0100 Subject: [PATCH] Set the dimensions of the various layers at their creation - Use a unique helper function in display/display_utils.js; - Move those dimensions in css' side. --- src/display/annotation_layer.js | 21 ++------- src/display/display_utils.js | 43 +++++++++++++++++++ src/display/editor/annotation_editor_layer.js | 38 +++++++--------- src/display/text_layer.js | 26 ++--------- src/pdf.js | 2 + web/annotation_editor_layer_builder.js | 12 +++--- web/annotation_layer_builder.js | 3 +- web/pdf_page_view.js | 20 ++++++--- web/pdf_viewer.css | 2 + 9 files changed, 89 insertions(+), 78 deletions(-) diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index 266278751..24507f906 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -34,6 +34,7 @@ import { DOMSVGFactory, getFilenameFromUrl, PDFDateString, + setLayerDimensions, } from "./display_utils.js"; import { AnnotationStorage } from "./annotation_storage.js"; import { ColorConverters } from "../shared/scripting_utils.js"; @@ -2593,7 +2594,6 @@ class AnnotationLayer { static render(parameters) { const { annotations, div, viewport, accessibilityManager } = parameters; - this.#setDimensions(div, viewport); let zIndex = 0; for (const data of annotations) { @@ -2660,6 +2660,7 @@ class AnnotationLayer { } this.#setAnnotationCanvasMap(div, parameters.annotationCanvasMap); + setLayerDimensions(div, viewport); } /** @@ -2672,27 +2673,11 @@ class AnnotationLayer { static update(parameters) { const { annotationCanvasMap, div, viewport } = parameters; - this.#setDimensions(div, viewport); this.#setAnnotationCanvasMap(div, annotationCanvasMap); + setLayerDimensions(div, { rotation: viewport.rotation }); div.hidden = false; } - /** - * @param {HTMLDivElement} div - * @param {PageViewport} viewport - */ - static #setDimensions(div, { width, height, rotation }) { - const { style } = div; - - const flipOrientation = rotation % 180 !== 0, - widthStr = Math.floor(width) + "px", - heightStr = Math.floor(height) + "px"; - - style.width = flipOrientation ? heightStr : widthStr; - style.height = flipOrientation ? widthStr : heightStr; - div.setAttribute("data-main-rotation", rotation); - } - static #setAnnotationCanvasMap(div, annotationCanvasMap) { if (!annotationCanvasMap) { return; diff --git a/src/display/display_utils.js b/src/display/display_utils.js index 4b9c41164..814f277c5 100644 --- a/src/display/display_utils.js +++ b/src/display/display_utils.js @@ -614,6 +614,48 @@ function getCurrentTransformInverse(ctx) { return [a, b, c, d, e, f]; } +/** + * @param {HTMLDivElement} div + * @param {PageViewport} viewport + * @param {boolean} mustFlip + * @param {boolean} mustRotate + */ +function setLayerDimensions( + div, + viewport, + mustFlip = false, + mustRotate = true +) { + const { viewBox, rotation } = viewport; + if (viewBox) { + const [pageLLx, pageLLy, pageURx, pageURy] = viewBox; + const pageWidth = pageURx - pageLLx; + const pageHeight = pageURy - pageLLy; + const { style } = div; + + // TODO: Investigate if it could be interesting to use the css round + // function (https://developer.mozilla.org/en-US/docs/Web/CSS/round): + // const widthStr = + // `round(down, var(--scale-factor) * ${pageWidth}px, 1px)`; + // const heightStr = + // `round(down, var(--scale-factor) * ${pageHeight}px, 1px)`; + const widthStr = `calc(var(--scale-factor) * ${pageWidth}px)`; + const heightStr = `calc(var(--scale-factor) * ${pageHeight}px)`; + + if (!mustFlip || rotation % 180 === 0) { + style.width = widthStr; + style.height = heightStr; + } else { + style.width = heightStr; + style.height = widthStr; + } + } + + if (mustRotate) { + div.setAttribute("data-main-rotation", rotation); + } +} + export { AnnotationPrefix, deprecated, @@ -636,5 +678,6 @@ export { PDFDateString, PixelsPerInch, RenderingCancelledException, + setLayerDimensions, StatTimer, }; diff --git a/src/display/editor/annotation_editor_layer.js b/src/display/editor/annotation_editor_layer.js index 6f39ddd7c..c73ba7a5d 100644 --- a/src/display/editor/annotation_editor_layer.js +++ b/src/display/editor/annotation_editor_layer.js @@ -16,6 +16,7 @@ /** @typedef {import("./editor.js").AnnotationEditor} AnnotationEditor */ // eslint-disable-next-line max-len /** @typedef {import("./tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */ +/** @typedef {import("../display_utils.js").PageViewport} PageViewport */ // eslint-disable-next-line max-len /** @typedef {import("../../web/text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */ /** @typedef {import("../../web/interfaces").IL10n} IL10n */ @@ -24,6 +25,7 @@ import { AnnotationEditorType, FeatureTest } from "../../shared/util.js"; import { bindEvents } from "./tools.js"; import { FreeTextEditor } from "./freetext.js"; import { InkEditor } from "./ink.js"; +import { setLayerDimensions } from "../display_utils.js"; /** * @typedef {Object} AnnotationEditorLayerOptions @@ -36,6 +38,11 @@ import { InkEditor } from "./ink.js"; * @property {IL10n} l10n */ +/** + * @typedef {Object} RenderEditorLayerOptions + * @property {PageViewport} viewport + */ + /** * Manage all the different editors on a page. */ @@ -529,12 +536,12 @@ class AnnotationEditorLayer { /** * Render the main editor. - * @param {Object} parameters + * @param {RenderEditorLayerOptions} parameters */ - render(parameters) { - this.viewport = parameters.viewport; + render({ viewport }) { + this.viewport = viewport; + setLayerDimensions(this.div, viewport); bindEvents(this, this.div, ["dragover", "drop"]); - this.setDimensions(); for (const editor of this.#uiManager.getEditors(this.pageIndex)) { this.add(editor); } @@ -543,16 +550,16 @@ class AnnotationEditorLayer { /** * Update the main editor. - * @param {Object} parameters + * @param {RenderEditorLayerOptions} parameters */ - update(parameters) { + update({ viewport }) { // Editors have their dimensions/positions in percent so to avoid any // issues (see #15582), we must commit the current one before changing // the viewport. this.#uiManager.commitOrRemove(); - this.viewport = parameters.viewport; - this.setDimensions(); + this.viewport = viewport; + setLayerDimensions(this.div, { rotation: viewport.rotation }); this.updateMode(); } @@ -567,21 +574,6 @@ class AnnotationEditorLayer { return [width, height]; } - - /** - * Set the dimensions of the main div. - */ - setDimensions() { - const { width, height, rotation } = this.viewport; - - const flipOrientation = rotation % 180 !== 0, - widthStr = Math.floor(width) + "px", - heightStr = Math.floor(height) + "px"; - - this.div.style.width = flipOrientation ? heightStr : widthStr; - this.div.style.height = flipOrientation ? widthStr : heightStr; - this.div.setAttribute("data-main-rotation", rotation); - } } export { AnnotationEditorLayer }; diff --git a/src/display/text_layer.js b/src/display/text_layer.js index e9f0aef0d..0160be396 100644 --- a/src/display/text_layer.js +++ b/src/display/text_layer.js @@ -22,7 +22,7 @@ import { FeatureTest, Util, } from "../shared/util.js"; -import { deprecated } from "./display_utils.js"; +import { deprecated, setLayerDimensions } from "./display_utils.js"; /** * Text layer render parameters. @@ -330,7 +330,7 @@ class TextLayerRenderTask { this._pageWidth = pageURx - pageLLx; this._pageHeight = pageURy - pageLLy; - setTextLayerDimensions(container, viewport); + setLayerDimensions(container, viewport); // Always clean-up the temporary canvas once rendering is no longer pending. this._capability.promise @@ -485,7 +485,7 @@ function updateTextLayer({ mustRescale = true, }) { if (mustRotate) { - setTextLayerDimensions(container, { rotation: viewport.rotation }); + setLayerDimensions(container, { rotation: viewport.rotation }); } if (mustRescale) { @@ -507,24 +507,4 @@ function updateTextLayer({ } } -/** - * @param {HTMLDivElement} div - * @param {import("./display_utils").PageViewport} viewport - */ -function setTextLayerDimensions(div, viewport) { - if (!viewport.viewBox) { - div.setAttribute("data-main-rotation", viewport.rotation); - return; - } - - const [pageLLx, pageLLy, pageURx, pageURy] = viewport.viewBox; - const pageWidth = pageURx - pageLLx; - const pageHeight = pageURy - pageLLy; - const { style } = div; - - style.width = `calc(var(--scale-factor) * ${pageWidth}px)`; - style.height = `calc(var(--scale-factor) * ${pageHeight}px)`; - div.setAttribute("data-main-rotation", viewport.rotation); -} - export { renderTextLayer, TextLayerRenderTask, updateTextLayer }; diff --git a/src/pdf.js b/src/pdf.js index 9dd5ebf77..182ac5ed6 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -60,6 +60,7 @@ import { PDFDateString, PixelsPerInch, RenderingCancelledException, + setLayerDimensions, } from "./display/display_utils.js"; import { renderTextLayer, updateTextLayer } from "./display/text_layer.js"; import { AnnotationEditorLayer } from "./display/editor/annotation_editor_layer.js"; @@ -141,6 +142,7 @@ export { PixelsPerInch, RenderingCancelledException, renderTextLayer, + setLayerDimensions, shadow, SVGGraphics, UnexpectedResponseException, diff --git a/web/annotation_editor_layer_builder.js b/web/annotation_editor_layer_builder.js index e912ff60b..4dd31d18b 100644 --- a/web/annotation_editor_layer_builder.js +++ b/web/annotation_editor_layer_builder.js @@ -72,14 +72,14 @@ class AnnotationEditorLayerBuilder { } // Create an AnnotationEditor layer div - this.div = document.createElement("div"); - this.div.className = "annotationEditorLayer"; - this.div.tabIndex = 0; - this.pageDiv.append(this.div); + const div = (this.div = document.createElement("div")); + div.className = "annotationEditorLayer"; + div.tabIndex = 0; + this.pageDiv.append(div); this.annotationEditorLayer = new AnnotationEditorLayer({ uiManager: this.#uiManager, - div: this.div, + div, accessibilityManager: this.accessibilityManager, pageIndex: this.pdfPage.pageNumber - 1, l10n: this.l10n, @@ -88,7 +88,7 @@ class AnnotationEditorLayerBuilder { const parameters = { viewport: clonedViewport, - div: this.div, + div, annotations: null, intent, }; diff --git a/web/annotation_layer_builder.js b/web/annotation_layer_builder.js index efbf308bf..7d4da43ec 100644 --- a/web/annotation_layer_builder.js +++ b/web/annotation_layer_builder.js @@ -131,10 +131,9 @@ class AnnotationLayerBuilder { } else { // Create an annotation layer div and render the annotations // if there is at least one annotation. - this.div = document.createElement("div"); + this.div = parameters.div = document.createElement("div"); this.div.className = "annotationLayer"; this.pageDiv.append(this.div); - parameters.div = this.div; AnnotationLayer.render(parameters); this.l10n.translate(this.div); diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index befa9de82..b23a9dd7b 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -38,6 +38,7 @@ import { createPromiseCapability, PixelsPerInch, RenderingCancelledException, + setLayerDimensions, SVGGraphics, } from "pdfjs-lib"; import { @@ -179,8 +180,6 @@ class PDFPageView { const div = document.createElement("div"); div.className = "page"; - div.style.width = Math.round(this.viewport.width) + "px"; - div.style.height = Math.round(this.viewport.height) + "px"; div.setAttribute("data-page-number", this.id); div.setAttribute("role", "region"); this.l10n.get("page_landmark", { page: this.id }).then(msg => { @@ -188,6 +187,8 @@ class PDFPageView { }); this.div = div; + this.#setDimensions(); + container?.append(div); if ( @@ -219,6 +220,16 @@ class PDFPageView { } } + #setDimensions() { + const { div, viewport } = this; + setLayerDimensions( + div, + viewport, + /* mustFlip = */ true, + /* mustRotate = */ false + ); + } + setPdfPage(pdfPage) { this.pdfPage = pdfPage; this.pdfPageRotate = pdfPage.rotate; @@ -400,9 +411,8 @@ class PDFPageView { }); this.renderingState = RenderingStates.INITIAL; + this.#setDimensions(); const div = this.div; - div.style.width = Math.round(this.viewport.width) + "px"; - div.style.height = Math.round(this.viewport.height) + "px"; const childNodes = div.childNodes, zoomLayerNode = (keepZoomLayer && this.zoomLayer) || null, @@ -724,8 +734,6 @@ class PDFPageView { // Wrap the canvas so that if it has a CSS transform for high DPI the // overflow will be hidden in Firefox. const canvasWrapper = document.createElement("div"); - canvasWrapper.style.width = div.style.width; - canvasWrapper.style.height = div.style.height; canvasWrapper.classList.add("canvasWrapper"); if (this.textLayer) { diff --git a/web/pdf_viewer.css b/web/pdf_viewer.css index 26a06533f..2a6055adf 100644 --- a/web/pdf_viewer.css +++ b/web/pdf_viewer.css @@ -53,6 +53,8 @@ .pdfViewer .canvasWrapper { overflow: hidden; + width: 100%; + height: 100%; } .pdfViewer .page {