mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Move font-variant-alternates outside of mako
This commit is contained in:
parent
333c6ef7fa
commit
aeae3113bf
6 changed files with 317 additions and 205 deletions
|
@ -2402,7 +2402,7 @@ fn static_assert() {
|
||||||
<% impl_simple_type_with_conversion("font_language_override", "mFont.languageOverride") %>
|
<% impl_simple_type_with_conversion("font_language_override", "mFont.languageOverride") %>
|
||||||
|
|
||||||
pub fn set_font_variant_alternates(&mut self,
|
pub fn set_font_variant_alternates(&mut self,
|
||||||
v: longhands::font_variant_alternates::computed_value::T,
|
v: values::computed::font::FontVariantAlternates,
|
||||||
device: &Device) {
|
device: &Device) {
|
||||||
use gecko_bindings::bindings::{Gecko_ClearAlternateValues, Gecko_AppendAlternateValues};
|
use gecko_bindings::bindings::{Gecko_ClearAlternateValues, Gecko_AppendAlternateValues};
|
||||||
use gecko_bindings::bindings::Gecko_nsFont_ResetFontFeatureValuesLookup;
|
use gecko_bindings::bindings::Gecko_nsFont_ResetFontFeatureValuesLookup;
|
||||||
|
@ -2410,7 +2410,7 @@ fn static_assert() {
|
||||||
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
|
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
|
||||||
use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
|
use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
|
||||||
% endfor
|
% endfor
|
||||||
use self::longhands::font_variant_alternates::VariantAlternates;
|
use values::specified::font::VariantAlternates;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_ClearAlternateValues(&mut self.gecko.mFont, v.len());
|
Gecko_ClearAlternateValues(&mut self.gecko.mFont, v.len());
|
||||||
|
@ -2471,13 +2471,13 @@ fn static_assert() {
|
||||||
self.copy_font_variant_alternates_from(other)
|
self.copy_font_variant_alternates_from(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone_font_variant_alternates(&self) -> longhands::font_variant_alternates::computed_value::T {
|
pub fn clone_font_variant_alternates(&self) -> values::computed::font::FontVariantAlternates {
|
||||||
use Atom;
|
use Atom;
|
||||||
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
|
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
|
||||||
use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
|
use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
|
||||||
% endfor
|
% endfor
|
||||||
use properties::longhands::font_variant_alternates::VariantAlternates;
|
use values::specified::font::VariantAlternates;
|
||||||
use properties::longhands::font_variant_alternates::VariantAlternatesList;
|
use values::specified::font::VariantAlternatesList;
|
||||||
use values::CustomIdent;
|
use values::CustomIdent;
|
||||||
|
|
||||||
if self.gecko.mFont.variantAlternates == NS_FONT_VARIANT_ALTERNATES_NORMAL as u16 {
|
if self.gecko.mFont.variantAlternates == NS_FONT_VARIANT_ALTERNATES_NORMAL as u16 {
|
||||||
|
|
|
@ -670,204 +670,14 @@ ${helpers.single_keyword_system("font-kerning",
|
||||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||||
animation_value_type="discrete")}
|
animation_value_type="discrete")}
|
||||||
|
|
||||||
<%helpers:longhand name="font-variant-alternates" products="gecko" animation_value_type="discrete"
|
${helpers.predefined_type("font-variant-alternates",
|
||||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
|
"FontVariantAlternates",
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates">
|
products="gecko",
|
||||||
use properties::longhands::system_font::SystemFont;
|
initial_value="computed::FontVariantAlternates::get_initial_value()",
|
||||||
use std::fmt;
|
initial_specified_value="specified::FontVariantAlternates::get_initial_specified_value()",
|
||||||
use style_traits::ToCss;
|
animation_value_type="discrete",
|
||||||
use values::CustomIdent;
|
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||||
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates")}
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
|
||||||
pub enum VariantAlternates {
|
|
||||||
Stylistic(CustomIdent),
|
|
||||||
Styleset(Box<[CustomIdent]>),
|
|
||||||
CharacterVariant(Box<[CustomIdent]>),
|
|
||||||
Swash(CustomIdent),
|
|
||||||
Ornaments(CustomIdent),
|
|
||||||
Annotation(CustomIdent),
|
|
||||||
HistoricalForms,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
|
||||||
pub struct VariantAlternatesList(pub Box<[VariantAlternates]>);
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
|
||||||
pub enum SpecifiedValue {
|
|
||||||
Value(VariantAlternatesList),
|
|
||||||
System(SystemFont)
|
|
||||||
}
|
|
||||||
|
|
||||||
<%self:simple_system_boilerplate name="font_variant_alternates"></%self:simple_system_boilerplate>
|
|
||||||
|
|
||||||
impl ToCss for VariantAlternates {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match *self {
|
|
||||||
% for value in "swash stylistic ornaments annotation".split():
|
|
||||||
VariantAlternates::${to_camel_case(value)}(ref atom) => {
|
|
||||||
dest.write_str("${value}")?;
|
|
||||||
dest.write_str("(")?;
|
|
||||||
atom.to_css(dest)?;
|
|
||||||
dest.write_str(")")
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
% for value in "styleset character-variant".split():
|
|
||||||
VariantAlternates::${to_camel_case(value)}(ref vec) => {
|
|
||||||
dest.write_str("${value}")?;
|
|
||||||
dest.write_str("(")?;
|
|
||||||
let mut iter = vec.iter();
|
|
||||||
iter.next().unwrap().to_css(dest)?;
|
|
||||||
for c in iter {
|
|
||||||
dest.write_str(", ")?;
|
|
||||||
c.to_css(dest)?;
|
|
||||||
}
|
|
||||||
dest.write_str(")")
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
VariantAlternates::HistoricalForms => {
|
|
||||||
dest.write_str("historical-forms")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for VariantAlternatesList {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
if self.0.is_empty() {
|
|
||||||
return dest.write_str("normal");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut iter = self.0.iter();
|
|
||||||
iter.next().unwrap().to_css(dest)?;
|
|
||||||
for alternate in iter {
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
alternate.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VariantAlternatesList {
|
|
||||||
/// Returns the length of all variant alternates.
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.0.iter().fold(0, |acc, alternate| {
|
|
||||||
match *alternate {
|
|
||||||
% for value in "Swash Stylistic Ornaments Annotation".split():
|
|
||||||
VariantAlternates::${value}(_) => {
|
|
||||||
acc + 1
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
% for value in "Styleset CharacterVariant".split():
|
|
||||||
VariantAlternates::${value}(ref slice) => {
|
|
||||||
acc + slice.len()
|
|
||||||
}
|
|
||||||
% endfor
|
|
||||||
_ => acc,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod computed_value {
|
|
||||||
pub type T = super::VariantAlternatesList;
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
|
||||||
VariantAlternatesList(vec![].into_boxed_slice())
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
|
||||||
SpecifiedValue::Value(VariantAlternatesList(vec![].into_boxed_slice()))
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
|
||||||
pub struct ParsingFlags: u8 {
|
|
||||||
const NORMAL = 0;
|
|
||||||
const HISTORICAL_FORMS = 0x01;
|
|
||||||
const STYLISTIC = 0x02;
|
|
||||||
const STYLESET = 0x04;
|
|
||||||
const CHARACTER_VARIANT = 0x08;
|
|
||||||
const SWASH = 0x10;
|
|
||||||
const ORNAMENTS = 0x20;
|
|
||||||
const ANNOTATION = 0x40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// normal |
|
|
||||||
/// [ stylistic(<feature-value-name>) ||
|
|
||||||
/// historical-forms ||
|
|
||||||
/// styleset(<feature-value-name> #) ||
|
|
||||||
/// character-variant(<feature-value-name> #) ||
|
|
||||||
/// swash(<feature-value-name>) ||
|
|
||||||
/// ornaments(<feature-value-name>) ||
|
|
||||||
/// annotation(<feature-value-name>) ]
|
|
||||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
|
||||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
|
||||||
let mut alternates = Vec::new();
|
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
|
||||||
return Ok(SpecifiedValue::Value(VariantAlternatesList(alternates.into_boxed_slice())));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut parsed_alternates = ParsingFlags::empty();
|
|
||||||
macro_rules! check_if_parsed(
|
|
||||||
($input:expr, $flag:path) => (
|
|
||||||
if parsed_alternates.contains($flag) {
|
|
||||||
return Err($input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
|
||||||
}
|
|
||||||
parsed_alternates |= $flag;
|
|
||||||
)
|
|
||||||
);
|
|
||||||
while let Ok(_) = input.try(|input| {
|
|
||||||
// FIXME: remove clone() when lifetimes are non-lexical
|
|
||||||
match input.next()?.clone() {
|
|
||||||
Token::Ident(ref ident) => {
|
|
||||||
if *ident == "historical-forms" {
|
|
||||||
check_if_parsed!(input, ParsingFlags::HISTORICAL_FORMS);
|
|
||||||
alternates.push(VariantAlternates::HistoricalForms);
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Token::Function(ref name) => {
|
|
||||||
input.parse_nested_block(|i| {
|
|
||||||
match_ignore_ascii_case! { &name,
|
|
||||||
% for value in "swash stylistic ornaments annotation".split():
|
|
||||||
"${value}" => {
|
|
||||||
check_if_parsed!(i, ParsingFlags::${value.upper()});
|
|
||||||
let location = i.current_source_location();
|
|
||||||
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
|
||||||
alternates.push(VariantAlternates::${to_camel_case(value)}(ident));
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
% for value in "styleset character-variant".split():
|
|
||||||
"${value}" => {
|
|
||||||
check_if_parsed!(i, ParsingFlags:: ${to_rust_ident(value).upper()});
|
|
||||||
let idents = i.parse_comma_separated(|i| {
|
|
||||||
let location = i.current_source_location();
|
|
||||||
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
|
||||||
})?;
|
|
||||||
alternates.push(VariantAlternates::${to_camel_case(value)}(idents.into_boxed_slice()));
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
_ => return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
_ => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
|
||||||
}
|
|
||||||
}) { }
|
|
||||||
|
|
||||||
if parsed_alternates.is_empty() {
|
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
|
||||||
}
|
|
||||||
Ok(SpecifiedValue::Value(VariantAlternatesList(alternates.into_boxed_slice())))
|
|
||||||
}
|
|
||||||
</%helpers:longhand>
|
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
macro_rules! exclusive_value {
|
macro_rules! exclusive_value {
|
||||||
|
|
|
@ -265,6 +265,17 @@ impl ToAnimatedValue for FontSizeAdjust {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use VariantAlternatesList as computed type of FontVariantAlternates
|
||||||
|
pub type FontVariantAlternates = specified::VariantAlternatesList;
|
||||||
|
|
||||||
|
impl FontVariantAlternates {
|
||||||
|
#[inline]
|
||||||
|
/// Get initial value with VariantAlternatesList
|
||||||
|
pub fn get_initial_value() -> Self {
|
||||||
|
specified::VariantAlternatesList(vec![].into_boxed_slice())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToComputedValue for specified::MozScriptMinSize {
|
impl ToComputedValue for specified::MozScriptMinSize {
|
||||||
type ComputedValue = MozScriptMinSize;
|
type ComputedValue = MozScriptMinSize;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,8 @@ pub use self::angle::Angle;
|
||||||
pub use self::background::{BackgroundSize, BackgroundRepeat};
|
pub use self::background::{BackgroundSize, BackgroundRepeat};
|
||||||
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
|
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
|
||||||
pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing};
|
pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing};
|
||||||
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, MozScriptLevel, MozScriptMinSize, XTextZoom};
|
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
|
||||||
|
pub use self::font::{MozScriptLevel, MozScriptMinSize, XTextZoom};
|
||||||
pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
|
pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
|
||||||
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
|
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
|
||||||
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
|
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
|
||||||
|
|
|
@ -10,8 +10,11 @@ use app_units::Au;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use properties::longhands::system_font::SystemFont;
|
use properties::longhands::system_font::SystemFont;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use std::ascii::AsciiExt;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{ToCss, StyleParseErrorKind, ParseError};
|
use style_traits::{ToCss, StyleParseErrorKind, ParseError};
|
||||||
|
use values::CustomIdent;
|
||||||
use values::computed::{font as computed, Context, Length, NonNegativeLength, ToComputedValue};
|
use values::computed::{font as computed, Context, Length, NonNegativeLength, ToComputedValue};
|
||||||
use values::specified::{AllowQuirks, LengthOrPercentage, NoCalcLength, Number};
|
use values::specified::{AllowQuirks, LengthOrPercentage, NoCalcLength, Number};
|
||||||
use values::specified::length::{AU_PER_PT, AU_PER_PX, FontBaseSize};
|
use values::specified::length::{AU_PER_PT, AU_PER_PX, FontBaseSize};
|
||||||
|
@ -610,6 +613,292 @@ impl Parse for FontSize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
||||||
|
/// Flags of variant alternates in bit
|
||||||
|
struct VariantAlternatesParsingFlags: u8 {
|
||||||
|
/// None of variant alternates enabled
|
||||||
|
const NORMAL = 0;
|
||||||
|
/// Historical forms
|
||||||
|
const HISTORICAL_FORMS = 0x01;
|
||||||
|
/// Stylistic Alternates
|
||||||
|
const STYLISTIC = 0x02;
|
||||||
|
/// Stylistic Sets
|
||||||
|
const STYLESET = 0x04;
|
||||||
|
/// Character Variant
|
||||||
|
const CHARACTER_VARIANT = 0x08;
|
||||||
|
/// Swash glyphs
|
||||||
|
const SWASH = 0x10;
|
||||||
|
/// Ornaments glyphs
|
||||||
|
const ORNAMENTS = 0x20;
|
||||||
|
/// Annotation forms
|
||||||
|
const ANNOTATION = 0x40;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
||||||
|
/// Set of variant alternates
|
||||||
|
pub enum VariantAlternates {
|
||||||
|
/// Enables display of stylistic alternates
|
||||||
|
Stylistic(CustomIdent),
|
||||||
|
/// Enables display with stylistic sets
|
||||||
|
Styleset(Box<[CustomIdent]>),
|
||||||
|
/// Enables display of specific character variants
|
||||||
|
CharacterVariant(Box<[CustomIdent]>),
|
||||||
|
/// Enables display of swash glyphs
|
||||||
|
Swash(CustomIdent),
|
||||||
|
/// Enables replacement of default glyphs with ornaments
|
||||||
|
Ornaments(CustomIdent),
|
||||||
|
/// Enables display of alternate annotation forms
|
||||||
|
Annotation(CustomIdent),
|
||||||
|
/// Enables display of historical forms
|
||||||
|
HistoricalForms,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for VariantAlternates {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
VariantAlternates::Swash(ref atom) => {
|
||||||
|
dest.write_str("swash")?;
|
||||||
|
dest.write_str("(")?;
|
||||||
|
atom.to_css(dest)?;
|
||||||
|
dest.write_str(")")
|
||||||
|
},
|
||||||
|
VariantAlternates::Stylistic(ref atom) => {
|
||||||
|
dest.write_str("stylistic")?;
|
||||||
|
dest.write_str("(")?;
|
||||||
|
atom.to_css(dest)?;
|
||||||
|
dest.write_str(")")
|
||||||
|
},
|
||||||
|
VariantAlternates::Ornaments(ref atom) => {
|
||||||
|
dest.write_str("ornaments")?;
|
||||||
|
dest.write_str("(")?;
|
||||||
|
atom.to_css(dest)?;
|
||||||
|
dest.write_str(")")
|
||||||
|
},
|
||||||
|
VariantAlternates::Annotation(ref atom) => {
|
||||||
|
dest.write_str("annotation")?;
|
||||||
|
dest.write_str("(")?;
|
||||||
|
atom.to_css(dest)?;
|
||||||
|
dest.write_str(")")
|
||||||
|
},
|
||||||
|
VariantAlternates::Styleset(ref vec) => {
|
||||||
|
dest.write_str("styleset")?;
|
||||||
|
dest.write_str("(")?;
|
||||||
|
let mut iter = vec.iter();
|
||||||
|
iter.next().unwrap().to_css(dest)?;
|
||||||
|
for c in iter {
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
c.to_css(dest)?;
|
||||||
|
}
|
||||||
|
dest.write_str(")")
|
||||||
|
},
|
||||||
|
VariantAlternates::CharacterVariant(ref vec) => {
|
||||||
|
dest.write_str("character-variant")?;
|
||||||
|
dest.write_str("(")?;
|
||||||
|
let mut iter = vec.iter();
|
||||||
|
iter.next().unwrap().to_css(dest)?;
|
||||||
|
for c in iter {
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
c.to_css(dest)?;
|
||||||
|
}
|
||||||
|
dest.write_str(")")
|
||||||
|
},
|
||||||
|
VariantAlternates::HistoricalForms => {
|
||||||
|
dest.write_str("historical-forms")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
||||||
|
/// List of Variant Alternates
|
||||||
|
pub struct VariantAlternatesList(pub Box<[VariantAlternates]>);
|
||||||
|
|
||||||
|
impl VariantAlternatesList {
|
||||||
|
/// Returns the length of all variant alternates.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.0.iter().fold(0, |acc, alternate| {
|
||||||
|
match *alternate {
|
||||||
|
VariantAlternates::Swash(_) | VariantAlternates::Stylistic(_) |
|
||||||
|
VariantAlternates::Ornaments(_) | VariantAlternates::Annotation(_) => {
|
||||||
|
acc + 1
|
||||||
|
},
|
||||||
|
VariantAlternates::Styleset(ref slice) |
|
||||||
|
VariantAlternates::CharacterVariant(ref slice) => {
|
||||||
|
acc + slice.len()
|
||||||
|
},
|
||||||
|
_ => acc,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for VariantAlternatesList {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
if self.0.is_empty() {
|
||||||
|
return dest.write_str("normal");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut iter = self.0.iter();
|
||||||
|
iter.next().unwrap().to_css(dest)?;
|
||||||
|
for alternate in iter {
|
||||||
|
dest.write_str(" ")?;
|
||||||
|
alternate.to_css(dest)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||||
|
/// Control over the selection of these alternate glyphs
|
||||||
|
pub enum FontVariantAlternates {
|
||||||
|
/// Use alternative glyph from value
|
||||||
|
Value(VariantAlternatesList),
|
||||||
|
/// Use system font glyph
|
||||||
|
System(SystemFont)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontVariantAlternates {
|
||||||
|
#[inline]
|
||||||
|
/// Get initial specified value with VariantAlternatesList
|
||||||
|
pub fn get_initial_specified_value() -> Self {
|
||||||
|
FontVariantAlternates::Value(VariantAlternatesList(vec![].into_boxed_slice()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get FontVariantAlternates with system font
|
||||||
|
pub fn system_font(f: SystemFont) -> Self {
|
||||||
|
FontVariantAlternates::System(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get SystemFont of FontVariantAlternates
|
||||||
|
pub fn get_system(&self) -> Option<SystemFont> {
|
||||||
|
if let FontVariantAlternates::System(s) = *self {
|
||||||
|
Some(s)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for FontVariantAlternates {
|
||||||
|
type ComputedValue = computed::FontVariantAlternates;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, _context: &Context) -> computed::FontVariantAlternates {
|
||||||
|
match *self {
|
||||||
|
FontVariantAlternates::Value(ref v) => v.clone(),
|
||||||
|
FontVariantAlternates::System(_) => {
|
||||||
|
#[cfg(feature = "gecko")] {
|
||||||
|
_context.cached_system_font.as_ref().unwrap().font_variant_alternates.clone()
|
||||||
|
}
|
||||||
|
#[cfg(feature = "servo")] {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_computed_value(other: &computed::FontVariantAlternates) -> Self {
|
||||||
|
FontVariantAlternates::Value(other.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for FontVariantAlternates {
|
||||||
|
/// normal |
|
||||||
|
/// [ stylistic(<feature-value-name>) ||
|
||||||
|
/// historical-forms ||
|
||||||
|
/// styleset(<feature-value-name> #) ||
|
||||||
|
/// character-variant(<feature-value-name> #) ||
|
||||||
|
/// swash(<feature-value-name>) ||
|
||||||
|
/// ornaments(<feature-value-name>) ||
|
||||||
|
/// annotation(<feature-value-name>) ]
|
||||||
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<FontVariantAlternates, ParseError<'i>> {
|
||||||
|
let mut alternates = Vec::new();
|
||||||
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
return Ok(FontVariantAlternates::Value(VariantAlternatesList(alternates.into_boxed_slice())));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut parsed_alternates = VariantAlternatesParsingFlags::empty();
|
||||||
|
macro_rules! check_if_parsed(
|
||||||
|
($input:expr, $flag:path) => (
|
||||||
|
if parsed_alternates.contains($flag) {
|
||||||
|
return Err($input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||||
|
}
|
||||||
|
parsed_alternates |= $flag;
|
||||||
|
)
|
||||||
|
);
|
||||||
|
while let Ok(_) = input.try(|input| {
|
||||||
|
// FIXME: remove clone() when lifetimes are non-lexical
|
||||||
|
match input.next()?.clone() {
|
||||||
|
Token::Ident(ref value) if value.eq_ignore_ascii_case("historical-forms") => {
|
||||||
|
check_if_parsed!(input, VariantAlternatesParsingFlags::HISTORICAL_FORMS);
|
||||||
|
alternates.push(VariantAlternates::HistoricalForms);
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
Token::Function(ref name) => {
|
||||||
|
input.parse_nested_block(|i| {
|
||||||
|
match_ignore_ascii_case! { &name,
|
||||||
|
"swash" => {
|
||||||
|
check_if_parsed!(i, VariantAlternatesParsingFlags::SWASH);
|
||||||
|
let location = i.current_source_location();
|
||||||
|
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
||||||
|
alternates.push(VariantAlternates::Swash(ident));
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
"stylistic" => {
|
||||||
|
check_if_parsed!(i, VariantAlternatesParsingFlags::STYLISTIC);
|
||||||
|
let location = i.current_source_location();
|
||||||
|
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
||||||
|
alternates.push(VariantAlternates::Stylistic(ident));
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
"ornaments" => {
|
||||||
|
check_if_parsed!(i, VariantAlternatesParsingFlags::ORNAMENTS);
|
||||||
|
let location = i.current_source_location();
|
||||||
|
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
||||||
|
alternates.push(VariantAlternates::Ornaments(ident));
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
"annotation" => {
|
||||||
|
check_if_parsed!(i, VariantAlternatesParsingFlags::ANNOTATION);
|
||||||
|
let location = i.current_source_location();
|
||||||
|
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
||||||
|
alternates.push(VariantAlternates::Annotation(ident));
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
"styleset" => {
|
||||||
|
check_if_parsed!(i, VariantAlternatesParsingFlags::STYLESET);
|
||||||
|
let idents = i.parse_comma_separated(|i| {
|
||||||
|
let location = i.current_source_location();
|
||||||
|
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
||||||
|
})?;
|
||||||
|
alternates.push(VariantAlternates::Styleset(idents.into_boxed_slice()));
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
"character-variant" => {
|
||||||
|
check_if_parsed!(i, VariantAlternatesParsingFlags::CHARACTER_VARIANT);
|
||||||
|
let idents = i.parse_comma_separated(|i| {
|
||||||
|
let location = i.current_source_location();
|
||||||
|
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
||||||
|
})?;
|
||||||
|
alternates.push(VariantAlternates::CharacterVariant(idents.into_boxed_slice()));
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
_ => return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
_ => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||||
|
}
|
||||||
|
}) { }
|
||||||
|
|
||||||
|
if parsed_alternates.is_empty() {
|
||||||
|
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||||
|
}
|
||||||
|
Ok(FontVariantAlternates::Value(VariantAlternatesList(alternates.into_boxed_slice())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||||
/// Whether user agents are allowed to synthesize bold or oblique font faces
|
/// Whether user agents are allowed to synthesize bold or oblique font faces
|
||||||
/// when a font family lacks bold or italic faces
|
/// when a font family lacks bold or italic faces
|
||||||
|
|
|
@ -30,7 +30,8 @@ pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, Justify
|
||||||
pub use self::background::{BackgroundRepeat, BackgroundSize};
|
pub use self::background::{BackgroundRepeat, BackgroundSize};
|
||||||
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
||||||
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
|
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
|
||||||
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, MozScriptLevel, MozScriptMinSize, XTextZoom};
|
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
|
||||||
|
pub use self::font::{MozScriptLevel, MozScriptMinSize, XTextZoom};
|
||||||
pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
|
pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
|
||||||
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
|
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
|
||||||
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
|
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue