aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/block.rs103
-rw-r--r--components/layout/flow.rs20
-rw-r--r--components/layout/fragment.rs43
-rw-r--r--components/layout/inline.rs2
-rw-r--r--components/layout/list_item.rs2
-rw-r--r--components/layout/model.rs39
-rw-r--r--components/script/dom/element.rs15
-rw-r--r--components/style/properties.mako.rs42
-rw-r--r--components/style/values.rs1
-rw-r--r--tests/wpt/metadata-css/css21_dev/html4/block-in-inline-percents-001.htm.ini3
10 files changed, 151 insertions, 119 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs
index c7304865ecb..7bd383b30e8 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -699,7 +699,7 @@ impl BlockFlow {
/// Right now, this only gets the containing block size for absolutely positioned elements.
/// Note: We assume this is called in a top-down traversal, so it is ok to reference the CB.
#[inline]
- pub fn containing_block_size(&mut self, viewport_size: &Size2D<Au>, descendant: OpaqueFlow)
+ pub fn containing_block_size(&self, viewport_size: &Size2D<Au>, descendant: OpaqueFlow)
-> LogicalSize<Au> {
debug_assert!(self.base.flags.contains(IS_ABSOLUTELY_POSITIONED));
if self.is_fixed() {
@@ -929,6 +929,7 @@ impl BlockFlow {
let (collapsible_margins, delta) =
margin_collapse_info.finish_and_compute_collapsible_margins(
&self.fragment,
+ self.base.block_container_explicit_block_size,
can_collapse_block_end_margin_with_kids);
self.base.collapsible_margins = collapsible_margins;
translate_including_floats(&mut cur_b, delta, &mut floats);
@@ -1095,14 +1096,69 @@ impl BlockFlow {
self.base.position.size);
}
+ pub fn explicit_block_containing_size(&self, layout_context: &LayoutContext) -> Option<Au> {
+ if self.is_root() || self.is_fixed() {
+ let screen_size = LogicalSize::from_physical(self.fragment.style.writing_mode,
+ layout_context.shared.screen_size);
+ Some(screen_size.block)
+ } else if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
+ self.base.absolute_cb.explicit_block_containing_size(layout_context)
+ } else {
+ self.base.block_container_explicit_block_size
+ }
+ }
+
+ fn explicit_block_size(&self, containing_block_size: Option<Au>) -> Option<Au> {
+ let content_block_size = self.fragment.style().content_block_size();
+
+ match (content_block_size, containing_block_size) {
+ (LengthOrPercentageOrAuto::Length(length), _) => Some(length),
+ (LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => {
+ Some(container_size.scale_by(percent))
+ }
+ (LengthOrPercentageOrAuto::Percentage(_), None) => {
+ None
+ }
+ (LengthOrPercentageOrAuto::Auto, None) => {
+ None
+ }
+ (LengthOrPercentageOrAuto::Auto, Some(container_size)) => {
+ let (block_start, block_end) = {
+ let position = self.fragment.style().logical_position();
+ (MaybeAuto::from_style(position.block_start, container_size),
+ MaybeAuto::from_style(position.block_end, container_size))
+ };
+
+ match (block_start, block_end) {
+ (MaybeAuto::Specified(block_start), MaybeAuto::Specified(block_end)) => {
+ let available_block_size = container_size - self.fragment.border_padding.block_start_end();
+
+ // Non-auto margin-block-start and margin-block-end values have already been
+ // calculated during assign-inline-size.
+ let margin = self.fragment.style().logical_margin();
+ let margin_block_start = match margin.block_start {
+ LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto,
+ _ => MaybeAuto::Specified(self.fragment.margin.block_start)
+ };
+ let margin_block_end = match margin.block_end {
+ LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto,
+ _ => MaybeAuto::Specified(self.fragment.margin.block_end)
+ };
+
+ let margin_block_start = margin_block_start.specified_or_zero();
+ let margin_block_end = margin_block_end.specified_or_zero();
+ let sum = block_start + block_end + margin_block_start + margin_block_end;
+ Some(available_block_size - sum)
+ }
+
+ (_, _) => {
+ None
+ }
+ }
+ }
+ }
+ }
- /// Calculate and set the block-size, offsets, etc. for absolutely positioned flow.
- ///
- /// The layout for its in-flow children has been done during normal layout.
- /// This is just the calculation of:
- /// + block-size for the flow
- /// + position in the block direction of the flow with respect to its Containing Block.
- /// + block-size, vertical margins, and y-coordinate for the flow's box.
fn calculate_absolute_block_size_and_margins(&mut self, layout_context: &LayoutContext) {
let opaque_self = OpaqueFlow::from_flow(self);
let containing_block_block_size =
@@ -1140,7 +1196,7 @@ impl BlockFlow {
// Calculate used value of block-size just like we do for inline replaced elements.
// TODO: Pass in the containing block block-size when Fragment's
// assign-block-size can handle it correctly.
- self.fragment.assign_replaced_block_size_if_necessary(containing_block_block_size);
+ self.fragment.assign_replaced_block_size_if_necessary(Some(containing_block_block_size));
// TODO: Right now, this content block-size value includes the
// margin because of erroneous block-size calculation in fragment.
// Check this when that has been fixed.
@@ -1248,28 +1304,13 @@ impl BlockFlow {
inline_size_of_preceding_right_floats = self.inline_size_of_preceding_right_floats;
}
- // Calculate non-auto block size to pass to children.
- let content_block_size = self.fragment.style().content_block_size();
-
- let parent_container_size = if self.is_root() {
- let screen_size = LogicalSize::from_physical(self.fragment.style.writing_mode,
- layout_context.shared.screen_size);
- Some(screen_size.block)
- } else {
- self.base.block_container_explicit_block_size
- };
+ let opaque_self = OpaqueFlow::from_flow(self);
- let explicit_content_size = match (content_block_size, parent_container_size) {
- (LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => {
- Some(container_size.scale_by(percent))
- }
- (LengthOrPercentageOrAuto::Percentage(_), None) |
- (LengthOrPercentageOrAuto::Auto, _) => None,
- (LengthOrPercentageOrAuto::Length(length), _) => Some(length),
- };
+ // Calculate non-auto block size to pass to children.
+ let parent_container_size = self.explicit_block_containing_size(layout_context);
+ let explicit_content_size = self.explicit_block_size(parent_container_size);
// Calculate containing block inline size.
- let opaque_self = OpaqueFlow::from_flow(self);
let containing_block_size = if flags.contains(IS_ABSOLUTELY_POSITIONED) {
self.containing_block_size(&layout_context.shared.screen_size, opaque_self).inline
} else {
@@ -1286,7 +1327,9 @@ impl BlockFlow {
while let Some((i, kid)) = iterator.next() {
{
let kid_base = flow::mut_base(kid);
- kid_base.block_container_explicit_block_size = explicit_content_size;
+ if !kid_base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
+ kid_base.block_container_explicit_block_size = explicit_content_size;
+ }
}
// Determine float impaction, and update the inline size speculations if necessary.
@@ -1675,7 +1718,7 @@ impl Flow for BlockFlow {
// Assign block-size for fragment if it is an image fragment.
let containing_block_block_size =
- self.base.block_container_explicit_block_size.unwrap_or(Au(0));
+ self.base.block_container_explicit_block_size;
self.fragment.assign_replaced_block_size_if_necessary(containing_block_block_size);
if !self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
self.base.position.size.block = self.fragment.border_box.size.block;
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index 64ee4d2e0d2..d315b9962db 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -1389,7 +1389,7 @@ impl ContainingBlockLink {
}
#[inline]
- pub fn generated_containing_block_size(&mut self, for_flow: OpaqueFlow) -> LogicalSize<Au> {
+ pub fn generated_containing_block_size(&self, for_flow: OpaqueFlow) -> LogicalSize<Au> {
match self.link {
None => {
panic!("Link to containing block not established; perhaps you forgot to call \
@@ -1398,6 +1398,24 @@ impl ContainingBlockLink {
Some(ref link) => link.upgrade().unwrap().generated_containing_block_size(for_flow),
}
}
+
+ #[inline]
+ pub fn explicit_block_containing_size(&self, layout_context: &LayoutContext) -> Option<Au> {
+ match self.link {
+ None => {
+ panic!("Link to containing block not established; perhaps you forgot to call \
+ `set_absolute_descendants`?")
+ }
+ Some(ref link) => {
+ let flow = link.upgrade().unwrap();
+ if flow.is_block_like() {
+ flow.as_immutable_block().explicit_block_containing_size(layout_context)
+ } else {
+ None
+ }
+ }
+ }
+ }
}
/// A wrapper for the pointer address of a flow. These pointer addresses may only be compared for
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 7285adca0e3..475535bbe97 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -216,10 +216,10 @@ impl fmt::Debug for SpecificFragmentInfo {
fn clamp_size(size: Au,
min_size: LengthOrPercentage,
max_size: LengthOrPercentageOrNone,
- container_inline_size: Au)
+ container_size: Au)
-> Au {
- let min_size = model::specified(min_size, container_inline_size);
- let max_size = model::specified_or_none(max_size, container_inline_size);
+ let min_size = model::specified(min_size, container_size);
+ let max_size = model::specified_or_none(max_size, container_size);
max(min_size, match max_size {
None => size,
@@ -442,11 +442,15 @@ impl ReplacedImageFragmentInfo {
// `style_length`: inline-size as given in the CSS
pub fn style_length(style_length: LengthOrPercentageOrAuto,
dom_length: Option<Au>,
- container_inline_size: Au) -> MaybeAuto {
- match (MaybeAuto::from_style(style_length,container_inline_size), dom_length) {
- (MaybeAuto::Specified(length), _) => MaybeAuto::Specified(length),
- (MaybeAuto::Auto, Some(length)) => MaybeAuto::Specified(length),
- (MaybeAuto::Auto, None) => MaybeAuto::Auto,
+ container_size: Option<Au>) -> MaybeAuto {
+ match (style_length, dom_length, container_size) {
+ (LengthOrPercentageOrAuto::Length(length), _, _) => MaybeAuto::Specified(length),
+ (LengthOrPercentageOrAuto::Percentage(pc), _, Some(container_size)) => {
+ MaybeAuto::Specified(container_size.scale_by(pc))
+ }
+ (LengthOrPercentageOrAuto::Percentage(_), _, None) => MaybeAuto::Auto,
+ (LengthOrPercentageOrAuto::Auto, Some(dom_length), _) => MaybeAuto::Specified(dom_length),
+ (LengthOrPercentageOrAuto::Auto, None, _) => MaybeAuto::Auto,
}
}
@@ -468,7 +472,7 @@ impl ReplacedImageFragmentInfo {
let inline_size = ReplacedImageFragmentInfo::style_length(
style_inline_size,
self.dom_inline_size,
- container_inline_size);
+ Some(container_inline_size));
let inline_size = match inline_size {
MaybeAuto::Auto => {
@@ -483,7 +487,7 @@ impl ReplacedImageFragmentInfo {
let specified_height = ReplacedImageFragmentInfo::style_length(
style_block_size,
self.dom_block_size,
- Au(0));
+ None);
let specified_height = match specified_height {
MaybeAuto::Auto => intrinsic_height,
MaybeAuto::Specified(h) => h,
@@ -510,7 +514,7 @@ impl ReplacedImageFragmentInfo {
pub fn calculate_replaced_block_size(&mut self,
style: &ComputedValues,
noncontent_block_size: Au,
- containing_block_block_size: Au,
+ containing_block_block_size: Option<Au>,
fragment_inline_size: Au,
fragment_block_size: Au)
-> Au {
@@ -574,12 +578,12 @@ impl IframeFragmentInfo {
IframeFragmentInfo::calculate_replaced_size(style.content_inline_size(),
style.min_inline_size(),
style.max_inline_size(),
- containing_size,
+ Some(containing_size),
Au::from_px(300))
}
#[inline]
- pub fn calculate_replaced_block_size(&self, style: &ComputedValues, containing_size: Au)
+ pub fn calculate_replaced_block_size(&self, style: &ComputedValues, containing_size: Option<Au>)
-> Au {
// Calculate the replaced block size (or default) as per CSS 2.1 § 10.3.2
IframeFragmentInfo::calculate_replaced_size(style.content_block_size(),
@@ -593,13 +597,16 @@ impl IframeFragmentInfo {
fn calculate_replaced_size(content_size: LengthOrPercentageOrAuto,
style_min_size: LengthOrPercentage,
style_max_size: LengthOrPercentageOrNone,
- containing_size: Au,
+ containing_size: Option<Au>,
default_size: Au) -> Au {
- let computed_size = match MaybeAuto::from_style(content_size, containing_size) {
- MaybeAuto::Specified(length) => length,
- MaybeAuto::Auto => default_size,
+ let computed_size = match (content_size, containing_size) {
+ (LengthOrPercentageOrAuto::Length(length), _) => length,
+ (LengthOrPercentageOrAuto::Percentage(pc), Some(container_size)) => container_size.scale_by(pc),
+ (LengthOrPercentageOrAuto::Percentage(_), None) => default_size,
+ (LengthOrPercentageOrAuto::Auto, _) => default_size,
};
+ let containing_size = containing_size.unwrap_or(Au(0));
let size = clamp_size(computed_size,
style_min_size,
style_max_size,
@@ -1714,7 +1721,7 @@ impl Fragment {
/// been assigned first.
///
/// Ideally, this should follow CSS 2.1 § 10.6.2.
- pub fn assign_replaced_block_size_if_necessary(&mut self, containing_block_block_size: Au) {
+ pub fn assign_replaced_block_size_if_necessary(&mut self, containing_block_block_size: Option<Au>) {
match self.specific {
SpecificFragmentInfo::Generic |
SpecificFragmentInfo::GeneratedContent(_) |
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index abf23e488dd..0d8e1e19347 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -1346,7 +1346,7 @@ impl Flow for InlineFlow {
// Assign the block-size and late-computed inline-sizes for the inline fragments.
let containing_block_block_size =
- self.base.block_container_explicit_block_size.unwrap_or(Au(0));
+ self.base.block_container_explicit_block_size;
for fragment in self.fragments.fragments.iter_mut() {
fragment.update_late_computed_replaced_inline_size_if_necessary();
fragment.assign_replaced_block_size_if_necessary(
diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs
index a1a108848ac..24ed6633d45 100644
--- a/components/layout/list_item.rs
+++ b/components/layout/list_item.rs
@@ -106,7 +106,7 @@ impl Flow for ListItemFlow {
if let Some(ref mut marker) = self.marker {
let containing_block_block_size =
- self.block_flow.base.block_container_explicit_block_size.unwrap_or(Au(0));
+ self.block_flow.base.block_container_explicit_block_size;
marker.assign_replaced_block_size_if_necessary(containing_block_block_size);
let font_metrics =
diff --git a/components/layout/model.rs b/components/layout/model.rs
index 3c5cda25314..469d618cdfb 100644
--- a/components/layout/model.rs
+++ b/components/layout/model.rs
@@ -126,29 +126,34 @@ impl MarginCollapseInfo {
pub fn finish_and_compute_collapsible_margins(mut self,
fragment: &Fragment,
+ containing_block_size: Option<Au>,
can_collapse_block_end_margin_with_kids: bool)
-> (CollapsibleMargins, Au) {
let state = match self.state {
MarginCollapseState::AccumulatingCollapsibleTopMargin => {
- match fragment.style().content_block_size() {
- LengthOrPercentageOrAuto::Auto | LengthOrPercentageOrAuto::Length(Au(0)) |
- LengthOrPercentageOrAuto::Percentage(0.) => {
- match fragment.style().min_block_size() {
- LengthOrPercentage::Length(Au(0)) | LengthOrPercentage::Percentage(0.) => {
- FinalMarginState::MarginsCollapseThrough
- },
- _ => {
- // If the fragment has non-zero min-block-size, margins may not
- // collapse through it.
- FinalMarginState::BottomMarginCollapses
- }
+ let may_collapse_through = match fragment.style().content_block_size() {
+ LengthOrPercentageOrAuto::Auto => true,
+ LengthOrPercentageOrAuto::Length(Au(0)) => true,
+ LengthOrPercentageOrAuto::Percentage(0.) => true,
+ LengthOrPercentageOrAuto::Percentage(_) if containing_block_size.is_none() => true,
+ _ => false,
+ };
+
+ if may_collapse_through {
+ match fragment.style().min_block_size() {
+ LengthOrPercentage::Length(Au(0)) | LengthOrPercentage::Percentage(0.) => {
+ FinalMarginState::MarginsCollapseThrough
+ },
+ _ => {
+ // If the fragment has non-zero min-block-size, margins may not
+ // collapse through it.
+ FinalMarginState::BottomMarginCollapses
}
- },
- _ => {
- // If the fragment has an explicitly specified block-size, margins may not
- // collapse through it.
- FinalMarginState::BottomMarginCollapses
}
+ } else {
+ // If the fragment has an explicitly specified block-size, margins may not
+ // collapse through it.
+ FinalMarginState::BottomMarginCollapses
}
}
MarginCollapseState::AccumulatingMarginIn => FinalMarginState::BottomMarginCollapses,
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 5ead9ead378..046b9a57c5f 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -390,15 +390,15 @@ impl RawLayoutElementHelpers for Element {
match height {
LengthOrPercentageOrAuto::Auto => {}
LengthOrPercentageOrAuto::Percentage(percentage) => {
- let width_value = specified::LengthOrPercentageOrAuto::Percentage(percentage);
- hints.push(from_declaration(PropertyDeclaration::Height(SpecifiedValue(
- height::SpecifiedValue(width_value)))));
+ let height_value = specified::LengthOrPercentageOrAuto::Percentage(percentage);
+ hints.push(from_declaration(
+ PropertyDeclaration::Height(SpecifiedValue(height_value))));
}
LengthOrPercentageOrAuto::Length(length) => {
- let width_value = specified::LengthOrPercentageOrAuto::Length(
+ let height_value = specified::LengthOrPercentageOrAuto::Length(
specified::Length::Absolute(length));
- hints.push(from_declaration(PropertyDeclaration::Height(SpecifiedValue(
- height::SpecifiedValue(width_value)))));
+ hints.push(from_declaration(
+ PropertyDeclaration::Height(SpecifiedValue(height_value))));
}
}
@@ -443,8 +443,7 @@ impl RawLayoutElementHelpers for Element {
let value = specified::Length::FontRelative(specified::FontRelativeLength::Em(rows as CSSFloat));
hints.push(from_declaration(
PropertyDeclaration::Height(SpecifiedValue(
- longhands::height::SpecifiedValue(
- specified::LengthOrPercentageOrAuto::Length(value))))));
+ specified::LengthOrPercentageOrAuto::Length(value)))));
}
diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs
index d17241e009f..23618284757 100644
--- a/components/style/properties.mako.rs
+++ b/components/style/properties.mako.rs
@@ -534,45 +534,10 @@ pub mod longhands {
${predefined_type("width", "LengthOrPercentageOrAuto",
"computed::LengthOrPercentageOrAuto::Auto",
"parse_non_negative")}
- <%self:longhand name="height">
- use values::computed::Context;
- use cssparser::ToCss;
- use std::fmt;
- impl ToCss for SpecifiedValue {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- self.0.to_css(dest)
- }
- }
-
- #[derive(Clone, PartialEq)]
- pub struct SpecifiedValue(pub specified::LengthOrPercentageOrAuto);
- pub mod computed_value {
- pub use values::computed::LengthOrPercentageOrAuto as T;
- }
- #[inline]
- pub fn get_initial_value() -> computed_value::T { computed::LengthOrPercentageOrAuto::Auto }
- #[inline]
- pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
- specified::LengthOrPercentageOrAuto::parse_non_negative(input).map(SpecifiedValue)
- }
-
- impl ToComputedValue for SpecifiedValue {
- type ComputedValue = computed_value::T;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> computed_value::T {
- match (self.0, context.inherited_height) {
- (specified::LengthOrPercentageOrAuto::Percentage(_),
- computed::LengthOrPercentageOrAuto::Auto)
- if !context.is_root_element && !context.positioned => {
- computed::LengthOrPercentageOrAuto::Auto
- },
- _ => self.0.to_computed_value(context)
- }
- }
- }
- </%self:longhand>
+ ${predefined_type("height", "LengthOrPercentageOrAuto",
+ "computed::LengthOrPercentageOrAuto::Auto",
+ "parse_non_negative")}
${predefined_type("min-width", "LengthOrPercentage",
"computed::LengthOrPercentage::Length(Au(0))",
@@ -6217,7 +6182,6 @@ pub fn cascade(viewport_size: Size2D<Au>,
viewport_size: viewport_size,
inherited_font_weight: inherited_font_style.font_weight,
inherited_font_size: inherited_font_style.font_size,
- inherited_height: inherited_style.get_box().height,
inherited_text_decorations_in_effect:
inherited_style.get_inheritedtext()._servo_text_decorations_in_effect,
// To be overridden by applicable declarations:
diff --git a/components/style/values.rs b/components/style/values.rs
index b03a239ae49..03167b3fd36 100644
--- a/components/style/values.rs
+++ b/components/style/values.rs
@@ -873,7 +873,6 @@ pub mod computed {
pub inherited_font_size: longhands::font_size::computed_value::T,
pub inherited_text_decorations_in_effect:
longhands::_servo_text_decorations_in_effect::computed_value::T,
- pub inherited_height: longhands::height::computed_value::T,
pub color: longhands::color::computed_value::T,
pub text_decoration: longhands::text_decoration::computed_value::T,
pub font_size: longhands::font_size::computed_value::T,
diff --git a/tests/wpt/metadata-css/css21_dev/html4/block-in-inline-percents-001.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/block-in-inline-percents-001.htm.ini
deleted file mode 100644
index 144a6902bd7..00000000000
--- a/tests/wpt/metadata-css/css21_dev/html4/block-in-inline-percents-001.htm.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[block-in-inline-percents-001.htm]
- type: reftest
- expected: FAIL