mattsplat / declarative-pdf
A typed, declarative PDF generation library with a block-layout engine.
Requires
- php: >=8.3
- ext-mbstring: *
- ext-zlib: *
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
Suggests
- ext-curl: Fallback for fetching image URLs when allow_url_fopen is disabled
- ext-gd: Needed to decode GIF and WebP images
- ext-iconv: Faster text encoding conversion
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-01 03:45:27 UTC
README
A reimagining of FPDF as a typed, declarative PDF library with a real
block-layout engine. Instead of driving a cursor (AddPage / SetFont /
Cell / Ln), you describe the document as an immutable tree of nodes and a
measure → paginate → render → serialise pipeline places everything.
Zero runtime dependencies beyond ext-zlib and ext-mbstring.
use Pdf\Document; use Pdf\Style\StylePatch; use Pdf\Style\TextAlign; Document::create() ->meta(fn ($m) => $m->title('Report')->author('Jo')) ->page(fn ($p) => $p ->heading(1, 'Overview') ->paragraph('A paragraph that wraps automatically across lines.') ->paragraph('Justified body text.', new StylePatch(align: TextAlign::Justify))) ->save('out.pdf');
The immutable Pdf\Node\* tree is public too, for when you want to build or
transform it directly — see Getting started.
Gallery
Rendered by the scripts in examples/ — php examples/<name>.php.
Install
composer require mattsplat/declarative-pdf
Requires PHP 8.3+ with ext-zlib and ext-mbstring. ext-gd is needed to
decode GIF and WebP images; ext-iconv for font encodings other than
Windows-1252.
Features
- Layout engine — greedy line breaking with justification, box-model pagination (split / keep-together / keep-with-next / widow–orphan), explicit page breaks, header and footer closures with a real total page count.
- Text — UTF-8 in, transcoded per font; inline bold / italic / underline /
strike / super- and subscript / links / hard breaks / inline images; inline
HTML (
b i u s sup sub a br). - Style — inheritance, per-node-type stylesheet rules, named class rules,
a sparse
StylePatchfor per-node overrides. - Fonts — the 14 core fonts; embedded TrueType (subsetted) and OpenType/CFF;
named and numeric weights via
FontFace. - Tables — automatic column sizing (auto / fixed / fraction), repeating headers across pages, row and cell splitting, colspans, per-cell alignment and background.
- Images — JPEG, PNG (with soft mask), GIF, WebP — from a path, an
http(s)://URL or adata:URI; block or inline. - Vector drawing —
Pathwith Bézier segments, solid or gradient fills (axial and radial/Shading), stroke, fill rules, caps and joins;Clipto an arbitrary path. - Charts — a thin
Chartnode over the path API: bar, line, pie, sparkline with a nice-number axis and legends. - Interactive forms — text / checkbox / radio / dropdown / list box /
button / signature fields as
/AcroFormwith self-drawn appearance streams (no/NeedAppearances); native submit / reset; an opt-in Acrobat JavaScript layer (calculations, formatting, validation). - Navigation & structure — internal and external links, a bookmark outline,
large-format sheets, absolute-area layout (
place/placeImage/placePdf/framewithFit,BoxAlign,ShrinkMode). - PDF import — a pure-PHP reader for trusted, unencrypted PDFs; one page imported as a vector Form XObject.
- Deterministic — with a fixed clock,
compress: falseand a fixed producer string the output is byte-stable; the golden-file tests depend on it.
Documentation — docs/
| Getting started | install, first document, output destinations, determinism |
| Cookbook | task-oriented recipes for every feature |
| API reference | every builder method, node, style option, enum |
| Architecture | the pipeline, the box model, what was ported |
| Roadmap | what is planned, sized and prioritised |
| FPDF vs. declarative | the seven FPDF tutorials, side by side |
| Comparison | vs. FPDF / TCPDF / tc-lib-pdf / PDFBlocks — feature matrix, trade-offs |
| Interactive forms | AcroForm fields and the JavaScript caveat |
Not yet implemented — see the roadmap: CFF font subsetting, tagged PDF / PDF-A, XMP metadata, encryption, full document-to-document merge, FDF / XFDF, dash arrays.
Development
composer install composer check # phpstan (level 6) + phpunit composer test # phpunit only composer stan # phpstan only for f in examples/*.php; do php "$f"; done # render every example UPDATE_GOLDENS=1 composer test # regenerate golden PDFs after an intended change
CI runs PHPStan + PHPUnit on PHP 8.3 and 8.4, plus a job that renders every
example and runs qpdf --check / pdftotext on the output. See
CONTRIBUTING.md.
Embedded fonts
tools/makefont/ is FPDF's offline builder for custom-font definitions:
php tools/makefont/makefont.php MyFont.ttf cp1252 # -> MyFont.json (+ MyFont.z); then: # $fonts->register('MyFont', FontFace::regular(), 'MyFont.json'); php tools/makefont/makefont.php MyFont.otf cp1252 # PostScript (CFF) outlines -> MyFont.json (+ MyFont.cff.z), embedded whole
Licence & attribution
MIT (LICENSE). This is a from-scratch reimagining of FPDF 1.9 —
the high-level API and layout engine are original; the byte-level PDF writer,
font metrics / embedding, ToUnicode CMaps and image decoders were ported from
FPDF (source comments citing fpdf.php:NNN refer to that release). FPDF's
permissive licence and the SIL Open Font License covering the bundled test /
example fonts are reproduced in NOTICE.





