pdftoolkit / opentype
Pure-object OpenType metadata, variable outlines, metrics, substitutions and glyph positioning
Requires
- php: ^8.3
- php-64bit: *
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-15 19:18:53 UTC
README
English | Français
Pure-object OpenType metadata, variable outlines, metrics and layout for PHP 8.3+.
OpenType belongs to PDFToolkit, while remaining
independent of PDF: installing pdftoolkit/opentype installs no PDF package.
Its names and structures follow the OpenType 1.9.1 specification.
Read individual TrueType/OTTO fonts, multilingual metadata and horizontal/vertical metrics; normalize user axes, evaluate variable metrics, assemble quadratic TrueType outlines and execute cubic CFF/CFF2 programs. GSUB substitutions and GPOS positioning use immutable script, language, feature, lookup, anchor and variation objects. Applications explicitly select instances and execution policies. There is no global registry or hidden file access.
composer require 'pdftoolkit/opentype:^0.3'
PHP 8.3 or newer and a 64-bit platform are required. There are no runtime package or extension dependencies. CI validates PHP 8.3, 8.4 and 8.5.
Follow the objects
use PDFToolkit\OpenType\Cmap\UnicodeCmapReader; use PDFToolkit\OpenType\Sfnt\SfntReader; use PDFToolkit\OpenType\Substitution\FeatureSelection; use PDFToolkit\OpenType\Substitution\GlyphSequence; use PDFToolkit\OpenType\Substitution\GsubReader; use PDFToolkit\OpenType\Substitution\SubstitutionEngine; use PDFToolkit\OpenType\Value\CodePoint; use PDFToolkit\OpenType\Value\Tag; // The application supplies bytes; the library does not open a file. $font = (new SfntReader())->read($fontBytes); $cmap = (new UnicodeCmapReader())->read($font->table(new Tag('cmap')), $font->glyphCount()); $input = new GlyphSequence([ $cmap->glyphFor(new CodePoint(0x66)), // f $cmap->glyphFor(new CodePoint(0x66)), // f $cmap->glyphFor(new CodePoint(0x69)), // i ]); $gsub = (new GsubReader())->read($font->table(new Tag('GSUB')), $font->glyphCount()); $selection = new FeatureSelection(new Tag('latn'), features: [new Tag('liga')]); $result = (new SubstitutionEngine())->apply($gsub, $selection, $input);
The character map first maps Unicode scalars to this font's glyph IDs. The GSUB
reader constructs its layout tables. The engine selects the language system and
features, applies their lookups and returns a new glyph sequence. An ffi
ligature is produced only if the font and selection define it. Source clusters
remain available for subsequent text handling.
Guides follow each object contract:
- Substitutions and positioning.
- User axes, variable metrics, names and OS/2, headers and styles.
- TrueType outlines, gvar/cvar and phantom metrics, CFF/CFF2 outlines, precomputed device metrics.
The architecture, coverage, security policy and shared documentation describe the boundaries. API pages are generated from the exact published source.
Scope of 0.3
| Mechanism | Implementation |
|---|---|
| Individual SFNT and cmap | TrueType/OTTO directories, checksums, Unicode 4/12/14 mappings |
| Metadata | Complete head/hhea/maxp/post, name 0/1, OS/2 0–5 and STAT 1.0–1.2 records |
| Axes and metrics | fvar/avar 1.0 normalization, horizontal/vertical metrics, native HVAR/VVAR/MVAR |
| TrueType geometry | Bounded loca/glyf decoding, composite assembly, quadratic paths, native gvar/cvar and explicit phantom metrics |
| CFF/CFF2 geometry | Bounded Type 2 programs and subroutines, cubic paths, explicit matrices, encodings and native blends |
| Layout | GSUB 1–8, GDEF, GPOS 1–9, all contextual formats, native variations and Device corrections |
| Device declarations | gasp recommendations, hdmx widths, LTSH thresholds and VDMX heights with explicit selection |
The coverage inventory identifies 27 implemented table scopes, 4 partial tables and 19 pending tables. TrueType instruction execution, CFF hint application, color/bitmap/baseline/math/justification tables, legacy auxiliary tables, collections, WOFF/WOFF2, writing and subsetting remain absent. Executing an unhinted outline or metric instance does not write a static font. Preserved bytes do not establish semantic support.
The layout engines consume an already ordered glyph sequence. Complete Unicode
shaping, bidirectional layout and rasterization need separate consumers. PDF
embedding and HTML conversion retain their own explicit format contracts. The
0.x API may evolve between minor releases.
The supplied Adobe OTGuide.pdf is retained unchanged as a usage reference. Its original name, 13 pages and SHA-256 are recorded alongside it. Technical definitions use the official specification. The guide retains its original rights; MIT applies to the package code. The PDF and development fixtures are excluded from Composer distributions.
Development
composer install composer check php examples/substitution.php php examples/manual-ligature.php php examples/font-metrics.php php examples/positioning.php php examples/variable-layout.php php examples/variable-outlines.php
The example uses a reproducible font authored for the tests and prints its glyph
substitutions. Independent validators live in tools/.
Release notes record each published version.