integration_api/
integration_api.rs1use rust_fontconfig::{FcFontCache, FcWeight, FontId, PatternMatch};
10
11fn main() {
12 println!("=== Font Integration Pipeline ===\n");
13
14 println!("Step 1: Build font cache");
16 let cache = FcFontCache::build();
17 println!(" {} fonts loaded\n", cache.list().len());
18
19 let css_families = vec![
21 "Helvetica".to_string(),
22 "Arial".to_string(),
23 "sans-serif".to_string(),
24 ];
25 println!("Step 2: Resolve font-family: {:?}\n", css_families);
26
27 let chain = cache.resolve_font_chain(
28 &css_families,
29 FcWeight::Normal,
30 PatternMatch::False,
31 PatternMatch::False,
32 &mut Vec::new(),
33 );
34
35 for (i, group) in chain.css_fallbacks.iter().enumerate() {
36 print!(" [{}] '{}': {} fonts", i + 1, group.css_name, group.fonts.len());
37 if let Some(first) = group.fonts.first() {
38 if let Some(meta) = cache.get_metadata_by_id(&first.id) {
39 print!(
40 " (first: {:?})",
41 meta.name.as_ref().or(meta.family.as_ref())
42 );
43 }
44 }
45 println!();
46 }
47 println!(
48 " + {} unicode fallback fonts\n",
49 chain.unicode_fallbacks.len()
50 );
51
52 let text = "Hello 世界! Привет мир";
54 println!("Step 3: Resolve text: '{}'\n", text);
55
56 let resolved = chain.resolve_text(&cache, text);
57
58 let mut runs: Vec<(String, Option<FontId>)> = Vec::new();
60 let mut current_text = String::new();
61 let mut current_id: Option<FontId> = None;
62
63 for (ch, info) in &resolved {
64 let this_id = info.as_ref().map(|(id, _)| *id);
65 if this_id != current_id {
66 if !current_text.is_empty() {
67 runs.push((current_text.clone(), current_id));
68 current_text.clear();
69 }
70 current_id = this_id;
71 }
72 current_text.push(*ch);
73 }
74 if !current_text.is_empty() {
75 runs.push((current_text, current_id));
76 }
77
78 println!(" Font runs:");
79 for (run_text, font_id) in &runs {
80 let name = font_id
81 .as_ref()
82 .and_then(|id| cache.get_metadata_by_id(id))
83 .and_then(|m| m.name.clone().or(m.family.clone()))
84 .unwrap_or_else(|| "[NO FONT]".into());
85 println!(" '{}' -> {}", run_text, name);
86 }
87
88 let unique_fonts: std::collections::HashSet<_> =
90 runs.iter().filter_map(|(_, id)| *id).collect();
91
92 println!(
93 "\nStep 4: Load fonts ({} unique needed)\n",
94 unique_fonts.len()
95 );
96 for font_id in &unique_fonts {
97 if let Some(meta) = cache.get_metadata_by_id(font_id) {
98 let name = meta
99 .name
100 .as_ref()
101 .or(meta.family.as_ref())
102 .map(|s| s.as_str())
103 .unwrap_or("?");
104 if let Some(source) = cache.get_font_by_id(font_id) {
105 match source {
106 rust_fontconfig::FontSource::Disk(path) => {
107 println!(" {} -> {}", name, path.path);
108 }
109 rust_fontconfig::FontSource::Memory(font) => {
110 println!(" {} -> memory (id: {})", name, font.id);
111 }
112 }
113 }
114 }
115 }
116
117 println!("\nPipeline summary:");
118 println!(" 1. FcFontCache::build() — once at startup");
119 println!(" 2. cache.resolve_font_chain() — per CSS font-family");
120 println!(" 3. chain.resolve_text() — per text run");
121 println!(" 4. cache.get_font_by_id() — load bytes for shaping");
122}