Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Editor] When resizing a stamp annotation, the opposite corner must stay fixed #19201

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 42 additions & 67 deletions src/display/editor/stamp.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ class StampEditor extends AnnotationEditor {

#canvas = null;

#observer = null;

#resizeTimeoutId = null;

#isSvg = false;
Expand Down Expand Up @@ -305,8 +303,6 @@ class StampEditor extends AnnotationEditor {
this._uiManager.imageManager.deleteId(this.#bitmapId);
this.#canvas?.remove();
this.#canvas = null;
this.#observer?.disconnect();
this.#observer = null;
if (this.#resizeTimeoutId) {
clearTimeout(this.#resizeTimeoutId);
this.#resizeTimeoutId = null;
Expand Down Expand Up @@ -398,9 +394,34 @@ class StampEditor extends AnnotationEditor {
);
}

this._uiManager.addShouldRescale(this);

return this.div;
}

/** @inheritdoc */
_onResized() {
// We used a CSS-zoom during the resizing, but now it's resized we can
// rescale correctly the bitmap to fit the new dimensions.
this.onScaleChanging();
}

onScaleChanging() {
if (!this.parent) {
return;
}
if (this.#resizeTimeoutId !== null) {
clearTimeout(this.#resizeTimeoutId);
}
// The user's zooming the page, there is no need to redraw the bitmap at
// each step, hence we wait a bit before redrawing it.
const TIME_TO_WAIT = 200;
this.#resizeTimeoutId = setTimeout(() => {
this.#resizeTimeoutId = null;
this.#drawBitmap();
}, TIME_TO_WAIT);
}

#createCanvas() {
const { div } = this;
let { width, height } = this.#bitmap;
Expand Down Expand Up @@ -433,15 +454,23 @@ class StampEditor extends AnnotationEditor {
canvas.setAttribute("role", "img");
this.addContainer(canvas);

this.width = width / pageWidth;
this.height = height / pageHeight;
if (this._initialOptions?.isCentered) {
this.center();
} else {
this.fixAndSetPosition();
}
this._initialOptions = null;

if (
!this._uiManager.useNewAltTextWhenAddingImage ||
!this._uiManager.useNewAltTextFlow ||
this.annotationElementId
) {
div.hidden = false;
}
this.#drawBitmap(width, height);
this.#createObserver();
this.#drawBitmap();
if (!this.#hasBeenAddedInUndoStack) {
this.parent.addUndoableEditor(this);
this.#hasBeenAddedInUndoStack = true;
Expand Down Expand Up @@ -584,37 +613,6 @@ class StampEditor extends AnnotationEditor {
return { canvas, width, height, imageData };
}

/**
* When the dimensions of the div change the inner canvas must
* renew its dimensions, hence it must redraw its own contents.
* @param {number} width - the new width of the div
* @param {number} height - the new height of the div
* @returns
*/
#setDimensions(width, height) {
const [parentWidth, parentHeight] = this.parentDimensions;
this.width = width / parentWidth;
this.height = height / parentHeight;
if (this._initialOptions?.isCentered) {
this.center();
} else {
this.fixAndSetPosition();
}
this._initialOptions = null;
if (this.#resizeTimeoutId !== null) {
clearTimeout(this.#resizeTimeoutId);
}
// When the user is resizing the editor we just use CSS to scale the image
// to avoid redrawing it too often.
// And once the user stops resizing the editor we redraw the image in
// rescaling it correctly (see this.#scaleBitmap).
const TIME_TO_WAIT = 200;
this.#resizeTimeoutId = setTimeout(() => {
this.#resizeTimeoutId = null;
this.#drawBitmap(width, height);
}, TIME_TO_WAIT);
}

#scaleBitmap(width, height) {
const { width: bitmapWidth, height: bitmapHeight } = this.#bitmap;

Expand Down Expand Up @@ -660,18 +658,21 @@ class StampEditor extends AnnotationEditor {
return bitmap;
}

#drawBitmap(width, height) {
#drawBitmap() {
const [parentWidth, parentHeight] = this.parentDimensions;
const { width, height } = this;
const outputScale = new OutputScale();
const scaledWidth = Math.ceil(width * outputScale.sx);
const scaledHeight = Math.ceil(height * outputScale.sy);

const scaledWidth = Math.ceil(width * parentWidth * outputScale.sx);
const scaledHeight = Math.ceil(height * parentHeight * outputScale.sy);
const canvas = this.#canvas;

if (
!canvas ||
(canvas.width === scaledWidth && canvas.height === scaledHeight)
) {
return;
}

canvas.width = scaledWidth;
canvas.height = scaledHeight;

Expand Down Expand Up @@ -746,32 +747,6 @@ class StampEditor extends AnnotationEditor {
return structuredClone(this.#bitmap);
}

/**
* Create the resize observer.
*/
#createObserver() {
if (!this._uiManager._signal) {
// This method is called after the canvas has been created but the canvas
// creation is async, so it's possible that the viewer has been closed.
return;
}
this.#observer = new ResizeObserver(entries => {
const rect = entries[0].contentRect;
if (rect.width && rect.height) {
this.#setDimensions(rect.width, rect.height);
}
});
this.#observer.observe(this.div);
this._uiManager._signal.addEventListener(
"abort",
() => {
this.#observer?.disconnect();
this.#observer = null;
},
{ once: true }
);
}

