From bb381a435631160d8304d33617a53800aad0b41d Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Sun, 29 Apr 2018 09:03:31 +1000 Subject: [PATCH] Bug 1434130 part 9 - Use unified list for TextDecorationLine and implement its SpecifiedValueInfo. r=emilio MozReview-Commit-ID: 2sCnK1AecFk --HG-- extra : source : adc038d9c64ae32ca74ecaa46ca5cf0b9d5fdb77 --- .../components/style/values/computed/text.rs | 33 +-- .../components/style/values/specified/text.rs | 201 ++++++++++-------- 2 files changed, 112 insertions(+), 122 deletions(-) diff --git a/servo/components/style/values/computed/text.rs b/servo/components/style/values/computed/text.rs index 7afb774effc4..f2bcf11fe62f 100644 --- a/servo/components/style/values/computed/text.rs +++ b/servo/components/style/values/computed/text.rs @@ -15,8 +15,7 @@ use values::generics::text::InitialLetter as GenericInitialLetter; use values::generics::text::LineHeight as GenericLineHeight; use values::generics::text::MozTabSize as GenericMozTabSize; use values::generics::text::Spacing; -use values::specified::text::{TextDecorationLine, TextEmphasisFillMode}; -use values::specified::text::{TextEmphasisShapeKeyword, TextOverflowSide}; +use values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword, TextOverflowSide}; pub use values::specified::TextAlignKeyword as TextAlign; pub use values::specified::TextEmphasisPosition; @@ -79,36 +78,6 @@ impl ToCss for TextOverflow { } } -impl ToCss for TextDecorationLine { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: Write, - { - let mut has_any = false; - - macro_rules! write_value { - ($line:path => $css:expr) => { - if self.contains($line) { - if has_any { - dest.write_str(" ")?; - } - dest.write_str($css)?; - has_any = true; - } - }; - } - write_value!(TextDecorationLine::UNDERLINE => "underline"); - write_value!(TextDecorationLine::OVERLINE => "overline"); - write_value!(TextDecorationLine::LINE_THROUGH => "line-through"); - write_value!(TextDecorationLine::BLINK => "blink"); - if !has_any { - dest.write_str("none")?; - } - - Ok(()) - } -} - /// A struct that represents the _used_ value of the text-decoration property. /// /// FIXME(emilio): This is done at style resolution time, though probably should diff --git a/servo/components/style/values/specified/text.rs b/servo/components/style/values/specified/text.rs index 4bae78fc8f03..70947ac08262 100644 --- a/servo/components/style/values/specified/text.rs +++ b/servo/components/style/values/specified/text.rs @@ -9,7 +9,9 @@ use parser::{Parse, ParserContext}; use properties::longhands::writing_mode::computed_value::T as SpecifiedWritingMode; use selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Write}; -use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; +use style_traits::{CssWriter, KeywordsCollectFn, ParseError}; +use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; +use style_traits::values::SequenceWriter; use unicode_segmentation::UnicodeSegmentation; use values::computed::{Context, ToComputedValue}; use values::computed::text::LineHeight as ComputedLineHeight; @@ -251,32 +253,117 @@ impl ToComputedValue for TextOverflow { } } -bitflags! { - #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)] - /// Specified keyword values for the text-decoration-line property. - pub struct TextDecorationLine: u8 { - /// No text decoration line is specified - const NONE = 0; - /// Underline - const UNDERLINE = 0x01; - /// Overline - const OVERLINE = 0x02; - /// Line through - const LINE_THROUGH = 0x04; - /// Blink - const BLINK = 0x08; - #[cfg(feature = "gecko")] - /// Only set by presentation attributes - /// - /// Setting this will mean that text-decorations use the color - /// specified by `color` in quirks mode. - /// - /// For example, this gives text - /// a red text decoration - const COLOR_OVERRIDE = 0x10; +macro_rules! impl_text_decoration_line { + { + $( + $(#[$($meta:tt)+])* + $ident:ident / $css:expr => $value:expr, + )+ + } => { + bitflags! { + #[derive(MallocSizeOf, ToComputedValue)] + /// Specified keyword values for the text-decoration-line property. + pub struct TextDecorationLine: u8 { + /// No text decoration line is specified + const NONE = 0; + $( + $(#[$($meta)+])* + const $ident = $value; + )+ + #[cfg(feature = "gecko")] + /// Only set by presentation attributes + /// + /// Setting this will mean that text-decorations use the color + /// specified by `color` in quirks mode. + /// + /// For example, this gives text + /// a red text decoration + const COLOR_OVERRIDE = 0x10; + } + } + + impl Parse for TextDecorationLine { + /// none | [ underline || overline || line-through || blink ] + fn parse<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + let mut result = TextDecorationLine::NONE; + if input + .try(|input| input.expect_ident_matching("none")) + .is_ok() + { + return Ok(result); + } + + loop { + let result = input.try(|input| { + let ident = input.expect_ident().map_err(|_| ())?; + match_ignore_ascii_case! { ident, + $( + $css => { + if result.contains(TextDecorationLine::$ident) { + Err(()) + } else { + result.insert(TextDecorationLine::$ident); + Ok(()) + } + } + )+ + _ => Err(()), + } + }); + if result.is_err() { + break; + } + } + + if !result.is_empty() { + Ok(result) + } else { + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + } + } + } + + impl ToCss for TextDecorationLine { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + if self.is_empty() { + return dest.write_str("none"); + } + + let mut writer = SequenceWriter::new(dest, " "); + $( + if self.contains(TextDecorationLine::$ident) { + writer.raw_item($css)?; + } + )+ + Ok(()) + } + } + + impl SpecifiedValueInfo for TextDecorationLine { + fn collect_completion_keywords(f: KeywordsCollectFn) { + f(&["none", $($css,)+]); + } + } } } +impl_text_decoration_line! { + /// Underline + UNDERLINE / "underline" => 1 << 0, + /// Overline + OVERLINE / "overline" => 1 << 1, + /// Line through + LINE_THROUGH / "line-through" => 1 << 2, + /// Blink + BLINK / "blink" => 1 << 3, +} + #[cfg(feature = "gecko")] impl_bitflags_conversions!(TextDecorationLine); @@ -288,72 +375,6 @@ impl TextDecorationLine { } } -impl Parse for TextDecorationLine { - /// none | [ underline || overline || line-through || blink ] - fn parse<'i, 't>( - _context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - let mut result = TextDecorationLine::NONE; - if input - .try(|input| input.expect_ident_matching("none")) - .is_ok() - { - return Ok(result); - } - - loop { - let result = input.try(|input| { - let ident = input.expect_ident().map_err(|_| ())?; - match_ignore_ascii_case! { ident, - "underline" => { - if result.contains(TextDecorationLine::UNDERLINE) { - Err(()) - } else { - result.insert(TextDecorationLine::UNDERLINE); - Ok(()) - } - } - "overline" => { - if result.contains(TextDecorationLine::OVERLINE) { - Err(()) - } else { - result.insert(TextDecorationLine::OVERLINE); - Ok(()) - } - } - "line-through" => { - if result.contains(TextDecorationLine::LINE_THROUGH) { - Err(()) - } else { - result.insert(TextDecorationLine::LINE_THROUGH); - Ok(()) - } - } - "blink" => { - if result.contains(TextDecorationLine::BLINK) { - Err(()) - } else { - result.insert(TextDecorationLine::BLINK); - Ok(()) - } - } - _ => Err(()), - } - }); - if result.is_err() { - break; - } - } - - if !result.is_empty() { - Ok(result) - } else { - Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) - } - } -} - macro_rules! define_text_align_keyword { ($( $(#[$($meta:tt)+])*