Merge pull request #20244 from calixteman/fix_deleting_popup

[Editor] Fix saving a deleted popup
This commit is contained in:
Tim van der Meij 2025-09-08 21:23:47 +02:00 committed by GitHub
commit 3f0d39b024
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 82 additions and 46 deletions

View File

@ -1810,8 +1810,8 @@ class MarkupAnnotation extends Annotation {
});
const retRef = { ref: annotationRef };
if (annotation.popup) {
const popup = annotation.popup;
const { popup } = annotation;
if (popup) {
if (popup.deleted) {
annotationDict.delete("Popup");
annotationDict.delete("Contents");

View File

@ -309,7 +309,7 @@ class Dict {
}
delete(key) {
delete this._map[key];
this._map.delete(key);
}
}

View File

@ -1749,7 +1749,14 @@ class AnnotationEditor {
* @returns {Object | null}
*/
serialize(isForCopying = false, context = null) {
unreachable("An editor must be serializable");
return {
annotationType: this.mode,
pageIndex: this.pageIndex,
rect: this.getPDFRect(),
rotation: this.rotation,
structTreeParentId: this._structTreeParentId,
popupRef: this._initialData?.popupRef || "",
};
}
/**

View File

@ -833,21 +833,14 @@ class FreeTextEditor extends AnnotationEditor {
return this.serializeDeleted();
}
const rect = this.getPDFRect();
const color = AnnotationEditor._colorManager.convert(
this.isAttachedToDOM ? getComputedStyle(this.editorDiv).color : this.color
);
const serialized = {
annotationType: AnnotationEditorType.FREETEXT,
const serialized = Object.assign(super.serialize(isForCopying), {
color,
fontSize: this.#fontSize,
value: this.#serializeContent(),
pageIndex: this.pageIndex,
rect,
rotation: this.rotation,
structTreeParentId: this._structTreeParentId,
};
});
this.addComment(serialized);
if (isForCopying) {

View File

@ -1036,23 +1036,17 @@ class HighlightEditor extends AnnotationEditor {
return this.serializeDeleted();
}
const rect = this.getPDFRect();
const color = AnnotationEditor._colorManager.convert(
this._uiManager.getNonHCMColor(this.color)
);
const serialized = {
annotationType: AnnotationEditorType.HIGHLIGHT,
const serialized = super.serialize(isForCopying);
Object.assign(serialized, {
color,
opacity: this.opacity,
thickness: this.#thickness,
quadPoints: this.#serializeBoxes(),
outlines: this.#serializeOutlines(rect),
pageIndex: this.pageIndex,
rect,
rotation: this.#getRotation(),
structTreeParentId: this._structTreeParentId,
};
outlines: this.#serializeOutlines(serialized.rect),
});
this.addComment(serialized);
if (this.annotationElementId && !this.#hasElementChanged(serialized)) {

View File

@ -247,7 +247,7 @@ class InkEditor extends DrawingEditor {
return this.serializeDeleted();
}
const { lines, points, rect } = this.serializeDraw(isForCopying);
const { lines, points } = this.serializeDraw(isForCopying);
const {
_drawingOptions: {
stroke,
@ -255,8 +255,7 @@ class InkEditor extends DrawingEditor {
"stroke-width": thickness,
},
} = this;
const serialized = {
annotationType: AnnotationEditorType.INK,
const serialized = Object.assign(super.serialize(isForCopying), {
color: AnnotationEditor._colorManager.convert(stroke),
opacity,
thickness,
@ -264,11 +263,7 @@ class InkEditor extends DrawingEditor {
lines,
points,
},
pageIndex: this.pageIndex,
rect,
rotation: this.rotation,
structTreeParentId: this._structTreeParentId,
};
});
this.addComment(serialized);
if (isForCopying) {

View File

@ -374,21 +374,16 @@ class SignatureEditor extends DrawingEditor {
return null;
}
const { lines, points, rect } = this.serializeDraw(isForCopying);
const { lines, points } = this.serializeDraw(isForCopying);
const {
_drawingOptions: { "stroke-width": thickness },
} = this;
const serialized = {
annotationType: AnnotationEditorType.SIGNATURE,
const serialized = Object.assign(super.serialize(isForCopying), {
isSignature: true,
areContours: this.#isExtracted,
color: [0, 0, 0],
thickness: this.#isExtracted ? 0 : thickness,
pageIndex: this.pageIndex,
rect,
rotation: this.rotation,
structTreeParentId: this._structTreeParentId,
};
});
this.addComment(serialized);
if (isForCopying) {
serialized.paths = { lines, points };

View File

@ -842,15 +842,10 @@ class StampEditor extends AnnotationEditor {
return this.serializeDeleted();
}
const serialized = {
annotationType: AnnotationEditorType.STAMP,
const serialized = Object.assign(super.serialize(isForCopying), {
bitmapId: this.#bitmapId,
pageIndex: this.pageIndex,
rect: this.getPDFRect(),
rotation: this.rotation,
isSvg: this.#isSvg,
structTreeParentId: this._structTreeParentId,
};
});
this.addComment(serialized);
if (isForCopying) {

View File

@ -5023,6 +5023,63 @@ describe("annotation", function () {
"endobj\n"
);
});
it("should update an existing Highlight annotation in removing its popup", async function () {
const popupRef = Ref.get(111, 0);
const highlightDict = new Dict();
highlightDict.set("Type", Name.get("Annot"));
highlightDict.set("Subtype", Name.get("Highlight"));
highlightDict.set("Rotate", 0);
highlightDict.set("CreationDate", "D:20190423");
highlightDict.set("Contents", "Hello PDF.js World !");
highlightDict.set("Popup", popupRef);
const highlightRef = Ref.get(143, 0);
const highlightPopupDict = new Dict();
highlightPopupDict.set("Type", Name.get("Annot"));
highlightPopupDict.set("Subtype", Name.get("Popup"));
highlightPopupDict.set("Open", false);
highlightPopupDict.set("Rect", [1, 2, 3, 4]);
highlightPopupDict.set("Parent", highlightRef);
const xref = (partialEvaluator.xref = new XRefMock([
{ ref: highlightRef, data: highlightDict },
{ ref: popupRef, data: highlightPopupDict },
]));
const changes = new RefSetCache();
const task = new WorkerTask("test Highlight update");
await AnnotationFactory.saveNewAnnotations(
partialEvaluator,
task,
[
{
annotationType: AnnotationEditorType.HIGHLIGHT,
rotation: 90,
popup: {
contents: "",
deleted: true,
rect: [1, 2, 3, 4],
},
id: "143R",
ref: highlightRef,
oldAnnotation: highlightDict,
popupRef,
},
],
null,
changes
);
const data = await writeChanges(changes, xref);
const base = data[0].data.replaceAll(/\(D:\d+\)/g, "(date)");
expect(base).toEqual(
"143 0 obj\n" +
"<< /Type /Annot /Subtype /Highlight /Rotate 90 /CreationDate (date) /M (date) " +
"/F 4>>\n" +
"endobj\n"
);
});
});
describe("UnderlineAnnotation", function () {