The admitted icons as Kotlin data, so the app draws them crisp at any size in their own colours.
Each icon is two strings: its size * size pixels (. empty, otherwise an index) and its palette
(six hex digits per index). Strings are constants, so a couple of hundred icons do not grow a method
past the JVM's limit the way array literals would.
The Kotlin file for every admitted icon. svg returns the text of an icon's file, so this stays free of
the file system.
12pub fn generate(svg: impl Fn(&IconId) -> Result<String, String>) -> Result<String, String> { 13 let mut out = String::from( 14 "// Generated by `cargo run -p whiskers-icons --bin gen-kotlin` (tools/build-core.sh). Do not edit.\n\ 15 // The icons are shuqikhor/pixel-icons by shuqikhor, restricted to crates/whiskers-icons/allowlist.txt.\n\ 16 package app.whiskers.art\n\n\ 17 /** An admitted pixel icon: `pixels` has `size * size` characters, `.` for empty or an index into `palette`. */\n\ 18 class PixelIconData(val size: Int, val pixels: String, val palette: String)\n\n\ 19 object PixelIconSet {\n val all: Map<String, PixelIconData> = mapOf(\n", 20 ); 21 for id in IconId::all() { 22 let text = svg(&id).map_err(|e| format!("{id}: {e}"))?; 23 let icon = Icon::parse(&text).map_err(|e| format!("{id}: {e}"))?; 24 let colours = icon.colours(); 25 if colours.len() > 36 { 26 return Err(format!("{id}: more than 36 colours")); 27 } 28 let ascii = icon.ascii().replace('\n', ""); 29 let palette: String = colours.iter().map(|c| format!("{:02X}{:02X}{:02X}", c[0], c[1], c[2])).collect(); 30 out.push_str(&format!(" \"{id}\" to PixelIconData({}, \"{ascii}\", \"{palette}\"),\n", icon.size)); 31 } 32 out.push_str(" )\n}\n"); 33 Ok(out) 34}