From 3d544294af5455da14afab65cdb003f59a432538 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Thu, 9 Apr 2026 09:31:05 +0200 Subject: [PATCH] Take into account the alignment when printing/saving a comb field It fixes #21068. --- src/core/annotation.js | 12 +++++++++++- test/pdfs/.gitignore | 1 + test/pdfs/issue21068.pdf | Bin 0 -> 7557 bytes test/test_manifest.json | 22 ++++++++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/pdfs/issue21068.pdf diff --git a/src/core/annotation.js b/src/core/annotation.js index 8d38ec8ae..beafa8e1f 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -2544,6 +2544,7 @@ class WidgetAnnotation extends Annotation { defaultVPadding, descent, lineHeight, + alignment, annotationStorage ); } @@ -2907,6 +2908,7 @@ class TextWidgetAnnotation extends WidgetAnnotation { vPadding, descent, lineHeight, + alignment, annotationStorage ) { const combWidth = width / this.data.maxLen; @@ -2919,11 +2921,19 @@ class TextWidgetAnnotation extends WidgetAnnotation { buf.push(`(${escapeString(text.substring(start, end))}) Tj`); } + const textWidth = combWidth * positions.length; + let hShift = hPadding; + if (alignment === 1) { + hShift += Math.floor((width - textWidth) / (2 * combWidth)) * combWidth; + } else if (alignment === 2) { + hShift += width - textWidth; + } + const renderedComb = buf.join(` ${numberToString(combWidth)} 0 Td `); return ( `/Tx BMC q ${colors}BT ` + defaultAppearance + - ` 1 0 0 1 ${numberToString(hPadding)} ${numberToString( + ` 1 0 0 1 ${numberToString(hShift)} ${numberToString( vPadding + descent )} Tm ${renderedComb}` + " ET Q EMC" diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index f75ed2f4d..65edc5dc8 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -898,3 +898,4 @@ !function_based_shading.pdf !issue16091.pdf !issue7821.pdf +!issue21068.pdf diff --git a/test/pdfs/issue21068.pdf b/test/pdfs/issue21068.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2495958adfafa7a3f6a03cd97476df26c866365a GIT binary patch literal 7557 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 uaHijpr6^8N!_%b3Uj literal 0 HcmV?d00001 diff --git a/test/test_manifest.json b/test/test_manifest.json index 98d7ec427..711f9ab49 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -14075,5 +14075,27 @@ "md5": "7f0f390a70228fffe95835518ec266c5", "rounds": 1, "type": "eq" + }, + { + "id": "issue21068", + "file": "pdfs/issue21068.pdf", + "md5": "69558d166186923ad9d639d91884dbd6", + "rounds": 1, + "type": "eq", + "print": true, + "annotationStorage": { + "27R": { + "value": "123" + }, + "28R": { + "value": "123" + }, + "29R": { + "value": "1234" + }, + "30R": { + "value": "123" + } + } } ]