Font Handling
=============
This guide covers font embedding, subsetting, and optimization for SVG output.
Overview
--------
psd2svg can embed fonts directly in SVG files using ``@font-face`` CSS rules. For web delivery, font subsetting dramatically reduces file sizes by including only the glyphs actually used.
**Note:** Font subsetting is enabled by default when embedding fonts. The required ``fonttools`` package is automatically installed with psd2svg.
**Platform Support:**
* **Linux/macOS**: Full font resolution and embedding via fontconfig
* **Windows**: Full font resolution and embedding via Windows registry + fontTools parsing
Font Embedding Basics
----------------------
Simple Embedding
~~~~~~~~~~~~~~~~
Embed fonts as base64-encoded data URIs in the SVG:
.. code-block:: python
from psd2svg import SVGDocument
from psd_tools import PSDImage
psdimage = PSDImage.open("input.psd")
document = SVGDocument.from_psd(psdimage)
document.save("output.svg", embed_fonts=True)
**Result:** Fonts are embedded as base64-encoded TTF/OTF files in ``@font-face`` rules.
**Pros:**
* Self-contained SVG files (no external font dependencies)
* Consistent rendering across platforms
* Works offline
**Cons:**
* Much larger file sizes (100KB+ per font)
* Base64 encoding adds ~33% overhead
* May include glyphs not used in the document
Font Resolution Process
-----------------------
psd2svg uses a two-phase process for handling fonts in text layers:
Two-Phase Font Handling
~~~~~~~~~~~~~~~~~~~~~~~~
**Phase 1: Conversion (from_psd)**
During PSD to SVG conversion, PostScript font names are preserved in the SVG tree:
.. code-block:: python
from psd2svg import SVGDocument
from psd_tools import PSDImage
psdimage = PSDImage.open("input.psd") # Text uses PostScript name "ArialMT"
document = SVGDocument.from_psd(psdimage)
# SVG tree now contains: ...
At this stage, font names remain as PostScript names (e.g., "ArialMT", "TimesNewRomanPSMT").
**Phase 2: Output (save/tostring)**
During SVG output, font names are resolved based on the embedding mode:
**Without font embedding** (``embed_fonts=False``, default):
.. code-block:: python
# Uses static font mapping (~4,950 fonts)
document.save("output.svg")
# Result: ...
* PostScript names are mapped to CSS family names using static mapping
* No system font queries are performed
* Works on all platforms without external dependencies
**With font embedding** (``embed_fonts=True``):
.. code-block:: python
# Uses platform-specific font resolution
document.save("output.svg", embed_fonts=True)
# Result: ...
# @font-face { font-family: 'DejaVu Sans'; ... }
* PostScript names are resolved to system fonts via fontconfig (Linux/macOS) or Windows registry
* Automatically handles font substitution when requested font is unavailable
* Embeds the actual system font file found
* Logs font resolution at INFO level
**Example with substitution:**
If "ArialMT" is requested but Arial is not installed, the system may substitute DejaVu Sans:
.. code-block:: text
INFO Resolved font 'ArialMT' → 'DejaVu Sans' (file: '/usr/share/fonts/...')
The generated SVG will use the substituted font:
.. code-block:: xml
Hello World
.. code-block:: css
/* Font embedded in