diff --git a/src/display/text_layer.js b/src/display/text_layer.js index 3bcb2fb7aa478..1a8b6f9dc9dd9 100644 --- a/src/display/text_layer.js +++ b/src/display/text_layer.js @@ -62,11 +62,13 @@ const MAX_TEXT_DIVS_TO_RENDER = 100000; const DEFAULT_FONT_SIZE = 30; const DEFAULT_FONT_ASCENT = 0.8; const ascentCache = new Map(); -let _canvasContext = null; +const _canvasContexts = new Map(); const pendingTextLayers = new Set(); function getCtx(lang = null) { - if (!_canvasContext) { + lang = lang || ""; + let canvasContext = _canvasContexts.get(lang); + if (!canvasContext) { // We don't use an OffscreenCanvas here because we use serif/sans serif // fonts with it and they depends on the locale. // In Firefox, the element get a lang attribute that depends on what @@ -78,19 +80,23 @@ function getCtx(lang = null) { // OffscreenCanvas. const canvas = document.createElement("canvas"); canvas.className = "hiddenCanvasElement"; + canvas.lang = lang; document.body.append(canvas); - _canvasContext = canvas.getContext("2d", { alpha: false }); + canvasContext = canvas.getContext("2d", { alpha: false }); + _canvasContexts.set(lang, canvasContext); } - return _canvasContext; + return canvasContext; } function cleanupTextLayer() { if (pendingTextLayers.size > 0) { return; } - _canvasContext?.canvas.remove(); - _canvasContext = null; + for (const canvasContext of _canvasContexts.values()) { + canvasContext.canvas.remove(); + } + _canvasContexts.clear(); } function getAscent(fontFamily, lang) { diff --git a/test/integration/text_layer_spec.mjs b/test/integration/text_layer_spec.mjs index 1fd8296b808ba..89725a61feeb6 100644 --- a/test/integration/text_layer_spec.mjs +++ b/test/integration/text_layer_spec.mjs @@ -290,4 +290,44 @@ describe("Text layer", () => { }); }); }); + describe("Text layer is aligned with the canvas layer", () => { + let pages; + beforeAll(async () => { + pages = await loadAndWait( + "Misaligned Text Layer.pdf", + `.page[data-page-number = "1"] .endOfContent` + ); + }); + afterAll(async () => { + await closePages(pages); + }); + + it("The width of text-span is correct", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + const lines = [ + "exceeding 1000 mm in Kyushu district, southwestern Japan, in", + "early July 2020. Especially, an elongated and stagnated mesoscale", + "convective system formed around the Kuma River in central", + "Kyushu district produced localized heavy rainfall with precipita-", + "tion amounts larger than 600 mm in 13 hours. Characteristics of", + ]; + const expectedWidth = 227; + const expectedWidthChrome = 242; + // In Chrome, an extra space character is included at the end + // of the text-span resulting in difference in widths + for (const line of lines) { + const pageNumber = 1; + const spanRect = await getSpanRectFromText(page, pageNumber, line); + const actualWidth = Math.round(spanRect.width); + if (browserName === "chrome") { + expect(actualWidth).toBeCloseTo(expectedWidthChrome, 1); + } else { + expect(actualWidth).toBeCloseTo(expectedWidth, 1); + } + } + }) + ); + }); + }); }); diff --git a/web/Misaligned Text Layer.pdf b/web/Misaligned Text Layer.pdf new file mode 100644 index 0000000000000..f35bae53db01e Binary files /dev/null and b/web/Misaligned Text Layer.pdf differ