lewp_css/domain/at_rules/font_feature_values/
at_rule.rs1use {
5 super::{
6 FontFeatureValuesDeclaration,
7 PairValues,
8 SingleValue,
9 VectorValues,
10 },
11 crate::{
12 domain::at_rules::font_face::FamilyName,
13 parsers::{FontFeatureValuesAtRuleParser, ParserContext},
14 CustomParseError,
15 },
16 cssparser::{ParseError, Parser, RuleListParser, ToCss},
17 std::fmt,
18};
19
20#[derive(Clone, Debug, PartialEq)]
24pub struct FontFeatureValuesAtRule {
25 pub family_names: Vec<FamilyName>,
29
30 pub swash: Vec<FontFeatureValuesDeclaration<SingleValue>>,
32
33 pub stylistic: Vec<FontFeatureValuesDeclaration<SingleValue>>,
35
36 pub ornaments: Vec<FontFeatureValuesDeclaration<SingleValue>>,
38
39 pub annotation: Vec<FontFeatureValuesDeclaration<SingleValue>>,
41
42 pub character_variant: Vec<FontFeatureValuesDeclaration<PairValues>>,
44
45 pub styleset: Vec<FontFeatureValuesDeclaration<VectorValues>>,
47}
48
49impl ToCss for FontFeatureValuesAtRule {
50 fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
51 dest.write_str("@font-feature-values ")?;
52 self.font_family_to_css(dest)?;
53 dest.write_char('{')?;
54 self.value_to_css(dest)?;
55 dest.write_char('}')
56 }
57}
58
59impl FontFeatureValuesAtRule {
60 #[inline(always)]
61 fn new(family_names: Vec<FamilyName>) -> Self {
62 Self {
63 family_names,
64 swash: vec![],
65 stylistic: vec![],
66 ornaments: vec![],
67 annotation: vec![],
68 character_variant: vec![],
69 styleset: vec![],
70 }
71 }
72
73 pub(crate) fn parse_body<'i: 't, 't>(
74 context: &ParserContext,
75 input: &mut Parser<'i, 't>,
76 family_names: Vec<FamilyName>,
77 ) -> Result<Self, ParseError<'i, CustomParseError<'i>>> {
78 let mut fontFeatureValuesRule = Self::new(family_names);
79
80 {
81 let iterator = RuleListParser::new_for_nested_rule(
82 input,
83 FontFeatureValuesAtRuleParser {
84 context,
85 rule: &mut fontFeatureValuesRule,
86 },
87 );
88 for possiblePreciseParseError in iterator {
89 if possiblePreciseParseError.is_err() {
90 return Err(possiblePreciseParseError.unwrap_err().0);
91 }
92 }
93 }
94
95 Ok(fontFeatureValuesRule)
96 }
97
98 pub(crate) fn font_family_to_css<W: fmt::Write>(
100 &self,
101 dest: &mut W,
102 ) -> fmt::Result {
103 let mut iter = self.family_names.iter();
104 iter.next().unwrap().to_css(dest)?;
105 for val in iter {
106 dest.write_char(',')?;
107 val.to_css(dest)?;
108 }
109 Ok(())
110 }
111
112 pub(crate) fn value_to_css<W: fmt::Write>(
114 &self,
115 dest: &mut W,
116 ) -> fmt::Result {
117 #[inline(always)]
118 fn writeBlock<W: fmt::Write, T: ToCss>(
119 dest: &mut W,
120 name: &str,
121 block: &Vec<FontFeatureValuesDeclaration<T>>,
122 ) -> fmt::Result {
123 if !block.is_empty() {
124 dest.write_char('@')?;
125 dest.write_str(name)?;
126 dest.write_char('{')?;
127
128 let length = block.len();
129 if length != 0 {
130 for index in 0..(length - 1) {
131 (unsafe { block.get_unchecked(index) }).to_css(dest)?;
132 }
133 (unsafe { block.get_unchecked(length - 1) })
134 .to_css_without_trailing_semicolon(dest)?;
135 }
136
137 dest.write_char('}')
138 } else {
139 Ok(())
140 }
141 }
142
143 writeBlock(dest, "swash", &self.swash)?;
144 writeBlock(dest, "stylistic", &self.stylistic)?;
145 writeBlock(dest, "ornaments", &self.ornaments)?;
146 writeBlock(dest, "annotation", &self.annotation)?;
147 writeBlock(dest, "character-variant", &self.character_variant)?;
148 writeBlock(dest, "styleset", &self.styleset)
149 }
150
151 pub fn len(&self) -> usize {
153 let mut len = self.swash.len();
154 len += self.stylistic.len();
155 len += self.ornaments.len();
156 len += self.annotation.len();
157 len += self.character_variant.len();
158 len + self.styleset.len()
159 }
160}