Take all the viewBox into account when computing the coordinates of an annotation in the page (fixes #15789)
This commit is contained in:
parent
fe3df4dcb4
commit
4f0bfabe7a
@ -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");
|
||||||
|
@ -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]);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -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
BIN
test/pdfs/issue15789.pdf
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user