diff --git a/components/layout/block.rs b/components/layout/block.rs index e573e422448..7c54df6e17c 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -327,8 +327,12 @@ impl CandidateBSizeIterator { (LengthOrPercentageOrAuto::Percentage(percent), Some(block_container_block_size)) => { MaybeAuto::Specified(block_container_block_size.scale_by(percent)) } + (LengthOrPercentageOrAuto::Calc(calc), Some(block_container_block_size)) => { + MaybeAuto::Specified(calc.length() + block_container_block_size.scale_by(calc.percentage())) + } (LengthOrPercentageOrAuto::Percentage(_), None) | (LengthOrPercentageOrAuto::Auto, _) => MaybeAuto::Auto, (LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(length), + (LengthOrPercentageOrAuto::Calc(calc), _) => MaybeAuto::Specified(calc.length()), }; let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) { (LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => @@ -1118,6 +1122,12 @@ impl BlockFlow { let content_block_size = self.fragment.style().content_block_size(); match (content_block_size, containing_block_size) { + (LengthOrPercentageOrAuto::Calc(calc), Some(container_size)) => { + Some(container_size.scale_by(calc.percentage()) + calc.length()) + } + (LengthOrPercentageOrAuto::Calc(calc), _) => { + Some(calc.length()) + }, (LengthOrPercentageOrAuto::Length(length), _) => Some(length), (LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => { Some(container_size.scale_by(percent)) diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 02af5569d84..8e3c92cad5e 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -463,6 +463,12 @@ impl ReplacedImageFragmentInfo { MaybeAuto::Specified(container_size.scale_by(pc)) } (LengthOrPercentageOrAuto::Percentage(_), _, None) => MaybeAuto::Auto, + (LengthOrPercentageOrAuto::Calc(calc), _, Some(container_size)) => { + MaybeAuto::Specified(calc.length() + container_size.scale_by(calc.percentage())) + } + (LengthOrPercentageOrAuto::Calc(calc), _, None) => { + MaybeAuto::Specified(calc.length()) + } (LengthOrPercentageOrAuto::Auto, Some(dom_length), _) => MaybeAuto::Specified(dom_length), (LengthOrPercentageOrAuto::Auto, None, _) => MaybeAuto::Auto, } @@ -616,6 +622,10 @@ impl IframeFragmentInfo { let computed_size = match (content_size, containing_size) { (LengthOrPercentageOrAuto::Length(length), _) => length, (LengthOrPercentageOrAuto::Percentage(pc), Some(container_size)) => container_size.scale_by(pc), + (LengthOrPercentageOrAuto::Calc(calc), Some(container_size)) => { + container_size.scale_by(calc.percentage()) + calc.length() + }, + (LengthOrPercentageOrAuto::Calc(calc), None) => calc.length(), (LengthOrPercentageOrAuto::Percentage(_), None) => default_size, (LengthOrPercentageOrAuto::Auto, _) => default_size, }; @@ -1285,6 +1295,7 @@ impl Fragment { } (Some(dom_inline_size), _) => dom_inline_size, (None, LengthOrPercentageOrAuto::Length(length)) => length, + (None, LengthOrPercentageOrAuto::Calc(calc)) => calc.length(), }; result.union_block(&IntrinsicISizes { minimum_inline_size: image_inline_size, diff --git a/components/layout/model.rs b/components/layout/model.rs index ca50b7790d3..45efadf1246 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -379,6 +379,9 @@ impl MaybeAuto { LengthOrPercentageOrAuto::Percentage(percent) => { MaybeAuto::Specified(containing_length.scale_by(percent)) } + LengthOrPercentageOrAuto::Calc(calc) => { + MaybeAuto::Specified(calc.length() + containing_length.scale_by(calc.percentage())) + } LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(length) } } diff --git a/components/layout/table.rs b/components/layout/table.rs index f5ef95f1989..2e351b117fa 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -267,11 +267,13 @@ impl Flow for TableFlow { self.column_intrinsic_inline_sizes.push(ColumnIntrinsicInlineSize { minimum_length: match *specified_inline_size { LengthOrPercentageOrAuto::Auto | + LengthOrPercentageOrAuto::Calc(_) | LengthOrPercentageOrAuto::Percentage(_) => Au(0), LengthOrPercentageOrAuto::Length(length) => length, }, percentage: match *specified_inline_size { LengthOrPercentageOrAuto::Auto | + LengthOrPercentageOrAuto::Calc(_) | LengthOrPercentageOrAuto::Length(_) => 0.0, LengthOrPercentageOrAuto::Percentage(percentage) => percentage, }, diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index e2b155bca78..eb02eade5b1 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -272,6 +272,7 @@ impl Flow for TableRowFlow { let child_column_inline_size = ColumnIntrinsicInlineSize { minimum_length: match child_specified_inline_size { LengthOrPercentageOrAuto::Auto | + LengthOrPercentageOrAuto::Calc(_) | LengthOrPercentageOrAuto::Percentage(_) => { child_base.intrinsic_inline_sizes.minimum_inline_size } @@ -279,6 +280,7 @@ impl Flow for TableRowFlow { }, percentage: match child_specified_inline_size { LengthOrPercentageOrAuto::Auto | + LengthOrPercentageOrAuto::Calc(_) | LengthOrPercentageOrAuto::Length(_) => 0.0, LengthOrPercentageOrAuto::Percentage(percentage) => percentage, }, @@ -286,6 +288,7 @@ impl Flow for TableRowFlow { constrained: match child_specified_inline_size { LengthOrPercentageOrAuto::Length(_) => true, LengthOrPercentageOrAuto::Auto | + LengthOrPercentageOrAuto::Calc(_) | LengthOrPercentageOrAuto::Percentage(_) => false, }, }; diff --git a/components/style/values.rs b/components/style/values.rs index a3dcac5a81a..c44190fff9d 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -490,6 +490,7 @@ pub mod specified { Length(Length), Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] Auto, + Calc(Calc), } impl ToCss for LengthOrPercentageOrAuto { @@ -499,6 +500,7 @@ pub mod specified { &LengthOrPercentageOrAuto::Percentage(percentage) => write!(dest, "{}%", percentage * 100.), &LengthOrPercentageOrAuto::Auto => dest.write_str("auto"), + &LengthOrPercentageOrAuto::Calc(calc) => calc.to_css(dest), } } } @@ -516,6 +518,10 @@ pub mod specified { Ok(LengthOrPercentageOrAuto::Length(Length::Absolute(Au(0)))), Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => Ok(LengthOrPercentageOrAuto::Auto), + Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { + let calc = try!(input.parse_nested_block(Calc::parse)); + Ok(LengthOrPercentageOrAuto::Calc(calc)) + }, _ => Err(()) } } @@ -1122,6 +1128,7 @@ pub mod computed { Length(Au), Percentage(CSSFloat), Auto, + Calc(Calc), } impl fmt::Debug for LengthOrPercentageOrAuto { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1129,6 +1136,8 @@ pub mod computed { &LengthOrPercentageOrAuto::Length(length) => write!(f, "{:?}", length), &LengthOrPercentageOrAuto::Percentage(percentage) => write!(f, "{}%", percentage * 100.), &LengthOrPercentageOrAuto::Auto => write!(f, "auto"), + // XXX HACK WRONG + &LengthOrPercentageOrAuto::Calc(calc) => write!(f, "{}%", 100.), } } } @@ -1148,6 +1157,9 @@ pub mod computed { specified::LengthOrPercentageOrAuto::Auto => { LengthOrPercentageOrAuto::Auto } + specified::LengthOrPercentageOrAuto::Calc(calc) => { + LengthOrPercentageOrAuto::Calc(calc.to_computed_value(context)) + } } } } @@ -1159,6 +1171,7 @@ pub mod computed { &LengthOrPercentageOrAuto::Percentage(percentage) => write!(dest, "{}%", percentage * 100.), &LengthOrPercentageOrAuto::Auto => dest.write_str("auto"), + &LengthOrPercentageOrAuto::Calc(calc) => calc.to_css(dest), } } } diff --git a/components/style/viewport.rs b/components/style/viewport.rs index 15dcac2eefe..bb38050f9b4 100644 --- a/components/style/viewport.rs +++ b/components/style/viewport.rs @@ -437,6 +437,8 @@ impl ViewportConstraints { LengthOrPercentageOrAuto::Percentage(value) => Some(initial_viewport.$dimension.scale_by(value)), LengthOrPercentageOrAuto::Auto => None, + // XXX WRONG HACK + LengthOrPercentageOrAuto::Calc(calc) => None, } } else { None