atelier/text

Map Unicode text to positioned font glyphs, vector outlines, and SVG documents using alto/font and atelier/svg.

Maintainers

Package info

github.com/ateliersvg/text

pkg:composer/atelier/text

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.8.0 2026-08-14 23:25 UTC

This package is auto-updated.

Last update: 2026-08-14 23:29:02 UTC


README

Turn Unicode text into positioned glyphs, vector outlines, and SVG, in PHP.

PHP Version Tests PHPUnit PHPStan Stable License

Text drawn as paths owes nothing to the fonts installed on the machine that opens it. This package reads a font file, looks each codepoint up in its cmap, positions the glyphs, and returns their outlines as SVG path data or a complete document.

echo SvgText::fromFile('Inter-Regular.woff2')->path('Hello', size: 72)->d();

Font parsing and discovery come from alto/font; document construction comes from atelier/svg. Backed by an extensive test suite and PHPStan at its highest level.

Path data · Whole documents · Choosing a font · What it does not do · Public API · Documentation

Installation

composer require atelier/text

Requires PHP 8.4 and ext-mbstring. WOFF2 files also need a Brotli decoder that alto/font supports: either ext-brotli or the brotli command-line binary. Checking which one you have, and what happens without either, is in Installation.

Quick start

use Atelier\Text\SvgText;

$path = SvgText::fromFile(__DIR__.'/fonts/Inter-Regular.woff2')
    ->path('Hello', size: 72, baselineY: 84);

echo '<svg viewBox="0 0 240 100" xmlns="http://www.w3.org/2000/svg">';
echo '<path d="'.htmlspecialchars($path->d(), \ENT_QUOTES).'" />';
echo '</svg>';

Both calls, side by side, are in Getting started.

Path data

path() returns a TextPath, whose d() is the combined outline of the whole run. That is the form to use when the text has to sit inside a drawing you are already building, or be handed to something that only speaks path data.

Letter spacing and word spacing are arguments, not post-processing. baselineY is the line the glyphs sit on rather than the top of the text, which is the one that catches people out. See Path data.

Whole documents

svg() returns an atelier/svg document instead, with one group per glyph carrying a data-char attribute.

$svg = SvgText::fromFile(__DIR__.'/fonts/Inter-Regular.woff2')
    ->svg('Hello', size: 72, idPrefix: 'headline');

echo $svg->toPrettyString();

Groups carry no id by default. Passing idPrefix makes them deterministic, which is what an animation or a stylesheet needs to address a single glyph. See SVG documents.

Choosing a font

A path is one option; a query against a directory of fonts is the other.

use Alto\Font\FontFinder;
use Alto\Font\FontQuery;
use Atelier\Text\SvgText;

$finder = FontFinder::fromDirectories(__DIR__.'/fonts');

$font = SvgText::fromFinder($finder, FontQuery::family('Inter')->weight(700));
$path = $font->path('Hello', size: 72);

Every format the installed alto/font supports is available here. A query that matches nothing, and how a finder caches what it scans, are in Loading a font.

What it does not do

The mapper performs one direct cmap lookup per codepoint and returns a left-to-right run. It does not do font fallback, bidirectional text, ligatures, kerning, script shaping, or anything HarfBuzz-compatible.

That is a deliberate boundary rather than a gap: Shaping\TextShaperInterface is the seam where a real shaping engine plugs in, and everything downstream consumes its GlyphRun. What that contract already allows, and what writing a replacement takes, are in Shaping.

A codepoint the font has no glyph for throws MissingGlyphException. A size that is not finite and positive, or a non-finite coordinate, throws InvalidArgumentException. Both, and what alto/font throws instead when a file will not load, are in Errors.

Public API

Type What it is for
SvgText the facade: path data and documents, from a file or a finder
FontText an immutable font-backed text specification
TextPathGenerator one combined Outline\TextPath
Outline\OutlinerInterface a seam for custom outline generation
Shaping\TextShaperInterface the shaped-run contract, with GlyphRun, PositionedGlyph, TextDirection

Converters and renderers marked @internal are outside the compatibility promise. Most applications need SvgText and nothing else.

Example

php examples/woff2-demo.php

Writes examples/output/woff2/index.html from the bundled open-source Inter fixture.

Documentation

  • Installation: the requirements, and checking a Brotli decoder.
  • Getting started: the two calls, and which one to reach for.
  • Loading a font: a path, a finder, and a query that matches nothing.
  • Path data: placement, spacing, and what a TextPath carries.
  • SVG documents: glyph groups, deterministic ids, and composing.
  • Shaping: what the mapper does, what it will not, and the seam.
  • Errors: every exception, and which layer throws it.

The full documentation is published at ateliersvg.com/text.

Contributing

Before submitting code, run:

composer qa   # PHP-CS-Fixer, PHPStan at level max, and PHPUnit

Changes to public behaviour need a test and a documentation update.

Support

Bug reports, security disclosures, and contribution guidelines are collected at ateliersvg.com/support.

Atelier is maintained by Simon André.

License

Atelier Text is released under the MIT License.