|
|
Donner 0.5.1
Embeddable browser-grade SVG2 engine
|
Status: Partial Standard: CSS Fonts Level 4 Related: text/overview.md
CSS Fonts Level 4 defines font selection, loading, and rendering properties. SVG uses these as presentation attributes on text elements. This document tracks our support level and implementation plan for CSS font properties within the donner SVG renderer.
| Property | Status | Notes |
|---|---|---|
| font-family | Implemented | Parsed as comma-separated list. Resolved via FontManager::findFont() against registered @font-face rules. Falls back to embedded Public Sans. |
| font-size | Implemented | Supports px, em, %, and other CSS length units. Inherited. Keywords (small, large, x-large etc.) not yet supported. |
| font-weight | Implemented | Supports normal (400), bold (700), and numeric 100-900. Per-span resolution selects weight-matched font from registered @font-face rules. Keywords bolder/lighter not supported. |
| Property | CSS Fonts 4 Section | Priority | Notes |
|---|---|---|---|
| font-style | 3.3 | High | normal, italic, oblique [<angle>]. Needed for italic text rendering. |
| font-variant | 3.6 | Low | Shorthand for sub-properties (caps, ligatures, etc.). Complex parsing. |
| font-stretch | 3.4 | Low | condensed, expanded, percentage. Rarely used in SVG. |
| font-size-adjust | 3.5 | Low | Adjusts x-height across font fallback. Complex metric computation. |
| Property | CSS Fonts 4 Section | Priority | Notes |
|---|---|---|---|
| font | 3.7 | Medium | Shorthand (font: bold 16px/1.2 "Noto Sans"). Common in CSS stylesheets. |
| font-synthesis | 3.8 | Low | Controls synthetic bold/italic. Not commonly used in SVG. |
| font-feature-settings | 6.12 | Medium | Direct OpenType feature control ("liga" 0, "smcp" 1). Passes to HarfBuzz hb_feature_t. |
| font-variation-settings | 5.2 | Low | Variable font axis values. Requires variable font support. |
| font-optical-sizing | 5.3 | Low | Automatic optical sizing for variable fonts. |
| font-palette | 7.1 | Low | Color font palette selection. |
| line-height | Related (CSS Inline 3) | Medium | Not in CSS Fonts 4 but essential for multi-line text. |
@font-face rules are supported with the following descriptors:
| Descriptor | Status | Notes |
|---|---|---|
| font-family | Implemented | Family name for matching. |
| src | Partial | Data (inline bytes) supported. url() and local() not implemented. |
| font-weight | Implemented | Stored in FontFace::fontWeight. Weight matching in findFont(family, weight). |
| font-style | Not implemented | No style matching (italic vs normal). |
| font-stretch | Not implemented | No stretch matching. |
| font-display | Not applicable | Only relevant for web loading behavior. |
| unicode-range | Not implemented | Would enable per-codepoint font fallback. |
CSS Fonts 4 Section 4.7 defines a multi-step matching algorithm:
Our current implementation:
Add font-style as a CSS property and @font-face descriptor.
PropertyRegistry changes:
Where FontStyle is an enum: Normal, Italic, Oblique.
FontFace changes:
Font matching: Update findFont(family, weight) → findFont(family, weight, style).
Test registration: Parse style from filename suffix: NotoSans-Italic.ttf → FontStyle::Italic.
Parse the font shorthand property which combines: font: [font-style] [font-variant] [font-weight] font-size[/line-height] font-family
Example: font: bold 16px "Noto Sans" → weight=700, size=16px, family="Noto Sans".
Pass OpenType feature settings to HarfBuzz via hb_feature_t. Parse format: font-feature-settings: "liga" 0, "smcp" 1
TextShaper changes: Store parsed features in TextParams and pass to hb_shape():
Support CSS font-size keywords: xx-small, x-small, small, medium, large, x-large, xx-large, smaller, larger.
Map to pixel values per CSS spec (medium = 16px, each step ~1.2x).
Support font-variation-settings for variable font axes (wght, wdth, ital, etc.). Requires FreeType's FT_Set_Var_Design_Coordinates API.
Per-script font fallback: when the primary font lacks glyphs for a script (checked via FT_Get_Char_Index), iterates all registered @font-face rules to find one with coverage. This handles cases like "Noto Sans" requested for Arabic text falling back to Amiri.
Current font-related test results (--config=text-full):
| Test Group | Passing | Failing | Notes |
|---|---|---|---|
| a-font-weight-* | 0 | 6 | All have 18K threshold — our renderer produces different widths |
| a-font-size-* | 3 | 8 | Missing keyword support, relative units |
| e-tspan-006 | ✅ | Bold tspan now renders with NotoSans-Bold | |
| e-tspan-024 | 16,722px | Bold + text-anchor interaction | |
| e-tspan-028 | 9,336px | Mixed font-size in nested tspan |