pub struct FontManager<T> {
pub fc_cache: FcFontCache,
pub parsed_fonts: Arc<Mutex<HashMap<FontId, T>>>,
pub font_chain_cache: HashMap<FontChainKey, FontFallbackChain>,
pub embedded_fonts: Mutex<HashMap<u64, FontRef>>,
pub font_hash_to_families: HashMap<u64, StyleFontFamilyVec>,
pub registry: Option<Arc<FcFontRegistry>>,
pub last_resolved_font_stacks_sig: Option<u64>,
pub memory_families: HashMap<String, Vec<MemoryFace>>,
/* private fields */
}Fields§
§fc_cache: FcFontCacheThe font-path cache. FcFontCache in rust-fontconfig 4.1 is
already a shared handle internally (Arc<RwLock<_>>), so no
further Arc<...> wrapping is needed — clones are cheap and
all clones see builder writes instantly.
parsed_fonts: Arc<Mutex<HashMap<FontId, T>>>Holds the actual parsed font (usually with the font bytes attached).
Wrapped in Arc so multiple FontManager instances can share the same
pool of already-parsed fonts (avoids re-reading from disk).
font_chain_cache: HashMap<FontChainKey, FontFallbackChain>§embedded_fonts: Mutex<HashMap<u64, FontRef>>Cache for direct FontRefs (embedded fonts like Material Icons)
These are fonts referenced via FontStack::Ref that bypass fontconfig
font_hash_to_families: HashMap<u64, StyleFontFamilyVec>Reverse map: font_family_hash → actual StyleFontFamilyVec.
Accumulated across DOMs. Used by font collection and text shaping to
resolve compact cache hashes without get_property_slow.
registry: Option<Arc<FcFontRegistry>>Optional link back to the live FcFontRegistry. When present,
chain resolution uses
rust_fontconfig::registry::FcFontRegistry::request_and_resolve_with_scripts
which lazy-parses system fonts as the DOM requests them
(scout-on-demand). None falls back to querying whatever is
already in the shared cache.
last_resolved_font_stacks_sig: Option<u64>FxHash of the prev_font_hashes slice at the moment the last
successful collect_and_resolve_font_chains_with_registration
call populated font_chain_cache. Lets repeated layouts of the
same DOM skip the ~1.5 ms (cold) / ~0.9 ms (warm) chain resolver
when the set of font-family hashes has not changed. Cleared
whenever font_chain_cache is explicitly emptied.
memory_families: HashMap<String, Vec<MemoryFace>>Index of every font registered by FAMILY NAME into fc_cache’s
in-memory font table (bundled fonts, embedder fonts, the built-in
mock test fonts): normalized family name → the FontMatch the
resolver should emit for it.
WHY THIS EXISTS (architectural, see resolve_font_chains_fast):
the fast chain resolver in rust-fontconfig 4.4
(FcFontRegistry::request_fonts_fast) resolves families purely
against known_paths — i.e. fonts that exist as FILES ON DISK.
In-memory fonts are invisible to it, so a family registered with
FcFontCache::with_memory_fonts could never be matched by name
on the production path (which always has a live registry): it
silently fell back to a system font. This index is consulted
FIRST, before the disk probe, so a memory-registered family wins
exactly as CSS says it should.
Implementations§
Source§impl<T: ParsedFontTrait> FontManager<T>
impl<T: ParsedFontTrait> FontManager<T>
Sourcepub fn new(fc_cache: FcFontCache) -> Result<Self, LayoutError>
pub fn new(fc_cache: FcFontCache) -> Result<Self, LayoutError>
§Errors
Returns a LayoutError if the font cache cannot be initialized.
Sourcepub fn register_named_font(
&mut self,
family: &str,
bytes: &[u8],
coverage: Vec<UnicodeRange>,
) -> FontId
pub fn register_named_font( &mut self, family: &str, bytes: &[u8], coverage: Vec<UnicodeRange>, ) -> FontId
Register a font by FAMILY NAME from raw bytes, as an in-memory font
in the shared FcFontCache.
This is the ONE hook an embedder (or a test) uses to make a font
resolvable by font-family: "<family>". It mints one FontId for
the font, inserts it into the fontconfig cache’s memory-font table
(so get_font_bytes / load_fonts_from_disk find it with no
special-casing) and indexes it in Self::memory_families so the
fast chain resolver can match it by name.
coverage are the codepoint ranges the font actually covers.
Passing the true ranges matters: FontFallbackChain::resolve_char
skips any font that reports no coverage, and a font claiming
coverage it doesn’t have would render .notdef instead of falling
back.
Returns the FontId the family now resolves to.
Sourcepub fn register_named_font_in_tier(
&mut self,
family: &str,
bytes: &[u8],
coverage: Vec<UnicodeRange>,
tier: MemoryFontTier,
) -> FontId
pub fn register_named_font_in_tier( &mut self, family: &str, bytes: &[u8], coverage: Vec<UnicodeRange>, tier: MemoryFontTier, ) -> FontId
Register an in-memory face under family at an explicit
MemoryFontTier.
Self::register_named_font is this with MemoryFontTier::Primary.
Use MemoryFontTier::Fallback to offer a face for a family without
displacing whatever is installed - a caller that ships stand-in fonts for
serif/sans-serif/monospace wants the system’s faces to win on a
desktop and its own to be there on wasm, and that is the tier that does
both.
Sourcepub fn register_builtin_mock_fonts(&mut self)
pub fn register_builtin_mock_fonts(&mut self)
Register the built-in mock test fonts (see
crate::text3::mock_fonts). Called from every constructor: the
mock families are only reachable if a stylesheet names them, and
having them always present means tests exercise the same font
path as production instead of a test-only bypass.
Create a FontManager sharing the font-path cache handle.
The parsed_fonts pool starts empty. Fonts loaded during the first
layout pass are cached and will be available on subsequent calls
if you clone the parsed_fonts Arc before creating the next instance.
For full sharing, prefer from_arc_shared().
§Errors
Returns a LayoutError if the font cache cannot be initialized.
Create a FontManager sharing both the font-path cache and the
already-parsed font data with another FontManager.
This avoids re-reading and re-parsing font files from disk when rendering multiple documents that use the same fonts.
§Errors
Returns a LayoutError if the font cache cannot be initialized.
Sourcepub fn with_registry(self, registry: Arc<FcFontRegistry>) -> Self
pub fn with_registry(self, registry: Arc<FcFontRegistry>) -> Self
Attach a FcFontRegistry to this FontManager so subsequent
chain-resolution calls use the on-demand path
(rust_fontconfig::registry::FcFontRegistry::request_and_resolve_with_scripts).
Get a shareable handle to the parsed-font pool.
Pass this to from_arc_shared() to create a new FontManager that
reuses already-parsed fonts.
Sourcepub fn set_font_chain_cache(
&mut self,
chains: HashMap<FontChainKey, FontFallbackChain>,
)
pub fn set_font_chain_cache( &mut self, chains: HashMap<FontChainKey, FontFallbackChain>, )
Set the font chain cache from externally resolved chains
This should be called with the result of resolve_font_chains() or
collect_and_resolve_font_chains() from solver3::getters.
Sourcepub fn set_font_chain_cache_with_sig(
&mut self,
chains: HashMap<FontChainKey, FontFallbackChain>,
sig: Option<u64>,
)
pub fn set_font_chain_cache_with_sig( &mut self, chains: HashMap<FontChainKey, FontFallbackChain>, sig: Option<u64>, )
Set the font chain cache and record the input signature so
subsequent layouts with the same prev_font_hashes skip the
resolver. Pass sig = None if the caller cannot compute a
reliable signature — equivalent to the single-arg
set_font_chain_cache.
Sourcepub fn merge_font_chain_cache(
&mut self,
chains: HashMap<FontChainKey, FontFallbackChain>,
)
pub fn merge_font_chain_cache( &mut self, chains: HashMap<FontChainKey, FontFallbackChain>, )
Merge additional font chains into the existing cache
Useful when processing multiple DOMs that may have different font requirements.
Sourcepub const fn get_font_chain_cache(
&self,
) -> &HashMap<FontChainKey, FontFallbackChain>
pub const fn get_font_chain_cache( &self, ) -> &HashMap<FontChainKey, FontFallbackChain>
Get a reference to the font chain cache
Sourcepub fn get_embedded_font_by_hash(&self, font_hash: u64) -> Option<FontRef>
pub fn get_embedded_font_by_hash(&self, font_hash: u64) -> Option<FontRef>
Get an embedded font by its hash (used for WebRender registration)
Returns the FontRef if it exists in the embedded_fonts cache.
§Panics
Panics if the internal font-cache mutex is poisoned.
Sourcepub fn get_font_by_hash(&self, font_hash: u64) -> Option<T>
pub fn get_font_by_hash(&self, font_hash: u64) -> Option<T>
Get a parsed font by its hash (used for WebRender registration)
Returns the parsed font if it exists in the parsed_fonts cache.
§Panics
Panics if the internal font-cache mutex is poisoned.
Sourcepub fn resolve_font_by_hash(&self, font_hash: u64) -> Option<FontRef>
pub fn resolve_font_by_hash(&self, font_hash: u64) -> Option<FontRef>
THE font lookup: resolve a font_hash — the value layout stamps onto every
shaped glyph and carries in DisplayListItem::Text — back to the face that
produced it.
A FontManager shapes with faces from TWO pools: parsed_fonts (loaded from
the resolved font chains) and embedded_fonts (handed to it directly by the
DOM as StyleFontFamily::Ref — Material Icons and every other
FontStack::Ref). Both can put a hash in the display list, so a renderer that
consults only one of them silently drops user-visible text. That is exactly
what shipped in 0.2.0: the CPU renderer searched parsed_fonts alone, so
every widget icon vanished with [cpurender] Font hash … not found in FontManager while layout had happily measured and positioned it.
Every renderer resolves through this one function, so “layout produced this hash” and “the renderer can draw this hash” cannot disagree.
§Panics
Panics if the internal font-cache mutex is poisoned.
Sourcepub fn register_embedded_font(&self, font_ref: &FontRef)
pub fn register_embedded_font(&self, font_ref: &FontRef)
Register an embedded FontRef for later lookup by hash
This is called when using FontStack::Ref during shaping
§Panics
Panics if the internal font-cache mutex is poisoned.
Sourcepub fn get_loaded_fonts(&self) -> LoadedFonts<T>
pub fn get_loaded_fonts(&self) -> LoadedFonts<T>
Get a snapshot of all currently loaded fonts
This returns a copy of all parsed fonts, which can be passed to the shaper.
No locking is required after this call - the returned HashMap is independent.
NOTE: This should be called AFTER loading all required fonts for a layout pass.
§Panics
Panics if the internal font-cache mutex is poisoned.
Sourcepub fn get_loaded_font_ids(&self) -> HashSet<FontId>
pub fn get_loaded_font_ids(&self) -> HashSet<FontId>
Get the set of FontIds that are currently loaded
This is useful for computing which fonts need to be loaded (diff with required fonts).
§Panics
Panics if the internal font-cache mutex is poisoned.
Sourcepub fn insert_font(&self, font_id: FontId, font: T) -> Option<T>
pub fn insert_font(&self, font_id: FontId, font: T) -> Option<T>
Insert a loaded font into the cache
Returns the old font if one was already present for this FontId.
§Panics
Panics if the internal font-cache mutex is poisoned.
Sourcepub fn insert_fonts(&self, fonts: impl IntoIterator<Item = (FontId, T)>)
pub fn insert_fonts(&self, fonts: impl IntoIterator<Item = (FontId, T)>)
Insert multiple loaded fonts into the cache
This is more efficient than calling insert_font multiple times
because it only acquires the lock once.
§Panics
Panics if the internal font-cache mutex is poisoned.
Sourcepub fn load_missing_for_chains<F>(
&self,
chains: &ResolvedFontChains,
load_fn: F,
) -> Vec<(FontId, String)>
pub fn load_missing_for_chains<F>( &self, chains: &ResolvedFontChains, load_fn: F, ) -> Vec<(FontId, String)>
One-shot helper that resolves “what fonts does chains need
that this manager hasn’t loaded yet” and loads them via the
supplied load_fn closure (typically
PathLoader::load_font_shared for the production lazy-decode
path). Updates parsed_fonts in place and returns any failures
for the caller to log.
Replaces the same four-step collect → compute_diff → load_from_disk → insert_fonts dance previously inlined in
LayoutWindow::layout_document, the CPU rasterizer pre-fill
in cpurender.rs, and FontContext::load_fonts_for_chains.
Sourcepub fn replace_fc_cache(&mut self, fc_cache: FcFontCache)
pub fn replace_fc_cache(&mut self, fc_cache: FcFontCache)
Replace the backing FcFontCache and re-register the built-in memory fonts.
Memory fonts (the mock test fonts, and any register_named_font bytes) live
ONLY inside the cache. A bare self.fc_cache = new therefore strands them: their
FontIds stay in memory_families but their bytes are gone with the old cache,
so chain resolution matches them yet loading fails and text silently falls back
(e.g. font-family: "Azul Mock Mono" measuring with the fallback font’s metrics).
Use this whenever the cache is swapped for a fresh snapshot (registry handle,
rebuilt system cache) instead of assigning the field directly.
Sourcepub fn remove_font(&self, font_id: &FontId) -> Option<T>
pub fn remove_font(&self, font_id: &FontId) -> Option<T>
Remove a font from the cache
Returns the removed font if it was present.
§Panics
Panics if the internal font-cache mutex is poisoned.
Sourcepub fn garbage_collect_fonts(
&mut self,
keep_ids: &HashSet<FontId>,
keep_hashes: &HashSet<u64>,
) -> usize
pub fn garbage_collect_fonts( &mut self, keep_ids: &HashSet<FontId>, keep_hashes: &HashSet<u64>, ) -> usize
FONT GC — evict everything the CURRENT document no longer references.
keep_ids are the FontIds reachable from the font chains just resolved
for this document; keep_hashes are the font-family hashes present in its
CSS property cache. Anything else belonged to a node that is gone.
Without this, parsed_fonts / font_hash_to_families only ever GREW: a
font loaded for one node stayed resident for the life of the window even
after the node (and every other user of that family) disappeared — an app
that cycles fonts (font picker, editor, live CSS) leaked every font it ever
touched.
Eviction is always safe: load_missing_for_chains re-loads any font a
later layout turns out to need. The cost of a wrong guess is one re-parse,
never a missing glyph.
Returns the number of parsed fonts evicted.
§Panics
Panics if the internal font-cache mutex is poisoned.
Source§impl FontManager<FontRef>
impl FontManager<FontRef>
Sourcepub fn evict_unused(&self, idle: Duration) -> usize
pub fn evict_unused(&self, idle: Duration) -> usize
Evict the cached LocaGlyf for every face that hasn’t had a
get_or_decode_glyph call within the last idle duration.
Only LocaGlyfState::Deferred faces (the production lazy
path) can be evicted — they keep their source Arc<[u8]> so
the next glyph access re-parses cheaply. LocaGlyfState::Loaded
faces from the eager path stay put.
Returns the number of faces evicted. Embedders can call this
from a memory-pressure hook or on a timer; servo-shot
exposes it via --azul-evict-after-each for measurement.
Trait Implementations§
Auto Trait Implementations§
impl<T> !Freeze for FontManager<T>
impl<T> RefUnwindSafe for FontManager<T>
impl<T> Send for FontManager<T>where
T: Send,
impl<T> Sync for FontManager<T>where
T: Send,
impl<T> Unpin for FontManager<T>
impl<T> UnsafeUnpin for FontManager<T>
impl<T> UnwindSafe for FontManager<T>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more