pub struct FcFontRegistry {Show 13 fields
pub cache: FcFontCache,
pub known_paths: RwLock<BTreeMap<String, Vec<PathBuf>>>,
pub build_queue: Mutex<Vec<FcBuildJob>>,
pub queue_condvar: Condvar,
pub processed_paths: Mutex<HashSet<PathBuf>>,
pub completed_paths: Mutex<HashSet<PathBuf>>,
pub progress: Condvar,
pub scan_complete: Atomic<bool>,
pub build_complete: Atomic<bool>,
pub shutdown: Atomic<bool>,
pub cache_loaded: Atomic<bool>,
pub lazy_scout: Atomic<bool>,
pub os: OperatingSystem,
}Expand description
Thread-safe, incrementally-populated font registry.
Wraps an FcFontCache behind a RwLock so that background threads can
populate it concurrently while the main thread reads from it.
Fields§
§cache: FcFontCacheThe underlying font cache, populated incrementally by Builder threads.
As of v4.1, FcFontCache carries its own internal RwLock and
Arc, so the registry can hand out handles (via shared_cache)
that live-update with builder writes — no outer lock needed,
no staleness for snapshot-holders downstream.
known_paths: RwLock<BTreeMap<String, Vec<PathBuf>>>Maps guessed lowercase family name → file paths
build_queue: Mutex<Vec<FcBuildJob>>§queue_condvar: CondvarNotified when new jobs are added to build_queue or on shutdown.
Builder threads wait on this (paired with build_queue).
processed_paths: Mutex<HashSet<PathBuf>>Paths claimed for parsing (set BEFORE parsing, for deduplication).
completed_paths: Mutex<HashSet<PathBuf>>Paths fully parsed and inserted into cache (set AFTER parsing).
progress: CondvarNotified when any progress occurs: font completed, scan done, build done.
The main thread waits on this (paired with completed_paths).
scan_complete: Atomic<bool>§build_complete: Atomic<bool>§shutdown: Atomic<bool>§cache_loaded: Atomic<bool>Whether a disk cache was successfully loaded (skip blocking in request_fonts)
lazy_scout: Atomic<bool>When true, the scout populates known_paths + sets
scan_complete but does NOT push every path onto
build_queue. Builders therefore idle until a caller runs
FcFontRegistry::request_fonts or
FcFontRegistry::request_and_resolve_with_scripts, which
priority-bumps only the requested families into the queue.
Cuts steady-state memory: the ~300 system fonts on macOS
each cost ~50 KiB of parsed NAME + OS/2 metadata in the
cache’s pattern map — skipping those that the current
workload never touches saves ~15 MiB on a short-lived
headless render.
Set via FcFontRegistry::set_scout_lazy before
FcFontRegistry::spawn_scout_and_builders. Defaults to
false to preserve the existing eager-scout behaviour for
long-running embedders who want the disk cache to populate
in the background.
os: OperatingSystemImplementations§
Source§impl FcFontRegistry
impl FcFontRegistry
Sourcepub fn new() -> Arc<FcFontRegistry> ⓘ
pub fn new() -> Arc<FcFontRegistry> ⓘ
Create a new empty registry.
Sourcepub fn set_scout_lazy(&self, lazy: bool)
pub fn set_scout_lazy(&self, lazy: bool)
Enable/disable lazy scout mode. See FcFontRegistry::lazy_scout
for what this changes. Must be called before
FcFontRegistry::spawn_scout_and_builders — the scout thread
reads the flag once when it starts iterating the build queue.
Sourcepub fn register_memory_fonts(&self, fonts: Vec<NamedFont>)
pub fn register_memory_fonts(&self, fonts: Vec<NamedFont>)
Register in-memory (bundled) fonts. These are available immediately.
Sourcepub fn spawn_scout_and_builders(self: &Arc<FcFontRegistry>)
pub fn spawn_scout_and_builders(self: &Arc<FcFontRegistry>)
Spawn the Scout thread and Builder pool. Returns immediately.
Sourcepub fn request_fonts(
&self,
family_stacks: &[Vec<String>],
) -> Vec<FontFallbackChain>
pub fn request_fonts( &self, family_stacks: &[Vec<String>], ) -> Vec<FontFallbackChain>
Block the calling thread until all requested font families are loaded (or confirmed to not exist on the system).
This is called by the layout engine before the first layout pass. It boosts the priority of any not-yet-loaded fonts to Critical and waits for the Builder to process them.
Hard timeout: 5 seconds.
Sourcepub fn get_metadata_by_id(&self, id: &FontId) -> Option<FcPattern>
pub fn get_metadata_by_id(&self, id: &FontId) -> Option<FcPattern>
Get font metadata by ID.
Sourcepub fn get_font_bytes(&self, id: &FontId) -> Option<Arc<FontBytes>>
pub fn get_font_bytes(&self, id: &FontId) -> Option<Arc<FontBytes>>
Get font bytes for a given font ID — disk-backed fonts come
back as a shared mmap; in-memory fonts as Owned. See
FcFontCache::get_font_bytes for the lifetime semantics.
Sourcepub fn get_disk_font_path(&self, id: &FontId) -> Option<FcFontPath>
pub fn get_disk_font_path(&self, id: &FontId) -> Option<FcFontPath>
Get the disk font path for a font ID.
Sourcepub fn is_memory_font(&self, id: &FontId) -> bool
pub fn is_memory_font(&self, id: &FontId) -> bool
Check if a font ID is a memory font.
Sourcepub fn query(&self, pattern: &FcPattern) -> Option<FontMatch>
pub fn query(&self, pattern: &FcPattern) -> Option<FontMatch>
Query the registry for a font matching the given pattern.
Sourcepub fn resolve_font_chain(
&self,
font_families: &[String],
weight: FcWeight,
italic: PatternMatch,
oblique: PatternMatch,
) -> FontFallbackChain
pub fn resolve_font_chain( &self, font_families: &[String], weight: FcWeight, italic: PatternMatch, oblique: PatternMatch, ) -> FontFallbackChain
Resolve a complete font fallback chain for a CSS font-family stack.
Sourcepub fn request_and_resolve_with_scripts(
&self,
font_families: &[String],
weight: FcWeight,
italic: PatternMatch,
oblique: PatternMatch,
scripts_hint: Option<&[UnicodeRange]>,
) -> FontFallbackChain
pub fn request_and_resolve_with_scripts( &self, font_families: &[String], weight: FcWeight, italic: PatternMatch, oblique: PatternMatch, scripts_hint: Option<&[UnicodeRange]>, ) -> FontFallbackChain
On-demand font-chain resolution: triggers the scout + builder to parse the requested families (if not already parsed), waits for them via condvar, then resolves a full fallback chain with the caller-supplied weight / italic / oblique / scripts_hint.
This is the “scout-on-demand” entry point: callers can skip
the eager request_fonts(common_stacks) at init and pay the
per-family parse only when a DOM actually needs that family.
On excel.html that cuts the init cost from ~150 ms to ~10 ms
and peak RSS from ~71 MiB to ~55 MiB because only the
~2 families excel uses get parsed, not the full common-stack
set (~35 fonts across Helvetica/Lucida/Menlo/Times/NewYork/
Courier/SFNS).
Re-entrant from layout: holds no locks for the duration of the
call, and request_fonts internally handles the scan_complete
wait + priority-bump + completed_paths wait.
Get a shared handle on the cache. The returned FcFontCache
shares state with this registry (and with every other holder
of the handle): writes by builder threads via [insert_font]
are immediately visible to all readers.
Replaces v4.0’s into_fc_font_cache (which took a deep
snapshot) — the deep copy was the source of the stale-state
bug in lazy-scout mode, since builders kept writing to the
registry’s cache while downstream holders were stuck on a
frozen copy.
Sourcepub fn wait_for_scout(&self)
pub fn wait_for_scout(&self)
Block until the background scout + builder threads have
populated the in-memory pattern map with every font’s NAME +
OS/2 metadata (most importantly unicode_ranges). Returns
immediately if a disk cache was loaded, both scan + build
already completed, or the 5 s deadline elapses.
Callers that skip [request_fonts] but still need a fully
populated FcFontCache snapshot (e.g. headless renderers
that do their own font-chain resolution) must invoke this
first — otherwise into_fc_font_cache may capture the cache
mid-build and every resolve_char call will return None
because unicode_ranges is empty for not-yet-parsed fonts.
This waits for build_complete (not just scan_complete) —
the scout finishes readdir quickly but the builder threads
do the actual header parsing, and it is the builder output
that populates unicode_ranges.
Sourcepub fn is_scan_complete(&self) -> bool
pub fn is_scan_complete(&self) -> bool
Returns true if the Scout has finished enumerating all font directories.
Sourcepub fn is_build_complete(&self) -> bool
pub fn is_build_complete(&self) -> bool
Returns true if all fonts in the queue have been processed.
Sourcepub fn is_cache_loaded(&self) -> bool
pub fn is_cache_loaded(&self) -> bool
Returns true if a disk cache was successfully loaded at startup.
Sourcepub fn request_fonts_fast(
&self,
requests: &[(Vec<String>, BTreeSet<char>)],
weight: FcWeight,
italic: PatternMatch,
) -> Vec<FontFallbackChain>
pub fn request_fonts_fast( &self, requests: &[(Vec<String>, BTreeSet<char>)], weight: FcWeight, italic: PatternMatch, ) -> Vec<FontFallbackChain>
Fast-path font resolution: for each stack + codepoints pair,
return a FontFallbackChain built by cmap-probing candidate
files until coverage is satisfied.
Semantics (one face per family — CSS-correct):
- Iterate the expanded family stack in CSS order.
- For each family, walk candidate file paths from
known_paths, and within each file walk faces sorted by style match (best (bold, italic) match to the request first). The first face that covers any currently-uncovered codepoint is added to the chain; we then move to the next family. - Stop the whole stack as soon as every requested codepoint is covered.
- Any codepoints still uncovered after the last family is a
miss (e.g. emoji against a sans-serif-only stack); the
shaper will display
.notdeffor them. This matches CSS’s behaviour for fonts that don’t cover the requested chars.
Bypasses the builder-thread dance entirely — no jobs queued, no 5 s deadline, no full allsorts parse. ~100 µs per face touched on warm FS.
Sourcepub fn insert_font(&self, pattern: FcPattern, path: FcFontPath)
pub fn insert_font(&self, pattern: FcPattern, path: FcFontPath)
Insert a parsed font into the cache (called by Builder threads).
Source§impl FcFontRegistry
impl FcFontRegistry
Sourcepub fn scout_thread(&self)
pub fn scout_thread(&self)
Scout thread: enumerates font directories and populates the build queue.
- Walks all OS font directories recursively, collecting font file paths.
- Tokenizes each filename and assigns a priority (High for common OS fonts, Low for everything else).
- Populates
known_paths(family → file paths) andbuild_queue. - Signals
scan_completewhen done.
Sourcepub fn builder_thread(&self)
pub fn builder_thread(&self)
Builder thread loop: pops jobs from the priority queue, parses fonts, and inserts results into the registry.
Exit conditions:
shutdownis set (registry is dropping).- In eager mode: once the scout finishes the initial
directory walk, queue empties, and every queued path is
processed. At that point
build_completeflips and the thread returns. - In lazy-scout mode: the thread keeps waiting on
queue_condvarindefinitely, because the scout does not pre-queue anything — all jobs come in later fromFcFontRegistry::request_fonts. Exiting on the “queue empty + scan complete” condition (as the eager path does) would race the Critical job push and cause the request to hang forever.
Source§impl FcFontRegistry
impl FcFontRegistry
Sourcepub fn load_from_disk_cache(&self) -> Option<()>
pub fn load_from_disk_cache(&self) -> Option<()>
Load font metadata from the on-disk cache.
Reads and deserializes the bincode font manifest from the platform
cache directory, then populates the inner FcFontCache with all cached
patterns, font paths, and token indices. Marks all cached file paths as
processed/completed so builder threads skip them.
Returns Some(()) on success, None if the cache is missing,
unreadable, malformed, or has a version mismatch.
On WASM this is a no-op that always returns None.
Sourcepub fn save_to_disk_cache(&self) -> Option<()>
pub fn save_to_disk_cache(&self) -> Option<()>
Serialize the current registry state to the on-disk font cache.
Collects all discovered font paths and their parsed metadata into a
FontManifest, then writes it as bincode to the platform cache
directory (e.g. ~/.cache/rfc/fonts/manifest.bin on Linux).
Returns None if the cache path cannot be determined, the parent
directory cannot be created, or serialization / writing fails.
On WASM this is a no-op that always returns None (no filesystem access).
Trait Implementations§
Source§impl Debug for FcFontRegistry
impl Debug for FcFontRegistry
Source§impl Drop for FcFontRegistry
impl Drop for FcFontRegistry
Auto Trait Implementations§
impl !Freeze for FcFontRegistry
impl RefUnwindSafe for FcFontRegistry
impl Send for FcFontRegistry
impl Sync for FcFontRegistry
impl Unpin for FcFontRegistry
impl UnsafeUnpin for FcFontRegistry
impl UnwindSafe for FcFontRegistry
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