1use schemars::{
2 schema::{InstanceType, Schema, SchemaObject, SingleOrVec},
3 JsonSchema,
4};
5
6macro_rules! create_definitions {
7 ($($(#[$meta:meta])* ($name:ident, $idx:expr)),* $(,)?) => {
8
9 /// The OpenType features that can be configured for a given font.
10 #[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
11 pub struct FontFeatures {
12 enabled: u64,
13 disabled: u64,
14 }
15
16 impl FontFeatures {
17 $(
18 /// Get the current value of the corresponding OpenType feature
19 pub fn $name(&self) -> Option<bool> {
20 if (self.enabled & (1 << $idx)) != 0 {
21 Some(true)
22 } else if (self.disabled & (1 << $idx)) != 0 {
23 Some(false)
24 } else {
25 None
26 }
27 }
28 )*
29 }
30
31 impl std::fmt::Debug for FontFeatures {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 let mut debug = f.debug_struct("FontFeatures");
34 $(
35 if let Some(value) = self.$name() {
36 debug.field(stringify!($name), &value);
37 };
38 )*
39 debug.finish()
40 }
41 }
42
43 impl<'de> serde::Deserialize<'de> for FontFeatures {
44 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45 where
46 D: serde::Deserializer<'de>,
47 {
48 use serde::de::{MapAccess, Visitor};
49 use std::fmt;
50
51 struct FontFeaturesVisitor;
52
53 impl<'de> Visitor<'de> for FontFeaturesVisitor {
54 type Value = FontFeatures;
55
56 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
57 formatter.write_str("a map of font features")
58 }
59
60 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
61 where
62 M: MapAccess<'de>,
63 {
64 let mut enabled: u64 = 0;
65 let mut disabled: u64 = 0;
66
67 while let Some((key, value)) = access.next_entry::<String, Option<bool>>()? {
68 let idx = match key.as_str() {
69 $(stringify!($name) => $idx,)*
70 _ => continue,
71 };
72 match value {
73 Some(true) => enabled |= 1 << idx,
74 Some(false) => disabled |= 1 << idx,
75 None => {}
76 };
77 }
78 Ok(FontFeatures { enabled, disabled })
79 }
80 }
81
82 let features = deserializer.deserialize_map(FontFeaturesVisitor)?;
83 Ok(features)
84 }
85 }
86
87 impl serde::Serialize for FontFeatures {
88 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89 where
90 S: serde::Serializer,
91 {
92 use serde::ser::SerializeMap;
93
94 let mut map = serializer.serialize_map(None)?;
95
96 $(
97 let feature = stringify!($name);
98 if let Some(value) = self.$name() {
99 map.serialize_entry(feature, &value)?;
100 }
101 )*
102
103 map.end()
104 }
105 }
106
107 impl JsonSchema for FontFeatures {
108 fn schema_name() -> String {
109 "FontFeatures".into()
110 }
111
112 fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> Schema {
113 let mut schema = SchemaObject::default();
114 let properties = &mut schema.object().properties;
115 let feature_schema = Schema::Object(SchemaObject {
116 instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Boolean))),
117 ..Default::default()
118 });
119
120 $(
121 properties.insert(stringify!($name).to_owned(), feature_schema.clone());
122 )*
123
124 schema.into()
125 }
126 }
127 };
128}
129
130create_definitions!(
131 (calt, 0),
132 (case, 1),
133 (cpsp, 2),
134 (frac, 3),
135 (liga, 4),
136 (onum, 5),
137 (ordn, 6),
138 (pnum, 7),
139 (ss01, 8),
140 (ss02, 9),
141 (ss03, 10),
142 (ss04, 11),
143 (ss05, 12),
144 (ss06, 13),
145 (ss07, 14),
146 (ss08, 15),
147 (ss09, 16),
148 (ss10, 17),
149 (ss11, 18),
150 (ss12, 19),
151 (ss13, 20),
152 (ss14, 21),
153 (ss15, 22),
154 (ss16, 23),
155 (ss17, 24),
156 (ss18, 25),
157 (ss19, 26),
158 (ss20, 27),
159 (subs, 28),
160 (sups, 29),
161 (swsh, 30),
162 (titl, 31),
163 (tnum, 32),
164 (zero, 33)
165);