Skip to content

Commit

Permalink
Merge pull request #18419 from calixteman/reuse_old_dict_when_updating
Browse files Browse the repository at this point in the history
[Editor] Update the freetext annotation dictionary instead of creating a new one when updating an existing freetext
  • Loading branch information
calixteman committed Jul 11, 2024
2 parents e8d35c2 + 6711123 commit 9b1b5ff
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 6 deletions.
29 changes: 23 additions & 6 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -1711,18 +1711,28 @@ class MarkupAnnotation extends Annotation {
}

static async createNewAnnotation(xref, annotation, dependencies, params) {
const annotationRef = (annotation.ref ||= xref.getNewTemporaryRef());
let oldAnnotation;
if (annotation.ref) {
oldAnnotation = (await xref.fetchIfRefAsync(annotation.ref)).clone();
} else {
annotation.ref = xref.getNewTemporaryRef();
}

const annotationRef = annotation.ref;
const ap = await this.createNewAppearanceStream(annotation, xref, params);
const buffer = [];
let annotationDict;

if (ap) {
const apRef = xref.getNewTemporaryRef();
annotationDict = this.createNewDict(annotation, xref, { apRef });
annotationDict = this.createNewDict(annotation, xref, {
apRef,
oldAnnotation,
});
await writeObject(apRef, ap, buffer, xref);
dependencies.push({ ref: apRef, data: buffer.join("") });
} else {
annotationDict = this.createNewDict(annotation, xref, {});
annotationDict = this.createNewDict(annotation, xref, { oldAnnotation });
}
if (Number.isInteger(annotation.parentTreeId)) {
annotationDict.set("StructParent", annotation.parentTreeId);
Expand Down Expand Up @@ -3826,12 +3836,19 @@ class FreeTextAnnotation extends MarkupAnnotation {
return this._hasAppearance;
}

static createNewDict(annotation, xref, { apRef, ap }) {
static createNewDict(annotation, xref, { apRef, ap, oldAnnotation }) {
const { color, fontSize, rect, rotation, user, value } = annotation;
const freetext = new Dict(xref);
const freetext = oldAnnotation || new Dict(xref);
freetext.set("Type", Name.get("Annot"));
freetext.set("Subtype", Name.get("FreeText"));
freetext.set("CreationDate", `D:${getModificationDate()}`);
if (oldAnnotation) {
freetext.set("M", `D:${getModificationDate()}`);
// TODO: We should try to generate a new RC from the content we've.
// For now we can just remove it to avoid any issues.
freetext.delete("RC");
} else {
freetext.set("CreationDate", `D:${getModificationDate()}`);
}
freetext.set("Rect", rect);
const da = `/Helv ${fontSize} Tf ${getPdfColor(color, /* isFill */ true)}`;
freetext.set("DA", da);
Expand Down
4 changes: 4 additions & 0 deletions src/core/primitives.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ class Dict {
}
return dict;
}

delete(key) {
delete this._map[key];
}
}

class Ref {
Expand Down
40 changes: 40 additions & 0 deletions test/unit/annotation_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4257,6 +4257,46 @@ describe("annotation", function () {
]);
});

it("should update an existing FreeText annotation", async function () {
const freeTextDict = new Dict();
freeTextDict.set("Type", Name.get("Annot"));
freeTextDict.set("Subtype", Name.get("FreeText"));
freeTextDict.set("CreationDate", "D:20190423");
freeTextDict.set("Foo", Name.get("Bar"));

const freeTextRef = Ref.get(143, 0);
partialEvaluator.xref = new XRefMock([
{ ref: freeTextRef, data: freeTextDict },
]);

const task = new WorkerTask("test FreeText update");
const data = await AnnotationFactory.saveNewAnnotations(
partialEvaluator,
task,
[
{
annotationType: AnnotationEditorType.FREETEXT,
rect: [12, 34, 56, 78],
rotation: 0,
fontSize: 10,
color: [0, 0, 0],
value: "Hello PDF.js World !",
id: "143R",
ref: freeTextRef,
},
]
);

const base = data.annotations[0].data.replaceAll(/\(D:\d+\)/g, "(date)");
expect(base).toEqual(
"143 0 obj\n" +
"<< /Type /Annot /Subtype /FreeText /CreationDate (date) /Foo /Bar /M (date) " +
"/Rect [12 34 56 78] /DA (/Helv 10 Tf 0 g) /Contents (Hello PDF.js World !) " +
"/F 4 /Border [0 0 0] /Rotate 0 /AP << /N 2 0 R>>>>\n" +
"endobj\n"
);
});

it("should extract the text from a FreeText annotation", async function () {
partialEvaluator.xref = new XRefMock();
const task = new WorkerTask("test FreeText text extraction");
Expand Down

0 comments on commit 9b1b5ff

Please sign in to comment.