From d73fc6820998ad543a57da550eb806f58f80ef1c Mon Sep 17 00:00:00 2001 From: Ilyong Cho Date: Tue, 29 Oct 2013 20:09:46 +0900 Subject: [PATCH 1/2] Parse `min-width` and `max-width` --- src/components/style/common_types.rs | 44 +++++++++++++++++++++++++ src/components/style/properties.rs.mako | 10 +++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/components/style/common_types.rs b/src/components/style/common_types.rs index 0d61ff6c108..723ffa989e3 100644 --- a/src/components/style/common_types.rs +++ b/src/components/style/common_types.rs @@ -123,6 +123,35 @@ pub mod specified { LengthOrPercentageOrAuto::parse_internal(input, /* negative_ok = */ false) } } + + #[deriving(Clone)] + pub enum LengthOrPercentageOrNone { + LPN_Length(Length), + LPN_Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] + LPN_None, + } + impl LengthOrPercentageOrNone { + fn parse_internal(input: &ComponentValue, negative_ok: bool) + -> Option { + match input { + &Dimension(ref value, ref unit) if negative_ok || value.value >= 0. + => Length::parse_dimension(value.value, unit.as_slice()).map(LPN_Length), + &ast::Percentage(ref value) if negative_ok || value.value >= 0. + => Some(LPN_Percentage(value.value / 100.)), + &Number(ref value) if value.value == 0. => Some(LPN_Length(Au_(Au(0)))), + &Ident(ref value) if value.eq_ignore_ascii_case("none") => Some(LPN_None), + _ => None + } + } + #[inline] + pub fn parse(input: &ComponentValue) -> Option { + LengthOrPercentageOrNone::parse_internal(input, /* negative_ok = */ true) + } + #[inline] + pub fn parse_non_negative(input: &ComponentValue) -> Option { + LengthOrPercentageOrNone::parse_internal(input, /* negative_ok = */ false) + } + } } pub mod computed { @@ -185,4 +214,19 @@ pub mod computed { specified::LPA_Auto => LPA_Auto, } } + + #[deriving(Eq, Clone)] + pub enum LengthOrPercentageOrNone { + LPN_Length(Au), + LPN_Percentage(CSSFloat), + LPN_None, + } + pub fn compute_LengthOrPercentageOrNone(value: specified::LengthOrPercentageOrNone, + context: &Context) -> LengthOrPercentageOrNone { + match value { + specified::LPN_Length(value) => LPN_Length(compute_Au(value, context)), + specified::LPN_Percentage(value) => LPN_Percentage(value), + specified::LPN_None => LPN_None, + } + } } diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index c12062e504d..6204a567181 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -267,6 +267,13 @@ pub mod longhands { "computed::LPA_Auto", "parse_non_negative")} + ${predefined_type("min-width", "LengthOrPercentage", + "computed::LP_Length(Au(0))", + "parse_non_negative")} + ${predefined_type("max-width", "LengthOrPercentageOrNone", + "computed::LPN_None", + "parse_non_negative")} + <%self:single_component_value name="line-height"> #[deriving(Clone)] pub enum SpecifiedValue { @@ -1123,5 +1130,6 @@ pub mod computed_values { pub use cssparser::RGBA; pub use super::common_types::computed::{ LengthOrPercentage, LP_Length, LP_Percentage, - LengthOrPercentageOrAuto, LPA_Length, LPA_Percentage, LPA_Auto}; + LengthOrPercentageOrAuto, LPA_Length, LPA_Percentage, LPA_Auto, + LengthOrPercentageOrNone, LPN_Length, LPN_Percentage, LPN_None}; } From ce6a3ec4bdd416fdb4e482373404df6333e7ce6c Mon Sep 17 00:00:00 2001 From: Ilyong Cho Date: Tue, 29 Oct 2013 20:58:46 +0900 Subject: [PATCH 2/2] Implement max-width, min-width for BlockFlow. --- src/components/main/layout/block.rs | 33 +++++++++++++++++++++++++---- src/components/main/layout/model.rs | 20 +++++++++++++---- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index 7a852dbf117..b0745e1050f 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -9,7 +9,7 @@ use layout::context::LayoutContext; use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData}; use layout::flow::{BlockFlowClass, FlowClass, FlowContext, FlowData, ImmutableFlowUtils}; use layout::flow; -use layout::model::{MaybeAuto, Specified, Auto}; +use layout::model::{MaybeAuto, Specified, Auto, specified_or_none, specified}; use layout::float_context::{FloatContext, Invalid}; use std::cell::Cell; @@ -391,16 +391,41 @@ impl FlowContext for BlockFlow { let margin_bottom = MaybeAuto::from_style(style.Margin.margin_bottom, remaining_width).specified_or_zero(); - let (width, margin_left, margin_right) = + let (width, maybe_margin_left, maybe_margin_right) = (MaybeAuto::from_style(style.Box.width, remaining_width), MaybeAuto::from_style(style.Margin.margin_left, remaining_width), MaybeAuto::from_style(style.Margin.margin_right, remaining_width)); let (width, margin_left, margin_right) = self.compute_horiz(width, - margin_left, - margin_right, + maybe_margin_left, + maybe_margin_right, available_width); + // If the tentative used width is greater than 'max-width', width should be recalculated, + // but this time using the computed value of 'max-width' as the computed value for 'width'. + let (width, margin_left, margin_right) = { + match specified_or_none(style.Box.max_width, remaining_width) { + Some(value) if value < width => self.compute_horiz(Specified(value), + maybe_margin_left, + maybe_margin_right, + available_width), + _ => (width, margin_left, margin_right) + } + }; + // If the resulting width is smaller than 'min-width', width should be recalculated, + // but this time using the value of 'min-width' as the computed value for 'width'. + let (width, margin_left, margin_right) = { + let computed_min_width = specified(style.Box.min_width, remaining_width); + if computed_min_width > width { + self.compute_horiz(Specified(computed_min_width), + maybe_margin_left, + maybe_margin_right, + available_width) + } else { + (width, margin_left, margin_right) + } + }; + model.margin.top = margin_top; model.margin.right = margin_right; model.margin.bottom = margin_bottom; diff --git a/src/components/main/layout/model.rs b/src/components/main/layout/model.rs index 1569442f63a..f44c2ce0db0 100644 --- a/src/components/main/layout/model.rs +++ b/src/components/main/layout/model.rs @@ -104,9 +104,21 @@ impl BoxModel { } pub fn compute_padding_length(&self, padding: computed::LengthOrPercentage, content_box_width: Au) -> Au { - match padding { - computed::LP_Length(length) => length, - computed::LP_Percentage(p) => content_box_width.scale_by(p) - } + specified(padding, content_box_width) + } +} + +pub fn specified_or_none(length: computed::LengthOrPercentageOrNone, containing_length: Au) -> Option { + match length { + computed::LPN_None => None, + computed::LPN_Percentage(percent) => Some(containing_length.scale_by(percent)), + computed::LPN_Length(length) => Some(length), + } +} + +pub fn specified(length: computed::LengthOrPercentage, containing_length: Au) -> Au { + match length { + computed::LP_Length(length) => length, + computed::LP_Percentage(p) => containing_length.scale_by(p) } }