Skip to content

Text and Fonts

Dragon edited this page Jun 3, 2026 · 1 revision

Text and Fonts

This page covers everything related to placing text on a page: selecting a font, changing its size, writing strings and multi-line blocks, registering custom TTF/OTF families, and measuring string widths. Use these features whenever you need freeform text outside a cell flow.

Setting fonts

Font size is always in points, regardless of the document unit. Every page created via addPage() starts with Helvetica 11 already set, so you only need to call setFont() when you want something different.

use DragonOfMercy\PhpPdf\Font;

// Switch to Helvetica Bold 18 pt.
$page->setFont(Font::helvetica()->bold(), 18);
$page->text(20, 30, 'Hello World');     // coordinates in the document unit (mm by default)

// Times Italic 12 pt.
$page->setFont(Font::times()->italic(), 12);
$page->text(20, 50, 'Resume - cafe, naivete, oeuvre');

// Courier Regular 10 pt.
$page->setFont(Font::courier(), 10);
$page->text(20, 70, "Line 1\nLine 2\nLine 3");

// Change family/variant while keeping the current size (omit the size argument).
$page->setFont(Font::helvetica()->bold()); // still 10 pt

// Change only the size, keeping the current family and variant.
$page->setFontSize(24);

// Save and restore font state.
$savedFont = $page->getFont();
$savedSize = $page->getFontSize();

Standard font factories

The twelve built-in PDF fonts are available through three static factories on Font. All support ->bold() and ->italic() chaining, and both can be combined.

Factory Variants available
Font::helvetica() regular, bold, italic, bold-italic
Font::times() regular, bold, italic, bold-italic
Font::courier() regular, bold, italic, bold-italic

Standard fonts use WinAnsi encoding, which covers Western European characters. For full Unicode coverage register a custom font family (see below).

API reference

Method Description
setFont(Font $font, float $size = null) Set the active font; size in points, optional when a font is already set
setFontSize(float $size) Change only the size (points), keeping the current family and variant
getFont(): Font Return the currently active Font instance
getFontSize(): float Return the currently active size in points

Placing text

text(x, y, string) places a string at the given coordinates (in the document unit). Newline characters \n produce multi-line output; line height is driven by the current leading.

$page->setFont(Font::courier(), 10);
$page->text(20, 70, "Line 1\nLine 2\nLine 3");

Coordinates mark the baseline of the first line, measured from the top-left corner of the page. The Y axis is top-down.

Custom TTF / OTF fonts

Beyond the twelve built-in fonts you can register TrueType (.ttf) and OpenType/CFF (.otf, OTTO) families on the document. Each registration declares a family alias and up to four variant files.

use DragonOfMercy\PhpPdf\{Document, Font};

$pdf = new Document();
$pdf->registerFontFamily('Inter',
    regular:    __DIR__ . '/fonts/Inter.ttf',
    bold:       __DIR__ . '/fonts/Inter-Bold.ttf',
);

$page = $pdf->addPage();
$page->setFont(Font::custom('Inter'), 14);
$page->text(50, 50, 'Resume, cafe, naivete, oeuvre'); // Latin
$page->text(50, 70, "\u{0391} \u{0392} \u{0393} \u{0394}"); // Greek: Alpha Beta Gamma Delta
$page->text(50, 90, "\u{041C}\u{043E}\u{0441}\u{043A}\u{0432}\u{0430}"); // Cyrillic: Moscow

$page->setFont(Font::custom('Inter')->bold(), 14);
$page->text(50, 110, 'Bold variant');

$pdf->save('out.pdf');

Font::custom('alias') mirrors the standard factories and supports the same chaining: ->bold(), ->italic(), or both combined.

Variant fallback chain

When a requested style is not registered, the library falls back in this order:

Requested Fallback order
->bold()->italic() boldItalic > bold > italic > regular
->bold() bold > regular
->italic() italic > regular
(plain) regular (always required)

Registration behaviour

  • registerFontFamily() parses each font file eagerly: missing files, unsupported flavours, malformed tables, and missing required tables raise PdfException immediately at registration time - not later during page rendering.
  • Each alias maps to exactly one family. Registering an alias that is already registered raises PdfException. Register a family once, with all its variants in a single call.
  • Glyphs are automatically subsetted to those actually used in the document, so even multi-megabyte CJK families produce small PDFs.

Supported scripts and formats

  • TrueType outlines (.ttf) and OpenType / CFF outlines (.otf, OTTO).
  • Full Unicode coverage, including supplementary planes.
  • Left-to-right scripts: Latin, Greek, Cyrillic, and others. Copy-paste from the rendered PDF works correctly.

Not supported (out of scope)

  • TrueType Collection (.ttc).
  • Variable fonts.
  • Kerning, ligatures, and complex shaping (GPOS / GSUB).
  • Right-to-left scripts, Arabic, Indic, and other scripts requiring shaping.
  • Vertical writing.

Text measurement

stringWidth() returns the rendered width of a string in the document unit at the current font and size. Useful for computing positions or deciding whether text needs wrapping.

$page->setFont(Font::helvetica(), 12);
$width = $page->stringWidth('Hello'); // ~9.64 mm, or ~27.34 in PT mode

The result changes whenever the active font or font size changes, so call stringWidth() after setFont() / setFontSize().

See also

Clone this wiki locally