unicode_aware_fonts/
unicode_aware_fonts.rs

1//! Example demonstrating unicode-aware font resolution
2//! 
3//! This shows how to resolve font chains and then query them for specific text.
4
5use rust_fontconfig::{FcFontCache, FcWeight, PatternMatch};
6
7fn main() {
8    // Initialize font cache
9    let cache = FcFontCache::build();
10    
11    println!("=== Unicode-Aware Font Selection ===\n");
12    
13    // Step 1: Create a font chain for sans-serif fonts
14    println!("Step 1: Resolve font chain for 'sans-serif'");
15    let mut trace = Vec::new();
16    let chain = cache.resolve_font_chain(
17        &vec!["sans-serif".to_string()],
18        FcWeight::Normal,
19        PatternMatch::False,  // italic
20        PatternMatch::False,  // oblique
21        &mut trace,
22    );
23    
24    println!("  Font chain has {} CSS fallbacks and {} unicode fallbacks\n", 
25             chain.css_fallbacks.len(),
26             chain.unicode_fallbacks.len());
27    
28    // Step 2: Resolve different texts against the chain
29    println!("Step 2: Resolve various texts against the font chain\n");
30    
31    // Latin text
32    let latin_text = "Hello World";
33    println!("Latin text: '{}'", latin_text);
34    print_text_resolution(&cache, &chain, latin_text);
35    
36    // CJK (Chinese) text
37    let cjk_text = "你好世界";
38    println!("\nCJK text: '{}'", cjk_text);
39    print_text_resolution(&cache, &chain, cjk_text);
40    
41    // Japanese text
42    let japanese_text = "こんにちは世界";
43    println!("\nJapanese text: '{}'", japanese_text);
44    print_text_resolution(&cache, &chain, japanese_text);
45    
46    // Arabic text
47    let arabic_text = "مرحبا بالعالم";
48    println!("\nArabic text: '{}'", arabic_text);
49    print_text_resolution(&cache, &chain, arabic_text);
50    
51    // Cyrillic text
52    let cyrillic_text = "Привет мир";
53    println!("\nCyrillic text: '{}'", cyrillic_text);
54    print_text_resolution(&cache, &chain, cyrillic_text);
55    
56    // Mixed text
57    let mixed_text = "Hello 世界 Привет";
58    println!("\nMixed text: '{}'", mixed_text);
59    print_text_resolution(&cache, &chain, mixed_text);
60    
61    println!("\n=== Summary ===");
62    println!("The workflow is:");
63    println!("1. resolve_font_chain() - creates a fallback chain from CSS font-family");
64    println!("2. chain.resolve_text() - maps each character to a font in the chain");
65    println!("3. Use the font IDs to load and render glyphs");
66}
67
68fn print_text_resolution(
69    cache: &FcFontCache,
70    chain: &rust_fontconfig::FontFallbackChain,
71    text: &str,
72) {
73    let resolved = chain.resolve_text(cache, text);
74    
75    // Group consecutive characters by font
76    let mut current_font: Option<String> = None;
77    let mut current_segment = String::new();
78    
79    for (ch, font_info) in resolved {
80        let font_name = font_info.map(|(id, _)| {
81            cache.get_metadata_by_id(&id)
82                .and_then(|p| p.name.clone().or(p.family.clone()))
83                .unwrap_or_else(|| format!("{:?}", id))
84        });
85        
86        if font_name != current_font {
87            if !current_segment.is_empty() {
88                println!("  '{}' -> {}", 
89                         current_segment, 
90                         current_font.as_deref().unwrap_or("[NO FONT]"));
91                current_segment.clear();
92            }
93            current_font = font_name;
94        }
95        current_segment.push(ch);
96    }
97    
98    if !current_segment.is_empty() {
99        println!("  '{}' -> {}", 
100                 current_segment, 
101                 current_font.as_deref().unwrap_or("[NO FONT]"));
102    }
103}