Take all the viewBox into account when computing the coordinates of an annotation in the page (fixes #15789)

This commit is contained in:
Calixte Denizet 2022-12-07 18:27:32 +01:00
parent fe3df4dcb4
commit 4f0bfabe7a
4 changed files with 115 additions and 35 deletions

View File

@ -68,8 +68,17 @@ class AnnotationEditor {
this.div = null;
this._uiManager = parameters.uiManager;
this.rotation = this.parent.viewport.rotation;
this.pageDimensions = this.parent.pageDimensions;
const {
rotation,
viewBox: [pageLLx, pageLLy, pageURx, pageURy],
} = this.parent.viewport;
this.rotation = rotation;
const pageWidth = pageURx - pageLLx;
const pageHeight = pageURy - pageLLy;
this.pageDimensions = [pageWidth, pageHeight];
this.pageTranslation = [pageLLx, pageLLy];
const [width, height] = this.parentDimensions;
this.x = parameters.x / width;
this.y = parameters.y / height;
@ -341,6 +350,7 @@ class AnnotationEditor {
getRect(tx, ty) {
const scale = this.parentScale;
const [pageWidth, pageHeight] = this.pageDimensions;
const [pageX, pageY] = this.pageTranslation;
const shiftX = tx / scale;
const shiftY = ty / scale;
const x = this.x * pageWidth;
@ -351,31 +361,31 @@ class AnnotationEditor {
switch (this.rotation) {
case 0:
return [
x + shiftX,
pageHeight - y - shiftY - height,
x + shiftX + width,
pageHeight - y - shiftY,
x + shiftX + pageX,
pageHeight - y - shiftY - height + pageY,
x + shiftX + width + pageX,
pageHeight - y - shiftY + pageY,
];
case 90:
return [
x + shiftY,
pageHeight - y + shiftX,
x + shiftY + height,
pageHeight - y + shiftX + width,
x + shiftY + pageX,
pageHeight - y + shiftX + pageY,
x + shiftY + height + pageX,
pageHeight - y + shiftX + width + pageY,
];
case 180:
return [
x - shiftX - width,
pageHeight - y + shiftY,
x - shiftX,
pageHeight - y + shiftY + height,
x - shiftX - width + pageX,
pageHeight - y + shiftY + pageY,
x - shiftX + pageX,
pageHeight - y + shiftY + height + pageY,
];
case 270:
return [
x - shiftY - height,
pageHeight - y - shiftX - width,
x - shiftY,
pageHeight - y - shiftX,
x - shiftY - height + pageX,
pageHeight - y - shiftX - width + pageY,
x - shiftY + pageX,
pageHeight - y - shiftX + pageY,
];
default:
throw new Error("Invalid rotation");

View File

@ -547,24 +547,9 @@ describe("Editor", () => {
await page.mouse.click(rect.x + 100, rect.y + 100);
await page.type(`${getEditorSelector(currentId)} .internal`, data);
const editorRect = await page.$eval(
getEditorSelector(currentId),
el => {
const { x, y, width, height } = el.getBoundingClientRect();
return {
x,
y,
width,
height,
};
}
);
// Commit.
await page.mouse.click(
editorRect.x,
editorRect.y + 2 * editorRect.height
);
await page.keyboard.press("Escape");
await page.waitForTimeout(10);
await waitForSelectedEditor(page, getEditorSelector(currentId));
await waitForStorageEntries(page, currentId + 1);
@ -646,4 +631,88 @@ describe("Editor", () => {
);
});
});
describe("issue 15789", () => {
let pages;
beforeAll(async () => {
pages = await loadAndWait("issue15789.pdf", ".annotationEditorLayer");
pages = await Promise.all(
pages.map(async ([browserName, page]) => {
await page.select("#scaleSelect", "1");
return [browserName, page];
})
);
});
afterAll(async () => {
await closePages(pages);
});
it("must take the media box into account", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await page.click("#editorFreeText");
let currentId = 0;
for (let step = 0; step < 3; step++) {
const rect = await page.$eval(".annotationEditorLayer", el => {
// With Chrome something is wrong when serializing a DomRect,
// hence we extract the values and just return them.
const { x, y, width, height } = el.getBoundingClientRect();
return { x, y, width, height };
});
const data = `Hello ${step}`;
const x = rect.x + 0.1 * rect.width;
const y = rect.y + 0.1 * rect.height;
await page.mouse.click(x, y);
await page.type(`${getEditorSelector(currentId)} .internal`, data);
// Commit.
await page.keyboard.press("Escape");
await page.waitForTimeout(10);
await page.evaluate(() => {
document.getElementById("pageRotateCw").click();
});
currentId += 1;
await page.waitForTimeout(10);
}
const serialize = proprName =>
page.evaluate(
name =>
[
...window.PDFViewerApplication.pdfDocument.annotationStorage.serializable.values(),
].map(x => x[name]),
proprName
);
const rects = (await serialize("rect")).map(rect =>
rect.slice(0, 2).map(x => Math.floor(x))
);
const expected = [
[-28, 695],
[-38, -10],
[501, -20],
];
// Dimensions aren't exactly the same from a platform to an other
// so we're a bit tolerant here with the numbers.
// Anyway the goal is to check that the bottom left corner of the
// media box is taken into account.
// The pdf has a media box equals to [-99 -99 612.0 792.0].
const diffs = rects.map(
(rect, i) =>
Math.abs(rect[0] - expected[i][0]) < 10 &&
Math.abs(rect[1] - expected[i][1]) < 10
);
expect(diffs)
.withContext(`In ${browserName}`)
.toEqual([true, true, true]);
})
);
});
});
});

View File

@ -559,3 +559,4 @@
!bug1802888.pdf
!issue15759.pdf
!issue15753.pdf
!issue15789.pdf

BIN
test/pdfs/issue15789.pdf Executable file

Binary file not shown.