Skip to content

PDF A Conformance

Dragon edited this page Jun 3, 2026 · 4 revisions

PDF/A Conformance

Produce archival-grade PDF files that comply with ISO 19005 (PDF/A-2 or PDF/A-3). Call $doc->enablePdfA() before save() / output() and the library enforces all required constraints, embeds the necessary metadata and colour profile, and generates a file that passes veraPDF validation.

Enabling PDF/A

use DragonOfMercy\PhpPdf\Document;
use DragonOfMercy\PhpPdf\Font\Unit;
use DragonOfMercy\PhpPdf\PdfA\PdfALevel;

$doc = new Document(Unit::MM);
$doc->enablePdfA(PdfALevel::A2B);

// All fonts must be embedded - register a custom font family
$doc->registerFontFamily('DejaVu', 'fonts/DejaVuSans.ttf');

$page = $doc->addPage();
$page->setFont('DejaVu', 12);
$page->cell(0, 10, 'Archival document');

$doc->save('archive.pdf');

PdfALevel cases

Case Standard Description
PdfALevel::A2B ISO 19005-2, level B Basic: correct visual reproduction.
PdfALevel::A2U ISO 19005-2, level U Unicode: A-2b plus a valid ToUnicode map on every font (satisfied automatically by custom embedded fonts).
PdfALevel::A3B ISO 19005-3, level B A-2b plus support for embedded associated files (e.g. Factur-X XML).
PdfALevel::A3U ISO 19005-3, level U A-2u plus support for embedded associated files.

What enablePdfA() injects at output time

  1. Forced metadata path. The XMP packet, the /Info dictionary, and the document /ID pair are always written. Normally /ID and full XMP are optional.
  2. sRGB output intent. An [OutputIntent] array is added to the catalog referencing a bundled 588-byte littleCMS sRGB ICC profile (/OutputConditionIdentifier (sRGB IEC61966-2.1)).
  3. pdfaid XMP schema. A pdfaid:part (2 or 3) and pdfaid:conformance (B or U) block is prepended to the XMP packet.

The PDF version header is already %PDF-1.7, satisfying the PDF/A-2 and PDF/A-3 version requirements.

Font requirement

PDF/A forbids non-embedded fonts. All standard-14 fonts (Helvetica, Times, Courier, etc.) are not embedded and will cause a conformance guard error. Register every font via Document::registerFontFamily() before using it.

$doc->enablePdfA(PdfALevel::A2B);

// Register and use a custom embedded font
$doc->registerFontFamily('OpenSans', 'fonts/OpenSans-Regular.ttf', 'fonts/OpenSans-Bold.ttf');
$page->setFont('OpenSans', 12);

PDF/A-2u and A-3u require a valid ToUnicode CMap on every font. Custom embedded fonts already carry /ToUnicode streams produced during subsetting, so the U variant is essentially free.

Guards that throw

PdfAConformanceGuard is called by output() before serialization. It throws a PdfException in any of these cases:

Condition Error
A non-embedded standard font (Helvetica, Times, Courier, etc.) is in use. Register all fonts with registerFontFamily().
Encryption is configured on the same document. PDF/A forbids encryption.
Document JavaScript (addDocumentScript()) is present. PDF/A forbids embedded scripts.
Appended revisions (addSignature(), addDocumentTimestamp(), enableLtv()) are present. PDF/A forbids incremental updates of this kind.

Additionally, calling attachFile() on a document configured for PDF/A-2 (part 2) throws immediately because embedded associated files are only permitted at part 3.

Associated files (PDF/A-3 only)

PDF/A-3 allows embedding machine-readable files alongside the human-readable PDF. The most common use case is a Factur-X or ZUGFeRD e-invoice XML.

use DragonOfMercy\PhpPdf\PdfA\AFRelationship;

$doc->enablePdfA(PdfALevel::A3B);

$xml = file_get_contents('factur-x.xml');
$doc->attachFile(
    $xml,
    'factur-x.xml',
    AFRelationship::Data,
    'text/xml',
    'Factur-X invoice data',
);
$doc->save('invoice-pdfa3.pdf');

Document::attachFile() parameters

Parameter Type Default Description
$bytes string - Raw file content.
$name string - Filename (used as the key in the /EmbeddedFiles name tree and as /F / /UF).
$relationship AFRelationship Data Semantic relationship of the file to the document.
$mime string 'application/octet-stream' MIME type of the embedded file.
$description string|null null Optional human-readable description.
$modDate DateTimeImmutable|null now Modification date. Pass explicitly for deterministic output.

AFRelationship cases

Case PDF name Typical use
AFRelationship::Source Source File from which this PDF was generated.
AFRelationship::Data Data Machine-readable data represented in the PDF (Factur-X default).
AFRelationship::Alternative Alternative Alternative representation of the document content.
AFRelationship::Supplement Supplement Supplementary material.
AFRelationship::Unspecified Unspecified Relationship not specified.

Attachments work on documents without enablePdfA() as well; in that case they are plain PDF attachments with no conformance restriction.

Validation

The library ships a golden test (tests/Golden/PdfA2ConformanceTest.php) that pipes the rendered output through veraPDF --flavour 2b|2u|3b and asserts isCompliant="true". The test auto-skips when a JRE or the veraPDF CLI jar are absent. Run it with:

cd build/
vendor/bin/phpunit tests/Golden/PdfA2ConformanceTest.php

See also

Clone this wiki locally