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.div = null;
this._uiManager = parameters.uiManager; this._uiManager = parameters.uiManager;
this.rotation = this.parent.viewport.rotation; const {
this.pageDimensions = this.parent.pageDimensions; 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; const [width, height] = this.parentDimensions;
this.x = parameters.x / width; this.x = parameters.x / width;
this.y = parameters.y / height; this.y = parameters.y / height;
@ -341,6 +350,7 @@ class AnnotationEditor {
getRect(tx, ty) { getRect(tx, ty) {
const scale = this.parentScale; const scale = this.parentScale;
const [pageWidth, pageHeight] = this.pageDimensions; const [pageWidth, pageHeight] = this.pageDimensions;
const [pageX, pageY] = this.pageTranslation;
const shiftX = tx / scale; const shiftX = tx / scale;
const shiftY = ty / scale; const shiftY = ty / scale;
const x = this.x * pageWidth; const x = this.x * pageWidth;
@ -351,31 +361,31 @@ class AnnotationEditor {
switch (this.rotation) { switch (this.rotation) {
case 0: case 0:
return [ return [
x + shiftX, x + shiftX + pageX,
pageHeight - y - shiftY - height, pageHeight - y - shiftY - height + pageY,
x + shiftX + width, x + shiftX + width + pageX,
pageHeight - y - shiftY, pageHeight - y - shiftY + pageY,
]; ];
case 90: case 90:
return [ return [
x + shiftY, x + shiftY + pageX,
pageHeight - y + shiftX, pageHeight - y + shiftX + pageY,
x + shiftY + height, x + shiftY + height + pageX,
pageHeight - y + shiftX + width, pageHeight - y + shiftX + width + pageY,
]; ];
case 180: case 180:
return [ return [
x - shiftX - width, x - shiftX - width + pageX,
pageHeight - y + shiftY, pageHeight - y + shiftY + pageY,
x - shiftX, x - shiftX + pageX,
pageHeight - y + shiftY + height, pageHeight - y + shiftY + height + pageY,
]; ];
case 270: case 270:
return [ return [
x - shiftY - height, x - shiftY - height + pageX,
pageHeight - y - shiftX - width, pageHeight - y - shiftX - width + pageY,
x - shiftY, x - shiftY + pageX,
pageHeight - y - shiftX, pageHeight - y - shiftX + pageY,
]; ];
default: default:
throw new Error("Invalid rotation"); 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.mouse.click(rect.x + 100, rect.y + 100);
await page.type(`${getEditorSelector(currentId)} .internal`, data); 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. // Commit.
await page.mouse.click( await page.keyboard.press("Escape");
editorRect.x, await page.waitForTimeout(10);
editorRect.y + 2 * editorRect.height
);
await waitForSelectedEditor(page, getEditorSelector(currentId)); await waitForSelectedEditor(page, getEditorSelector(currentId));
await waitForStorageEntries(page, currentId + 1); 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 !bug1802888.pdf
!issue15759.pdf !issue15759.pdf
!issue15753.pdf !issue15753.pdf
!issue15789.pdf

BIN
test/pdfs/issue15789.pdf Executable file

Binary file not shown.