From b17cce572107d5b3e5361d6a681442d3833fa03f Mon Sep 17 00:00:00 2001 From: Aditi Date: Fri, 17 May 2024 14:35:21 +0530 Subject: [PATCH] Add `lang` attribute to canvas element Fixes issue #16843. In certain cases, the text layer was misaligned due to a difference between the `lang` attribute of the viewer and the canvas. This commit addresses the problem by adding the `lang` attribute to the canvas. The issue was caused because PDF.js uses serif/sans-serif fonts to generate the text layer and relies on system fonts. The difference in the `lang` attribute led to different fonts being picked, causing the misalignment. --- src/display/text_layer.js | 17 +++++++++++------ test/pdfs/issue16843.pdf.link | 1 + test/test_manifest.json | 9 +++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 test/pdfs/issue16843.pdf.link diff --git a/src/display/text_layer.js b/src/display/text_layer.js index 3bcb2fb7aa478..45a62224f78c5 100644 --- a/src/display/text_layer.js +++ b/src/display/text_layer.js @@ -62,11 +62,12 @@ 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) { + 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 +79,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/pdfs/issue16843.pdf.link b/test/pdfs/issue16843.pdf.link new file mode 100644 index 0000000000000..e1949e8315bd8 --- /dev/null +++ b/test/pdfs/issue16843.pdf.link @@ -0,0 +1 @@ +https://github.com/mozilla/pdf.js/files/12366234/16_2020-044.pdf \ No newline at end of file diff --git a/test/test_manifest.json b/test/test_manifest.json index 74bc215d9b695..6f6016d4a4ad8 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -2202,6 +2202,15 @@ "lastPage": 1, "type": "eq" }, + { + "id": "issue16843", + "file": "pdfs/issue16843.pdf", + "md5": "2845b2f7f02690c388c24c488297028a", + "rounds": 1, + "link": true, + "firstPage": 1, + "type": "text" + }, { "id": "issue5509", "file": "pdfs/issue5509.pdf",