Skip to content

Commit fb9600a

Browse files
nicolaasuniCopilot
andcommitted
added PDF/A documentation and extra notes
Co-authored-by: Copilot <copilot@github.com>
1 parent dac5cc6 commit fb9600a

3 files changed

Lines changed: 68 additions & 25 deletions

File tree

README.md

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ If this project is useful to you, please consider [supporting development via Gi
2727
- [PDF Import](#pdf-import)
2828
- [Remote Resources and fileOptions](#remote-resources-and-fileoptions)
2929
- [Digital Signatures](#digital-signatures)
30+
- [PDF/A Archival](#pdfa-archival)
3031
- [PDF/X Conformance](#pdfx-conformance)
3132
- [PDF/UA Accessibility](#pdfua-accessibility)
3233
- [Development](#development)
@@ -121,7 +122,7 @@ The fastest way to evaluate the library is to follow the installation and font s
121122
- each feature (OCSP, CRL, cert embedding, DSS, VRI) can be enabled independently via `setSignature()` LTV options
122123
- **PDF annotations**: links, text notes, file attachments, markup, shapes, media, and widgets
123124
- **JavaScript** embedding
124-
- **PDF/A** (1/2/3, including a/b/u conformance levels) — see [Factur-X / ZUGFeRD](#other) below
125+
- **PDF/A** (1/2/3, including a/b/u conformance levels) — see [PDF/A Archival](#pdfa-archival) section and [E001_invoice.php](examples/E001_invoice.php) for a Factur-X / ZUGFeRD example
125126
- **PDF/X** (generic alias, PDF/X-1a, PDF/X-3, PDF/X-4, PDF/X-5) — print-exchange conformance: per-variant OutputIntent identifiers, GTS_PDFXVersion in Info dict and XMP, PDF version enforcement, CMYK color forcing for restrictive profiles (X-1a, X-3), transparency restrictions, and suppression of encryption and JavaScript
126127
- **PDF/UA** (generic alias, PDF/UA-1, PDF/UA-2) — accessibility conformance: tagged structure tree (`StructTreeRoot` / `ParentTree`), `MarkInfo /Marked true`, document language (`/Lang`), `DisplayDocTitle true`, `ActualText` for ligatures and special glyphs, figure alt-text tagging, and heading-level clamping to prevent skipped levels; PDF/UA-2 targets PDF 2.0
127128

@@ -210,6 +211,14 @@ composer update
210211
composer require ...
211212
```
212213

214+
To also cover `composer dump-autoload` (used in many CI pipelines), add the hook to `post-autoload-dump` as well:
215+
216+
```json
217+
"post-autoload-dump": [
218+
"@tc-lib-pdf-fonts"
219+
]
220+
```
221+
213222
If you prefer to generate fonts manually, run the build in the `tc-lib-pdf-font` package:
214223

215224
```bash
@@ -256,7 +265,12 @@ $pdf->page->addContent($bfont['out']);
256265

257266
$html = '<h1>Hello, PDF!</h1><p>Generated with tc-lib-pdf.</p>';
258267

259-
$pdf->addHTMLCell($html, 15, 20, 180);
268+
$pdf->addHTMLCell(
269+
html: $html,
270+
posx: 15, // mm from left page edge
271+
posy: 20, // mm from top page edge
272+
width: 180, // mm wide (0 = to right margin)
273+
);
260274

261275
$rawpdf = $pdf->getOutPDFString();
262276

@@ -265,6 +279,8 @@ $pdf->renderPDF($rawpdf);
265279

266280
`getOutPDFString()` returns the raw PDF bytes. `renderPDF()` streams those bytes to the browser; if you need file storage or an email attachment, keep the returned string and write or hand it off yourself.
267281

282+
> **Note:** `realpath()` returns `false` when the fonts directory does not yet exist. If you see `K_PATH_FONTS` errors on first run, verify that fonts were generated after `composer install` (see [Font Setup](#font-setup)).
283+
268284
For more complete examples — including invoices, images, barcodes, HTML tables, dedicated HTML selector/form/table showcases, PDF/X, and PDF/UA — see the [examples](examples) directory.
269285
Annotation-focused runnable example: [examples/E027_annotations.php](examples/E027_annotations.php).
270286

@@ -334,17 +350,6 @@ $tpl = $pdf->addPageFromImport($sourceId, 2);
334350
- Full document append: [examples/E066_import_document_append.php](examples/E066_import_document_append.php)
335351
- Advanced N-up composition from imported pages: [examples/E067_import_page_region_nup.php](examples/E067_import_page_region_nup.php)
336352

337-
### Migrating from FPDI-style workflows
338-
339-
If you are migrating legacy FPDI-like code paths, map concepts to the native API as follows:
340-
341-
- `setSourceFile()` -> `setImportSourceFile()` + `getSourcePageCount()`
342-
- `importPage()` -> `importPage()` (returns a typed `PageTemplate` value object)
343-
- `useTemplate()` -> `useImportedPage()`
344-
- manual page-loop append flows -> `appendDocument()`
345-
346-
Unlike FPDI numeric template IDs, `tc-lib-pdf` returns typed `PageTemplate` objects and keeps import behavior inside the same library stack (`tc-lib-*`) without external importer dependencies.
347-
348353
### Import limitations and fidelity notes
349354

350355
- Form and annotation semantics are not merged into editable destination structures; pages are imported as Form XObjects.
@@ -486,19 +491,57 @@ openssl pkcs12 -export -in tcpdf.crt -inkey tcpdf.key -out tcpdf.p12
486491

487492
---
488493

494+
## PDF/A Archival
495+
496+
`tc-lib-pdf` supports PDF/A output for long-term archival workflows (ISO 19005). Pass the mode string as the `mode` argument to the `Tcpdf` constructor:
497+
498+
```php
499+
// PDF/A-1b (default conformance level when suffix is omitted)
500+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa1');
501+
502+
// Explicit conformance levels
503+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa1a'); // PDF/A-1a
504+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa1b'); // PDF/A-1b
505+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa2a'); // PDF/A-2a
506+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa2b'); // PDF/A-2b
507+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa2u'); // PDF/A-2u
508+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa3a'); // PDF/A-3a
509+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa3b'); // PDF/A-3b
510+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa3u'); // PDF/A-3u
511+
```
512+
513+
| Mode suffix | Conformance | Unicode ToUnicode | Tagged structure |
514+
|-------------|-------------|-------------------|------------------|
515+
| `a` | Level A | required | required |
516+
| `b` | Level B | required | not required |
517+
| `u` | Level U (parts 2/3 only) | required | not required |
518+
519+
PDF/A-3 supports embedding arbitrary file attachments (for example XML invoice payloads). This is the basis for **Factur-X / ZUGFeRD** workflows — embed the structured XML in a PDF/A-3 document and register the relationship via XMP metadata:
520+
521+
```php
522+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfa3');
523+
// ... build document ...
524+
$pdf->Annotation(/* file attachment annotation pointing to the XML */);
525+
$pdf->setCustomXMP('x:xmpmeta.rdf:RDF.rdf:Description.pdfaExtension:schemas.rdf:Bag', $xmpBag);
526+
```
527+
528+
Runnable example (invoice with embedded Factur-X XML): [examples/E001_invoice.php](examples/E001_invoice.php).
529+
530+
---
531+
489532
## PDF/X Conformance
490533

491-
`tc-lib-pdf` supports multiple PDF/X profiles for print-exchange workflows. Pass the mode string as the fifth argument to the `Tcpdf` constructor:
534+
`tc-lib-pdf` supports multiple PDF/X profiles for print-exchange workflows. Pass the mode string as the `mode` argument to the `Tcpdf` constructor:
492535

493536
```php
494537
// Generic PDF/X alias (maps to the library's baseline print-exchange workflow)
495-
$pdf = new \Com\Tecnick\Pdf\Tcpdf('mm', true, false, true, 'pdfx');
538+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfx');
496539

497540
// Specific variants
498-
$pdf = new \Com\Tecnick\Pdf\Tcpdf('mm', true, false, true, 'pdfx1a'); // PDF/X-1a:2003
499-
$pdf = new \Com\Tecnick\Pdf\Tcpdf('mm', true, false, true, 'pdfx3'); // PDF/X-3:2003
500-
$pdf = new \Com\Tecnick\Pdf\Tcpdf('mm', true, false, true, 'pdfx4'); // PDF/X-4:2010
501-
$pdf = new \Com\Tecnick\Pdf\Tcpdf('mm', true, false, true, 'pdfx5'); // PDF/X-5g:2010
541+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfx1a'); // PDF/X-1a:2003
542+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfx3'); // PDF/X-3:2003
543+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfx4'); // PDF/X-4:2010
544+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfx5'); // PDF/X-5g:2010
502545
```
503546

504547
Each variant automatically applies the appropriate conformance constraints:
@@ -518,15 +561,15 @@ Runnable examples: [examples/E010_pdfx.php](examples/E010_pdfx.php) through [exa
518561

519562
## PDF/UA Accessibility
520563

521-
`tc-lib-pdf` supports tagged PDF output conforming to PDF/UA (ISO 14289). Pass the mode string as the fifth argument to the `Tcpdf` constructor:
564+
`tc-lib-pdf` supports tagged PDF output conforming to PDF/UA (ISO 14289). Pass the mode string as the `mode` argument to the `Tcpdf` constructor:
522565

523566
```php
524567
// Generic PDF/UA alias
525-
$pdf = new \Com\Tecnick\Pdf\Tcpdf('mm', true, false, true, 'pdfua');
568+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfua');
526569

527570
// Specific parts
528-
$pdf = new \Com\Tecnick\Pdf\Tcpdf('mm', true, false, true, 'pdfua1'); // PDF/UA-1 (PDF 1.7)
529-
$pdf = new \Com\Tecnick\Pdf\Tcpdf('mm', true, false, true, 'pdfua2'); // PDF/UA-2 (PDF 2.0)
571+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfua1'); // PDF/UA-1 (PDF 1.7)
572+
$pdf = new \Com\Tecnick\Pdf\Tcpdf(mode: 'pdfua2'); // PDF/UA-2 (PDF 2.0)
530573
```
531574

532575
When a PDF/UA mode is active the library automatically:

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8.12.0
1+
8.12.1

src/Base.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ abstract class Base
190190
/**
191191
* TCPDF version.
192192
*/
193-
protected string $version = '8.12.0';
193+
protected string $version = '8.12.1';
194194

195195
/**
196196
* Time is seconds since EPOCH when the document was created.

0 commit comments

Comments
 (0)