Releases: fschutt/rust-fontconfig
1.2.0
Breaking Changes
-
resolve_font_chain()signature changed: Thetextparameter has been removed. Font chains are now resolved based on CSS properties only (font-family, weight, italic, oblique), not text content.- cache.resolve_font_chain(&families, text, weight, italic, oblique, &mut trace); + cache.resolve_font_chain(&families, weight, italic, oblique, &mut trace);
-
query_all()method removed: Usecache.list()with filtering instead.- let fonts = cache.query_all(&pattern, &mut trace); + let fonts: Vec<_> = cache.list().into_iter() + .filter(|(pattern, _id)| /* your filter */) + .collect();
-
query_for_text()moved toFontFallbackChain: Text-to-font resolution now requires a font chain first.- let fonts = cache.query_for_text(&pattern, text, &mut trace); + let chain = cache.resolve_font_chain(&families, weight, italic, oblique, &mut trace); + let font_runs = chain.query_for_text(&cache, text);
Added
-
FontFallbackChain::resolve_text(): Returns per-character font assignments asVec<(char, Option<(FontId, String)>)>for fine-grained control. -
FontFallbackChain::resolve_char(): Resolve a single character to its font using the font chain. -
CssFallbackGroupstruct: Groups fonts by their CSS source name, making it clear which CSS font-family each font came from. -
Font chain caching: Identical CSS font-family stacks now share cached font chains, improving performance when the same fonts are used with different text content.
Changed
-
Architecture: The new two-step workflow (chain resolution → text querying) better matches CSS/browser font handling semantics and enables better caching.
-
Performance: Font chains are now cached by CSS properties, avoiding redundant font resolution for the same font-family declarations.
Links
- Documentation: https://docs.rs/rust-fontconfig
- Crate: https://crates.io/crates/rust-fontconfig
- Repository: https://github.com/fschutt/rust-fontconfig
1.0.0
rust-fontconfig v1.0.0 Release Notes
Overview
rust-fontconfig is a pure-Rust alternative to the Linux fontconfig library with no system dependencies. It supports .woff, .woff2, .ttc, .otf, and .ttf formats and works on Windows, macOS, and WASM environments.
Key Features
- Zero external dependencies - uses Rust's native libraries only
- Cross-platform support (Linux, Windows, macOS, and WASM)
- Memory-safe font parsing via allsorts (reduces risk of font-based attacks)
- Multithreaded font loading and parsing
- In-memory font caching for improved performance
- Flexible font matching by name, family, style, and Unicode ranges
- Automatic fallback selection for multilingual text
- C API for integration with non-Rust languages
Improvements Over C Implementation
- Smaller codebase than original fontconfig (~190,000 lines of C)
- Multithreaded parsing for faster initialization
- Memory-mapping for efficient file access
- Selective table parsing (only reads tables needed for matching)
- Lower memory consumption due to fewer allocations
- In-memory caching (vs disk-only in original implementation)
Usage (Rust)
use rust_fontconfig::{FcFontCache, FcPattern};
fn main() {
let cache = FcFontCache::build();
// Simple query
let results = cache.query(
&FcPattern {
name: Some(String::from("Arial")),
..Default::default()
},
&mut Vec::new()
);
if let Some(font_match) = results {
println!("Font match ID: {:?}", font_match.id);
}
// find all monospace fonts
let fonts = cache.query_all(
&FcPattern {
monospace: PatternMatch::True,
..Default::default()
},
&mut Vec::new()
);
println!("Found {} monospace fonts", fonts.len());
// Multilingual text support with fallback fonts
let matched_fonts = cache.query_for_text(
&FcPattern::default(),
"Hello 你好 Здравствуйте",
&mut Vec::new()
);
println!("You need {} fonts to render this text", matched_fonts.len());
}Usage (C)
- Put
rust_fontconfig.hin the same directory andlibrust_fontconfig.soin the same directory - Compile with
gcc -I. -L. -lrust_fontconfig example.c -o exampleclang -I. -L. -lrust_fontconfig example.c -o example
./exampleto run
#include <stdio.h>
#include "rust_fontconfig.h"
int main() {
// Build the font cache
FcFontCache cache = fc_cache_build();
if (!cache) {
fprintf(stderr, "Failed to build font cache\n");
return 1;
}
// Create a pattern to search for Arial
FcPattern* pattern = fc_pattern_new();
fc_pattern_set_name(pattern, "Arial");
// Search for the font
FcTraceMsg* trace = NULL;
size_t trace_count = 0;
FcFontMatch* match = fc_cache_query(cache, pattern, &trace, &trace_count);
if (match) {
char id_str[40];
fc_font_id_to_string(&match->id, id_str, sizeof(id_str));
printf("Found font! ID: %s\n", id_str);
// Get the font path
FcFontPath* font_path = fc_cache_get_font_path(cache, &match->id);
if (font_path) {
printf("Font path: %s (index: %zu)\n", font_path->path, font_path->font_index);
fc_font_path_free(font_path);
}
fc_font_match_free(match);
} else {
printf("Font not found\n");
}
// Clean up
fc_pattern_free(pattern);
if (trace) fc_trace_free(trace, trace_count);
fc_cache_free(cache);
return 0;
}Links
- Documentation: https://docs.rs/rust-fontconfig
- Crate: https://crates.io/crates/rust-fontconfig
- Repository: https://github.com/fschutt/rust-fontconfig