Table of contents
tc-lib-pdf delegates font parsing, subsetting, embedding, and generated font data to tc-lib-pdf-font.
How the Font Stack Is Split
tc-lib-pdf: document generation, text layout, and PDF output orchestration.tc-lib-pdf-font: font loading, parsing, subsetting, embedding, and font data generation.
This package boundary keeps the core PDF engine focused and lets the font pipeline evolve independently.
Supported Font Types
The tc-lib ecosystem supports the major font classes expected in production PDF workflows:
- TrueType Unicode (UTF-8)
- OpenType Unicode (v1)
- TrueType
- OpenType (v1)
- Type1
- CID-0
- PDF core (standard) fonts
Embedding and Subsetting
Choose the embedding model based on delivery constraints and interoperability requirements:
- Full embedding: Best compatibility across readers and operating systems.
- Subsetting: Smaller output by embedding only the glyphs used in the document.
- Non-embedded usage (where applicable): Smaller files, but rendering depends on client-side font availability.
For public distribution, embedding with subsetting is usually the safest default.
Font Setup
When you install tc-lib-pdf as a dependency, the fonts from the companion tc-lib-pdf-font package must be generated before they can be used.
Composer does not execute scripts declared by dependencies, so add the font generation step to your consuming project:
{
"scripts": {
"tc-lib-pdf-fonts": [
"[ -d vendor/tecnickcom/tc-lib-pdf-font ] && make -C vendor/tecnickcom/tc-lib-pdf-font deps fonts || true"
],
"post-install-cmd": [
"@tc-lib-pdf-fonts"
],
"post-update-cmd": [
"@tc-lib-pdf-fonts"
],
"post-autoload-dump": [
"@tc-lib-pdf-fonts"
]
}
}
This covers composer install, composer update, composer require, and composer dump-autoload.
If you prefer manual generation:
make -C vendor/tecnickcom/tc-lib-pdf-font deps fonts
Generated fonts are cached under vendor/tecnickcom/tc-lib-pdf-font/target/fonts/.
The Makefile and the util/ directory are part of the distributed package, so font generation and the conversion utility work on a --prefer-dist install too.
A missing asset directory is reported as unable to read file: helvetica.json when the first page is written.
TCPDF 7.x
tecnickcom/tcpdf 7.x is a compatibility facade over tc-lib-pdf and uses the same font assets, so it needs the same generation step. Add the composer.json hook above to the project that requires TCPDF, or run the one-liner from the project root.
TCPDF resolves the installed tc-lib-pdf-font package on its own, so K_PATH_FONTS does not have to be defined. Define it only to load font assets from another directory:
require __DIR__ . '/vendor/autoload.php';
define('K_PATH_FONTS', '/opt/app/fonts/');
Custom Font Import
For a runnable end-to-end workflow, see /examples/E072_import_new_font/.
Example commands from the project root:
mkdir -p target/fonts/source target/fonts/custom
curl -fL --retry 3 -o target/fonts/source/NotoSans-Regular.ttf \
https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/NotoSans/NotoSans-Regular.ttf
php vendor/tecnickcom/tc-lib-pdf-font/util/convert.php \
--outpath=target/fonts/custom \
--type=TrueTypeUnicode \
--flags=32 \
--encoding_id=10 \
--fonts=target/fonts/source/NotoSans-Regular.ttf
--encoding_id=10 selects the full Unicode cmap subtable of the font, which is required to render characters above U+FFFF. See Unicode Text Encoding.
Then point K_PATH_FONTS to the generated directory before creating the Tcpdf instance:
\define('K_PATH_FONTS', '/opt/app/fonts/tc-lib-pdf');
For shared or immutable environments, generate fonts once into a persistent directory outside vendor/ and reuse that path across deployments.
Unicode Text Encoding
A TrueTypeUnicode font is written as a composite (Type0) font with the Identity-H encoding, so every character in a content stream is a 2-byte code. That code is the glyph index of the font (/CIDToGIDMap /Identity), and the mapping back to Unicode is carried by a /ToUnicode CMap generated for the glyphs the document uses. Text search, copy and paste, and assistive technologies read that CMap.
Consequences for a document:
- Characters above U+FFFF are rendered, given the font conversion described below.
- No
CIDToGIDMapstream is embedded. - The
.ctg.zfile of a font is read when the text is encoded, not only when the font is embedded. It must stay next to the.jsondefinition file.
Supplementary-Plane Characters
Characters outside the Basic Multilingual Plane, such as the mathematical alphanumeric symbols (U+1D400 to U+1D7FF), emoji, and the CJK extensions, are mapped by the format 12 cmap subtable of a font. That subtable is only read when the font is converted with --encoding_id=10:
php vendor/tecnickcom/tc-lib-pdf-font/util/convert.php \
--outpath=target/fonts/custom \
--type=TrueTypeUnicode \
--flags=32 \
--encoding_id=10 \
--fonts=target/fonts/source/MyFont-Regular.ttf
--encoding_id=10 is a safe default for any TrueTypeUnicode font: a font without a format 12 subtable falls back to the BMP one.
The fonts bundled with tc-lib-pdf-font are converted with --encoding_id=1 and therefore cover the BMP only. To use a supplementary-plane character, convert a font that contains it with --encoding_id=10 and point K_PATH_FONTS to the output directory.
A character with no glyph in the font is drawn as .notdef, as with any other missing character.
Font Selection and the Current Font
A string is always measured and encoded with the current font of the stack. Adding the font operator of another font to the page content does not change that, so the two must be kept in agreement:
// Wrong: the text is measured and encoded with the font that is current on the stack,
// which is $fontB here, whatever operator was added to the page.
$fontA = $pdf->font->insert($pdf->pon, 'dejavusans', 'B', 18);
$fontB = $pdf->font->insert($pdf->pon, 'dejavusans', '', 10);
$pdf->page->addContent($fontA['out']);
$pdf->page->addContent($pdf->getTextCell(txt: 'Heading', posx: 15, posy: 20, width: 180));
Make the wanted font current instead, with insert() or by cloning an already inserted one:
$fontA = $pdf->font->cloneFont($pdf->pon, $fontA['idx'], null, $fontA['size']);
$pdf->page->addContent($fontA['out']);
$pdf->page->addContent($pdf->getTextCell(txt: 'Heading', posx: 15, posy: 20, width: 180));
cloneFont() inherits the size of the current font when $size is null, so pass the size explicitly to keep the one of the cloned font. See /examples/E044_toc_index/.
With a byte font (Core, TrueType, Type1) a mismatch only affects the metrics used for layout, since the character codes mean the same thing in every font. With a TrueTypeUnicode font the codes are the glyph indices of the font that encoded them, so a mismatch would draw unrelated glyphs: a text object using such a font therefore selects it explicitly, and the current font of the stack wins over any operator previously added to the page.
Practical Guidance
- Use Unicode-capable fonts for multilingual and right-to-left text.
- Validate fallback behavior for missing glyphs early in development.
- Keep font licensing and provenance explicit in your build and release pipeline.
- Prefer persistent generated font directories when dependency reinstalls are common.
Installation References
Install the full PDF stack:
composer require tecnickcom/tc-lib-pdf
Install the font package directly when integrating font workflows in isolation:
composer require tecnickcom/tc-lib-pdf-font
Third-Party Fonts
PHP font metadata files under the fonts directory are covered by the project license (GNU LGPL v3). They can be regenerated with the built-in font utilities.
Original source files are renamed for compatibility and compressed with PHP gzcompress (.z extension) where applicable.
| Prefix | Source | License |
|---|---|---|
freefont | GNU FreeFont | GNU GPL v3 |
pdfa | tc-font-pdfa (derived from GNU FreeFont) | GNU GPL v3 |
dejavu | DejaVu Fonts 2.35 | Bitstream Vera (with DejaVu public-domain changes) |
unifont | GNU Unifont 15.1.03 | GPL v2+ with font embedding exception (also distributed under SIL OFL 1.1) |
cid0 | GNU Unifont (CID mappings) | GPL v2+ with font embedding exception |
core | Adobe Core14 AFM | Adobe copyright terms (see AFM notices) |
References
- tc-lib-pdf overview: /
- tc-lib-pdf API docs: /docs/srcdoc/tc-lib-pdf
- tc-lib-pdf-font project page: /projects/tc-lib-pdf-font/
- tc-lib-pdf-font API docs: /docs/srcdoc/tc-lib-pdf-font
Previous: /docs/cache/
Overview: /docs/
Next: /docs/development/