mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
Implement parsing/serialization for text-emphasis-style
This commit is contained in:
parent
6c28d4446a
commit
6102159a4b
4 changed files with 236 additions and 1 deletions
|
@ -737,7 +737,182 @@ ${helpers.single_keyword("text-align-last",
|
|||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
<%helpers:longhand name="text-emphasis-style" products="none" animatable="False">
|
||||
use computed_values::writing_mode::T as writing_mode;
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
use values::LocalToCss;
|
||||
use values::NoViewportPercentage;
|
||||
|
||||
impl NoViewportPercentage for SpecifiedValue {}
|
||||
|
||||
pub mod computed_value {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum T {
|
||||
Keyword(Keyword),
|
||||
None,
|
||||
String(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct Keyword {
|
||||
pub fill: bool,
|
||||
pub shape: super::ShapeKeyword,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum SpecifiedValue {
|
||||
Keyword(Keyword),
|
||||
None,
|
||||
String(String),
|
||||
}
|
||||
|
||||
impl ToCss for computed_value::T {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
computed_value::T::Keyword(ref keyword) => keyword.to_css(dest),
|
||||
computed_value::T::None => dest.write_str("none"),
|
||||
computed_value::T::String(ref string) => write!(dest, "\"{}\"", string),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
SpecifiedValue::Keyword(ref keyword) => keyword.to_css(dest),
|
||||
SpecifiedValue::None => dest.write_str("none"),
|
||||
SpecifiedValue::String(ref string) => write!(dest, "\"{}\"", string),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct Keyword {
|
||||
pub fill: Option<bool>,
|
||||
pub shape: Option<ShapeKeyword>,
|
||||
}
|
||||
|
||||
impl ToCss for Keyword {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
let mut has_fill = false;
|
||||
if let Some(fill) = self.fill {
|
||||
has_fill = true;
|
||||
if fill {
|
||||
try!(dest.write_str("filled"));
|
||||
} else {
|
||||
try!(dest.write_str("open"));
|
||||
}
|
||||
}
|
||||
if let Some(shape) = self.shape {
|
||||
if has_fill {
|
||||
try!(dest.write_str(" "));
|
||||
}
|
||||
try!(shape.to_css(dest));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl ToCss for computed_value::Keyword {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
if self.fill {
|
||||
try!(dest.write_str("filled"));
|
||||
} else {
|
||||
try!(dest.write_str("open"));
|
||||
}
|
||||
try!(dest.write_str(" "));
|
||||
self.shape.to_css(dest)
|
||||
}
|
||||
}
|
||||
|
||||
define_css_keyword_enum!(ShapeKeyword:
|
||||
"dot" => Dot,
|
||||
"circle" => Circle,
|
||||
"double-circle" => DoubleCircle,
|
||||
"triangle" => Triangle,
|
||||
"sesame" => Sesame);
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T::None
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
match *self {
|
||||
SpecifiedValue::Keyword(ref keyword) => {
|
||||
let default_shape = if context.style().get_inheritedbox()
|
||||
.writing_mode == writing_mode::horizontal_tb {
|
||||
ShapeKeyword::Circle
|
||||
} else {
|
||||
ShapeKeyword::Sesame
|
||||
};
|
||||
computed_value::T::Keyword(computed_value::Keyword {
|
||||
fill: keyword.fill.unwrap_or(true),
|
||||
shape: keyword.shape.unwrap_or(default_shape)
|
||||
})
|
||||
},
|
||||
SpecifiedValue::None => computed_value::T::None,
|
||||
SpecifiedValue::String(ref s) => {
|
||||
let string = if s.len() > 1 {
|
||||
s.chars().nth(0).unwrap().to_string()
|
||||
} else { s.clone() };
|
||||
computed_value::T::String(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
match *computed {
|
||||
computed_value::T::Keyword(ref keyword) => SpecifiedValue::Keyword(Keyword {
|
||||
fill: Some(keyword.fill),
|
||||
shape: Some(keyword.shape)
|
||||
}),
|
||||
computed_value::T::None => SpecifiedValue::None,
|
||||
computed_value::T::String(ref string) => SpecifiedValue::String(string.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(SpecifiedValue::None);
|
||||
}
|
||||
|
||||
if let Ok(s) = input.try(|input| input.expect_string()) {
|
||||
// Handle <string>
|
||||
Ok(SpecifiedValue::String(s.into_owned()))
|
||||
} else {
|
||||
// Handle a pair of keywords
|
||||
let mut shape = input.try(ShapeKeyword::parse);
|
||||
let fill = if input.try(|input| input.expect_ident_matching("filled")).is_ok() {
|
||||
Some(true)
|
||||
} else if input.try(|input| input.expect_ident_matching("open")).is_ok() {
|
||||
Some(false)
|
||||
} else { None };
|
||||
if let Err(_) = shape {
|
||||
shape = input.try(ShapeKeyword::parse);
|
||||
}
|
||||
|
||||
// At least one of shape or fill must be handled
|
||||
if let (None, Err(_)) = (fill, shape) {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(SpecifiedValue::Keyword(Keyword {
|
||||
fill: fill,
|
||||
shape: shape.ok()
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
// TODO(pcwalton): `full-width`
|
||||
${helpers.single_keyword("text-transform",
|
||||
|
|
|
@ -1639,7 +1639,8 @@ pub fn cascade(viewport_size: Size2D<Au>,
|
|||
PropertyDeclaration::Color(_) |
|
||||
PropertyDeclaration::Position(_) |
|
||||
PropertyDeclaration::Float(_) |
|
||||
PropertyDeclaration::TextDecoration${'' if product == 'servo' else 'Line'}(_)
|
||||
PropertyDeclaration::TextDecoration${'' if product == 'servo' else 'Line'}(_) |
|
||||
PropertyDeclaration::TextEmphasisStyle(_)
|
||||
);
|
||||
if
|
||||
% if category_to_cascade_now == "early":
|
||||
|
|
58
tests/unit/style/parsing/inherited_text.rs
Normal file
58
tests/unit/style/parsing/inherited_text.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::Parser;
|
||||
use media_queries::CSSErrorReporterTest;
|
||||
use style::parser::ParserContext;
|
||||
use style::stylesheets::Origin;
|
||||
use url::Url;
|
||||
|
||||
#[test]
|
||||
fn text_emphasis_style_longhand_should_parse_properly() {
|
||||
use style::properties::longhands::text_emphasis_style;
|
||||
use style::properties::longhands::text_emphasis_style::{ShapeKeyword, SpecifiedValue, Keyword};
|
||||
|
||||
let none = parse_longhand!(text_emphasis_style, "none");
|
||||
assert_eq!(none, SpecifiedValue::None);
|
||||
|
||||
let fill = parse_longhand!(text_emphasis_style, "open");
|
||||
let fill_struct = SpecifiedValue::Keyword(Keyword {
|
||||
fill: Some(false),
|
||||
shape: None
|
||||
});
|
||||
assert_eq!(fill, fill_struct);
|
||||
|
||||
let shape = parse_longhand!(text_emphasis_style, "triangle");
|
||||
let shape_struct = SpecifiedValue::Keyword(Keyword {
|
||||
fill: None,
|
||||
shape: Some(ShapeKeyword::Triangle)
|
||||
});
|
||||
assert_eq!(shape, shape_struct);
|
||||
|
||||
let fill_shape = parse_longhand!(text_emphasis_style, "filled dot");
|
||||
let fill_shape_struct = SpecifiedValue::Keyword(Keyword {
|
||||
fill: Some(true),
|
||||
shape: Some(ShapeKeyword::Dot)
|
||||
});
|
||||
assert_eq!(fill_shape, fill_shape_struct);
|
||||
|
||||
let shape_fill = parse_longhand!(text_emphasis_style, "dot filled");
|
||||
let shape_fill_struct = SpecifiedValue::Keyword(Keyword {
|
||||
fill: Some(true),
|
||||
shape: Some(ShapeKeyword::Dot)
|
||||
});
|
||||
assert_eq!(shape_fill, shape_fill_struct);
|
||||
|
||||
let a_string = parse_longhand!(text_emphasis_style, "\"a\"");
|
||||
let a_string_struct = SpecifiedValue::String("a".to_string());
|
||||
assert_eq!(a_string, a_string_struct);
|
||||
|
||||
let chinese_string = parse_longhand!(text_emphasis_style, "\"点\"");
|
||||
let chinese_string_struct = SpecifiedValue::String("点".to_string());
|
||||
assert_eq!(chinese_string, chinese_string_struct);
|
||||
|
||||
let unicode_string = parse_longhand!(text_emphasis_style, "\"\\25B2\"");
|
||||
let unicode_string_struct = SpecifiedValue::String("▲".to_string());
|
||||
assert_eq!(unicode_string, unicode_string_struct);
|
||||
}
|
|
@ -63,6 +63,7 @@ macro_rules! parse_longhand {
|
|||
|
||||
mod basic_shape;
|
||||
mod image;
|
||||
mod inherited_text;
|
||||
mod mask;
|
||||
mod position;
|
||||
mod selectors;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue