Avoid to have a white line around the canvas
The canvas must have the same dims as the page in order to avoid to see the page background.
This commit is contained in:
parent
77c7ec6927
commit
68332ec236
@ -1103,8 +1103,12 @@ function setLayerDimensions(
|
|||||||
|
|
||||||
const w = `var(--scale-factor) * ${pageWidth}px`,
|
const w = `var(--scale-factor) * ${pageWidth}px`,
|
||||||
h = `var(--scale-factor) * ${pageHeight}px`;
|
h = `var(--scale-factor) * ${pageHeight}px`;
|
||||||
const widthStr = useRound ? `round(${w}, 1px)` : `calc(${w})`,
|
const widthStr = useRound
|
||||||
heightStr = useRound ? `round(${h}, 1px)` : `calc(${h})`;
|
? `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) {
|
if (!mustFlip || viewport.rotation % 180 === 0) {
|
||||||
style.width = widthStr;
|
style.width = widthStr;
|
||||||
|
|||||||
@ -19,7 +19,10 @@ import {
|
|||||||
createPromise,
|
createPromise,
|
||||||
getSpanRectFromText,
|
getSpanRectFromText,
|
||||||
loadAndWait,
|
loadAndWait,
|
||||||
|
scrollIntoView,
|
||||||
|
waitForPageRendered,
|
||||||
} from "./test_utils.mjs";
|
} from "./test_utils.mjs";
|
||||||
|
import { PNG } from "pngjs";
|
||||||
|
|
||||||
describe("PDF viewer", () => {
|
describe("PDF viewer", () => {
|
||||||
describe("Zoom origin", () => {
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -665,3 +665,4 @@
|
|||||||
!highlights.pdf
|
!highlights.pdf
|
||||||
!highlight.pdf
|
!highlight.pdf
|
||||||
!bug1708040.pdf
|
!bug1708040.pdf
|
||||||
|
!issue18694.pdf
|
||||||
|
|||||||
BIN
test/pdfs/issue18694.pdf
Executable file
BIN
test/pdfs/issue18694.pdf
Executable file
Binary file not shown.
@ -16,6 +16,7 @@
|
|||||||
import {
|
import {
|
||||||
backtrackBeforeAllVisibleElements,
|
backtrackBeforeAllVisibleElements,
|
||||||
binarySearchFirstItem,
|
binarySearchFirstItem,
|
||||||
|
calcRound,
|
||||||
getPageSizeInches,
|
getPageSizeInches,
|
||||||
getVisibleElements,
|
getVisibleElements,
|
||||||
isPortraitOrientation,
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import {
|
|||||||
} from "pdfjs-lib";
|
} from "pdfjs-lib";
|
||||||
import {
|
import {
|
||||||
approximateFraction,
|
approximateFraction,
|
||||||
|
calcRound,
|
||||||
DEFAULT_SCALE,
|
DEFAULT_SCALE,
|
||||||
floorToDivide,
|
floorToDivide,
|
||||||
OutputScale,
|
OutputScale,
|
||||||
@ -127,6 +128,10 @@ class PDFPageView {
|
|||||||
|
|
||||||
#previousRotation = null;
|
#previousRotation = null;
|
||||||
|
|
||||||
|
#scaleRoundX = 1;
|
||||||
|
|
||||||
|
#scaleRoundY = 1;
|
||||||
|
|
||||||
#renderError = null;
|
#renderError = null;
|
||||||
|
|
||||||
#renderingState = RenderingStates.INITIAL;
|
#renderingState = RenderingStates.INITIAL;
|
||||||
@ -1039,11 +1044,27 @@ class PDFPageView {
|
|||||||
const sfx = approximateFraction(outputScale.sx);
|
const sfx = approximateFraction(outputScale.sx);
|
||||||
const sfy = approximateFraction(outputScale.sy);
|
const sfy = approximateFraction(outputScale.sy);
|
||||||
|
|
||||||
canvas.width = floorToDivide(width * outputScale.sx, sfx[0]);
|
const canvasWidth = (canvas.width = floorToDivide(
|
||||||
canvas.height = floorToDivide(height * outputScale.sy, sfy[0]);
|
calcRound(width * outputScale.sx),
|
||||||
const { style } = canvas;
|
sfx[0]
|
||||||
style.width = floorToDivide(width, sfx[1]) + "px";
|
));
|
||||||
style.height = floorToDivide(height, sfy[1]) + "px";
|
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.
|
// Add the viewport so it's known what it was originally drawn with.
|
||||||
this.#viewportMap.set(canvas, viewport);
|
this.#viewportMap.set(canvas, viewport);
|
||||||
|
|||||||
@ -83,6 +83,8 @@
|
|||||||
canvas {
|
canvas {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: block;
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
&[hidden] {
|
&[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
@ -101,6 +103,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pdfViewer .page {
|
.pdfViewer .page {
|
||||||
|
--scale-round-x: 1px;
|
||||||
|
--scale-round-y: 1px;
|
||||||
|
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
width: 816px;
|
width: 816px;
|
||||||
height: 1056px;
|
height: 1056px;
|
||||||
|
|||||||
@ -862,6 +862,25 @@ function toggleExpandedBtn(button, toggle, view = null) {
|
|||||||
view?.classList.toggle("hidden", !toggle);
|
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 {
|
export {
|
||||||
animationStarted,
|
animationStarted,
|
||||||
apiPageLayoutToViewerModes,
|
apiPageLayoutToViewerModes,
|
||||||
@ -870,6 +889,7 @@ export {
|
|||||||
AutoPrintRegExp,
|
AutoPrintRegExp,
|
||||||
backtrackBeforeAllVisibleElements, // only exported for testing
|
backtrackBeforeAllVisibleElements, // only exported for testing
|
||||||
binarySearchFirstItem,
|
binarySearchFirstItem,
|
||||||
|
calcRound,
|
||||||
CursorTool,
|
CursorTool,
|
||||||
DEFAULT_SCALE,
|
DEFAULT_SCALE,
|
||||||
DEFAULT_SCALE_DELTA,
|
DEFAULT_SCALE_DELTA,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user