Search by

An explicit object model and writer for ISO 32000-1 PDF 1.7

v0.5.5 2026-10-14 07:17 UTC

This package is not auto-updated.

Last update: 2026-10-14 07:27:29 UTC


README

English | Français

An explicit object model of PDF 1.7 / ISO 32000-1:2008, for PHP 8.3 or newer.

This library represents the format's syntax and structures down to names, numbers, references, dictionary entries and operators. It does not provide a layout API. A higher-level library can construct these objects while retaining control over their composition.

The project belongs to the PDFToolkit organisation. This repository is the core: it contains the objects and mechanisms described by the Adobe/ISO standard, including writing. Reading external PDFs, converting PNG/JPEG files and parsing TrueType fonts belong to three optional packages. Each module depends on the core; installing the core to generate a PDF does not install any of these modules.

The online documentation brings together guides, the reference for every component and tutorials with code and viewable PDFs. It is maintained in PDFToolkit/pdftoolkit.github.io, using published versions pinned to their exact commits. Pages identify package versions and the documentation commit separately.

The 0.x series is intended for developers building and exploring this model. Before version 1.0, a new minor version may change names and signatures; patch versions preserve their series' API. Implemented scope and limitations are listed in the specification coverage.

Definitions are based on the Adobe/ISO documents PDF32000_2008.pdf and adobe_supplement_iso32000.pdf, retained in this repository. The supplement guide explains Adobe PDF 1.7 extension level 3, its provenance and mechanisms. The Adobe reference guide also presents the 2006 reference, its errata, the redaction addendum and their portfolio. All Adobe PDFs supplied to the project retain their original names and bytes; the four archived references are excluded from Composer archives. PDF 2.0 and PDF/A, PDF/X and PDF/UA profiles are additional specifications.

Installation

Core 0.5 requires PHP 8.3 or newer and the ctype, iconv and zlib extensions. AES and CMS backends are optional and require openssl. roukmoute/pdf is available on Packagist:

composer require 'roukmoute/pdf:^0.5.5'

API changes are recorded in the changelog and 0.5 migration guide. To follow development after this series, replace the stable constraint with dev-master.

Optional modules

Package Responsibility
pdftoolkit/pdf-reader Read objects and revisions from an external PDF, validate pages and inheritance, inspect their streams.
pdftoolkit/pdf-images Inspect JPEG files and decode PNG files into core image objects.
pdftoolkit/pdf-fonts Parse a static TrueType font and prepare metrics and mappings for core font objects.

Each module has a stable 0.1.6 release on Packagist, compatible with core series 0.2, 0.3, 0.4 and 0.5 and PHP 8.3 or newer. Composer automatically installs the core required by the selected module. For example, to import image files:

composer require 'pdftoolkit/pdf-images:^0.1.6'

The module installs the core using its stable constraint. The package guide explains their boundaries, installation and reader operation. Keep the application's composer.lock to pin the selected versions and commits.

Development and checks

From a repository clone:

composer install
composer check
php examples/hello-world.php hello-world.pdf
php examples/object-stream.php object-stream.pdf

Production code depends only on PHP and these three extensions. PHPUnit 12, PHPStan, PHP-CS-Fixer and modules used by examples are development dependencies locked in composer.lock. Their presence in this checkout adds no production dependencies to applications using the core. CI runs tests and validates example PDFs under PHP 8.3, 8.4 and 8.5. Tests also fail on PHP deprecations and warnings. The changelog describes every published version.

To validate this checkout, including from its tag, set COMPOSER_ROOT_VERSION=0.5.x-dev before composer install. This variable identifies the current core as part of the 0.5 series expected by modules. Development dependencies use stable 0.1 modules whose exact versions and sources are locked in composer.lock. CI also sets this variable for branches, tags and pull requests.

Object-by-object construction

