From 5f5d9dfc28f63effe8c5ff9fec8193258fc6a04e Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Mon, 19 May 2025 12:52:54 +0200 Subject: [PATCH 1/2] Support Type3 fonts with an incomplete /FontDescriptor dictionary (issue 19954) We have a fallback for the common case of Type3 fonts without a /FontDescriptor dictionary, however we also need to handle the case where it's present but lacking the required /FontName entry. --- src/core/evaluator.js | 8 +++++++- test/pdfs/issue19954.pdf.link | 1 + test/test_manifest.json | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 test/pdfs/issue19954.pdf.link diff --git a/src/core/evaluator.js b/src/core/evaluator.js index e84bad23e..aaf382f3b 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -4420,7 +4420,13 @@ class PartialEvaluator { const fontNameStr = fontName?.name; const baseFontStr = baseFont?.name; - if (!isType3Font && fontNameStr !== baseFontStr) { + if (isType3Font) { + if (!fontNameStr) { + // The Type3 font has a /FontDescriptor, however it's incomplete, hence + // why we didn't create a barbebones one above (fixes issue19954.pdf). + fontName = Name.get(type); + } + } else if (fontNameStr !== baseFontStr) { info( `The FontDescriptor's FontName is "${fontNameStr}" but ` + `should be the same as the Font's BaseFont "${baseFontStr}".` diff --git a/test/pdfs/issue19954.pdf.link b/test/pdfs/issue19954.pdf.link new file mode 100644 index 000000000..7b0fae3e8 --- /dev/null +++ b/test/pdfs/issue19954.pdf.link @@ -0,0 +1 @@ +https://github.com/user-attachments/files/20281525/Capital.Bancorp.Inc.Corporate.Responsibility.2025509.SD000000003063823863-1-2.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 71d7d8551..a36995a32 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -2859,6 +2859,15 @@ "rounds": 1, "type": "eq" }, + { + "id": "issue19954", + "file": "pdfs/issue19954.pdf", + "md5": "9742309bb321691b53b96069dfc1099b", + "link": true, + "rounds": 1, + "lastPage": 1, + "type": "text" + }, { "id": "IndexedCS_negative_and_high", "file": "pdfs/IndexedCS_negative_and_high.pdf", From c02ea0c681028ffc004c2e72237cf047b93269d0 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Mon, 19 May 2025 13:19:45 +0200 Subject: [PATCH 2/2] Simplify how we handle Type3 fonts without a /FontDescriptor dictionary Part of this is very old code, which we can now simplify a little bit. --- src/core/evaluator.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/core/evaluator.js b/src/core/evaluator.js index aaf382f3b..a32be74ce 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -4313,12 +4313,9 @@ class PartialEvaluator { if (!descriptor) { if (isType3Font) { - const bbox = lookupNormalRect(dict.getArray("FontBBox"), [0, 0, 0, 0]); // FontDescriptor is only required for Type3 fonts when the document - // is a tagged pdf. Create a barbebones one to get by. - descriptor = new Dict(null); - descriptor.set("FontName", Name.get(type)); - descriptor.set("FontBBox", bbox); + // is a tagged pdf. + descriptor = Dict.empty; } else { // Before PDF 1.5 if the font was one of the base 14 fonts, having a // FontDescriptor was not required. @@ -4422,8 +4419,8 @@ class PartialEvaluator { const baseFontStr = baseFont?.name; if (isType3Font) { if (!fontNameStr) { - // The Type3 font has a /FontDescriptor, however it's incomplete, hence - // why we didn't create a barbebones one above (fixes issue19954.pdf). + // Since the /FontDescriptor is optional in Type3 fonts, ensure that we + // always have a "valid" /FontName (fixes issue19954.pdf). fontName = Name.get(type); } } else if (fontNameStr !== baseFontStr) { @@ -4444,8 +4441,8 @@ class PartialEvaluator { ) { fontName = null; } + fontName ||= baseFont; } - fontName ||= baseFont; if (!(fontName instanceof Name)) { throw new FormatError("invalid font name"); @@ -4523,7 +4520,7 @@ class PartialEvaluator { ); const bbox = lookupNormalRect( descriptor.getArray("FontBBox") || dict.getArray("FontBBox"), - undefined + isType3Font ? [0, 0, 0, 0] : undefined ); let ascent = descriptor.get("Ascent"); if (typeof ascent !== "number") { @@ -4711,9 +4708,9 @@ class TranslatedFont { const fontResources = this.dict.get("Resources") || resources; const charProcOperatorList = Object.create(null); - const fontBBox = Util.normalizeRect(font.bbox || [0, 0, 0, 0]), - width = fontBBox[2] - fontBBox[0], - height = fontBBox[3] - fontBBox[1]; + const [x0, y0, x1, y1] = font.bbox, + width = x1 - x0, + height = y1 - y0; const fontBBoxSize = Math.hypot(width, height); for (const key of charProcs.getKeys()) {