unicode_aware_fonts/
unicode_aware_fonts.rs1use rust_fontconfig::{FcFontCache, FcWeight, FontFallbackChain, PatternMatch};
10
11fn main() {
12 let cache = FcFontCache::build();
13
14 println!("=== Unicode-Aware Font Selection ===\n");
15
16 let chain = cache.resolve_font_chain(
18 &["sans-serif".to_string()],
19 FcWeight::Normal,
20 PatternMatch::False,
21 PatternMatch::False,
22 &mut Vec::new(),
23 );
24
25 println!(
26 "Font chain: {} CSS fallbacks, {} unicode fallbacks\n",
27 chain.css_fallbacks.len(),
28 chain.unicode_fallbacks.len()
29 );
30
31 let texts = [
33 ("Latin", "Hello World"),
34 ("CJK", "你好世界"),
35 ("Japanese", "こんにちは世界"),
36 ("Arabic", "مرحبا بالعالم"),
37 ("Cyrillic", "Привет мир"),
38 ("Mixed", "Hello 世界 Привет"),
39 ];
40
41 for (label, text) in &texts {
42 println!("{} text: '{}'", label, text);
43 print_resolution(&cache, &chain, text);
44 println!();
45 }
46
47 println!("Workflow:");
48 println!(" 1. resolve_font_chain() — creates fallback chain from CSS font-family");
49 println!(" 2. chain.resolve_text() — maps each character to a font");
50 println!(" 3. Use font IDs to load and render glyphs");
51}
52
53fn print_resolution(cache: &FcFontCache, chain: &FontFallbackChain, text: &str) {
54 let resolved = chain.resolve_text(cache, text);
55
56 let mut current_font: Option<String> = None;
57 let mut segment = String::new();
58
59 for (ch, info) in &resolved {
60 let font_name = info.as_ref().and_then(|(id, _)| {
61 cache
62 .get_metadata_by_id(id)
63 .and_then(|m| m.name.clone().or(m.family.clone()))
64 });
65 if font_name != current_font {
66 if !segment.is_empty() {
67 println!(
68 " '{}' -> {}",
69 segment,
70 current_font.as_deref().unwrap_or("[NO FONT]")
71 );
72 segment.clear();
73 }
74 current_font = font_name;
75 }
76 segment.push(*ch);
77 }
78 if !segment.is_empty() {
79 println!(
80 " '{}' -> {}",
81 segment,
82 current_font.as_deref().unwrap_or("[NO FONT]")
83 );
84 }
85}