[Editor] Avoid to have some part of an editor outside its page (bug 1843303)

This commit is contained in:
Calixte Denizet 2023-07-13 18:31:08 +02:00
parent 717c766a42
commit a8867cf68a
7 changed files with 105 additions and 5 deletions

View File

@ -258,8 +258,7 @@ class AnnotationEditor {
this.x = (x + tx) / width;
this.y = (y + ty) / height;
this.div.style.left = `${100 * this.x}%`;
this.div.style.top = `${100 * this.y}%`;
this.fixAndSetPosition();
}
/**
@ -274,8 +273,41 @@ class AnnotationEditor {
this.x += x / width;
this.y += y / height;
this.div.style.left = `${100 * this.x}%`;
this.div.style.top = `${100 * this.y}%`;
this.fixAndSetPosition();
}
fixAndSetPosition() {
const [pageWidth, pageHeight] = this.pageDimensions;
let { x, y, width, height } = this;
width *= pageWidth;
height *= pageHeight;
x *= pageWidth;
y *= pageHeight;
switch (this.rotation) {
case 0:
x = Math.max(0, Math.min(pageWidth - width, x));
y = Math.max(0, Math.min(pageHeight - height, y));
break;
case 90:
x = Math.max(0, Math.min(pageWidth - height, x));
y = Math.min(pageHeight, Math.max(width, y));
break;
case 180:
x = Math.min(pageWidth, Math.max(width, x));
y = Math.min(pageHeight, Math.max(height, y));
break;
case 270:
x = Math.min(pageWidth, Math.max(height, x));
y = Math.max(0, Math.min(pageHeight - width, y));
break;
}
this.x = x / pageWidth;
this.y = y / pageHeight;
this.div.style.left = `${(100 * this.x).toFixed(2)}%`;
this.div.style.top = `${(100 * this.y).toFixed(2)}%`;
}
/**
@ -383,6 +415,17 @@ class AnnotationEditor {
this.div.addEventListener("focusin", this.#boundFocusin);
this.div.addEventListener("focusout", this.#boundFocusout);
const [parentWidth, parentHeight] = this.parentDimensions;
if (this.parentRotation % 180 !== 0) {
this.div.style.maxWidth = `${((100 * parentHeight) / parentWidth).toFixed(
2
)}%`;
this.div.style.maxHeight = `${(
(100 * parentWidth) /
parentHeight
).toFixed(2)}%`;
}
const [tx, ty] = this.getInitialTranslation();
this.translate(tx, ty);

View File

@ -357,6 +357,7 @@ class FreeTextEditor extends AnnotationEditor {
this.width = rect.height / parentWidth;
this.height = rect.width / parentHeight;
}
this.fixAndSetPosition();
}
/**

View File

@ -838,6 +838,7 @@ class InkEditor extends AnnotationEditor {
const [parentWidth, parentHeight] = this.parentDimensions;
this.width = width / parentWidth;
this.height = height / parentHeight;
this.fixAndSetPosition();
if (this.#disableEditing) {
this.#setScaleFactor(width, height);

View File

@ -254,6 +254,7 @@ class StampEditor extends AnnotationEditor {
this.width = width / parentWidth;
this.height = height / parentHeight;
this.setDims(width, height);
this.fixAndSetPosition();
if (this.#resizeTimeoutId !== null) {
clearTimeout(this.#resizeTimeoutId);
}

View File

@ -128,4 +128,51 @@ describe("Stamp Editor", () => {
);
});
});
describe("Page overflow", () => {
let pages;
beforeAll(async () => {
pages = await loadAndWait("empty.pdf", ".annotationEditorLayer", 50);
});
afterAll(async () => {
await closePages(pages);
});
it("must check that an added image stay within the page", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
if (browserName === "firefox") {
pending(
"Disabled in Firefox, because of https://bugzilla.mozilla.org/1553847."
);
}
await page.click("#editorStamp");
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 { right, bottom } = el.getBoundingClientRect();
return { x: right, y: bottom };
});
await page.mouse.click(rect.x - 10, rect.y - 10);
const input = await page.$("#stampEditorFileInput");
await input.uploadFile(
`${path.join(__dirname, "../images/firefox_logo.png")}`
);
await page.waitForTimeout(300);
const { left } = await getEditorDimensions(page, 0);
// The image is bigger than the page, so it has been scaled down to
// 75% of the page width.
expect(left).toEqual("25%");
})
);
});
});
});

View File

@ -161,7 +161,12 @@ function getEditorDimensions(page, id) {
return page.evaluate(n => {
const element = document.getElementById(`pdfjs_internal_editor_${n}`);
const { style } = element;
return { width: style.width, height: style.height };
return {
left: style.left,
top: style.top,
width: style.width,
height: style.height,
};
}, id);
}
exports.getEditorDimensions = getEditorDimensions;

View File

@ -88,6 +88,8 @@
z-index: 1;
transform-origin: 0 0;
cursor: auto;
max-width: 100%;
max-height: 100%;
}
.annotationEditorLayer :is(.inkEditor, .stampEditor) {