Skip to content

Commit

Permalink
Merge pull request #19201 from calixteman/fix_resize_stamp
Browse files Browse the repository at this point in the history
[Editor] When resizing a stamp annotation, the opposite corner must stay fixed
  • Loading branch information
calixteman authored Dec 10, 2024
2 parents f9ae9b0 + 99f3e6b commit 44421d3
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 125 deletions.
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

0 comments on commit 44421d3

Please sign in to comment.