79170645

Date: 2024-11-08 15:35:15
Score: 0.5
Natty:
Report link

This can be achieved by using the paid software package, Setasign-Core. The following demonstrates it (code found in the link provided by @JanSlabom in the comments):

<?php

use \SetaPDF_Core_Document_Page_Annotation_FreeText as FreeTextAnnotation;

// load and register the autoload function
require_once '../vendor/autoload.php';

// let's define some properties first
$x = 10;
$yTop = 10; // we take the upper left as the origin

$borderWidth = 1;

$borderColor = '#FF0000';
$fillColor = '#00FF00';
$textColor = '#0000FF';

$text = "Received: " . date('Y-m-d H:i:s');
$align = SetaPDF_Core_Text::ALIGN_LEFT;

// create a document instance by loading an existing PDF
$writer = new \SetaPDF_Core_Writer_File('test-form-annotated-signed.pdf', true);
$document = \SetaPDF_Core_Document::loadByFilename(
    'test-form-signed.pdf',
    $writer
    );

// we will need a font instance
$font = SetaPDF_Core_Font_Standard_Helvetica::create($document);
$fontSize = 12;

// now we create a text block first to know the final size:
$box = new SetaPDF_Core_Text_Block($font, $fontSize);
$box->setTextColor($textColor);
$box->setBorderWidth($borderWidth);
$box->setBorderColor($borderColor);
$box->setBackgroundColor($fillColor);
$box->setAlign($align);
$box->setText($text);
$box->setPadding(2);

$width = $box->getWidth();
$height = $box->getHeight();

// now draw the text block onto a canvas (we add the $borderWidth to show the complete border)
$appearance = SetaPDF_Core_XObject_Form::create($document, [0, 0, $width + $borderWidth, $height + $borderWidth]);
$box->draw($appearance->getCanvas(), $borderWidth / 2, $borderWidth / 2);

// now we need a page and calculate the correct coordinates for our annotation
$page = $document->getCatalog()->getPages()->getPage(1);
// we need its rotation
$rotation = $page->getRotation();
// ...and page boundary box
$box = $page->getBoundary();

// with this information we create a graphic state
$pageGs = new \SetaPDF_Core_Canvas_GraphicState();
switch ($rotation) {
    case 90:
        $pageGs->translate($box->getWidth(), 0);
        break;
    case 180:
        $pageGs->translate($box->getWidth(), $box->getHeight());
        break;
    case 270:
        $pageGs->translate(0, $box->getHeight());
        break;
}

$pageGs->rotate($box->llx, $box->lly, $rotation);
$pageGs->translate($box->llx, $box->lly);

// ...and a helper function to translate coordinates into vectors by using the page graphic state
$f = static function($x, $y) use ($pageGs) {
    $v = new \SetaPDF_Core_Geometry_Vector($x, $y);
    return $v->multiply($pageGs->getCurrentTransformationMatrix());
};

// calculate the ordinate
$y = $page->getHeight() - $height - $yTop;

$ll = $f($x, $y);
$ur = $f($x + $width + $borderWidth, $y + $height + $borderWidth);

// now we create the annotation object:
$annotation = new FreeTextAnnotation(
    [$ll->getX(), $ll->getY(), $ur->getX(), $ur->getY()],
    'Helv',
    $fontSize,
    $borderColor
    );
$annotation->getBorderStyle()->setWidth($borderWidth);
$annotation->setColor($fillColor);
$annotation->setTextLabel("John Dow"); // Used as Author in a Reader application
$annotation->setContents($text);
$annotation->setName(uniqid('', true));
$annotation->setModificationDate(new DateTime());
$annotation->setAppearance($appearance);

// now we need to add some things regarding "variable text" that are required by e.g. Acrobat (if you want to add
// e.g. a digital signature directly after adding a free-text annotation)
$dict = $annotation->getDictionary();
$dict->offsetSet(
    'DS',
    new SetaPDF_Core_Type_String('font: Helvetica, sans-serif ' . sprintf('%.2F', $fontSize) . 'pt;color: ' . $textColor)
    );
switch ($align) {
    case SetaPDF_Core_Text::ALIGN_CENTER:
        $align = 'center';
        break;
    case SetaPDF_Core_Text::ALIGN_RIGHT:
        $align = 'right';
        break;
    case SetaPDF_Core_Text::ALIGN_JUSTIFY:
        $align = 'justify';
        break;
    default:
        $align = 'left';
}

$dict->offsetSet('RC', new SetaPDF_Core_Type_String(
    '<?xml version="1.0"?><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" ' .
    'xfa:APIVersion="Acrobat:11.0.23" xfa:spec="2.0.2"  style="font-size:' . $fontSize . 'pt;text-align:' . $align .
    ';color:' . $textColor . ';font-weight:normal;font-style:normal;font-family:Helvetica,sans-serif;font-stretch:normal">' .
    '<p dir="ltr"><span style="font-family:Helvetica">' . htmlentities($annotation->getContents(), ENT_XML1) . '</span></p></body>'
    ));

// lastly add the annotation to the page
$page->getAnnotations()->add($annotation);

$document->save()->finish();
Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @JanSlabom
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: Benjamin