fonts.rs

  1use crate::json::{json, ToJson};
  2pub use font_kit::{
  3    metrics::Metrics,
  4    properties::{Properties, Stretch, Style, Weight},
  5};
  6use serde::{Deserialize, Deserializer};
  7
  8#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
  9pub struct FontId(pub usize);
 10
 11pub type GlyphId = u32;
 12
 13#[allow(non_camel_case_types)]
 14#[derive(Deserialize)]
 15enum WeightJson {
 16    thin,
 17    extra_light,
 18    light,
 19    normal,
 20    medium,
 21    semibold,
 22    bold,
 23    extra_bold,
 24    black,
 25}
 26
 27#[derive(Deserialize)]
 28struct PropertiesJson {
 29    weight: Option<WeightJson>,
 30    #[serde(default)]
 31    italic: bool,
 32}
 33
 34impl Into<Properties> for PropertiesJson {
 35    fn into(self) -> Properties {
 36        let mut result = Properties::new();
 37        result.weight = match self.weight.unwrap_or(WeightJson::normal) {
 38            WeightJson::thin => Weight::THIN,
 39            WeightJson::extra_light => Weight::EXTRA_LIGHT,
 40            WeightJson::light => Weight::LIGHT,
 41            WeightJson::normal => Weight::NORMAL,
 42            WeightJson::medium => Weight::MEDIUM,
 43            WeightJson::semibold => Weight::SEMIBOLD,
 44            WeightJson::bold => Weight::BOLD,
 45            WeightJson::extra_bold => Weight::EXTRA_BOLD,
 46            WeightJson::black => Weight::BLACK,
 47        };
 48        if self.italic {
 49            result.style = Style::Italic;
 50        }
 51        result
 52    }
 53}
 54
 55pub fn deserialize_option_font_properties<'de, D>(
 56    deserializer: D,
 57) -> Result<Option<Properties>, D::Error>
 58where
 59    D: Deserializer<'de>,
 60{
 61    let json: Option<PropertiesJson> = Deserialize::deserialize(deserializer)?;
 62    Ok(json.map(Into::into))
 63}
 64
 65pub fn deserialize_font_properties<'de, D>(deserializer: D) -> Result<Properties, D::Error>
 66where
 67    D: Deserializer<'de>,
 68{
 69    let json: PropertiesJson = Deserialize::deserialize(deserializer)?;
 70    Ok(json.into())
 71}
 72
 73pub fn font_properties_from_json(
 74    value: serde_json::Value,
 75) -> Result<Properties, serde_json::Error> {
 76    Ok(serde_json::from_value::<PropertiesJson>(value)?.into())
 77}
 78
 79impl ToJson for Properties {
 80    fn to_json(&self) -> crate::json::Value {
 81        json!({
 82            "style": self.style.to_json(),
 83            "weight": self.weight.to_json(),
 84            "stretch": self.stretch.to_json(),
 85        })
 86    }
 87}
 88
 89impl ToJson for Style {
 90    fn to_json(&self) -> crate::json::Value {
 91        match self {
 92            Style::Normal => json!("normal"),
 93            Style::Italic => json!("italic"),
 94            Style::Oblique => json!("oblique"),
 95        }
 96    }
 97}
 98
 99impl ToJson for Weight {
100    fn to_json(&self) -> crate::json::Value {
101        if self.0 == Weight::THIN.0 {
102            json!("thin")
103        } else if self.0 == Weight::EXTRA_LIGHT.0 {
104            json!("extra light")
105        } else if self.0 == Weight::LIGHT.0 {
106            json!("light")
107        } else if self.0 == Weight::NORMAL.0 {
108            json!("normal")
109        } else if self.0 == Weight::MEDIUM.0 {
110            json!("medium")
111        } else if self.0 == Weight::SEMIBOLD.0 {
112            json!("semibold")
113        } else if self.0 == Weight::BOLD.0 {
114            json!("bold")
115        } else if self.0 == Weight::EXTRA_BOLD.0 {
116            json!("extra bold")
117        } else if self.0 == Weight::BLACK.0 {
118            json!("black")
119        } else {
120            json!(self.0)
121        }
122    }
123}
124
125impl ToJson for Stretch {
126    fn to_json(&self) -> serde_json::Value {
127        json!(self.0)
128    }
129}