Skip to content

rust-fontconfig 3.0.0

Choose a tag to compare

@fschutt fschutt released this 02 Apr 21:28
· 85 commits to master since this release

Breaking Changes

  • FcPattern has a new field: render_config: FcFontRenderConfig was added. Code
    using struct literal construction (FcPattern { name: ..., family: ... }) must add
    render_config: FcFontRenderConfig::default() or use ..Default::default().
  • UnicodeRange is now #[repr(C)]: Layout is guaranteed to match C { uint32_t start; uint32_t end; }.
    This was already the case in practice but is now an explicit contract.
  • ffi feature now implies async-registry: The C bindings include the full
    registry (background thread) API. Previously ffi only implied parsing + std.

New Features

Per-font rendering config from fonts.conf (#16)

On Linux, fonts.conf <match target="font"> rules are now parsed and exposed via
FcFontRenderConfig on each FcPattern. Supported properties:

Field Type Description
antialias Option<bool> Enable/disable antialiasing
hinting Option<bool> Enable/disable hinting
hintstyle Option<FcHintStyle> None, Slight, Medium, Full
autohint Option<bool> Use autohinter
rgba Option<FcRgba> Subpixel order (Rgb, Bgr, Vrgb, Vbgr)
lcdfilter Option<FcLcdFilter> LCD filter mode
embeddedbitmap Option<bool> Use embedded bitmaps
embolden Option<bool> Synthetic bold
dpi Option<f64> Per-font DPI override
scale Option<f64> Scale factor
minspace Option<bool> Minimum spacing

All fields are None on macOS/Windows (use system defaults). New enums:
FcHintStyle, FcRgba, FcLcdFilter.

Async font registry C API

12 new C FFI functions expose the background-thread font loading API:

// Lifecycle
FcFontRegistry fc_registry_new(void);
void fc_registry_spawn(FcFontRegistry registry);
void fc_registry_shutdown(FcFontRegistry registry);
void fc_registry_free(FcFontRegistry registry);

// Priority-based font loading (blocks only for requested fonts)
FcFontChain* fc_registry_request_fonts(registry, stacks, counts, num, &out);
void fc_registry_chains_free(FcFontChain* chains, size_t count);

// Status
bool fc_registry_is_scan_complete(FcFontRegistry registry);
bool fc_registry_is_build_complete(FcFontRegistry registry);

// Query
FcFontMatch* fc_registry_query(FcFontRegistry registry, const FcPattern* pattern);
FcFontInfo* fc_registry_list_fonts(FcFontRegistry registry, size_t* count);
FcFontChain fc_registry_resolve_font_chain(registry, families, count, weight, italic, oblique);
FcFontPath* fc_registry_get_font_path(FcFontRegistry registry, const FcFontId* id);
FcFontMetadata* fc_registry_get_metadata(FcFontRegistry registry, const FcFontId* id);
FcFontRenderConfig fc_registry_get_render_config(FcFontRegistry registry, const FcFontId* id);
FcFontCache fc_registry_snapshot(FcFontRegistry registry);

Unicode script detection helpers

New public functions for checking Unicode block coverage:

pub fn has_cjk_ranges(ranges: &[UnicodeRange]) -> bool;
pub fn has_arabic_ranges(ranges: &[UnicodeRange]) -> bool;
pub fn has_cyrillic_ranges(ranges: &[UnicodeRange]) -> bool;
pub fn has_hebrew_ranges(ranges: &[UnicodeRange]) -> bool;
pub fn has_thai_ranges(ranges: &[UnicodeRange]) -> bool;

New public modules

Internal code has been restructured into public modules for better organization:

  • config -- OS-specific font directories, generic family expansion, tokenization
  • scoring -- Priority queue types and scoring heuristics for background loading
  • multithread -- Scout and builder thread implementations
  • disk_cache -- Disk cache serialization (behind cache feature)
  • utils -- Font file detection, family name normalization

Improvements

  • 14% code reduction (8018 -> 6905 lines) through systematic deduplication
  • FFI safety: Fixed Vec::from_raw_parts capacity mismatch UB in fc_registry_request_fonts
  • Code style: Flattened deeply nested if let patterns with let-else and functional chaining
  • CI: Added cross-compilation checks for WASM, iOS, iOS Simulator, Android targets;
    fixed Windows MSVC example execution; removed continue-on-error that hid failures

C Example

New ffi/example_registry.c with 3 demos showcasing the azul-style fast startup pattern:

  1. Azul-style fast startup: spawn threads -> request only needed fonts -> render first frame
    with 67/806 fonts loaded, remaining parse in background
  2. Incremental loading: request UI fonts (69 loaded) -> monospace for code editor (90) ->
    CJK for pasted Japanese text (116)
  3. Old vs new API comparison: blocking fc_cache_build() (806 fonts) vs async
    fc_registry_request_fonts() (67 fonts, rest in background)

Migration from 2.0.0

// Before (2.0.0)
let pattern = FcPattern {
    name: Some("Arial".into()),
    family: Some("Arial".into()),
    ..Default::default()
};

// After (3.0.0) -- add render_config or use ..Default::default()
let pattern = FcPattern {
    name: Some("Arial".into()),
    family: Some("Arial".into()),
    ..Default::default()  // render_config defaults to all-None
};

If you were constructing FcPattern with all fields explicitly, add:

render_config: FcFontRenderConfig::default(),