Skip to content

fix(svg): text in the document's fonts — Cyrillic, text-anchor, rotation - #44

Merged
dskripchenko merged 1 commit into
mainfrom
fix/svg-text-fonts
Oct 19, 2026
Merged

dskripchenko merged 1 commit into
mainfrom
fix/svg-text-fonts

Conversation

@dskripchenko

Copy link
Copy Markdown
Owner

Problem

SVG <text> was always set in base-14 Helvetica:

  • Cyrillic (any non-Latin) printed as ? — a stamp «ОПЛАЧЕНО» came out as ????????;
  • text-anchor was ignored — centred labels started at their anchor;
  • a group's transform did not reach the text — a rotated stamp printed its text level;
  • font properties of the group / style were ignored.

Found on a real insurance template in printable (stage acceptance).

Fix

  • SvgRenderer::render() takes an optional font resolver; Engine passes its own chain (family list, fallbacks, bold/italic faces, base-14 last) — SVG text gets the same fonts as a paragraph.
  • font-family, font-weight, font-style, font-size, fill, text-anchor inherited from ancestors and read from inline style.
  • Glyphs are placed by a text matrix derived from the SVG→PDF mapping of the text origin, so rotate/scale/skew apply.
  • New Page::showTextWithMatrix() (base-14 or embedded font, kerning via TJ) and ContentStream::textWithMatrix().

Not in scope: <tspan> positioning, <textPath>, dx/dy (documented).

Tests

tests/Svg/SvgTextFontTest.php: Cyrillic via the document font (pdftotext), inherited bold from <g> + size from style, anchor start/middle/end offsets, rotation angle of the text matrix, base-14 bold fallback. Full suite 2601 green, phpstan clean.

Docs: SVG section in en/de/ru/zh; CHANGELOG [Unreleased].

🤖 Generated with Claude Code

SVG <text> was always set in base-14 Helvetica: Cyrillic printed as "?"
(a stamp "ОПЛАЧЕНО" came out as "????????"), text-anchor was ignored and a
rotated group printed its text level.

- SvgRenderer::render() takes an optional font resolver; the engine passes
  its own chain (family, fallbacks, bold/italic faces, base-14 last).
- font-family/-weight/-style/-size, fill and text-anchor are inherited from
  the group and read from `style`.
- The glyphs are placed by a text matrix built from the SVG→PDF mapping, so
  rotate/scale/skew of a group apply to the text.
- Page::showTextWithMatrix(), ContentStream::textWithMatrix().

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@dskripchenko
dskripchenko merged commit 118a5e8 into main Oct 19, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant