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}