Donner SVG 0.8.0
0.8.0 ยท ebf353960.8.0 main
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
donner::svg::FontManager Class Reference

Manages font loading, caching, and lookup for text rendering. More...

#include "donner/svg/resources/FontManager.h"

Classes

struct  GlyphOutlineComplexity
 Validation-time allocation/work bound for one font outline. More...
class  DependencyCapture
 Record every catalog face consulted in a layout, including memoized and pending faces. The output survives this manager and can be attached to a stable preview/document task. More...

Public Member Functions

 FontManager (Registry &registry, size_t maximumLoadedFontBytes=kDefaultMaximumLoadedFontBytes, size_t maximumLoadedFonts=kDefaultMaximumLoadedFonts, size_t maximumFontValidationWork=kDefaultMaximumFontValidationWork)
 Construct a FontManager tied to the provided ECS registry.
 ~FontManager ()
 Destructor.
 FontManager (const FontManager &)=delete
FontManager & operator= (const FontManager &)=delete
 FontManager (FontManager &&)=delete
FontManager & operator= (FontManager &&)=delete
DependencyCapture captureDependencies (std::vector< FontFaceDependency > &output)
 Begin a scoped capture of font faces consulted during layout preparation.
void recordDependencies (std::span< const FontFaceDependency > dependencies)
 Attribute an already-prepared resource to the enclosing dependency capture.
std::vector< FontFaceDependency > faceDependencies () const
 Latest bounded consumer states. No provider/store callbacks access the registry.
bool refreshPendingFonts ()
 Retry pending faces from the normal serialized text/frame preparation path. Returns true when a successful resolution changed fontResourceRevision(), even if asset identity did not.
bool needsResourceRefresh () const
 Whether provider state changes need another normal preparation pass.
bool hasUnresolvedDependencies () const
 Whether current face dependencies still have unresolved states.
uint64_t fontResourceRevision () const
 Revision advanced when a resolved font change invalidates prepared text geometry.
bool fontDependenciesOverflowed () const
 Whether bounded dependency collection exceeded its resource limit.
void addFontFace (const css::FontFace &face)
 Register a @font-face declaration.
void setGenericFamilyMapping (std::string_view genericName, std::string_view realFamily)
 Register a mapping from a CSS generic family name (serif, sans-serif, monospace, cursive, fantasy) to a real font family name registered via addFontFace().
bool hasFamily (std::string_view family) const
 Returns whether any registered @font-face rule or the attached provider claims family, after resolving CSS generic names.
FontHandle findFont (std::string_view family)
 Find or load a font matching the given family name.
FontHandle findFont (std::string_view family, int weight)
 Find or load a font matching the given family name and weight.
FontHandle findFont (std::string_view family, int weight, int style, int stretch)
 Find or load a font matching the given family name, weight, style, and stretch.
FontHandle loadFontData (std::span< const uint8_t > data, FontDataTrust trust=FontDataTrust::Untrusted)
 Load encoded TTF/OTF/WOFF data (including WOFF2 in full-text builds).
std::span< const uint8_t > fontData (FontHandle handle) const
 Get the raw font data bytes for a handle.
std::optional< FontFaceRequest > providerFaceRequest (FontHandle handle) const
 Requested catalog face attributes for a loaded provider font, if any.
bool isGenericSansProviderFont (FontHandle handle) const
 Whether a loaded provider face is the editor's generic sans-serif family.
bool isImmutableCatalogFont (FontHandle handle) const
 Whether a loaded provider face is backed by an immutable catalog asset.
bool isTrustedFont (FontHandle handle) const
 Returns whether handle was loaded from an explicitly trusted source.
std::optional< GlyphOutlineComplexity > glyphOutlineComplexity (FontHandle handle, int glyphIndex) const
 Return a lifetime-safe O(1) pre-decode bound for a validated glyph.
std::optional< std::span< const uint8_t > > sfntTable (FontHandle handle, std::string_view tag) const
 Get a table from the cached, validated sfnt directory for a handle.
