Rich-Text Stamp

Introduction

The rich-text stamp class lets you stamp text that is styled by a subset of HTML and CSS onto existing PDF pages. Internally it encapsulates a rich-text block instance.

Following HTML tags are interpreted as you know from HTML:

  • <b> / <strong> for bold text
  • <i> / <em> for italic text
  • <u> for underline text
  • <sup> for superscript
  • <sub> for subscript
  • <br> / </br> for a line-break

You can use any other HTML tag such as <span> or <div>, too. Internally these tags are only parsed for their style attibute.

You can use the style attribute to define CSS styles for an element to any tag. Following CSS styles are supported:

  • font-family: (string)
  • font-size: (float|integer)(pt|%)
  • color: #RRGGBB hexadecimal notation
  • line-height: (float|integer)(%) unitless or percentual value

Font Handling

As each style (normal, bold, italic, italic+bold) of a font requires an individual font instance it is needed to have a kind of font-loading logic implemented. By default, the instance uses the standard font Helvetica and loads the different styles automatically by a predefined font-loader callable.

To use individual fonts and make use of TTF font subsets you have to pass your own font-loader which is a callable with following signature:

PHP
/**
 * @param SetaPDF_Core_Document $document
 * @param string $fontFamily The font family as passed to the font-family property.
 * @param string $fontStyle An empty string = normal, 'B' = bold, 'I' = italic, 'BI' = bold+italic.
 */
function (
    SetaPDF_Core_Document $document,
    string $fontFamily,
    string $fontStyle
): ?SetaPDF_Core_Font_FontInterface

The font instances created in this callable are bound to the document instance, and you need to take care of caching the instances appropriately to avoid an unneeded overhead. You also should make sure that the callable shares the font instances through different richt-text block or richt-text stamps instances.

A font-loader for e.g. DejaVuSans could look like:

PHP
$loadedFonts = [];
$fontLoader = function (\SetaPDF_Core_Document $document, $fontFamily, $fontStyle) use (&$loadedFonts) {
    $cacheKey = $document->getInstanceIdent() . '_' . $fontFamily . '_' . $fontStyle;
    if (!array_key_exists($cacheKey, $loadedFonts)) {
        $font = null;
        if ($fontFamily === 'DejaVuSans' && $fontStyle === '') {
            $font = new \SetaPDF_Core_Font_Type0_Subset($document, 'path/to/DejaVuSans.ttf');
        } elseif ($fontFamily === 'DejaVuSans' && $fontStyle === 'B') {
            $font = new \SetaPDF_Core_Font_Type0_Subset($document, 'path/to/DejaVuSans-Bold.ttf');
        } elseif ($fontFamily === 'DejaVuSans' && $fontStyle === 'I') {
            $font = new \SetaPDF_Core_Font_Type0_Subset($document, 'path/to/DejaVuSans-Oblique.ttf');
        } elseif ($fontFamily === 'DejaVuSans' && $fontStyle === 'BI') {
            $font = new \SetaPDF_Core_Font_Type0_Subset($document, 'path/to/DejaVuSans-BoldOblique.ttf');
        } 
        $loadedFonts[$cacheKey] = $font;
    }
    return $loadedFonts[$cacheKey];
};

and need to be passed to the constructor as the second argument.

Create an Instance

An instance of a rich-text stamp could be created by simply passing the document instance you initiate the stamper instance with to its constructor. The dependency to the document instance is required because of dynamic font loading:

PHP
$stamp = new \SetaPDF_Stamper_Stamp_RichText($document);

If you use your own font-loader, it needs to be passed as the second parameter:

PHP
$stamp = new \SetaPDF_Stamper_Stamp_RichText($document, $fontLoader);

You should define the default font-family afterwards, too:

PHP
$stamp->setDefaultFontFamily('DejaVuSans');

Configure Properties

Beside the general stamp properties the rich-text stamp class offers following properties to configured the text appearance in various ways:

Text

Text related properties could be controlled by following methods: 

getDefaultFontFamily()

getDefaultFontSize()

getDefaultLineHeight()

getText()

setDefaultFontFamily()

setDefaultFontSize()

setDefaultLineHeight()

setText()

Layout

To layout a richt-text stamp following methods are available:

getAlign()

Get the text alignment.

getHeight()

Get the height of this stamp.

getPaddingBottom()

Get the bottom padding.

getPaddingLeft()

Get the left padding.

getPaddingRight()

Get the right padding.

getPaddingTop()

Get the top padding.

getTextWidth()

Returns the width of the rich-text stamp without padding.

setAlign()

Set the text alignment.

setPadding()

Set the padding.

setPaddingBottom()

Set the bottom padding.

setPaddingLeft()

Set the left padding.

setPaddingRight()

Set the right padding.

setPaddingTop()

Set the top padding.

setTextWidth()

