diff --git a/src/display/editor/highlight.js b/src/display/editor/highlight.js index 3c98a8e61c1c3..4bc00f7d0fbf9 100644 --- a/src/display/editor/highlight.js +++ b/src/display/editor/highlight.js @@ -385,19 +385,12 @@ class HighlightEditor extends AnnotationEditor { #serializeOutlines(rect) { const [pageWidth, pageHeight] = this.pageDimensions; - const width = this.width * pageWidth; - const height = this.height * pageHeight; - const [tx, ty] = rect; - const outlines = []; - for (const outline of this.#highlightOutlines.outlines) { - const points = new Array(outline.length); - for (let i = 0; i < outline.length; i += 2) { - points[i] = tx + outline[i] * width; - points[i + 1] = ty + (1 - outline[i + 1]) * height; - } - outlines.push(points); - } - return outlines; + return this.#highlightOutlines.serialize( + rect[0], + rect[1], + this.width * pageWidth, + this.height * pageHeight + ); } /** @inheritdoc */ diff --git a/src/display/editor/outliner.js b/src/display/editor/outliner.js index 077fd71c8e30a..9d0425e9e1304 100644 --- a/src/display/editor/outliner.js +++ b/src/display/editor/outliner.js @@ -301,6 +301,19 @@ class HighlightOutline extends Outline { return buffer.join(" "); } + serialize(x, y, width, height) { + const outlines = []; + for (const outline of this.#outlines) { + const points = new Array(outline.length); + for (let i = 0; i < outline.length; i += 2) { + points[i] = x + outline[i] * width; + points[i + 1] = y + (1 - outline[i + 1]) * height; + } + outlines.push(points); + } + return outlines; + } + get box() { return this.#box; } diff --git a/test/integration/highlight_editor_spec.mjs b/test/integration/highlight_editor_spec.mjs index 6fb937441bf7e..b28eec62870c2 100644 --- a/test/integration/highlight_editor_spec.mjs +++ b/test/integration/highlight_editor_spec.mjs @@ -16,9 +16,11 @@ import { closePages, getEditorSelector, + getSerialized, kbSelectAll, loadAndWait, scrollIntoView, + waitForSerialized, } from "./test_utils.mjs"; const selectAll = async page => { @@ -160,18 +162,7 @@ describe("Highlight Editor", () => { await page.click("#editorHighlight"); await page.waitForSelector(".annotationEditorLayer.highlightEditing"); - const rect = await page.evaluate(() => { - for (const el of document.querySelectorAll( - `.page[data-page-number="1"] > .textLayer > span` - )) { - if (el.textContent === "Abstract") { - const { x, y, width, height } = el.getBoundingClientRect(); - return { x, y, width, height }; - } - } - return null; - }); - + const rect = await getSpanRectFromText(page, 1, "Abstract"); const x = rect.x + rect.width / 2; const y = rect.y + rect.height / 2; await page.mouse.click(x, y, { count: 2 }); @@ -282,4 +273,62 @@ describe("Highlight Editor", () => { ); }); }); + + describe("Highlight data serialization", () => { + let pages; + + beforeAll(async () => { + pages = await loadAndWait( + "tracemonkey.pdf", + ".annotationEditorLayer", + null, + null, + { highlightEditorColors: "red=#AB0000" } + ); + }); + + afterAll(async () => { + await closePages(pages); + }); + + it("must be correctly serialized", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await page.click("#editorHighlight"); + await page.waitForSelector(".annotationEditorLayer.highlightEditing"); + + const rect = await getSpanRectFromText(page, 1, "Abstract"); + const x = rect.x + rect.width / 2; + const y = rect.y + rect.height / 2; + await page.mouse.click(x, y, { count: 2 }); + + await page.waitForSelector(`${getEditorSelector(0)}`); + await page.waitForSelector( + `.page[data-page-number = "1"] svg.highlightOutline.selected` + ); + + await waitForSerialized(page, 1); + const serialized = (await getSerialized(page))[0]; + expect(serialized.annotationType) + .withContext(`In ${browserName}`) + .toEqual(9); + expect(serialized.color) + .withContext(`In ${browserName}`) + .toEqual([0xab, 0, 0]); + + // We don't check the quadPoints and outlines values because they're + // dependent on the font used in the text layer. + expect(serialized.quadPoints.length) + .withContext(`In ${browserName}`) + .toEqual(8); + expect(serialized.outlines.length) + .withContext(`In ${browserName}`) + .toEqual(1); + expect(serialized.outlines[0].length) + .withContext(`In ${browserName}`) + .toEqual(8); + }) + ); + }); + }); });