|
use dyn_any::DynAny; |
|
use std::collections::HashMap; |
|
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Hash, PartialEq, Eq, DynAny, specta::Type)] |
|
pub struct Font { |
|
#[serde(rename = "fontFamily")] |
|
pub font_family: String, |
|
#[serde(rename = "fontStyle", deserialize_with = "migrate_font_style")] |
|
pub font_style: String, |
|
} |
|
impl Font { |
|
pub fn new(font_family: String, font_style: String) -> Self { |
|
Self { font_family, font_style } |
|
} |
|
} |
|
impl Default for Font { |
|
fn default() -> Self { |
|
Self::new(crate::consts::DEFAULT_FONT_FAMILY.into(), crate::consts::DEFAULT_FONT_STYLE.into()) |
|
} |
|
} |
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default, PartialEq, DynAny)] |
|
pub struct FontCache { |
|
|
|
font_file_data: HashMap<Font, Vec<u8>>, |
|
|
|
preview_urls: HashMap<Font, String>, |
|
} |
|
|
|
impl FontCache { |
|
|
|
pub fn resolve_font<'a>(&'a self, font: &'a Font) -> Option<&'a Font> { |
|
if self.font_file_data.contains_key(font) { |
|
Some(font) |
|
} else { |
|
self.font_file_data |
|
.keys() |
|
.find(|font| font.font_family == crate::consts::DEFAULT_FONT_FAMILY && font.font_style == crate::consts::DEFAULT_FONT_STYLE) |
|
} |
|
} |
|
|
|
|
|
pub fn get(&self, font: &Font) -> Option<&Vec<u8>> { |
|
self.resolve_font(font).and_then(|font| self.font_file_data.get(font)) |
|
} |
|
|
|
|
|
pub fn loaded_font(&self, font: &Font) -> bool { |
|
self.font_file_data.contains_key(font) |
|
} |
|
|
|
|
|
pub fn insert(&mut self, font: Font, perview_url: String, data: Vec<u8>) { |
|
self.font_file_data.insert(font.clone(), data); |
|
self.preview_urls.insert(font, perview_url); |
|
} |
|
|
|
|
|
pub fn get_preview_url(&self, font: &Font) -> Option<&String> { |
|
self.preview_urls.get(font) |
|
} |
|
} |
|
|
|
impl std::hash::Hash for FontCache { |
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
|
self.preview_urls.len().hash(state); |
|
self.preview_urls.iter().for_each(|(font, url)| { |
|
font.hash(state); |
|
url.hash(state) |
|
}); |
|
self.font_file_data.len().hash(state); |
|
self.font_file_data.keys().for_each(|font| font.hash(state)); |
|
} |
|
} |
|
|
|
|
|
fn migrate_font_style<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<String, D::Error> { |
|
use serde::Deserialize; |
|
String::deserialize(deserializer).map(|name| if name == "Normal (400)" { "Regular (400)".to_string() } else { name }) |
|
} |
|
|