1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-19 22:58:07 +02:00

[Editor] Don't try to use an non-existing canvas when rendering an invisible existing stamp editor

It fixes #19239.

When the canvas isn't existing the editor has no image: it's fine because the editor is invisible.
Once it's made visible, the canvas is set when the annotation layer has been rendered.
This commit is contained in:
Calixte Denizet 2025-01-09 18:10:47 +01:00
parent f1166f480f
commit 06f72d5662
7 changed files with 160 additions and 15 deletions

View file

@ -3301,6 +3301,22 @@ class AnnotationLayer {
} else {
firstChild.after(canvas);
}
const editableAnnotation = this.#editableAnnotations.get(id);
if (!editableAnnotation) {
continue;
}
if (editableAnnotation._hasNoCanvas) {
// The canvas wasn't available when the annotation was created.
this._annotationEditorUIManager?.setMissingCanvas(
id,
element.id,
canvas
);
editableAnnotation._hasNoCanvas = false;
} else {
editableAnnotation.canvas = canvas;
}
}
this.#annotationCanvasMap.clear();
}

View file

@ -40,6 +40,8 @@ class StampEditor extends AnnotationEditor {
#canvas = null;
#missingCanvas = false;
#resizeTimeoutId = null;
#isSvg = false;
@ -352,7 +354,8 @@ class StampEditor extends AnnotationEditor {
this.#bitmap ||
this.#bitmapUrl ||
this.#bitmapFile ||
this.#bitmapId
this.#bitmapId ||
this.#missingCanvas
);
}
@ -379,10 +382,12 @@ class StampEditor extends AnnotationEditor {
this.addAltTextButton();
if (this.#bitmap) {
this.#createCanvas();
} else {
this.#getBitmap();
if (!this.#missingCanvas) {
if (this.#bitmap) {
this.#createCanvas();
} else {
this.#getBitmap();
}
}
if (this.width && !this.annotationElementId) {
@ -401,6 +406,22 @@ class StampEditor extends AnnotationEditor {
return this.div;
}
setCanvas(annotationElementId, canvas) {
const { id: bitmapId, bitmap } = this._uiManager.imageManager.getFromCanvas(
annotationElementId,
canvas
);
canvas.remove();
if (bitmapId && this._uiManager.imageManager.isValidId(bitmapId)) {
this.#bitmapId = bitmapId;
if (bitmap) {
this.#bitmap = bitmap;
}
this.#missingCanvas = false;
this.#createCanvas();
}
}
/** @inheritdoc */
_onResized() {
// We used a CSS-zoom during the resizing, but now it's resized we can
@ -752,6 +773,7 @@ class StampEditor extends AnnotationEditor {
/** @inheritdoc */
static async deserialize(data, parent, uiManager) {
let initialData = null;
let missingCanvas = false;
if (data instanceof StampAnnotationElement) {
const {
data: { rect, rotation, id, structParent, popupRef },
@ -759,13 +781,20 @@ class StampEditor extends AnnotationEditor {
parent: {
page: { pageNumber },
},
canvas,
} = data;
const canvas = container.querySelector("canvas");
const imageData = uiManager.imageManager.getFromCanvas(
container.id,
canvas
);
canvas.remove();
let bitmapId, bitmap;
if (canvas) {
delete data.canvas;
({ id: bitmapId, bitmap } = uiManager.imageManager.getFromCanvas(
container.id,
canvas
));
canvas.remove();
} else {
missingCanvas = true;
data._hasNoCanvas = true;
}
// When switching to edit mode, we wait for the structure tree to be
// ready (see pdf_viewer.js), so it's fine to use getAriaAttributesSync.
@ -776,8 +805,8 @@ class StampEditor extends AnnotationEditor {
initialData = data = {
annotationType: AnnotationEditorType.STAMP,
bitmapId: imageData.id,
bitmap: imageData.bitmap,
bitmapId,
bitmap,
pageIndex: pageNumber - 1,
rect: rect.slice(0),
rotation,
@ -795,7 +824,10 @@ class StampEditor extends AnnotationEditor {
const editor = await super.deserialize(data, parent, uiManager);
const { rect, bitmap, bitmapUrl, bitmapId, isSvg, accessibilityData } =
data;
if (bitmapId && uiManager.imageManager.isValidId(bitmapId)) {
if (missingCanvas) {
uiManager.addMissingCanvas(data.id, editor);
editor.#missingCanvas = true;
} else if (bitmapId && uiManager.imageManager.isValidId(bitmapId)) {
editor.#bitmapId = bitmapId;
if (bitmap) {
editor.#bitmap = bitmap;

View file

@ -654,6 +654,8 @@ class AnnotationEditorUIManager {
#mainHighlightColorPicker = null;
#missingCanvases = null;
#mlManager = null;
#mode = AnnotationEditorType.NONE;
@ -898,6 +900,7 @@ class AnnotationEditorUIManager {
this.#allLayers.clear();
this.#allEditors.clear();
this.#editorsToRescale.clear();
this.#missingCanvases?.clear();
this.#activeEditor = null;
this.#selectedEditors.clear();
this.#commandManager.destroy();
@ -1711,6 +1714,10 @@ class AnnotationEditorUIManager {
this.#updateModeCapability.resolve();
}
isInEditingMode() {
return this.#mode !== AnnotationEditorType.NONE;
}
addNewEditorFromKeyboard() {
if (this.currentLayer.canCreateNewEmptyEditor()) {
this.currentLayer.addNewEditor();
@ -1887,6 +1894,9 @@ class AnnotationEditorUIManager {
}, 0);
}
this.#allEditors.delete(editor.id);
if (editor.annotationElementId) {
this.#missingCanvases?.delete(editor.annotationElementId);
}
this.unselect(editor);
if (
!editor.annotationElementId ||
@ -2514,6 +2524,19 @@ class AnnotationEditorUIManager {
}
editor.renderAnnotationElement(annotation);
}
setMissingCanvas(annotationId, annotationElementId, canvas) {
const editor = this.#missingCanvases?.get(annotationId);
if (!editor) {
return;
}
editor.setCanvas(annotationElementId, canvas);
this.#missingCanvases.delete(annotationId);
}
addMissingCanvas(annotationId, editor) {
(this.#missingCanvases ||= new Map()).set(annotationId, editor);
}
}
export {