use {
super::{
FontFeatureValuesDeclaration,
PairValues,
SingleValue,
VectorValues,
},
crate::{
domain::at_rules::font_face::FamilyName,
parsers::{FontFeatureValuesAtRuleParser, ParserContext},
CustomParseError,
},
cssparser::{ParseError, Parser, RuleListParser, ToCss},
std::fmt,
};
#[derive(Clone, Debug, PartialEq)]
pub struct FontFeatureValuesAtRule {
pub family_names: Vec<FamilyName>,
pub swash: Vec<FontFeatureValuesDeclaration<SingleValue>>,
pub stylistic: Vec<FontFeatureValuesDeclaration<SingleValue>>,
pub ornaments: Vec<FontFeatureValuesDeclaration<SingleValue>>,
pub annotation: Vec<FontFeatureValuesDeclaration<SingleValue>>,
pub character_variant: Vec<FontFeatureValuesDeclaration<PairValues>>,
pub styleset: Vec<FontFeatureValuesDeclaration<VectorValues>>,
}
impl ToCss for FontFeatureValuesAtRule {
fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
dest.write_str("@font-feature-values ")?;
self.font_family_to_css(dest)?;
dest.write_char('{')?;
self.value_to_css(dest)?;
dest.write_char('}')
}
}
impl FontFeatureValuesAtRule {
#[inline(always)]
fn new(family_names: Vec<FamilyName>) -> Self {
Self {
family_names,
swash: vec![],
stylistic: vec![],
ornaments: vec![],
annotation: vec![],
character_variant: vec![],
styleset: vec![],
}
}
pub(crate) fn parse_body<'i: 't, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
family_names: Vec<FamilyName>,
) -> Result<Self, ParseError<'i, CustomParseError<'i>>> {
let mut fontFeatureValuesRule = Self::new(family_names);
{
let iterator = RuleListParser::new_for_nested_rule(
input,
FontFeatureValuesAtRuleParser {
context,
rule: &mut fontFeatureValuesRule,
},
);
for possiblePreciseParseError in iterator {
if possiblePreciseParseError.is_err() {
return Err(possiblePreciseParseError.unwrap_err().0);
}
}
}
Ok(fontFeatureValuesRule)
}
pub(crate) fn font_family_to_css<W: fmt::Write>(
&self,
dest: &mut W,
) -> fmt::Result {
let mut iter = self.family_names.iter();
iter.next().unwrap().to_css(dest)?;
for val in iter {
dest.write_char(',')?;
val.to_css(dest)?;
}
Ok(())
}
pub(crate) fn value_to_css<W: fmt::Write>(
&self,
dest: &mut W,
) -> fmt::Result {
#[inline(always)]
fn writeBlock<W: fmt::Write, T: ToCss>(
dest: &mut W,
name: &str,
block: &Vec<FontFeatureValuesDeclaration<T>>,
) -> fmt::Result {
if !block.is_empty() {
dest.write_char('@')?;
dest.write_str(name)?;
dest.write_char('{')?;
let length = block.len();
if length != 0 {
for index in 0..(length - 1) {
(unsafe { block.get_unchecked(index) }).to_css(dest)?;
}
(unsafe { block.get_unchecked(length - 1) })
.to_css_without_trailing_semicolon(dest)?;
}
dest.write_char('}')
} else {
Ok(())
}
}
writeBlock(dest, "swash", &self.swash)?;
writeBlock(dest, "stylistic", &self.stylistic)?;
writeBlock(dest, "ornaments", &self.ornaments)?;
writeBlock(dest, "annotation", &self.annotation)?;
writeBlock(dest, "character-variant", &self.character_variant)?;
writeBlock(dest, "styleset", &self.styleset)
}
pub fn len(&self) -> usize {
let mut len = self.swash.len();
len += self.stylistic.len();
len += self.ornaments.len();
len += self.annotation.len();
len += self.character_variant.len();
len + self.styleset.len()
}
}