diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-09-01 12:50:32 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-01 12:50:32 -0500 |
commit | 6c68680581afbdd59034cb1535bfd4439cfa7394 (patch) | |
tree | a316485e2a688decbc3bbfb716aa6446828fb40b /components | |
parent | fbf77e40fefee85bab516adc0ca5d963f55e557b (diff) | |
parent | bf00733e02320bae6dad400e773df7e5ba007aec (diff) | |
download | servo-6c68680581afbdd59034cb1535bfd4439cfa7394.tar.gz servo-6c68680581afbdd59034cb1535bfd4439cfa7394.zip |
Auto merge of #13122 - Manishearth:basic-shape-position-redux, r=SimonSapin
Handle specialized serialization of <position> in basic shapes
Fixes #13083
We temporarily broke basic-shape serialization in #13042 when 4-value positions were implemented, since I didn't want to increase the scope of that PR too much.
This fixes it.
r? @SimonSapin
cc @canaltinova
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13122)
<!-- Reviewable:end -->
Diffstat (limited to 'components')
-rw-r--r-- | components/style/values/specified/basic_shape.rs | 89 |
1 files changed, 86 insertions, 3 deletions
diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index e683b30e726..11da6b80598 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -16,7 +16,7 @@ use values::computed::basic_shape as computed_basic_shape; use values::computed::{Context, ToComputedValue, ComputedValueAsSpecified}; use values::specified::UrlExtraData; use values::specified::position::{Keyword, Position}; -use values::specified::{BorderRadiusSize, LengthOrPercentage}; +use values::specified::{BorderRadiusSize, LengthOrPercentage, Percentage}; /// A shape source, for some reference box /// @@ -241,6 +241,89 @@ impl ToComputedValue for InsetRect { } } +/// https://drafts.csswg.org/css-shapes/#basic-shape-serialization +/// +/// Positions get serialized differently with basic shapes. Keywords +/// are converted to percentages where possible. Only the two or four +/// value forms are used. In case of two keyword-percentage pairs, +/// the keywords are folded into the percentages +fn serialize_basicshape_position<W>(position: &Position, dest: &mut W) + -> fmt::Result where W: fmt::Write { + use values::specified::Length; + use values::specified::position::Keyword; + + // keyword-percentage pairs can be folded into a single percentage + fn fold_keyword(keyword: Option<Keyword>, length: Option<LengthOrPercentage>) + -> Option<LengthOrPercentage> { + let pc = match length.map(replace_with_percent) { + None => Percentage(0.0), // unspecified length = 0% + Some(LengthOrPercentage::Percentage(pc)) => pc, + _ => return None + }; + let percent = match keyword { + Some(Keyword::Center) => { + // center cannot pair with lengths + assert!(length.is_none()); + Percentage(0.5) + }, + Some(Keyword::Left) | Some(Keyword::Top) | None => pc, + Some(Keyword::Right) | Some(Keyword::Bottom) => Percentage(1.0 - pc.0), + }; + Some(LengthOrPercentage::Percentage(percent)) + } + + // 0 length should be replaced with 0% + fn replace_with_percent(input: LengthOrPercentage) -> LengthOrPercentage { + match input { + LengthOrPercentage::Length(Length::Absolute(au)) if au.0 == 0 => { + LengthOrPercentage::Percentage(Percentage(0.0)) + } + _ => { + input + } + } + } + + fn serialize_position_pair<W>(x: LengthOrPercentage, y: LengthOrPercentage, + dest: &mut W) -> fmt::Result where W: fmt::Write { + try!(replace_with_percent(x).to_css(dest)); + try!(dest.write_str(" ")); + replace_with_percent(y).to_css(dest) + } + + match (position.horiz_keyword, position.horiz_position, + position.vert_keyword, position.vert_position) { + (Some(hk), None, Some(vk), None) => { + // two keywords: serialize as two lengths + serialize_position_pair(hk.to_length_or_percentage(), + vk.to_length_or_percentage(), + dest) + } + (None, Some(hp), None, Some(vp)) => { + // two lengths: just serialize regularly + serialize_position_pair(hp, vp, dest) + } + (hk, hp, vk, vp) => { + // only fold if both fold; the three-value form isn't + // allowed here. + if let (Some(x), Some(y)) = (fold_keyword(hk, hp), fold_keyword(vk, vp)) { + serialize_position_pair(x, y, dest) + } else { + // We failed to reduce it to a two-value form, + // so we expand it to 4-value + let zero = LengthOrPercentage::Percentage(Percentage(0.0)); + try!(hk.unwrap_or(Keyword::Left).to_css(dest)); + try!(dest.write_str(" ")); + try!(replace_with_percent(hp.unwrap_or(zero)).to_css(dest)); + try!(dest.write_str(" ")); + try!(vk.unwrap_or(Keyword::Top).to_css(dest)); + try!(dest.write_str(" ")); + replace_with_percent(vp.unwrap_or(zero)).to_css(dest) + } + } + } +} + #[derive(Clone, PartialEq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] /// https://drafts.csswg.org/css-shapes/#funcdef-circle @@ -286,7 +369,7 @@ impl ToCss for Circle { try!(dest.write_str(" ")); } try!(dest.write_str("at ")); - try!(self.position.to_css(dest)); + try!(serialize_basicshape_position(&self.position, dest)); dest.write_str(")") } } @@ -355,7 +438,7 @@ impl ToCss for Ellipse { try!(dest.write_str(" ")); } try!(dest.write_str("at ")); - try!(self.position.to_css(dest)); + try!(serialize_basicshape_position(&self.position, dest)); dest.write_str(")") } } |