From e2db9bacefd45d1eb20258980e36d163ce261177 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 13 Jun 2022 11:01:55 +0200 Subject: [PATCH] Get rid of CSS transform on each annotation in the annotation layer - each annotation has its coordinates/dimensions expressed in percentage, hence it's correctly positioned whatever the scale factor is; - the font sizes are expressed in percentage too and the main font size is scaled thanks a css var (--scale-factor); - the rotation is now applied on the div annotationLayer; - this patch improve the rendering of some strings where the glyph spacing was not correct (it's a Firefox bug); - it helps to simplify the code and it should slightly improve the update of page (on zoom or rotation). --- src/core/annotation.js | 6 +- src/core/xfa/template.js | 2 +- src/core/xfa/xhtml.js | 4 + src/display/annotation_layer.js | 171 +++++++----------- src/display/base_factory.js | 10 +- src/display/canvas.js | 3 - src/display/editor/annotation_editor_layer.js | 9 - src/display/editor/freetext.js | 11 +- test/annotation_layer_builder_overrides.css | 7 + test/driver.js | 3 +- test/integration/freetext_editor_spec.js | 4 +- web/annotation_editor_layer_builder.css | 3 +- web/annotation_layer_builder.css | 64 +++++-- web/annotation_layer_builder.js | 3 + web/base_viewer.js | 5 +- web/pdf_page_view.js | 2 +- web/pdf_viewer.css | 2 +- 17 files changed, 154 insertions(+), 155 deletions(-) diff --git a/src/core/annotation.js b/src/core/annotation.js index ef61f78efada3..bd9dc692abfaf 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -432,6 +432,7 @@ class Annotation { this.setAppearance(dict); this.setBorderAndBackgroundColors(dict.get("MK")); + this._hasOwnCanvas = false; this._streams = []; if (this.appearance) { this._streams.push(this.appearance); @@ -450,7 +451,6 @@ class Annotation { modificationDate: this.modificationDate, rect: this.rectangle, subtype: params.subtype, - hasOwnCanvas: false, }; if (params.collectFields) { @@ -849,7 +849,7 @@ class Annotation { const data = this.data; let appearance = this.appearance; const isUsingOwnCanvas = - data.hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY; + this._hasOwnCanvas && intent & RenderingIntentFlag.DISPLAY; if (!appearance) { if (!isUsingOwnCanvas) { return Promise.resolve(new OperatorList()); @@ -2163,7 +2163,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { } else if (this.data.radioButton) { this._processRadioButton(params); } else if (this.data.pushButton) { - this.data.hasOwnCanvas = true; + this._hasOwnCanvas = true; this._processPushButton(params); } else { warn("Invalid field flags for button widget annotation"); diff --git a/src/core/xfa/template.js b/src/core/xfa/template.js index bd4e1b343d880..49e5f2698e95a 100644 --- a/src/core/xfa/template.js +++ b/src/core/xfa/template.js @@ -1425,7 +1425,7 @@ class ChoiceList extends XFAObject { const field = ui[$getParent](); const fontSize = (field.font && field.font.size) || 10; const optionStyle = { - fontSize: `calc(${fontSize}px * var(--zoom-factor))`, + fontSize: `calc(${fontSize}px * var(--scale-factor))`, }; const children = []; diff --git a/src/core/xfa/xhtml.js b/src/core/xfa/xhtml.js index bf5aceaef681c..e39c88d0e7929 100644 --- a/src/core/xfa/xhtml.js +++ b/src/core/xfa/xhtml.js @@ -182,6 +182,10 @@ function mapStyle(styleStr, node, richText) { ); } + if (richText && style.fontSize) { + style.fontSize = `calc(${style.fontSize} * var(--scale-factor))`; + } + fixTextIndent(style); return style; } diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index ba6a61f80abd8..49d06220643d4 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -197,7 +197,11 @@ class AnnotationElement { page = this.page, viewport = this.viewport; const container = document.createElement("section"); - let { width, height } = getRectDims(data.rect); + const { width, height } = getRectDims(data.rect); + + const [pageLLx, pageLLy, pageURx, pageURy] = viewport.viewBox; + const pageWidth = pageURx - pageLLx; + const pageHeight = pageURy - pageLLy; container.setAttribute("data-annotation-id", data.id); @@ -210,41 +214,13 @@ class AnnotationElement { page.view[3] - data.rect[3] + page.view[1], ]); - if (data.hasOwnCanvas) { - const transform = viewport.transform.slice(); - const [scaleX, scaleY] = Util.singularValueDecompose2dScale(transform); - width = Math.ceil(width * scaleX); - height = Math.ceil(height * scaleY); - rect[0] *= scaleX; - rect[1] *= scaleY; - // Reset the scale part of the transform matrix (which must be diagonal - // or anti-diagonal) in order to avoid to rescale the canvas. - // The canvas for the annotation is correctly scaled when it is drawn - // (see `beginAnnotation` in canvas.js). - for (let i = 0; i < 4; i++) { - transform[i] = Math.sign(transform[i]); - } - container.style.transform = `matrix(${transform.join(",")})`; - } else { - container.style.transform = `matrix(${viewport.transform.join(",")})`; - } - - container.style.transformOrigin = `${-rect[0]}px ${-rect[1]}px`; - if (!ignoreBorder && data.borderStyle.width > 0) { container.style.borderWidth = `${data.borderStyle.width}px`; - if (data.borderStyle.style !== AnnotationBorderStyleType.UNDERLINE) { - // Underline styles only have a bottom border, so we do not need - // to adjust for all borders. This yields a similar result as - // Adobe Acrobat/Reader. - width -= 2 * data.borderStyle.width; - height -= 2 * data.borderStyle.width; - } const horizontalRadius = data.borderStyle.horizontalCornerRadius; const verticalRadius = data.borderStyle.verticalCornerRadius; if (horizontalRadius > 0 || verticalRadius > 0) { - const radius = `${horizontalRadius}px / ${verticalRadius}px`; + const radius = `calc(${horizontalRadius}px * var(--scale-factor)) / calc(${verticalRadius}px * var(--scale-factor))`; container.style.borderRadius = radius; } @@ -286,15 +262,11 @@ class AnnotationElement { } } - container.style.left = `${rect[0]}px`; - container.style.top = `${rect[1]}px`; + container.style.left = `${(100 * (rect[0] - pageLLx)) / pageWidth}%`; + container.style.top = `${(100 * (rect[1] - pageLLy)) / pageHeight}%`; + container.style.width = `${(100 * width) / pageWidth}%`; + container.style.height = `${(100 * height) / pageHeight}%`; - if (data.hasOwnCanvas) { - container.style.width = container.style.height = "auto"; - } else { - container.style.width = `${width}px`; - container.style.height = `${height}px`; - } return container; } @@ -464,7 +436,7 @@ class AnnotationElement { const popup = popupElement.render(); // Position the popup next to the annotation's container. - popup.style.left = container.style.width; + popup.style.left = "100%"; container.append(popup); } @@ -820,8 +792,6 @@ class TextAnnotationElement extends AnnotationElement { this.container.className = "textAnnotation"; const image = document.createElement("img"); - image.style.height = this.container.style.height; - image.style.width = this.container.style.width; image.src = this.imageResourcesPath + "annotation-" + @@ -925,21 +895,20 @@ class WidgetAnnotationElement extends AnnotationElement { // it's instead based on the field height. // If the height is "big" then it could lead to a too big font size // so in this case use the one we've in the pdf (hence the min). + let computedFontSize; if (this.data.multiLine) { const height = Math.abs(this.data.rect[3] - this.data.rect[1]); const numberOfLines = Math.round(height / (LINE_FACTOR * fontSize)) || 1; const lineHeight = height / numberOfLines; - style.fontSize = `${Math.min( + computedFontSize = Math.min( fontSize, Math.round(lineHeight / LINE_FACTOR) - )}px`; + ); } else { const height = Math.abs(this.data.rect[3] - this.data.rect[1]); - style.fontSize = `${Math.min( - fontSize, - Math.round(height / LINE_FACTOR) - )}px`; + computedFontSize = Math.min(fontSize, Math.round(height / LINE_FACTOR)); } + style.fontSize = `${computedFontSize}%`; style.color = Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]); @@ -1227,7 +1196,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement { const combWidth = fieldWidth / this.data.maxLen; element.classList.add("comb"); - element.style.letterSpacing = `calc(${combWidth}px - 1ch)`; + element.style.letterSpacing = `calc(${combWidth}px * var(--scale-factor) - 1ch)`; } } else { element = document.createElement("div"); @@ -1464,10 +1433,6 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { value: this.data.fieldValue, }); - const fontSize = - this.data.defaultAppearanceData.fontSize || DEFAULT_FONT_SIZE; - const fontSizeStyle = `calc(${fontSize}px * var(--zoom-factor))`; - const selectElement = document.createElement("select"); GetElementsByNameSet.add(selectElement); selectElement.setAttribute("data-element-id", id); @@ -1499,9 +1464,6 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { const optionElement = document.createElement("option"); optionElement.textContent = option.displayValue; optionElement.value = option.exportValue; - if (this.data.combo) { - optionElement.style.fontSize = fontSizeStyle; - } if (storedData.value.includes(option.exportValue)) { optionElement.setAttribute("selected", true); addAnEmptyEntry = false; @@ -1749,9 +1711,12 @@ class PopupAnnotationElement extends AnnotationElement { rect[0] + this.data.parentRect[2] - this.data.parentRect[0]; const popupTop = rect[1]; - this.container.style.transformOrigin = `${-popupLeft}px ${-popupTop}px`; - this.container.style.left = `${popupLeft}px`; - this.container.style.top = `${popupTop}px`; + const [pageLLx, pageLLy, pageURx, pageURy] = this.viewport.viewBox; + const pageWidth = pageURx - pageLLx; + const pageHeight = pageURy - pageLLy; + + this.container.style.left = `${(100 * (popupLeft - pageLLx)) / pageWidth}%`; + this.container.style.top = `${(100 * (popupTop - pageLLy)) / pageHeight}%`; this.container.append(popup.render()); return this.container; @@ -1961,7 +1926,11 @@ class LineAnnotationElement extends AnnotationElement { // trigger the popup, not the entire container. const data = this.data; const { width, height } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height); + const svg = this.svgFactory.create( + width, + height, + /* skipDimensions = */ true + ); // PDF coordinates are calculated from a bottom left origin, so transform // the line coordinates to a top left origin for the SVG element. @@ -2006,7 +1975,11 @@ class SquareAnnotationElement extends AnnotationElement { // popup, not the entire container. const data = this.data; const { width, height } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height); + const svg = this.svgFactory.create( + width, + height, + /* skipDimensions = */ true + ); // The browser draws half of the borders inside the square and half of // the borders outside the square by default. This behavior cannot be @@ -2053,7 +2026,11 @@ class CircleAnnotationElement extends AnnotationElement { // popup, not the entire container. const data = this.data; const { width, height } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height); + const svg = this.svgFactory.create( + width, + height, + /* skipDimensions = */ true + ); // The browser draws half of the borders inside the circle and half of // the borders outside the circle by default. This behavior cannot be @@ -2103,7 +2080,11 @@ class PolylineAnnotationElement extends AnnotationElement { // popup, not the entire container. const data = this.data; const { width, height } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height); + const svg = this.svgFactory.create( + width, + height, + /* skipDimensions = */ true + ); // Convert the vertices array to a single points string that the SVG // polyline element expects ("x1,y1 x2,y2 ..."). PDF coordinates are @@ -2191,7 +2172,11 @@ class InkAnnotationElement extends AnnotationElement { // trigger for the popup. const data = this.data; const { width, height } = getRectDims(data.rect); - const svg = this.svgFactory.create(width, height); + const svg = this.svgFactory.create( + width, + height, + /* skipDimensions = */ true + ); for (const inkList of data.inkLists) { // Convert the ink list to a single points string that the SVG @@ -2515,55 +2500,27 @@ class AnnotationLayer { * @memberof AnnotationLayer */ static update(parameters) { - const { page, viewport, annotations, annotationCanvasMap, div } = - parameters; - const transform = viewport.transform; - const matrix = `matrix(${transform.join(",")})`; - - let scale, ownMatrix; - for (const data of annotations) { - const elements = div.querySelectorAll( - `[data-annotation-id="${data.id}"]` - ); - if (elements) { - for (const element of elements) { - if (data.hasOwnCanvas) { - const rect = Util.normalizeRect([ - data.rect[0], - page.view[3] - data.rect[1] + page.view[1], - data.rect[2], - page.view[3] - data.rect[3] + page.view[1], - ]); - - if (!ownMatrix) { - // When an annotation has its own canvas, then - // the scale has been already applied to the canvas, - // so we musn't scale it twice. - scale = Math.abs(transform[0] || transform[1]); - const ownTransform = transform.slice(); - for (let i = 0; i < 4; i++) { - ownTransform[i] = Math.sign(ownTransform[i]); - } - ownMatrix = `matrix(${ownTransform.join(",")})`; - } - - const left = rect[0] * scale; - const top = rect[1] * scale; - element.style.left = `${left}px`; - element.style.top = `${top}px`; - element.style.transformOrigin = `${-left}px ${-top}px`; - element.style.transform = ownMatrix; - } else { - element.style.transform = matrix; - } - } - } - } + const { annotationCanvasMap, div } = parameters; this.#setAnnotationCanvasMap(div, annotationCanvasMap); div.hidden = false; } + static setDimensions(div, viewport) { + const { width, height, rotation } = viewport; + const { style } = div; + + if (rotation === 0 || rotation === 180) { + style.width = `${width}px`; + style.height = `${height}px`; + } else { + style.width = `${height}px`; + style.height = `${width}px`; + } + + div.setAttribute("data-annotation-rotation", rotation); + } + static #setAnnotationCanvasMap(div, annotationCanvasMap) { if (!annotationCanvasMap) { return; diff --git a/src/display/base_factory.js b/src/display/base_factory.js index d50f7a2a357f0..a9e4a242c9645 100644 --- a/src/display/base_factory.js +++ b/src/display/base_factory.js @@ -143,14 +143,18 @@ class BaseSVGFactory { } } - create(width, height) { + create(width, height, skipDimensions = false) { if (width <= 0 || height <= 0) { throw new Error("Invalid SVG dimensions"); } const svg = this._createSVG("svg:svg"); svg.setAttribute("version", "1.1"); - svg.setAttribute("width", `${width}px`); - svg.setAttribute("height", `${height}px`); + + if (!skipDimensions) { + svg.setAttribute("width", `${width}px`); + svg.setAttribute("height", `${height}px`); + } + svg.setAttribute("preserveAspectRatio", "none"); svg.setAttribute("viewBox", `0 0 ${width} ${height}`); diff --git a/src/display/canvas.js b/src/display/canvas.js index cd3950cb893b3..98a6eec1fa9ec 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -3021,9 +3021,6 @@ class CanvasGraphics { canvasHeight ); const { canvas, context } = this.annotationCanvas; - const viewportScaleFactorStr = `var(--zoom-factor) * ${PixelsPerInch.PDF_TO_CSS_UNITS}`; - canvas.style.width = `calc(${width}px * ${viewportScaleFactorStr})`; - canvas.style.height = `calc(${height}px * ${viewportScaleFactorStr})`; this.annotationCanvasMap.set(id, canvas); this.annotationCanvas.savedCtx = this.ctx; this.ctx = context; diff --git a/src/display/editor/annotation_editor_layer.js b/src/display/editor/annotation_editor_layer.js index e19333a61ab4c..5a14760d24a04 100644 --- a/src/display/editor/annotation_editor_layer.js +++ b/src/display/editor/annotation_editor_layer.js @@ -24,7 +24,6 @@ import { AnnotationEditorType, Util } from "../../shared/util.js"; import { bindEvents, KeyboardManager } from "./tools.js"; import { FreeTextEditor } from "./freetext.js"; import { InkEditor } from "./ink.js"; -import { PixelsPerInch } from "../display_utils.js"; /** * @typedef {Object} AnnotationEditorLayerOptions @@ -492,14 +491,6 @@ class AnnotationEditorLayer { get scaleFactor() { return this.viewport.scale; } - - /** - * Get the zoom factor. - * @returns {number} - */ - get zoomFactor() { - return this.viewport.scale / PixelsPerInch.PDF_TO_CSS_UNITS; - } } export { AnnotationEditorLayer }; diff --git a/src/display/editor/freetext.js b/src/display/editor/freetext.js index 68c65ef370a1f..d657f2e3dd917 100644 --- a/src/display/editor/freetext.js +++ b/src/display/editor/freetext.js @@ -21,7 +21,6 @@ import { } from "../../shared/util.js"; import { AnnotationEditor } from "./editor.js"; import { bindEvents } from "./tools.js"; -import { PixelsPerInch } from "../display_utils.js"; /** * Basic text editor in order to create a FreeTex annotation. @@ -94,9 +93,9 @@ class FreeTextEditor extends AnnotationEditor { getInitialTranslation() { // The start of the base line is where the user clicked. return [ - -FreeTextEditor._internalPadding * this.parent.zoomFactor, + -FreeTextEditor._internalPadding * this.parent.scaleFactor, -(FreeTextEditor._internalPadding + this.#fontSize) * - this.parent.zoomFactor, + this.parent.scaleFactor, ]; } @@ -217,7 +216,7 @@ class FreeTextEditor extends AnnotationEditor { this.editorDiv.contentEditable = true; const { style } = this.editorDiv; - style.fontSize = `calc(${this.#fontSize}px * var(--zoom-factor))`; + style.fontSize = `${this.#fontSize}%`; style.color = this.#color; this.div.append(this.editorDiv); @@ -244,7 +243,7 @@ class FreeTextEditor extends AnnotationEditor { /** @inheritdoc */ serialize() { const rect = this.editorDiv.getBoundingClientRect(); - const padding = FreeTextEditor._internalPadding * this.parent.zoomFactor; + const padding = FreeTextEditor._internalPadding * this.parent.scaleFactor; const [x1, y1] = Util.applyTransform( [this.x + padding, this.y + padding + rect.height], this.parent.inverseViewportTransform @@ -257,7 +256,7 @@ class FreeTextEditor extends AnnotationEditor { return { annotationType: AnnotationEditorType.FREETEXT, color: [0, 0, 0], - fontSize: this.#fontSize / PixelsPerInch.PDF_TO_CSS_UNITS, + fontSize: this.#fontSize, value: this.#content, pageIndex: this.parent.pageIndex, rect: [x1, y1, x2, y2], diff --git a/test/annotation_layer_builder_overrides.css b/test/annotation_layer_builder_overrides.css index e93d59985157e..236e13f2bd60b 100644 --- a/test/annotation_layer_builder_overrides.css +++ b/test/annotation_layer_builder_overrides.css @@ -17,6 +17,13 @@ .annotationLayer { position: absolute; + font-size: calc(100px * var(--scale-factor)); +} + +.annotationLayer .buttonWidgetAnnotation.pushButton > img { + width: 100%; + height: 100%; + position: absolute; } .annotationLayer .buttonWidgetAnnotation.checkBox input, diff --git a/test/driver.js b/test/driver.js index bba4a09060293..f774b4d1fdfa2 100644 --- a/test/driver.js +++ b/test/driver.js @@ -215,7 +215,7 @@ class Rasterize { div.className = "annotationLayer"; const [common, overrides] = await this.annotationStylePromise; - style.textContent = `${common}\n${overrides}`; + style.textContent = `:root { --scale-factor: ${viewport.scale} } ${common}\n${overrides}`; const annotationViewport = viewport.clone({ dontFlip: true }); const annotationImageMap = await convertCanvasesToImages( @@ -234,6 +234,7 @@ class Rasterize { renderForms, annotationCanvasMap: annotationImageMap, }; + AnnotationLayer.setDimensions(div, annotationViewport); AnnotationLayer.render(parameters); // Inline SVG images from text annotations. diff --git a/test/integration/freetext_editor_spec.js b/test/integration/freetext_editor_spec.js index 9637d60d12a4b..25103b058ca1f 100644 --- a/test/integration/freetext_editor_spec.js +++ b/test/integration/freetext_editor_spec.js @@ -42,7 +42,7 @@ describe("Editor", () => { }); const data = "Hello PDF.js World !!"; - await page.mouse.click(rect.x + 10, rect.y + 10); + await page.mouse.click(rect.x + 100, rect.y + 100); await page.type(`${editorPrefix}0 .internal`, data); const editorRect = await page.$eval(`${editorPrefix}0`, el => { @@ -151,7 +151,7 @@ describe("Editor", () => { }); const data = "Hello PDF.js World !!"; - await page.mouse.click(rect.x + 10, rect.y + 10); + await page.mouse.click(rect.x + 100, rect.y + 100); await page.type(`${editorPrefix}5 .internal`, data); const editorRect = await page.$eval(`${editorPrefix}5`, el => { diff --git a/web/annotation_editor_layer_builder.css b/web/annotation_editor_layer_builder.css index 56e627ee3a2e2..fe4b9b1553f1a 100644 --- a/web/annotation_editor_layer_builder.css +++ b/web/annotation_editor_layer_builder.css @@ -27,13 +27,14 @@ position: absolute; top: 0; left: 0; + font-size: calc(100px * var(--scale-factor)); } .annotationEditorLayer .freeTextEditor { position: absolute; background: transparent; border-radius: 3px; - padding: calc(var(--freetext-padding) * var(--zoom-factor)); + padding: calc(var(--freetext-padding) * var(--scale-factor)); resize: none; width: auto; height: auto; diff --git a/web/annotation_layer_builder.css b/web/annotation_layer_builder.css index 17f796188a57d..bb8cb6bde9d49 100644 --- a/web/annotation_layer_builder.css +++ b/web/annotation_layer_builder.css @@ -27,9 +27,30 @@ } } +[data-annotation-rotation="90"] { + transform: rotate(90deg) translateY(-100%); +} +[data-annotation-rotation="180"] { + transform: rotate(180deg) translate(-100%, -100%); +} +[data-annotation-rotation="270"] { + transform: rotate(270deg) translateX(-100%); +} + +.annotationLayer { + position: absolute; + top: 0; + left: 0; + font-size: calc(100px * var(--scale-factor)); + pointer-events: none; + transform-origin: 0 0; +} + .annotationLayer section { position: absolute; text-align: initial; + pointer-events: auto; + box-sizing: border-box; } .annotationLayer .linkAnnotation > a, @@ -43,10 +64,8 @@ } .annotationLayer .buttonWidgetAnnotation.pushButton > canvas { - position: relative; - top: 0; - left: 0; - z-index: -1; + width: 100%; + height: 100%; } .annotationLayer .linkAnnotation > a:hover, @@ -59,6 +78,8 @@ .annotationLayer .textAnnotation img { position: absolute; cursor: pointer; + width: 100%; + height: 100%; } .annotationLayer .textWidgetAnnotation input, @@ -69,7 +90,7 @@ background-image: var(--annotation-unfocused-field-background); border: 1px solid transparent; box-sizing: border-box; - font: 9px sans-serif; + font: 9% sans-serif; height: 100%; margin: 0; vertical-align: top; @@ -186,27 +207,31 @@ .annotationLayer .popupWrapper { position: absolute; - width: 20em; + font-size: calc(9px * var(--scale-factor)); + width: 100%; + min-width: calc(180px * var(--scale-factor)); + pointer-events: none; } .annotationLayer .popup { position: absolute; z-index: 200; - max-width: 20em; + max-width: calc(180px * var(--scale-factor)); background-color: rgba(255, 255, 153, 1); - box-shadow: 0 2px 5px rgba(136, 136, 136, 1); - border-radius: 2px; - padding: 6px; - margin-left: 5px; + box-shadow: 0 calc(2px * var(--scale-factor)) calc(5px * var(--scale-factor)) + rgba(136, 136, 136, 1); + border-radius: calc(2px * var(--scale-factor)); + padding: calc(6px * var(--scale-factor)); + margin-left: calc(5px * var(--scale-factor)); cursor: pointer; font: message-box; - font-size: 9px; white-space: normal; word-wrap: break-word; + pointer-events: auto; } .annotationLayer .popup > * { - font-size: 9px; + font-size: calc(9px * var(--scale-factor)); } .annotationLayer .popup h1 { @@ -215,17 +240,18 @@ .annotationLayer .popupDate { display: inline-block; - margin-left: 5px; + margin-left: calc(5px * var(--scale-factor)); } .annotationLayer .popupContent { border-top: 1px solid rgba(51, 51, 51, 1); - margin-top: 2px; - padding-top: 2px; + margin-top: calc(2px * var(--scale-factor)); + padding-top: calc(2px * var(--scale-factor)); } .annotationLayer .richText > * { white-space: pre-wrap; + font-size: calc(9px * var(--scale-factor)); } .annotationLayer .highlightAnnotation, @@ -244,3 +270,9 @@ .annotationLayer .fileAttachmentAnnotation { cursor: pointer; } + +.annotationLayer section svg { + position: absolute; + width: 100%; + height: 100%; +} diff --git a/web/annotation_layer_builder.js b/web/annotation_layer_builder.js index aa1d9ac4ba53e..97a05cff44e53 100644 --- a/web/annotation_layer_builder.js +++ b/web/annotation_layer_builder.js @@ -117,11 +117,14 @@ class AnnotationLayerBuilder { if (this.div) { // If an annotationLayer already exists, refresh its children's // transformation matrices. + AnnotationLayer.setDimensions(this.div, viewport); AnnotationLayer.update(parameters); } else { // Create an annotation layer div and render the annotations // if there is at least one annotation. this.div = document.createElement("div"); + AnnotationLayer.setDimensions(this.div, viewport); + this.div.className = "annotationLayer"; this.pageDiv.append(this.div); parameters.div = this.div; diff --git a/web/base_viewer.js b/web/base_viewer.js index d4a34ce1dbb0b..83b717855387e 100644 --- a/web/base_viewer.js +++ b/web/base_viewer.js @@ -1048,7 +1048,10 @@ class BaseViewer { return; } - docStyle.setProperty("--zoom-factor", newScale); + docStyle.setProperty( + "--scale-factor", + newScale * PixelsPerInch.PDF_TO_CSS_UNITS + ); const updateArgs = { scale: newScale }; for (const pageView of this._pages) { diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index 2c77dd84d9fb7..3d4882dc4a16d 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -377,7 +377,7 @@ class PDFPageView { }); if (this._isStandalone) { - docStyle.setProperty("--zoom-factor", this.scale); + docStyle.setProperty("--scale-factor", this.viewport.scale); } if (this.svg) { diff --git a/web/pdf_viewer.css b/web/pdf_viewer.css index 98ddc44e19b67..c489106a90f94 100644 --- a/web/pdf_viewer.css +++ b/web/pdf_viewer.css @@ -23,7 +23,7 @@ --page-margin: 1px auto -8px; --page-border: 9px solid transparent; --spreadHorizontalWrapped-margin-LR: -3.5px; - --zoom-factor: 1; + --scale-factor: 1; } @media screen and (forced-colors: active) {