From d9999dceddc0d00a5b828cab39d8da1d15f085ef Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Thu, 2 Jul 2026 14:51:10 +0200 Subject: [PATCH] Apply the appearance-stream scale factor when text is shown, not on setFont The font size (Tf) and the text matrix (Tm) can appear in any order in an appearance stream. Applying the scale factor eagerly in setFont missed the case where Tf precedes Tm (e.g. Skia-generated FreeText), yielding a wrong guessed font size. --- src/core/default_appearance.js | 6 ++- test/integration/freetext_editor_spec.mjs | 43 ++++++++++++++++++++++ test/pdfs/.gitignore | 1 + test/pdfs/issue20504_skia.pdf | Bin 0 -> 19535 bytes 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 test/pdfs/issue20504_skia.pdf diff --git a/src/core/default_appearance.js b/src/core/default_appearance.js index 6b36572d6..888cb33e1 100644 --- a/src/core/default_appearance.js +++ b/src/core/default_appearance.js @@ -154,7 +154,7 @@ class AppearanceStreamEvaluator extends EvaluatorPreprocessor { result.fontName = fontName.name; } if (typeof fontSize === "number" && fontSize > 0) { - result.fontSize = fontSize * result.scaleFactor; + result.fontSize = fontSize; } break; case OPS.setFillColorSpace: @@ -184,6 +184,10 @@ class AppearanceStreamEvaluator extends EvaluatorPreprocessor { case OPS.showSpacedText: case OPS.nextLineShowText: case OPS.nextLineSetSpacingShowText: + // The font (Tf) and the text matrix (Tm) can be set in any order, + // so the scale factor is applied here, when text is actually shown + // and both are known to be in effect. + result.fontSize *= result.scaleFactor; breakLoop = true; break; } diff --git a/test/integration/freetext_editor_spec.mjs b/test/integration/freetext_editor_spec.mjs index 35f10c542..28240b5ac 100644 --- a/test/integration/freetext_editor_spec.mjs +++ b/test/integration/freetext_editor_spec.mjs @@ -1876,6 +1876,49 @@ describe("FreeText Editor", () => { }); }); + describe("FreeText (open existing generated with Skia)", () => { + let pages; + + beforeEach(async () => { + pages = await loadAndWait( + "issue20504_skia.pdf", + ".annotationEditorLayer", + 100 + ); + }); + + afterEach(async () => { + await closePages(pages); + }); + + it("must extract the font size when Tf comes before Tm", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + const id = "24R"; + await page.waitForSelector(getAnnotationSelector(id), { + visible: true, + }); + + await switchToFreeText(page); + + // The Skia appearance stream sets the font (Tf) before the text + // matrix (Tm), and the text matrix is scaled by 0.5 through a cm + // operator: 20 * 0.5 = 10. + const fontSize = await page.evaluate(() => { + const editorDiv = document.getElementById( + `pdfjs_internal_editor_0-editor` + ); + const match = editorDiv?.style.fontSize.match(/calc\((\d+)px/); + return match ? parseInt(match[1], 10) : 0; + }); + expect(fontSize) + .withContext(`In ${browserName}, editor 0 fontSize`) + .toEqual(10); + }) + ); + }); + }); + describe("Keyboard shortcuts when the editor layer isn't focused", () => { let pages; diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index a7b875122..54d04c8cf 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -941,3 +941,4 @@ !multimedia_annotations.pdf !issue17333.pdf !issue20504.pdf +!issue20504_skia.pdf diff --git a/test/pdfs/issue20504_skia.pdf b/test/pdfs/issue20504_skia.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ab5dd609c1cb797581b53a7c35fe745a78770be6 GIT binary patch literal 19535 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