Skip to content

Releases: fschutt/rust-fontconfig

1.2.0

25 Nov 23:02

Choose a tag to compare

Breaking Changes

  • resolve_font_chain() signature changed: The text parameter 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: Use cache.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 to FontFallbackChain: 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 as Vec<(char, Option<(FontId, String)>)> for fine-grained control.

  • FontFallbackChain::resolve_char(): Resolve a single character to its font using the font chain.

  • CssFallbackGroup struct: 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

1.0.0

13 Mar 22:07

Choose a tag to compare

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)

  1. Put rust_fontconfig.h in the same directory and librust_fontconfig.so in the same directory
  2. Compile with
    • gcc -I. -L. -lrust_fontconfig example.c -o example
    • clang -I. -L. -lrust_fontconfig example.c -o example
  3. ./example to 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