use super::badge_type::BadgeError;
use base64::{Engine as _, engine::general_purpose::STANDARD};
use css_color::Rgba;
use rusttype::{point, Font, Scale};
use std::path::Path;
use unicode_normalization::UnicodeNormalization;
pub fn load_font<'a>(bytes: &'static [u8]) -> Result<Font<'a>, BadgeError> {
match Font::try_from_bytes(bytes) {
Some(f) => Ok(f),
None => Err(BadgeError::CannotLoadFont),
}
}
pub fn get_text_dims(font: &Font, text: &str, font_size: f32) -> (String, f32) {
let norm_text = text.nfc().collect::<String>();
let scale = Scale::uniform(font_size);
let layout = font.layout(&norm_text, scale, point(0.0, 0.0));
let mut glyphs_width = layout.fold(0.0, |acc, x| {
acc + x.into_unpositioned().h_metrics().advance_width
});
if glyphs_width as usize % 2 == 0 {
glyphs_width += 1.0;
}
(norm_text, glyphs_width)
}
pub fn verify_color(color: &str) -> Result<String, BadgeError> {
let valid_color: Rgba = match color.parse() {
Ok(c) => c,
Err(_) => return Err(BadgeError::ColorNotValid(String::from(color))),
};
Ok(format!(
"rgb({}, {}, {})",
valid_color.red * 255.0,
valid_color.green * 255.0,
valid_color.blue * 255.0
))
}
pub fn uppercase_first_letter(s: &str) -> String {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
}
}
pub fn create_embedded_logo(logo_uri: &str) -> Result<String, BadgeError> {
if let Ok(uri) = ureq::get(logo_uri).call() {
Ok(uri.into_string().unwrap())
} else {
Err(BadgeError::CannotEmbedLogo(String::from(logo_uri)))
}
}
pub fn attempt_logo_download(logo_uri: &str) -> Result<String, BadgeError> {
let local_path = Path::new(logo_uri);
let data = match std::fs::read_to_string(local_path) {
Ok(f) => f,
Err(_) => create_embedded_logo(logo_uri)?,
};
Ok(format!(
"data:image/svg+xml;base64,{}",
STANDARD.encode(data.as_bytes())
))
}