1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-19 14:48:08 +02:00

Merge pull request #18698 from calixteman/issue18694

Avoid to have a white line around the canvas
This commit is contained in:
calixteman 2024-09-07 22:22:21 +02:00 committed by GitHub
commit 5369a24c9c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 146 additions and 7 deletions

View file

@ -1103,8 +1103,12 @@ function setLayerDimensions(
const w = `var(--scale-factor) * ${pageWidth}px`,
h = `var(--scale-factor) * ${pageHeight}px`;
const widthStr = useRound ? `round(${w}, 1px)` : `calc(${w})`,
heightStr = useRound ? `round(${h}, 1px)` : `calc(${h})`;
const widthStr = useRound
? `round(down, ${w}, var(--scale-round-x, 1px))`
: `calc(${w})`,
heightStr = useRound
? `round(down, ${h}, var(--scale-round-y, 1px))`
: `calc(${h})`;
if (!mustFlip || viewport.rotation % 180 === 0) {
style.width = widthStr;

View file

@ -19,7 +19,10 @@ import {
createPromise,
getSpanRectFromText,
loadAndWait,
scrollIntoView,
waitForPageRendered,
} from "./test_utils.mjs";
import { PNG } from "pngjs";
describe("PDF viewer", () => {
describe("Zoom origin", () => {
@ -365,4 +368,75 @@ describe("PDF viewer", () => {
});
});
});
describe("Canvas fits the page", () => {
let pages;
beforeAll(async () => {
pages = await loadAndWait(
"issue18694.pdf",
".textLayer .endOfContent",
"page-width"
);
});
afterAll(async () => {
await closePages(pages);
});
it("must check that canvas perfectly fits the page whatever the zoom level is", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
const debug = false;
// The pdf has a single page with a red background.
// We set the viewer background to red, because when screenshoting
// some part of the viewer background can be visible.
// But here we don't care about the viewer background: we only
// care about the page background and the canvas default color.
await page.evaluate(() => {
document.body.style.background = "#ff0000";
const toolbar = document.querySelector(".toolbar");
toolbar.style.display = "none";
});
await page.waitForSelector(".toolbar", { visible: false });
await page.evaluate(() => {
const p = document.querySelector(`.page[data-page-number="1"]`);
p.style.border = "none";
});
for (let i = 0; ; i++) {
const handle = await waitForPageRendered(page);
await page.evaluate(() => window.PDFViewerApplication.zoomOut());
await awaitPromise(handle);
await scrollIntoView(page, `.page[data-page-number="1"]`);
const element = await page.$(`.page[data-page-number="1"]`);
const png = await element.screenshot({
type: "png",
path: debug ? `foo${i}.png` : "",
});
const pageImage = PNG.sync.read(Buffer.from(png));
let buffer = new Uint32Array(pageImage.data.buffer);
// Search for the first red pixel.
const j = buffer.indexOf(0xff0000ff);
buffer = buffer.slice(j);
expect(buffer.every(x => x === 0xff0000ff))
.withContext(`In ${browserName}, in the ${i}th zoom in`)
.toBe(true);
const currentScale = await page.evaluate(
() => window.PDFViewerApplication.pdfViewer.currentScale
);
if (currentScale <= 0.1) {
break;
}
}
})
);
});
});
});

View file

@ -665,3 +665,4 @@
!highlights.pdf
!highlight.pdf
!bug1708040.pdf
!issue18694.pdf

BIN
test/pdfs/issue18694.pdf Executable file

Binary file not shown.

View file

@ -16,6 +16,7 @@
import {
backtrackBeforeAllVisibleElements,
binarySearchFirstItem,
calcRound,
getPageSizeInches,
getVisibleElements,
isPortraitOrientation,
@ -627,4 +628,17 @@ describe("ui_utils", function () {
});
});
});
describe("calcRound", function () {
it("should handle different browsers/environments correctly", function () {
if (
typeof window !== "undefined" &&
window.navigator?.userAgent?.includes("Firefox")
) {
expect(calcRound(1.6)).not.toEqual(1.6);
} else {
expect(calcRound(1.6)).toEqual(1.6);
}
});
});
});

View file

@ -33,6 +33,7 @@ import {
} from "pdfjs-lib";
import {
approximateFraction,
calcRound,
DEFAULT_SCALE,
floorToDivide,
OutputScale,
@ -127,6 +128,10 @@ class PDFPageView {
#previousRotation = null;
#scaleRoundX = 1;
#scaleRoundY = 1;
#renderError = null;
#renderingState = RenderingStates.INITIAL;
@ -1039,11 +1044,27 @@ class PDFPageView {
const sfx = approximateFraction(outputScale.sx);
const sfy = approximateFraction(outputScale.sy);
canvas.width = floorToDivide(width * outputScale.sx, sfx[0]);
canvas.height = floorToDivide(height * outputScale.sy, sfy[0]);
const { style } = canvas;
style.width = floorToDivide(width, sfx[1]) + "px";
style.height = floorToDivide(height, sfy[1]) + "px";
const canvasWidth = (canvas.width = floorToDivide(
calcRound(width * outputScale.sx),
sfx[0]
));
const canvasHeight = (canvas.height = floorToDivide(
calcRound(height * outputScale.sy),
sfy[0]
));
const pageWidth = floorToDivide(calcRound(width), sfx[1]);
const pageHeight = floorToDivide(calcRound(height), sfy[1]);
outputScale.sx = canvasWidth / pageWidth;
outputScale.sy = canvasHeight / pageHeight;
if (this.#scaleRoundX !== sfx[1]) {
div.style.setProperty("--scale-round-x", `${sfx[1]}px`);
this.#scaleRoundX = sfx[1];
}
if (this.#scaleRoundY !== sfy[1]) {
div.style.setProperty("--scale-round-y", `${sfy[1]}px`);
this.#scaleRoundY = sfy[1];
}
// Add the viewport so it's known what it was originally drawn with.
this.#viewportMap.set(canvas, viewport);

View file

@ -83,6 +83,8 @@
canvas {
margin: 0;
display: block;
width: 100%;
height: 100%;
&[hidden] {
display: none;
@ -101,6 +103,9 @@
}
.pdfViewer .page {
--scale-round-x: 1px;
--scale-round-y: 1px;
direction: ltr;
width: 816px;
height: 1056px;

View file

@ -862,6 +862,25 @@ function toggleExpandedBtn(button, toggle, view = null) {
view?.classList.toggle("hidden", !toggle);
}
// In Firefox, the css calc function uses f32 precision but the Chrome or Safari
// are using f64 one. So in order to have the same rendering in all browsers, we
// need to use the right precision in order to have correct dimensions.
const calcRound =
typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")
? Math.fround
: (function () {
if (
typeof PDFJSDev !== "undefined" &&
PDFJSDev.test("LIB") &&
typeof document === "undefined"
) {
return x => x;
}
const e = document.createElement("div");
e.style.width = "round(down, calc(1.6666666666666665 * 792px), 1px)";
return e.style.width === "calc(1320px)" ? Math.fround : x => x;
})();
export {
animationStarted,
apiPageLayoutToViewerModes,
@ -870,6 +889,7 @@ export {
AutoPrintRegExp,
backtrackBeforeAllVisibleElements, // only exported for testing
binarySearchFirstItem,
calcRound,
CursorTool,
DEFAULT_SCALE,
DEFAULT_SCALE_DELTA,