bool isValidatedFont (FontHandle handle) const
 Return true when handle has a cached validated sfnt directory.
bool fontsShareFamily (FontHandle first, FontHandle second) const
 Compare the actual family names cached from two loaded fonts, independently of CSS aliases.
size_t loadedFontBytes () const
 Font-data, cached-index, and family-name storage bytes charged to this registry's budget.
size_t numLoadedFonts () const
 Number of loaded font components currently charged to this registry's budget.
size_t fontValidationWork () const
 CFF validation work permanently consumed by load attempts in this registry.
size_t compressedFontDecompressionAttempts () const
 Compressed-font decompression attempts performed for this registry.
size_t numFaces () const
 Get the number of registered @font-face rules.
std::string_view faceFamilyName (size_t index) const
 Get the family name of a registered @font-face rule by index.
FontHandle fallbackFont ()
 Get the handle for the embedded fallback font (Public Sans).
void setFontProvider (const FontFamilyProvider *provider)
 Attach an external font provider (typically a FontCatalog) consulted during findFont() for family names not satisfied by a registered @font-face rule, before falling back to the embedded Public Sans font.

Static Public Member Functions

static void SetDefaultFontProvider (const FontFamilyProvider *provider)
 Set the process-wide default font provider.
static const FontFamilyProvider * DefaultFontProvider ()
 Returns the current process-wide default font provider (may be nullptr).

Static Public Attributes

static constexpr size_t kDefaultMaximumLoadedFontBytes = 64 * 1024 * 1024
 Default aggregate byte budget for font data loaded into one registry.
static constexpr size_t kDefaultMaximumLoadedFonts = 1024
 Default maximum number of font byte streams retained in one registry.
static constexpr size_t kDefaultMaximumFontValidationWork
 Default aggregate CFF validation work admitted for one registry.

Friends

struct FontManagerTestAccess

Detailed Description

Manages font loading, caching, and lookup for text rendering.

FontManager is the shared font infrastructure used by both the Skia and TinySkia backends. It handles:

  • Loading raw TTF/OTF font data.
  • Loading WOFF 1.0 fonts via the existing WoffParser, reconstructing the sfnt byte stream, then storing the reconstructed sfnt bytes.
  • Resolving @font-face source cascades.
  • Caching resolved family/style lookups to avoid repeated face scans.
  • Falling back to the embedded Public Sans font when no match is found.
  • Storing backend caches on the same font entity as the loaded bytes.

FontManager uses entt entities to store font data, with one entity per registered @font-face rule or directly-loaded font. Text backends can cache parsed backend objects directly on the same entity.

FontManager follows the registry's access discipline rather than providing internal locking. Const queries may run in parallel while the registry is held for reading; loads and other mutations require serialized write access. The registry must outlive every stack-local manager.


Class Documentation

◆ donner::svg::FontManager::GlyphOutlineComplexity

struct donner::svg::FontManager::GlyphOutlineComplexity

Validation-time allocation/work bound for one font outline.

Class Members
size_t maximumVertices = 0
size_t work = 0

Constructor & Destructor Documentation

◆ FontManager()

donner::svg::FontManager::FontManager ( Registry & registry,
size_t maximumLoadedFontBytes = kDefaultMaximumLoadedFontBytes,
size_t maximumLoadedFonts = kDefaultMaximumLoadedFonts,
size_t maximumFontValidationWork = kDefaultMaximumFontValidationWork )
explicit

Construct a FontManager tied to the provided ECS registry.

The first manager to perform a serialized font load for a registry establishes its aggregate byte, item, and untrusted CFF-validation limits. Read-only queries never establish or replace that state. Later manager instances for the same registry share it so loaded components and validation attempts remain accounted across manager lifetimes.

Construction does not access the registry context, so a FontManager can itself be safely constructed by registry.ctx().emplace<FontManager>(registry).

Member Function Documentation

◆ addFontFace()

void donner::svg::FontManager::addFontFace ( const css::FontFace & face)

Register a @font-face declaration.

Sources are resolved lazily on first findFont() call for the corresponding family name.

