Use font writers
Writers keep the selected face and change its output container. They do not reduce the character or glyph set. Use Create a font subset first when the output should contain fewer glyphs.
The examples assume Composer's autoloader is loaded, a source font exists at
fonts/Inter-Regular.ttf, and output exists. Run the first example with the
PHP Brotli extension installed; it creates three new font files and prints
nothing. Use Convert a font for a complete first script.
Write SFNT, WOFF, and WOFF2
<?php
use Alto\Font\Compression\BrotliExtensionCompressor;
use Alto\Font\Font;
use Alto\Font\Writer\SfntWriter;
use Alto\Font\Writer\Woff2Writer;
use Alto\Font\Writer\WoffWriter;
$font = Font::fromFile(__DIR__.'/fonts/Inter-Regular.ttf');
new SfntWriter()->write($font, __DIR__.'/output/inter.ttf');
new WoffWriter()->write($font, __DIR__.'/output/inter.woff');
new Woff2Writer(new BrotliExtensionCompressor())->write(
$font,
__DIR__.'/output/inter.woff2',
);The output directory must exist. Writers create a new file exclusively and never replace an existing path. A partial file is removed if writing fails.
Return bytes instead of writing a file
Every writer provides dump():
<?php
use Alto\Font\Compression\BrotliExtensionCompressor;
use Alto\Font\Writer\SfntWriter;
use Alto\Font\Writer\Woff2Writer;
use Alto\Font\Writer\WoffWriter;
$sfntBytes = new SfntWriter()->dump($font);
$woffBytes = new WoffWriter()->dump($font);
$woff2Bytes = new Woff2Writer(
new BrotliExtensionCompressor(),
)->dump($font);dump() materializes the complete output as one string. Use it for storage
APIs that accept bytes. Use write() for an exclusive filesystem destination.
Font::toSfnt() is the direct convenience API for in-memory SFNT output.
Extract a collection face
<?php
$font = Font::fromFile(__DIR__.'/fonts/Collection.ttc', faceIndex: 1);
new SfntWriter()->write($font, __DIR__.'/output/selected-face.ttf');A selected TTC or OTC face is always written as a standalone font.
Writer contracts
SfntWriter, WoffWriter, and Woff2Writer belong to Alto\Font\Writer.
They expose the same two methods:
| Signature | Result and side effects |
|---|---|
dump(Font $font): string |
Return all output bytes in memory. No output file is created. Compression adapters may use temporary resources. |
write(Font $font, string|Stringable $file): void |
Write a new local file. Its parent directory must exist; an existing destination is never replaced. |
SfntWriter and WoffWriter need no constructor arguments.
Woff2Writer requires a BrotliCompressorInterface; see
WOFF2 compression for the available adapters.
Understand reconstruction
| Source and target | Result |
|---|---|
| Unchanged standalone SFNT to SFNT | Preserved byte-for-byte |
| Collection face to SFNT | Standalone face with rebuilt directory and checksums |
| WOFF or WOFF2 to SFNT | Reconstructed standalone SFNT |
| Any supported face to WOFF | Each table uses Zlib level 6 only when compression makes it smaller |
| Any supported face to WOFF2 | Tables transformed when supported, then Brotli-compressed |
WOFF and WOFF2 container metadata and private-data blocks are not preserved
when a webfont is decoded and written again. WOFF and WOFF2 output remove
DSIG. WOFF2 output also updates required head.flags and may reconstruct
glyf, loca, and hmtx canonically. Rebuilt output is structurally
equivalent, not necessarily byte-for-byte identical.
Handle failures
| Exception | Meaning |
|---|---|
FontWriteException |
The destination is empty, exists already, or cannot be written |
CompressionException |
Zlib or Brotli compression, support, or temporary streams failed |
UnsupportedFontException |
The requested view or font feature cannot be written |
InvalidFontException |
Required source tables are malformed or inconsistent |
These exceptions implement FontExceptionInterface. A selected variable view
created with withVariations() cannot be written as a static font.
See WOFF2 compression for Brotli configuration and memory behavior.
Create the destination directory before writing and choose a new filename for a rerun: writers do not create directories or overwrite files. For compression or temporary-storage failures, check the WOFF2 runtime.
A selected variable view is read-only. Use withoutVariations() to write the
original variable font with all its axes, or supply a static source font when
you need a fixed-weight file. See Variable fonts.