Skip to content

Commit 9be5d04

Browse files
committed
fix(PhpNativeHandler): fix stamp rendering for GRAPHIC_ONLY and SIGNAME alignment
Three fixes: - useDefaultAppearance: false for invisible signatures (no visibleElements) to prevent the pdf-signer-php default stamp from appearing. - GRAPHIC_ONLY: buildXObject now returns an empty n2 stream immediately, preventing description text from leaking into graphic-only stamps. - GRAPHIC_ONLY: buildAppearanceForElement now assigns the user's drawn image to the full bbox (signatureImageFrame=null), fixing blank stamps. - SIGNAME_AND_DESCRIPTION: signer name is now horizontally centred within the left half of the stamp instead of being pinned to leftPadding. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 951d680 commit 9be5d04

1 file changed

Lines changed: 18 additions & 3 deletions

File tree

lib/Handler/SignEngine/PhpNativeHandler.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public function getSignedContent(): string {
7373
metadata: $metadata,
7474
timestamp: $timestamp,
7575
certificationLevel: $certificationLevel,
76+
useDefaultAppearance: false,
7677
),
7778
));
7879
}
@@ -143,13 +144,19 @@ private function buildAppearanceForElement(
143144
// GRAPHIC_AND_DESCRIPTION: user's drawn image goes into the n2 xObject layer
144145
// on the left half of the bbox so it does not distort or cover the description text.
145146
// Background (if enabled) still occupies the full n0 layer behind everything.
147+
// GRAPHIC_ONLY: user's drawn image occupies the full bbox in n2; no description text.
146148
$userImgPath = null;
147149
$userImgRect = null;
148150
if ($renderMode === SignerElementsService::RENDER_MODE_GRAPHIC_AND_DESCRIPTION) {
149151
if ($signatureImagePath !== '' && is_file($signatureImagePath)) {
150152
$userImgPath = $signatureImagePath;
151153
$userImgRect = [0.0, 0.0, (float)$width / 2.0, (float)$height];
152154
}
155+
} elseif ($renderMode === SignerElementsService::RENDER_MODE_GRAPHIC_ONLY) {
156+
if ($signatureImagePath !== '' && is_file($signatureImagePath)) {
157+
$userImgPath = $signatureImagePath;
158+
$userImgRect = null; // full bbox
159+
}
153160
}
154161

155162
return new SignatureAppearanceDto(
@@ -254,6 +261,11 @@ private function hasExistingSignatures(string $pdfContent): bool {
254261
* No image generation: pure PDF text operators.
255262
*/
256263
private function buildXObject(int $width, int $height, string $renderMode): SignatureAppearanceXObjectDto {
264+
// GRAPHIC_ONLY: only the background/signature image is shown; no text in n2.
265+
if ($renderMode === SignerElementsService::RENDER_MODE_GRAPHIC_ONLY) {
266+
return new SignatureAppearanceXObjectDto(stream: '', resources: []);
267+
}
268+
257269
$params = $this->getSignatureParams();
258270
$serverTimezone = new \DateTimeZone(date_default_timezone_get());
259271
$now = new \DateTime('now', $serverTimezone);
@@ -280,19 +292,22 @@ private function buildXObject(int $width, int $height, string $renderMode): Sign
280292
: ($this->readCertificate()['subject']['CN'] ?? '');
281293
if ($commonName !== '') {
282294
$nameFontSize = $this->signatureTextService->getSignatureFontSize();
283-
$leftHalfW = (float)$width / 2.0 - $leftPadding * 2;
284-
$nameLines = $this->wrapTextForPdf($commonName, $leftHalfW, $nameFontSize);
295+
$leftHalfW = (float)$width / 2.0;
296+
$nameLines = $this->wrapTextForPdf($commonName, $leftHalfW - $leftPadding * 2, $nameFontSize);
285297
$nameLineCount = count($nameLines);
286298
$totalNameHeight = $nameLineCount * $nameFontSize * 1.2;
287299
$nameStartY = ((float)$height + $totalNameHeight) / 2.0 - $nameFontSize;
288300
$nameStartY = max(0.0, $nameStartY);
289301
$nameY = $nameStartY;
302+
$estimatedCharWidth = $nameFontSize * 0.52;
290303
foreach ($nameLines as $nameLine) {
304+
$lineWidth = strlen($nameLine) * $estimatedCharWidth;
305+
$nameX = max($leftPadding, ($leftHalfW - $lineWidth) / 2.0);
291306
$escaped = $this->escapePdfText($nameLine);
292307
$stream .= "BT\n";
293308
$stream .= sprintf("/F1 %.2F Tf\n", $nameFontSize);
294309
$stream .= "0 0 0 rg\n";
295-
$stream .= sprintf("%.2F %.2F Td\n", $leftPadding, $nameY);
310+
$stream .= sprintf("%.2F %.2F Td\n", $nameX, $nameY);
296311
$stream .= sprintf("(%s) Tj\n", $escaped);
297312
$stream .= "ET\n";
298313
$nameY -= $nameFontSize * 1.2;

0 commit comments

Comments
 (0)