Registration is idempotent: re-registering a declaration that is byte-for-byte the same rule (same family, weight, style, stretch, and the same ordered source list pointing at the same payloads) reuses the entity minted the first time and leaves the resolution cache intact. Callers that re-announce a document's whole @font-face set on every style recompute therefore keep stable font entities, which keeps every downstream per-font cache (rendered glyph outlines, backend face objects) valid across unrelated document mutations. A rule that differs in any of those fields is a different declaration and mints a new entity, so newly loaded font data is never served from a stale entity.

Family names are compared case-insensitively, matching how findFont() selects a face, so two declarations differing only in the casing of their family name are one declaration here and numFaces() counts them once.

Parameters
faceThe parsed @font-face rule.

◆ captureDependencies()

DependencyCapture donner::svg::FontManager::captureDependencies ( std::vector< FontFaceDependency > & output)
inline

Begin a scoped capture of font faces consulted during layout preparation.

Parameters
outputCaller-owned dependency destination.

◆ faceFamilyName()

std::string_view donner::svg::FontManager::faceFamilyName ( size_t index) const

Get the family name of a registered @font-face rule by index.

Parameters
indexIndex into the registered faces (0 to numFaces()-1).
Returns
The family name, or empty string_view if index is out of range.

◆ findFont() [1/3]

FontHandle donner::svg::FontManager::findFont ( std::string_view family)

Find or load a font matching the given family name.

Resolution order:

  1. If the family is a CSS generic name with a registered mapping, resolve to the real name.
  2. Return an already-loaded entity if the best matching face has already been resolved.
  3. Walk registered @font-face rules whose font-family matches, trying each source.
  4. Fall back to the embedded Public Sans font.
Parameters
familyFont family name to look up.
Returns
A valid FontHandle, or an invalid handle if even the fallback fails.

◆ findFont() [2/3]

FontHandle donner::svg::FontManager::findFont ( std::string_view family,
int weight )

Find or load a font matching the given family name and weight.

Parameters
familyFont family name to look up.
weightCSS font-weight value (100-900, 400=normal, 700=bold).
Returns
A valid FontHandle, or falls back to findFont(family) if no weight match.

◆ findFont() [3/3]

FontHandle donner::svg::FontManager::findFont ( std::string_view family,
int weight,
int style,
int stretch )

Find or load a font matching the given family name, weight, style, and stretch.

Parameters
familyFont family name to look up.
weightCSS font-weight value (100-900, 400=normal, 700=bold).
styleCSS font-style value (0=normal, 1=italic, 2=oblique).
stretchCSS font-stretch value (1-9, 5=normal, matching FontStretch enum).
Returns
A valid FontHandle, or falls back to findFont(family, weight) if no match.

◆ fontData()

std::span< const uint8_t > donner::svg::FontManager::fontData ( FontHandle handle) const

Get the raw font data bytes for a handle.

This is useful for backends (like Skia) that need to create their own font objects from the raw data.

Parameters
handleA valid FontHandle.
Returns
Span of the raw font data, or empty span if the handle is invalid.

◆ fontsShareFamily()

bool donner::svg::FontManager::fontsShareFamily ( FontHandle first,
FontHandle second ) const

Compare the actual family names cached from two loaded fonts, independently of CSS aliases.

Equal valid handles match even without a name; different handles with missing or lossy names do not. This performs no decoding or allocation.

Parameters
firstFirst loaded font.
secondSecond loaded font.
Returns
Whether the handles identify the same face or a known common family.

◆ hasFamily()

bool donner::svg::FontManager::hasFamily ( std::string_view family) const

Returns whether any registered @font-face rule or the attached provider claims family, after resolving CSS generic names.

A font-family list must skip entries nothing provides so a later entry can match. findFont() cannot express that, because an unmatched family is answered with the embedded fallback rather than an invalid handle, so callers walking a list test availability here first. This performs no loading and leaves the resolution cache untouched.

