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::Rendertakes markup and a hash. The template is Template::Stencil, every value is escaped,rawis refused and the filters are a fixed list, so a template from a customer cannot become markup. -
A builder
PDF::Make::Builderchains 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,PageandCanvasgive 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 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.
