diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-09-25 16:04:45 +0200 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-09-25 16:07:33 +0200 |
commit | 638ba2ce6dad43b6db9ec408a4115091807846ac (patch) | |
tree | 233a8494d92de01487249f9c607ef492c719b72a | |
parent | 614da6b4a166def7dfb522ada92ad535283ae608 (diff) | |
download | servo-638ba2ce6dad43b6db9ec408a4115091807846ac.tar.gz servo-638ba2ce6dad43b6db9ec408a4115091807846ac.zip |
style: Simplify paint-order serialization when possible.
This matches Gecko, and fixes the last reported case in bug 1397619.
MozReview-Commit-ID: 4Z7GeaokKE1
Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
-rw-r--r-- | components/style/properties/longhand/inherited_svg.mako.rs | 92 |
1 files changed, 56 insertions, 36 deletions
diff --git a/components/style/properties/longhand/inherited_svg.mako.rs b/components/style/properties/longhand/inherited_svg.mako.rs index e9bf1cda65c..920c12f3f44 100644 --- a/components/style/properties/longhand/inherited_svg.mako.rs +++ b/components/style/properties/longhand/inherited_svg.mako.rs @@ -137,21 +137,27 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)", use std::fmt; use style_traits::ToCss; - pub const NORMAL: u8 = 0; - pub const FILL: u8 = 1; - pub const STROKE: u8 = 2; - pub const MARKERS: u8 = 3; - - // number of bits for each component - pub const SHIFT: u8 = 2; - // mask with above bits set - pub const MASK: u8 = 0b11; - // number of non-normal keyword values - pub const COUNT: u8 = 3; - // all keywords - pub const ALL: [u8; 3] = [FILL, STROKE, MARKERS]; - - /// Represented as a six-bit field, of 3 two-bit pairs + /// The specified value for a single CSS paint-order property. + #[repr(u8)] + #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, ToCss)] + pub enum PaintOrder { + Normal = 0, + Fill = 1, + Stroke = 2, + Markers = 3, + } + + /// Number of non-normal components. + const COUNT: u8 = 3; + + /// Number of bits for each component + const SHIFT: u8 = 2; + + /// Mask with above bits set + const MASK: u8 = 0b11; + + /// The specified value is tree `PaintOrder` values packed into the + /// bitfields below, as a six-bit field, of 3 two-bit pairs /// /// Each pair can be set to FILL, STROKE, or MARKERS /// Lowest significant bit pairs are highest priority. @@ -165,24 +171,33 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)", #[derive(Clone, Copy, Debug, PartialEq, ToComputedValue)] pub struct SpecifiedValue(pub u8); + impl SpecifiedValue { + fn normal() -> Self { + SpecifiedValue(0) + } + } + pub mod computed_value { pub use super::SpecifiedValue as T; } pub fn get_initial_value() -> SpecifiedValue { - SpecifiedValue(NORMAL) + SpecifiedValue::normal() } impl SpecifiedValue { - pub fn bits_at(&self, pos: u8) -> u8 { - (self.0 >> pos * SHIFT) & MASK + fn order_at(&self, pos: u8) -> PaintOrder { + // Safe because PaintOrder covers all possible patterns. + unsafe { ::std::mem::transmute((self.0 >> pos * SHIFT) & MASK) } } } - pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result<SpecifiedValue,ParseError<'i>> { + pub fn parse<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't> + ) -> Result<SpecifiedValue,ParseError<'i>> { if let Ok(()) = input.try(|i| i.expect_ident_matching("normal")) { - return Ok(SpecifiedValue(0)) + return Ok(SpecifiedValue::normal()) } let mut value = 0; @@ -194,21 +209,21 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)", loop { let result: Result<_, ParseError> = input.try(|i| { try_match_ident_ignore_ascii_case! { i.expect_ident()?, - "fill" => Ok(FILL), - "stroke" => Ok(STROKE), - "markers" => Ok(MARKERS), + "fill" => Ok(PaintOrder::Fill), + "stroke" => Ok(PaintOrder::Stroke), + "markers" => Ok(PaintOrder::Markers), } }); match result { Ok(val) => { - if (seen & (1 << val)) != 0 { + if (seen & (1 << val as u8)) != 0 { // don't parse the same ident twice return Err(StyleParseError::UnspecifiedError.into()) } - value |= val << (pos * SHIFT); - seen |= 1 << val; + value |= (val as u8) << (pos * SHIFT); + seen |= 1 << (val as u8); pos += 1; } Err(_) => break, @@ -216,13 +231,13 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)", } if value == 0 { - // couldn't find any keyword + // Couldn't find any keyword return Err(StyleParseError::UnspecifiedError.into()) } // fill in rest for i in pos..COUNT { - for paint in &ALL { + for paint in 0..COUNT { // if not seen, set bit at position, mark as seen if (seen & (1 << paint)) == 0 { seen |= 1 << paint; @@ -241,16 +256,21 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)", return dest.write_str("normal") } - for pos in 0..COUNT { + let mut last_pos_to_serialize = 0; + for i in (1..COUNT).rev() { + let component = self.order_at(i); + let earlier_component = self.order_at(i - 1); + if component < earlier_component { + last_pos_to_serialize = i - 1; + break; + } + } + + for pos in 0..last_pos_to_serialize + 1 { if pos != 0 { dest.write_str(" ")? } - match self.bits_at(pos) { - FILL => dest.write_str("fill")?, - STROKE => dest.write_str("stroke")?, - MARKERS => dest.write_str("markers")?, - _ => unreachable!(), - } + self.order_at(pos).to_css(dest)?; } Ok(()) } |