style: Use unified list for TextDecorationLine and implement its SpecifiedValueInfo.

Bug: 1434130
Reviewed-by: emilio
MozReview-Commit-ID: 2sCnK1AecFk
This commit is contained in:
Xidorn Quan 2018-04-29 09:03:31 +10:00 committed by Emilio Cobos Álvarez
parent 5437c96402
commit 20398491cc
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 112 additions and 122 deletions

View file

@ -15,8 +15,7 @@ use values::generics::text::InitialLetter as GenericInitialLetter;
use values::generics::text::LineHeight as GenericLineHeight; use values::generics::text::LineHeight as GenericLineHeight;
use values::generics::text::MozTabSize as GenericMozTabSize; use values::generics::text::MozTabSize as GenericMozTabSize;
use values::generics::text::Spacing; use values::generics::text::Spacing;
use values::specified::text::{TextDecorationLine, TextEmphasisFillMode}; use values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword, TextOverflowSide};
use values::specified::text::{TextEmphasisShapeKeyword, TextOverflowSide};
pub use values::specified::TextAlignKeyword as TextAlign; pub use values::specified::TextAlignKeyword as TextAlign;
pub use values::specified::TextEmphasisPosition; pub use values::specified::TextEmphasisPosition;
@ -79,36 +78,6 @@ impl ToCss for TextOverflow {
} }
} }
impl ToCss for TextDecorationLine {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> 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. /// A struct that represents the _used_ value of the text-decoration property.
/// ///
/// FIXME(emilio): This is done at style resolution time, though probably should /// FIXME(emilio): This is done at style resolution time, though probably should

View file

@ -9,7 +9,9 @@ use parser::{Parse, ParserContext};
use properties::longhands::writing_mode::computed_value::T as SpecifiedWritingMode; use properties::longhands::writing_mode::computed_value::T as SpecifiedWritingMode;
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use std::fmt::{self, Write}; 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 unicode_segmentation::UnicodeSegmentation;
use values::computed::{Context, ToComputedValue}; use values::computed::{Context, ToComputedValue};
use values::computed::text::LineHeight as ComputedLineHeight; use values::computed::text::LineHeight as ComputedLineHeight;
@ -251,20 +253,23 @@ impl ToComputedValue for TextOverflow {
} }
} }
bitflags! { macro_rules! impl_text_decoration_line {
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)] {
$(
$(#[$($meta:tt)+])*
$ident:ident / $css:expr => $value:expr,
)+
} => {
bitflags! {
#[derive(MallocSizeOf, ToComputedValue)]
/// Specified keyword values for the text-decoration-line property. /// Specified keyword values for the text-decoration-line property.
pub struct TextDecorationLine: u8 { pub struct TextDecorationLine: u8 {
/// No text decoration line is specified /// No text decoration line is specified
const NONE = 0; const NONE = 0;
/// Underline $(
const UNDERLINE = 0x01; $(#[$($meta)+])*
/// Overline const $ident = $value;
const OVERLINE = 0x02; )+
/// Line through
const LINE_THROUGH = 0x04;
/// Blink
const BLINK = 0x08;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
/// Only set by presentation attributes /// Only set by presentation attributes
/// ///
@ -275,20 +280,9 @@ bitflags! {
/// a red text decoration /// a red text decoration
const COLOR_OVERRIDE = 0x10; const COLOR_OVERRIDE = 0x10;
} }
}
#[cfg(feature = "gecko")]
impl_bitflags_conversions!(TextDecorationLine);
impl TextDecorationLine {
#[inline]
/// Returns the initial value of text-decoration-line
pub fn none() -> Self {
TextDecorationLine::NONE
} }
}
impl Parse for TextDecorationLine { impl Parse for TextDecorationLine {
/// none | [ underline || overline || line-through || blink ] /// none | [ underline || overline || line-through || blink ]
fn parse<'i, 't>( fn parse<'i, 't>(
_context: &ParserContext, _context: &ParserContext,
@ -306,38 +300,16 @@ impl Parse for TextDecorationLine {
let result = input.try(|input| { let result = input.try(|input| {
let ident = input.expect_ident().map_err(|_| ())?; let ident = input.expect_ident().map_err(|_| ())?;
match_ignore_ascii_case! { ident, match_ignore_ascii_case! { ident,
"underline" => { $(
if result.contains(TextDecorationLine::UNDERLINE) { $css => {
if result.contains(TextDecorationLine::$ident) {
Err(()) Err(())
} else { } else {
result.insert(TextDecorationLine::UNDERLINE); result.insert(TextDecorationLine::$ident);
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(()) Ok(())
} }
} }
)+
_ => Err(()), _ => Err(()),
} }
}); });
@ -352,6 +324,55 @@ impl Parse for TextDecorationLine {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
} }
} }
}
impl ToCss for TextDecorationLine {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> 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);
impl TextDecorationLine {
#[inline]
/// Returns the initial value of text-decoration-line
pub fn none() -> Self {
TextDecorationLine::NONE
}
} }
macro_rules! define_text_align_keyword { macro_rules! define_text_align_keyword {