Set the width of the text in the rich-text stamp. Padding is not included in this width.

Border and Background

getBackgroundColor()

Get the background color object.

getBorderColor()

Get the border color object.

getBorderWidth()

Get the border width.

setBackgroundColor()

Set the background color.

setBorderColor()

Set the border color.

setBorderWidth()

Set the border width.

Examples

Following some examples showing you some ideas of how to style a rich-text stamp:

PHP
<?php
/* Create a styled and transparent watermark and add it to all pages
 */

require_once('library/SetaPDF/Autoload.php');

// create a writer
$writer = new \SetaPDF_Core_Writer_Http('watermark.pdf', true);
// get a document instance
$document = \SetaPDF_Core_Document::loadByFilename(
    'files/pdfs/lenstown/Laboratory-Report.pdf', $writer
);

// create a stamper instance
$stamper = new \SetaPDF_Stamper($document);

// create rich-text stamp
$stamp = new \SetaPDF_Stamper_Stamp_RichText($document);
$text = <<<HTML
    <span style="font-size: 44pt;line-height: 0.8">
        <b style="color: #FF0000;font-size:200%;">C</b>ONFIDENTIA<b style="color: #FF0000;font-size:200%;">L</b>
    </span><br/>
    (for <u>internal</u> use only!)
HTML;

$stamp->setText($text);
$stamp->setAlign(\SetaPDF_Core_Text::ALIGN_CENTER);
$stamp->setOpacity(0.5);

// right bottom and callback
$stamper->addStamp($stamp, array(
    'position' => \SetaPDF_Stamper::POSITION_CENTER_MIDDLE,
    'rotation' => 60
));

// stamp the document
$stamper->stamp();

// show the whole page at opening time
$document->getCatalog()->setPageLayout(\SetaPDF_Core_Document_PageLayout::SINGLE_PAGE);

// save and send it to the client
$document->save()->finish();
PHP
<?php
/* Adds a styled users name and email into the center bottom of each page
 */

require_once('library/SetaPDF/Autoload.php');

// create a writer
$writer = new \SetaPDF_Core_Writer_Http('personalization.pdf', true);
// get a document instance
$document = \SetaPDF_Core_Document::loadByFilename(
    'files/pdfs/Brand-Guide.pdf', $writer
);

// create a stamper instance
$stamper = new \SetaPDF_Stamper($document);

// create rich-text stamp
$stamp = new \SetaPDF_Stamper_Stamp_RichText($document);
$text = <<<HTML
    Personalized for: <b>John Doe</b> (<u>test@example.com</u>)
HTML;
$stamp->setText($text);
$blue = new \SetaPDF_Core_DataStructure_Color_Rgb(56/255, 101/255, 174/255);
$stamp->setDefaultTextColor($blue);
$stamp->setPadding(2);
$stamp->setBackgroundColor('#f6f6f6');
$stamp->setBorderWidth(.5);
$stamp->setborderColor($blue);

// right bottom and callback
$stamper->addStamp($stamp, array(
    'position' => \SetaPDF_Stamper::POSITION_CENTER_BOTTOM,
    'translateY' => 20
));

// stamp the document
$stamper->stamp();

// show the whole page at opening time
$document->getCatalog()->setPageLayout(\SetaPDF_Core_Document_PageLayout::SINGLE_PAGE);

// save and send it to the client
$document->save()->finish();
PHP
<?php
/* This example takes a nearly empty fact-sheet paper and adds a header with a kind
 * of logo, contact and address information and a long justified and styled text.
 *
 * We also use TTF fonts in this example to show how to implement an own font-loader.
 */

require_once('library/SetaPDF/Autoload.php');

// create a writer
$writer = new \SetaPDF_Core_Writer_Http('fact-sheet.pdf', true);
// get a document instance
$document = \SetaPDF_Core_Document::loadByFilename(
    'files/pdfs/Fact-Sheet-without-personalization.pdf', $writer
);

// create a stamper instance
$stamper = new \SetaPDF_Stamper($document);

$loadedFonts = [];
$fontLoader = static function (\SetaPDF_Core_Document $document, $fontFamily, $fontStyle) use (&$loadedFonts) {
    $cacheKey = $document->getInstanceIdent() . '_' . $fontFamily . '_' . $fontStyle;
    if (!array_key_exists($cacheKey, $loadedFonts)) {
        $font = null;
        if ($fontFamily === 'DejaVuSans' && $fontStyle === '') {
            $font = new \SetaPDF_Core_Font_Type0_Subset($document, 'files/fonts/DejaVuSans.ttf');
        } elseif ($fontFamily === 'DejaVuSans' && $fontStyle === 'B') {
            $font = new \SetaPDF_Core_Font_Type0_Subset($document, 'files/fonts/DejaVuSans-Bold.ttf');
        } elseif ($fontFamily === 'DejaVuSans' && $fontStyle === 'I') {
            $font = new \SetaPDF_Core_Font_Type0_Subset($document, 'files/fonts/DejaVuSans-Oblique.ttf');
        } elseif ($fontFamily === 'DejaVuSans' && $fontStyle === 'BI') {
            $font = new \SetaPDF_Core_Font_Type0_Subset($document, 'files/fonts/DejaVuSans-BoldOblique.ttf');
        }
        $loadedFonts[$cacheKey] = $font;
    }
    return $loadedFonts[$cacheKey];
};

// fake a logo
$logo = new \SetaPDF_Stamper_Stamp_RichText($document, $fontLoader);
$logo->setDefaultFontFamily('DejaVuSans');
$logo->setDefaultFontSize(20);
$text = <<<HTML
    <b>cam<span style="color:#e94e1c">town</span></b>
HTML;
$logo->setText($text);

$stamper->addStamp($logo, array(
    'translateX' => 43,
    'translateY' => -28
));

// add the contact details on to the top right
$contact = new \SetaPDF_Stamper_Stamp_RichText($document, $fontLoader);
$contact->setDefaultFontFamily('DejaVuSans');
$contact->setDefaultFontSize(10);
$contact->setDefaultTextColor('#6d6e70');
$contact->setAlign(\SetaPDF_Core_Text::ALIGN_RIGHT);
$text = <<<HTML
    Phone: +01 | <span style="color:#000000;">CAM</span><span style="color:#e94e1c;">TOWN</span> (2268696)<br/>
    E-Mail: post@camtown-nonexist.com<br/>
    Web: www.camtown-nonexist.com
HTML;
$contact->setText($text);

$stamper->addStamp($contact, array(
    'position' => \SetaPDF_Stamper::POSITION_RIGHT_TOP,
    'translateX' => -42,
    'translateY' => -22
));

// add the address left beside the address
$address = new \SetaPDF_Stamper_Stamp_RichText($document, $fontLoader);
$address->setDefaultFontFamily('DejaVuSans');
$address->setDefaultFontSize(10);
$address->setDefaultTextColor('#6d6e70');
$text = <<<HTML
    <span style="color:#000000;">cam</span><span style="color:#e94e1c;">town</span> Ltd.<br/>
Linger Road. 45<br/>
1356 Campoda 
HTML;
$address->setText($text);

$stamper->addStamp($address, array(
    'position' => \SetaPDF_Stamper::POSITION_RIGHT_TOP,
    'translateX' => -$contact->getWidth() - 82,
    'translateY' => -22
));

$description = new \SetaPDF_Stamper_Stamp_RichText($document, $fontLoader);
$description->setDefaultFontFamily('DejaVuSans');
$description->setDefaultFontSize(10);
$text = <<<HTML
    <span style="font-size:200%;line-height: 1">L</span>orem ipsum dolor sit amet, consetetur sadipscing elitr 
    m<sup>2</sup>, sed diam nonumy eirmod tempor invidunt ut labore et dolore <b>magna</b> aliquyam erat, sed diam 
    voluptua. At vero eos et accusam<sub>(rounded)</sub> et justo duo dolores et ea rebum. Stet <i>clita</i> kasd 
    gubergren, no sea takimata sanctus est Lorem <u>ipsum dolor sit amet</u>! Lorem ipsum dolor sit amet, consetetur 
    sadipscing elitr, sed diam nonumy eirmod tempor 
    cam<span style="color:#e94e1c;">town</span> invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
    At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est
    Lorem ipsum dolor sit amet. <b>Lorem</b> ipsum dolor sit amet, consetetur sadipscing elitr, <u>sed diam nonumy
    <b>eirmod</b> tempor <i>invidunt</i></u> ut labore et dolore magna aliquyam erat, sed diam voluptua. At 
    <b><i>vero</i></b> eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata 
    sanctus est Lorem ipsum dolor sit amet.<br />
    <span style="font-size:200%;line-height: 1">O</span>rem ipsum dolor sit amet, consetetur sadipscing <b>elitr</b>,
    sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et 
    cam<span style="color:#e94e1c;">town</span> accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
    no sea <i>takimata</i> sanctus est Lorem <u>ipsum</u> dolor sit amet. Lorem ipsum dolor sit amet, consetetur 
    sadipscing elitr, sed diam nonumy <b>eirmod</b> tempor invidunt ut labore.
HTML;
$description->setText($text);
$description->setAlign(\SetaPDF_Core_Text::ALIGN_JUSTIFY);
$description->setTextWidth(510);

$stamper->addStamp($description, array(
    'position' => \SetaPDF_Stamper::POSITION_CENTER_BOTTOM,
    'translateY' => 50
));

// stamp the document
$stamper->stamp();

// save and send it to the client
$document->save()->finish();