$helvetica = new Type1Font(StandardFont::Helvetica);
$resources = new ResourceDictionary(
    new Font(new DictionaryType(
        new Entry(new NameType('F1'), new IndirectReference($helvetica)),
    )),
);
$contents = new StreamObject(new ContentStreams(
    new BeginTextObject(),
    new SetTextFontAndSize(new NameType('F1'), new NumericType(18)),
    new MoveTextPosition(new NumericType(72), new NumericType(720)),
    new ShowText(new LiteralString('Super !')),
    new EndTextObject(),
));
$page = new PageObject(
    new Rectangle(new NumericType(0), new NumericType(0), new NumericType(612), new NumericType(792)),
    $resources,
    $contents,
);
$pages = (new PageTreeNode())->addKid($page);
$catalog = new DocumentCatalog($pages);
$file = new FileStructure(new FileHeader('1.7'), new FileBody($catalog));
$file->writeTo('hello-world.pdf');

The complete example, with imports and metadata, is in examples/hello-world.php.

Tutorials and recipes

The tutorial path accompanies each script with an explanation, preview and variations to try. Code comments connect objects to PDF instructions and structures. Documentation is available in English and French.

Topic What the example explains
First document Font, resources, contents, page, catalog and document information.
Pages and text Resource inheritance, multiple pages, positions and leading.
Drawing Colours, paths, curves and graphics-state transformations.
Navigation Hierarchical bookmarks and destinations targeting pages.
Links Internal clickable annotations and URI actions.
Images Image XObject, inline image, RGB bytes and filters.
Gradient Type 2 PDF function and axial shading.
Compressed objects Content streams, object container and cross references.
TrueType font and Unicode Embedded program, CIDs, widths and ToUnicode mapping.
JPEG and PNG images Colours, PNG decoding, preserved JPEG data and transparency mask.
Incremental revisions Explicit replacements, preserved historical bytes and chained xrefs.

The table recipe combines these concepts in a concrete presentation. The recipe collection also explains how to contribute new examples.

Identity and responsibilities

  • PDF values are objects. Strings represent bytes; TextString explicitly encodes Unicode text.
  • An IndirectReference targets an instance. A SerializationContext assigns identifiers while writing one file. There is no singleton or global counter.
  • FileStructure describes the file; FileWriter writes it. Each write creates a fresh context and derives offsets and lengths from bytes actually emitted.
  • Dictionaries use Entry objects. with() and without() construct copies and preserve specialised model constraints.
  • Page trees and outlines use mutable graph builders with one parent and explicit references. Their structure calculates links and counts; standard definition objects are immutable.
  • Filters apply in the reverse of their decoding order. Streams are always referenced as indirect objects.

See the architecture guide for construction choices and standard coverage for traceability and limits.

The component guide explains each object family. The API reference provides signatures and links to code and the standard. The site build instructions describe generation and local checks in the documentation repository.

Coverage and limits

The catalogue records the reference's 392 tables, 823 indexed sections and 73 operator tokens. Dictionary tables produce named classes for their dictionaries, entries and immutable definitions. PDF names preserve their exact case, which is significant in the format.

Executable implementations cover fundamental objects, file writing, cross-reference tables and streams, compressed objects, content operators, page/name/number trees, destinations and outlines, standard fonts and all four PDF function representations.

The presence of a definition is not a declaration of complete conformance. The catalogue validates types, required references, unconditional requirements and certain value forms. Conditions, relationships between dictionaries and version rules that do not yet have specialised validation remain in their definitions and the coverage document.

The core composes font objects, CMaps, images and masks, forms, tagged structure and incremental revisions. It also writes filters, explicitly selected encryption, byte-range signatures, hybrid references and linearisation. Optional modules provide TrueType analysis, JPEG/PNG conversion and external PDF reading. Verified mechanisms and remaining rules are listed in the coverage inventory. Font program subsetting, complex scripts and importing an external graph with remapping require dedicated components. EncodedData explicitly declares already encoded bytes. Unsupported security requirements are rejected.

The writer currently assembles the file in memory. The reader is provided by pdftoolkit/pdf-reader. A rendering engine and layout API are outside the core.

Security

The security policy describes private reporting and trust boundaries. The security review explains serialisation protections and application responsibilities for paths, PDF actions and resource limits.

Definition generation

Structured resources and generated classes are versioned. Generation is reproducible from these resources; it does not reread the PDF at library runtime.

python tools/generate_specification.py

The tools/extract_spec.py extractor retains the source and PDF locations. It requires the Python dependencies listed in the specification documentation. Normative descriptions trace constraints still to be implemented; class generation does not replace algorithms.