Add to_computed method for CalcLengthOrPercentage

* Add to_computed method to calculate `calc()` value with parent size,
if parent container size is `None`, the result will be `None`.
* Add from_option method for `MaybeAuto`, to construct from
`Option<Au>`.
* Update some test case.
This commit is contained in:
石博文 2017-04-20 11:27:19 +08:00
parent 5062c4b117
commit 22f99c71b9
No known key found for this signature in database
GPG key ID: FC9610D6400A173C
8 changed files with 47 additions and 32 deletions

View file

@ -324,22 +324,20 @@ impl CandidateBSizeIterator {
(LengthOrPercentageOrAuto::Percentage(percent), Some(block_container_block_size)) => { (LengthOrPercentageOrAuto::Percentage(percent), Some(block_container_block_size)) => {
MaybeAuto::Specified(block_container_block_size.scale_by(percent)) MaybeAuto::Specified(block_container_block_size.scale_by(percent))
} }
(LengthOrPercentageOrAuto::Calc(calc), Some(block_container_block_size)) => { (LengthOrPercentageOrAuto::Calc(calc), _) => {
MaybeAuto::Specified(calc.length() + block_container_block_size.scale_by(calc.percentage())) MaybeAuto::from_option(calc.to_computed(block_container_block_size))
} }
(LengthOrPercentageOrAuto::Percentage(_), None) | (LengthOrPercentageOrAuto::Percentage(_), None) |
(LengthOrPercentageOrAuto::Auto, _) | (LengthOrPercentageOrAuto::Auto, _) => MaybeAuto::Auto,
(LengthOrPercentageOrAuto::Calc(_), _) => MaybeAuto::Auto,
(LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(length), (LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(length),
}; };
let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) { let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) {
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => { (LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => {
Some(block_container_block_size.scale_by(percent)) Some(block_container_block_size.scale_by(percent))
} }
(LengthOrPercentageOrNone::Calc(calc), Some(block_container_block_size)) => { (LengthOrPercentageOrNone::Calc(calc), _) => {
Some(block_container_block_size.scale_by(calc.percentage()) + calc.length()) calc.to_computed(block_container_block_size)
} }
(LengthOrPercentageOrNone::Calc(_), _) |
(LengthOrPercentageOrNone::Percentage(_), None) | (LengthOrPercentageOrNone::Percentage(_), None) |
(LengthOrPercentageOrNone::None, _) => None, (LengthOrPercentageOrNone::None, _) => None,
(LengthOrPercentageOrNone::Length(length), _) => Some(length), (LengthOrPercentageOrNone::Length(length), _) => Some(length),
@ -348,10 +346,9 @@ impl CandidateBSizeIterator {
(LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => { (LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => {
block_container_block_size.scale_by(percent) block_container_block_size.scale_by(percent)
} }
(LengthOrPercentage::Calc(calc), Some(block_container_block_size)) => { (LengthOrPercentage::Calc(calc), _) => {
calc.length() + block_container_block_size.scale_by(calc.percentage()) calc.to_computed(block_container_block_size).unwrap_or(Au(0))
} }
(LengthOrPercentage::Calc(calc), None) => calc.length(),
(LengthOrPercentage::Percentage(_), None) => Au(0), (LengthOrPercentage::Percentage(_), None) => Au(0),
(LengthOrPercentage::Length(length), _) => length, (LengthOrPercentage::Length(length), _) => length,
}; };
@ -1168,15 +1165,14 @@ impl BlockFlow {
let content_block_size = self.fragment.style().content_block_size(); let content_block_size = self.fragment.style().content_block_size();
match (content_block_size, containing_block_size) { match (content_block_size, containing_block_size) {
(LengthOrPercentageOrAuto::Calc(calc), Some(container_size)) => { (LengthOrPercentageOrAuto::Calc(calc), _) => {
Some(container_size.scale_by(calc.percentage()) + calc.length()) calc.to_computed(containing_block_size)
} }
(LengthOrPercentageOrAuto::Length(length), _) => Some(length), (LengthOrPercentageOrAuto::Length(length), _) => Some(length),
(LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => { (LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => {
Some(container_size.scale_by(percent)) Some(container_size.scale_by(percent))
} }
(LengthOrPercentageOrAuto::Percentage(_), None) | (LengthOrPercentageOrAuto::Percentage(_), None) |
(LengthOrPercentageOrAuto::Calc(_), None) |
(LengthOrPercentageOrAuto::Auto, None) => { (LengthOrPercentageOrAuto::Auto, None) => {
None None
} }

View file

@ -53,9 +53,9 @@ impl AxisSize {
} }
} }
LengthOrPercentageOrAuto::Calc(calc) => { LengthOrPercentageOrAuto::Calc(calc) => {
match content_size { match calc.to_computed(content_size) {
Some(size) => AxisSize::Definite(size.scale_by(calc.percentage())), Some(length) => AxisSize::Definite(length),
None => AxisSize::Infinite None => AxisSize::Infinite,
} }
} }
LengthOrPercentageOrAuto::Auto => { LengthOrPercentageOrAuto::Auto => {
@ -79,10 +79,8 @@ fn from_flex_basis(flex_basis: LengthOrPercentageOrAutoOrContent,
MaybeAuto::Specified(size.scale_by(percent)), MaybeAuto::Specified(size.scale_by(percent)),
(LengthOrPercentageOrAutoOrContent::Percentage(_), None) => (LengthOrPercentageOrAutoOrContent::Percentage(_), None) =>
MaybeAuto::Auto, MaybeAuto::Auto,
(LengthOrPercentageOrAutoOrContent::Calc(calc), Some(size)) => (LengthOrPercentageOrAutoOrContent::Calc(calc), _) =>
MaybeAuto::Specified(calc.length() + size.scale_by(calc.percentage())), MaybeAuto::from_option(calc.to_computed(containing_length)),
(LengthOrPercentageOrAutoOrContent::Calc(_), None) =>
MaybeAuto::Auto,
(LengthOrPercentageOrAutoOrContent::Content, _) => (LengthOrPercentageOrAutoOrContent::Content, _) =>
MaybeAuto::Auto, MaybeAuto::Auto,
(LengthOrPercentageOrAutoOrContent::Auto, Some(size)) => (LengthOrPercentageOrAutoOrContent::Auto, Some(size)) =>

View file

@ -408,12 +408,20 @@ impl MaybeAuto {
MaybeAuto::Specified(containing_length.scale_by(percent)) MaybeAuto::Specified(containing_length.scale_by(percent))
} }
LengthOrPercentageOrAuto::Calc(calc) => { LengthOrPercentageOrAuto::Calc(calc) => {
MaybeAuto::Specified(calc.length() + containing_length.scale_by(calc.percentage())) MaybeAuto::from_option(calc.to_computed(Some(containing_length)))
} }
LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(length) LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(length)
} }
} }
#[inline]
pub fn from_option(au: Option<Au>) -> MaybeAuto {
match au {
Some(l) => MaybeAuto::Specified(l),
_ => MaybeAuto::Auto,
}
}
#[inline] #[inline]
pub fn specified_or_default(&self, default: Au) -> Au { pub fn specified_or_default(&self, default: Au) -> Au {
match *self { match *self {
@ -455,8 +463,7 @@ pub fn specified_or_none(length: LengthOrPercentageOrNone, containing_length: Au
match length { match length {
LengthOrPercentageOrNone::None => None, LengthOrPercentageOrNone::None => None,
LengthOrPercentageOrNone::Percentage(percent) => Some(containing_length.scale_by(percent)), LengthOrPercentageOrNone::Percentage(percent) => Some(containing_length.scale_by(percent)),
LengthOrPercentageOrNone::Calc(calc) => LengthOrPercentageOrNone::Calc(calc) => calc.to_computed(Some(containing_length)),
Some(containing_length.scale_by(calc.percentage()) + calc.length()),
LengthOrPercentageOrNone::Length(length) => Some(length), LengthOrPercentageOrNone::Length(length) => Some(length),
} }
} }

View file

@ -76,6 +76,16 @@ impl CalcLengthOrPercentage {
pub fn percentage(&self) -> CSSFloat { pub fn percentage(&self) -> CSSFloat {
self.percentage.unwrap_or(0.) self.percentage.unwrap_or(0.)
} }
/// If there are special rules for computing percentages in a value (e.g. the height property),
/// they apply whenever a calc() expression contains percentages.
pub fn to_computed(&self, container_len: Option<Au>) -> Option<Au> {
match (container_len, self.percentage) {
(Some(len), Some(percent)) => Some(self.length + len.scale_by(percent)),
(_, None) => Some(self.length),
_ => None,
}
}
} }
impl From<LengthOrPercentage> for CalcLengthOrPercentage { impl From<LengthOrPercentage> for CalcLengthOrPercentage {

View file

@ -4,6 +4,19 @@
use app_units::Au; use app_units::Au;
use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_length}; use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_length};
use style::values::computed::CalcLengthOrPercentage;
#[test]
fn test_length_calc() {
let calc = CalcLengthOrPercentage { length: Au(10), percentage: Some(0.2) };
assert_eq!(calc.to_computed(Some(Au(10))), Some(Au(12)));
assert_eq!(calc.to_computed(Some(Au(0))), Some(Au(10)));
assert_eq!(calc.to_computed(None), None);
let calc = CalcLengthOrPercentage { length: Au(10), percentage: None };
assert_eq!(calc.to_computed(Some(Au(0))), Some(Au(10)));
assert_eq!(calc.to_computed(None), Some(Au(10)));
}
#[test] #[test]
fn test_parse_double() { fn test_parse_double() {

View file

@ -1,3 +0,0 @@
[calc-height-block-1.htm]
type: reftest
expected: FAIL

View file

@ -1,3 +0,0 @@
[calc-max-height-block-1.htm]
type: reftest
expected: FAIL

View file

@ -1,3 +0,0 @@
[calc-min-height-block-1.htm]
type: reftest
expected: FAIL