lewp_css/domain/at_rules/font_face/
font_face_at_rule.rs1use {
5 super::{
6 FamilyName,
7 FontDisplay,
8 FontFace,
9 FontFeatureSettings,
10 FontLanguageOverride,
11 FontStretch,
12 FontStyle,
13 FontWeight,
14 Source,
15 },
16 crate::{
17 parsers::{FontFaceAtRuleParser, ParserContext},
18 CustomParseError,
19 },
20 cssparser::{
21 DeclarationListParser,
22 ParseError,
23 Parser,
24 ToCss,
25 UnicodeRange,
26 },
27 std::fmt,
28};
29
30#[derive(Debug, Clone)]
34pub struct FontFaceAtRule {
35 pub family: Option<FamilyName>,
37
38 pub sources: Option<Vec<Source>>,
40
41 pub style: Option<FontStyle>,
43
44 pub weight: Option<FontWeight>,
46
47 pub stretch: Option<FontStretch>,
49
50 pub display: Option<FontDisplay>,
52
53 pub unicode_range: Option<Vec<UnicodeRange>>,
55
56 pub feature_settings: Option<FontFeatureSettings>,
58
59 pub language_override: Option<FontLanguageOverride>,
61}
62
63impl ToCss for FontFaceAtRule {
64 fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
65 #[inline(always)]
66 fn writePropertyDeclaration<W: fmt::Write, T: ToCss>(
67 afterFirst: &mut bool,
68 dest: &mut W,
69 name: &str,
70 value: &Option<T>,
71 ) -> fmt::Result {
72 if let &Some(ref value) = value {
73 if *afterFirst {
74 dest.write_char(';')?;
75 } else {
76 *afterFirst = true;
77 }
78
79 dest.write_str(name)?;
80 dest.write_char(':')?;
81 value.to_css(dest)
82 } else {
83 Ok(())
84 }
85 }
86
87 #[inline(always)]
88 fn writePropertyDeclarationValues<W: fmt::Write, T: ToCss>(
89 afterFirst: &mut bool,
90 dest: &mut W,
91 name: &str,
92 value: &Option<Vec<T>>,
93 ) -> fmt::Result {
94 if let &Some(ref value) = value {
95 if value.is_empty() {
96 return Ok(());
97 }
98
99 if *afterFirst {
100 dest.write_char(';')?;
101 } else {
102 *afterFirst = true;
103 }
104
105 dest.write_str(name)?;
106 dest.write_char(':')?;
107
108 let mut iterator = value.iter();
109 iterator.next().unwrap().to_css(dest)?;
110 for value in iterator {
111 dest.write_char(',')?;
112 value.to_css(dest)?;
113 }
114 }
115
116 Ok(())
117 }
118
119 dest.write_str("@font-face{")?;
120
121 let mut afterFirst = false;
122 writePropertyDeclaration(
123 &mut afterFirst,
124 dest,
125 "font-family",
126 &self.family,
127 )?;
128 writePropertyDeclarationValues(
129 &mut afterFirst,
130 dest,
131 "src",
132 &self.sources,
133 )?;
134 writePropertyDeclaration(
135 &mut afterFirst,
136 dest,
137 "font-style",
138 &self.style,
139 )?;
140 writePropertyDeclaration(
141 &mut afterFirst,
142 dest,
143 "font-weight",
144 &self.weight,
145 )?;
146 writePropertyDeclaration(
147 &mut afterFirst,
148 dest,
149 "font-stretch",
150 &self.stretch,
151 )?;
152 writePropertyDeclaration(
153 &mut afterFirst,
154 dest,
155 "font-display",
156 &self.display,
157 )?;
158 writePropertyDeclarationValues(
159 &mut afterFirst,
160 dest,
161 "unicode-range",
162 &self.unicode_range,
163 )?;
164 writePropertyDeclaration(
165 &mut afterFirst,
166 dest,
167 "font-feature-settings",
168 &self.feature_settings,
169 )?;
170 writePropertyDeclaration(
171 &mut afterFirst,
172 dest,
173 "font-language-override",
174 &self.language_override,
175 )?;
176
177 dest.write_char('}')
178 }
179}
180
181impl FontFaceAtRule {
182 #[inline(always)]
183 fn empty() -> Self {
184 Self {
185 family: None,
186 sources: None,
187 style: None,
188 weight: None,
189 stretch: None,
190 display: None,
191 unicode_range: None,
192 feature_settings: None,
193 language_override: None,
194 }
195 }
196
197 pub(crate) fn parse_body<'i: 't, 't>(
199 context: &ParserContext,
200 input: &mut Parser<'i, 't>,
201 ) -> Result<FontFaceAtRule, ParseError<'i, CustomParseError<'i>>> {
202 let mut rule = Self::empty();
203
204 {
205 let parser = FontFaceAtRuleParser {
206 context,
207 rule: &mut rule,
208 };
209
210 let iter = DeclarationListParser::new(input, parser);
211 for declaration in iter {
212 if declaration.is_err() {
213 return Err(declaration.unwrap_err().0);
214 }
215 }
216 }
217
218 Ok(rule)
219 }
220
221 pub fn font_face(&self) -> Option<FontFace> {
225 if self.family.is_some() && self.sources.is_some() {
226 Some(FontFace(self))
227 } else {
228 None
229 }
230 }
231}