Skip to content

Commit

Permalink
[Editor] When resizing a stamp annotation, the opposite corner must s…
Browse files Browse the repository at this point in the history
…tay fixed

It was due the resize observer which is removed thanks to this patch.
In order to reuse the dragAndDrop function in test, this patch slighty refactors it
in order to make it easier to use.
  • Loading branch information
calixteman committed Dec 9, 2024
1 parent 99eefb7 commit 99f3e6b
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 99f3e6b

Please sign in to comment.