From 9d4881ec566c376a16ff7252e8517433049764ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 7 Jun 2024 14:08:43 +0200 Subject: [PATCH] Respect `maxCanvasPixels` when computing camvas dimensions Ensure that we never round the canvas dimensions above `maxCanvasPixels` by rounding them to the preceeding multiple of the display ratio rather than the succeeding one. --- test/integration/viewer_spec.mjs | 13 +++++++------ web/pdf_page_view.js | 10 +++++----- web/ui_utils.js | 12 ++++++++---- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/test/integration/viewer_spec.mjs b/test/integration/viewer_spec.mjs index db87cd30089527..674d50eb4c4cf6 100644 --- a/test/integration/viewer_spec.mjs +++ b/test/integration/viewer_spec.mjs @@ -273,12 +273,13 @@ describe("PDF viewer", () => { .withContext(`In ${browserName}`) .toBeLessThan(originalCanvasSize * factor ** 2); - // Disabled because `canvasSize` is `4_012_800`, which is - // close to the limit but somehow a bit more. - // - // expect(canvasSize) - // .withContext(`In ${browserName}, MAX_CANVAS_PIXELS`) - // .toBeLessThan(MAX_CANVAS_PIXELS); + expect(canvasSize) + .withContext(`In ${browserName}, <= MAX_CANVAS_PIXELS`) + .toBeLessThanOrEqual(MAX_CANVAS_PIXELS); + + expect(canvasSize) + .withContext(`In ${browserName}, > MAX_CANVAS_PIXELS * 0.99`) + .toBeGreaterThan(MAX_CANVAS_PIXELS * 0.99); }) ); }); diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index 915f566f97813b..fde5d7dc5f6fde 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -34,9 +34,9 @@ import { import { approximateFraction, DEFAULT_SCALE, + floorToDivide, OutputScale, RenderingStates, - roundToDivide, TextLayerMode, } from "./ui_utils.js"; import { AnnotationEditorLayerBuilder } from "./annotation_editor_layer_builder.js"; @@ -1025,11 +1025,11 @@ class PDFPageView { const sfx = approximateFraction(outputScale.sx); const sfy = approximateFraction(outputScale.sy); - canvas.width = roundToDivide(width * outputScale.sx, sfx[0]); - canvas.height = roundToDivide(height * outputScale.sy, sfy[0]); + canvas.width = floorToDivide(width * outputScale.sx, sfx[0]); + canvas.height = floorToDivide(height * outputScale.sy, sfy[0]); const { style } = canvas; - style.width = roundToDivide(width, sfx[1]) + "px"; - style.height = roundToDivide(height, sfy[1]) + "px"; + style.width = floorToDivide(width, sfx[1]) + "px"; + style.height = floorToDivide(height, sfy[1]) + "px"; // Add the viewport so it's known what it was originally drawn with. this.#viewportMap.set(canvas, viewport); diff --git a/web/ui_utils.js b/web/ui_utils.js index a6c0bc7f15fab5..9ab1c739eb9aed 100644 --- a/web/ui_utils.js +++ b/web/ui_utils.js @@ -260,6 +260,7 @@ function binarySearchFirstItem(items, condition, start = 0) { * @param {number} x - Positive float number. * @returns {Array} Estimated fraction: the first array item is a numerator, * the second one is a denominator. + * They are both natural numbers. */ function approximateFraction(x) { // Fast paths for int numbers or their inversions. @@ -306,9 +307,12 @@ function approximateFraction(x) { return result; } -function roundToDivide(x, div) { - const r = x % div; - return r === 0 ? x : Math.round(x - r + div); +/** + * @param {number} x A positive number to round to a multiple of `div` + * @param {number} div A natural number + */ +function floorToDivide(x, div) { + return x - (x % div); } /** @@ -863,6 +867,7 @@ export { DEFAULT_SCALE_DELTA, DEFAULT_SCALE_VALUE, docStyle, + floorToDivide, getActiveOrFocusedElement, getPageSizeInches, getVisibleElements, @@ -881,7 +886,6 @@ export { ProgressBar, removeNullCharacters, RenderingStates, - roundToDivide, SCROLLBAR_PADDING, scrollIntoView, ScrollMode,