/** @inheritdoc */
static async deserialize(data, parent, uiManager) {
let initialData = null;
Expand Down
31 changes: 13 additions & 18 deletions test/integration/freetext_editor_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
copy,
copyToClipboard,
createPromise,
dragAndDropAnnotation,
dragAndDrop,
firstPageOnTop,
getEditors,
getEditorSelector,
Expand Down Expand Up @@ -954,19 +954,14 @@ describe("FreeText Editor", () => {
const serialized = await getSerialized(page);
expect(serialized).withContext(`In ${browserName}`).toEqual([]);

const editorRect = await getRect(page, getEditorSelector(0));
const editorSelector = getEditorSelector(0);
const editorRect = await getRect(page, editorSelector);

// Select the annotation we want to move.
await page.mouse.click(editorRect.x + 2, editorRect.y + 2);
await waitForSelectedEditor(page, getEditorSelector(0));
await waitForSelectedEditor(page, editorSelector);

await dragAndDropAnnotation(
page,
editorRect.x + editorRect.width / 2,
editorRect.y + editorRect.height / 2,
100,
100
);
await dragAndDrop(page, editorSelector, [[100, 100]]);
await waitForSerialized(page, 1);
})
);
Expand Down Expand Up @@ -2335,29 +2330,29 @@ describe("FreeText Editor", () => {
const allPositions = [];

for (let i = 0; i < 10; i++) {
const editorSelector = getEditorSelector(i);
await page.mouse.click(rect.x + 10 + 30 * i, rect.y + 100 + 5 * i);
await page.waitForSelector(getEditorSelector(i), {
await page.waitForSelector(editorSelector, {
visible: true,
});
await page.type(
`${getEditorSelector(i)} .internal`,
`${editorSelector} .internal`,
String.fromCharCode(65 + i)
);

// Commit.
await page.keyboard.press("Escape");
await page.waitForSelector(
`${getEditorSelector(i)} .overlay.enabled`
);
await page.waitForSelector(`${editorSelector} .overlay.enabled`);

allPositions.push(await getRect(page, getEditorSelector(i)));
allPositions.push(await getRect(page, editorSelector));
}

await selectAll(page);
await dragAndDropAnnotation(page, rect.x + 161, rect.y + 126, 39, 74);
await dragAndDrop(page, getEditorSelector(4), [[39, 74]]);

for (let i = 0; i < 10; i++) {
const pos = await getRect(page, getEditorSelector(i));
const editorSelector = getEditorSelector(i);
const pos = await getRect(page, editorSelector);
const oldPos = allPositions[i];
expect(Math.abs(Math.round(pos.x - oldPos.x) - 39))
.withContext(`In ${browserName}`)
Expand Down
10 changes: 2 additions & 8 deletions test/integration/ink_editor_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
awaitPromise,
closePages,
createPromise,
dragAndDropAnnotation,
dragAndDrop,
getAnnotationSelector,
getEditors,
getEditorSelector,
Expand Down Expand Up @@ -822,13 +822,7 @@ describe("Ink Editor", () => {
await page.mouse.click(editorRect.x + 2, editorRect.y + 2);
await waitForSelectedEditor(page, edgeB);

await dragAndDropAnnotation(
page,
editorRect.x + editorRect.width / 2,
editorRect.y + editorRect.height / 2,
100,
100
);
await dragAndDrop(page, edgeB, [[100, 100]]);
await waitForSerialized(page, 1);
})
);
Expand Down
Loading
Loading