Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/display/editor/freetext.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,15 @@ class FreeTextEditor extends AnnotationEditor {
getInitialTranslation() {
// The start of the base line is where the user clicked.
const scale = this.parentScale;
return [
-FreeTextEditor._internalPadding * scale,
-(FreeTextEditor._internalPadding + this.#fontSize) * scale,
];
const padding = FreeTextEditor._internalPadding * scale;
let fontSize = this.#fontSize;
if (this.isClone) {
// The serialized rect already includes this baseline shift. Applying it
// again moves the clone up by its font size. The padding must stay so
// that `getPDFRect()` round-trips (issue 22271).
fontSize = 0;
}
return [-padding, -(padding + fontSize * scale)];
}

/** @inheritdoc */
Expand Down
45 changes: 45 additions & 0 deletions test/integration/freetext_editor_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,51 @@ describe("FreeText Editor", () => {
});
});

describe("FreeText (clone)", () => {
let pages;

beforeEach(async () => {
pages = await loadAndWait("empty.pdf", ".annotationEditorLayer", 100);
});

afterEach(async () => {
await closePages(pages);
});

it("must keep the same rect when a FreeText editor is cloned", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await switchToFreeText(page);

const rect = await getRect(page, ".annotationEditorLayer");
await createFreeTextEditor({
page,
x: rect.x + 100,
y: rect.y + 100,
data: "Clone me",
});

// Same path as AnnotationEditorUIManager.findClonesForPage(), used
// when a page is copied with enableSplitMerge.
const rects = await page.evaluate(async () => {
const ui =
window.PDFViewerApplication.pdfViewer._layerProperties
.annotationEditorUIManager;
const [editor] = ui.getEditors(0);
const data = editor.serialize(true);
const layer = ui.getLayer(0);
const clone = await layer.deserialize(data);
clone.isClone = true;
layer.addOrRebuild(clone);
return [data.rect, clone.serialize(true).rect];
});

expect(rects[1]).withContext(`In ${browserName}`).toEqual(rects[0]);
})
);
});
});

describe("FreeText (multiselection)", () => {
let pages;

Expand Down