Text layout asks this once per family per span, and neither the family-list length nor the registered-rule count is bounded by anything but the document, so registered families are answered from a lowercased index maintained by addFontFace rather than by rescanning the rules. That index is per FontManager instance and covers the rules this instance has seen: it is seeded from the registry at construction and extended on each registration, so a second manager over the same registry that registers its own rules does not update this one's.

Like every other query here this writes nothing, so it is safe to run in parallel under the registry read lock. A family the provider already resolved through findFont is answered from a second index that resolution fills, and anything still unknown falls through to the provider, which is why FontFamilyProvider::hasFamily must answer in constant or logarithmic time.

Parameters
familyFont family name to test, before generic-name resolution.
Returns
True when a registered rule or the provider claims the resolved family.

◆ loadFontData()

FontHandle donner::svg::FontManager::loadFontData ( std::span< const uint8_t > data,
FontDataTrust trust = FontDataTrust::Untrusted )

Load encoded TTF/OTF/WOFF data (including WOFF2 in full-text builds).

The data is copied internally. The font is not associated with any family name; callers should use findFont() for name-based lookup.

The default treats the bytes as untrusted. The simple text backend refuses to pass untrusted bytes to stb_truetype because that parser does not accept a buffer length. Use FontDataTrust::Trusted only for application-controlled embedded or local-system fonts.

Parameters
dataEncoded font-file bytes supported by this build's text feature tier.
trustWhether the source is trusted enough for length-unaware font backends.
Returns
A valid FontHandle on success, or an invalid handle on failure.

◆ SetDefaultFontProvider()

void donner::svg::FontManager::SetDefaultFontProvider ( const FontFamilyProvider * provider)
static

Set the process-wide default font provider.

Every FontManager constructed afterwards adopts it (existing instances are unaffected). The editor installs its FontCatalog here so document render paths that create their own FontManager resolve embedded and system fonts without threading the catalog through every call site.

The provider is borrowed, not owned, and must outlive all FontManagers that adopt it.

◆ setFontProvider()

void donner::svg::FontManager::setFontProvider ( const FontFamilyProvider * provider)
inline

Attach an external font provider (typically a FontCatalog) consulted during findFont() for family names not satisfied by a registered @font-face rule, before falling back to the embedded Public Sans font.

The provider is borrowed, not owned, and must outlive this FontManager. Pass nullptr to detach.

Attaching a different provider abandons every font resolved through the previous one, since another provider may answer the same family with different bytes. Those fonts keep their entities and their share of the aggregate budget: handles to them may still be held by text runs and by backend caches keyed on the handle, so their bytes have to stay valid. The budget is released when the entities are destroyed, normally with the registry.

Resolution order for findFont(family):

  1. Matching @font-face rule registered via addFontFace() (document-provided fonts win).
  2. The attached provider (a FontCatalog tries Bundled families, then System families).
  3. Embedded Public Sans fallback.

◆ setGenericFamilyMapping()

void donner::svg::FontManager::setGenericFamilyMapping ( std::string_view genericName,
std::string_view realFamily )

Register a mapping from a CSS generic family name (serif, sans-serif, monospace, cursive, fantasy) to a real font family name registered via addFontFace().

This allows findFont("sans-serif") to resolve to the specified family.

Parameters
genericNameThe CSS generic family name (case-insensitive).
realFamilyThe real family name to resolve to.

◆ sfntTable()

std::optional< std::span< const uint8_t > > donner::svg::FontManager::sfntTable ( FontHandle handle,
std::string_view tag ) const

Get a table from the cached, validated sfnt directory for a handle.

Parameters
handleA valid FontHandle.
tagFour-byte sfnt table tag.
Returns
A bounded table span, or std::nullopt if the handle or tag is invalid or absent.

Member Data Documentation

◆ kDefaultMaximumFontValidationWork

size_t donner::svg::FontManager::kDefaultMaximumFontValidationWork
staticconstexpr
Initial value:
=
constexpr std::size_t kMaximumCffOutlineValidationWork
Default whole-font work ceiling for one bounded CFF validation.
Definition CffOutlineComplexity.h:12

Default aggregate CFF validation work admitted for one registry.


The documentation for this class was generated from the following file: