Modules · Docs · 0.15

PDF::Make

PDF generation, parsing and editing, in XS, from a template or a page at a time.

Three layers over one C core: a template and a hash of data, for a document someone else lays out, a chainable builder that wraps text and keeps track of pages, and the objects and operators of the PDF specification for everything else. It reads PDFs as well as writing them, and its only dependency is Object::Proto.

use PDF::Make::Markup::Render;

my $data = {
    company => { name => 'Smith & Sons <Ltd>' },     # escaped, never markup
    invoice => {
        number => 'INV-0042', due => '1 November 2026', total => 1234.5,
        lines  => [ { name => 'Design',  total => 900 },
                    { name => 'Hosting', total => 334.5 } ],
    },
};

my $pdf = PDF::Make::Markup::Render->render(<<'TPL', $data);
<doc page-size="A4" margin="48">
  <style h1="size:22;line-height:26" text="size:10" />
  <header>{% company.name %}</header>
  <h1>Invoice {% invoice.number %}</h1>
  <text>Payment due {% invoice.due %}</text>
  <table>
    <tr><th weight="4">Description</th><th align="right">Amount</th></tr>
    {% for l in invoice.lines %}
    <tr><td>{% l.name %}</td><td align="right">{% l.total | money %}</td></tr>
    {% end %}
  </table>
  <hr />
  <text align="right" size="12">Total due: <b>{% invoice.total | money %}</b></text>
</doc>
TPL

open my $fh, '>:raw', $ARGV[0] // 'invoice.pdf' or die $!;
print {$fh} $pdf;

What you get

  • A template and data

    PDF::Make::Markup::Render takes markup and a hash. The template is Template::Stencil, every value is escaped, raw is refused and the filters are a fixed list, so a template from a customer cannot become markup.

  • A builder

    PDF::Make::Builder chains pages, headings, wrapped text, images, shapes, tables, headers and footers, a table of contents and an outline, and does the coordinates and the font metrics.

  • The specification itself

    Document, Page and Canvas give every content-stream operator and the object graph, for when a document is a program.

  • Read and edit

    Parse an existing PDF, read its pages, extract text, tables, annotations and form values, and import pages into a new one.

  • Forms, layers and tags

    AcroForm fields, optional-content layers, attachments, colour spaces, TrueType fonts subset as they embed, and a structure tree for tagged, accessible PDF.

  • Signed, sealed and redacted

    RC4 and AES encryption, digital signatures, watermarks and stamps, redaction that removes the content and not only covers it, and linearisation for Fast Web View.

In use

use PDF::Make::Builder;

# the chainable layer: pages, text that wraps, shapes and an outline
PDF::Make::Builder->new(file_name => $ARGV[0] // 'report.pdf')
    ->add_page(page_size => 'A4')
    ->title('Quarterly Report')
    ->author('Jane Smith')
    ->add_h1(text => 'Q4 Results')
    ->add_text(text => 'Revenue increased 15% year-over-year, '
                     . 'and this sentence wraps to the width of the page by itself.')
    ->add_line(x => 72, ex => 523)
    ->add_outline('Q4 Results', page => 0)
    ->save;

The sample, as it comes out

The first page of the invoice the sample above makes: a header, Invoice INV-0042, a table of two lines and a total due of 1,234.50.

The first sample, run as it stands, makes this 2 KB PDF. The company name came in as Smith & Sons <Ltd> and went out as text, not as markup.

Get it

cpanm PDF::Make