Auto merge of #10198 - pcwalton:negative-ceiling, r=mbrubeck

layout: Allow floats to have negative ceilings due to negative margins.

This fixes `margin-collapse-104.htm`, which is currently accidentally
passing due to lack of #10085. When that PR lands, then that will become
a representative test case.

r? @mbrubeck

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10198)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-03-26 05:48:25 +05:30
commit 9b2ae3a62f
2 changed files with 29 additions and 20 deletions

View file

@ -56,14 +56,14 @@ struct FloatList {
/// Information about each of the floats here. /// Information about each of the floats here.
floats: PersistentList<Float>, floats: PersistentList<Float>,
/// Cached copy of the maximum block-start offset of the float. /// Cached copy of the maximum block-start offset of the float.
max_block_start: Au, max_block_start: Option<Au>,
} }
impl FloatList { impl FloatList {
fn new() -> FloatList { fn new() -> FloatList {
FloatList { FloatList {
floats: PersistentList::new(), floats: PersistentList::new(),
max_block_start: Au(0), max_block_start: None,
} }
} }
@ -247,15 +247,15 @@ impl Floats {
/// Adds a new float to the list. /// Adds a new float to the list.
pub fn add_float(&mut self, info: &PlacementInfo) { pub fn add_float(&mut self, info: &PlacementInfo) {
let new_info; let new_info = PlacementInfo {
{ size: info.size,
new_info = PlacementInfo { ceiling: match self.list.max_block_start {
size: info.size, None => info.ceiling,
ceiling: max(info.ceiling, self.list.max_block_start + self.offset.block), Some(max_block_start) => max(info.ceiling, max_block_start + self.offset.block),
max_inline_size: info.max_inline_size, },
kind: info.kind max_inline_size: info.max_inline_size,
} kind: info.kind
} };
debug!("add_float: added float with info {:?}", new_info); debug!("add_float: added float with info {:?}", new_info);
@ -269,7 +269,10 @@ impl Floats {
}; };
self.list.floats = self.list.floats.prepend_elem(new_float); self.list.floats = self.list.floats.prepend_elem(new_float);
self.list.max_block_start = max(self.list.max_block_start, new_float.bounds.start.b); self.list.max_block_start = match self.list.max_block_start {
None => Some(new_float.bounds.start.b),
Some(max_block_start) => Some(max(max_block_start, new_float.bounds.start.b)),
}
} }
/// Given the three sides of the bounding rectangle in the block-start direction, finds the /// Given the three sides of the bounding rectangle in the block-start direction, finds the

View file

@ -114,8 +114,8 @@ impl MarginCollapseInfo {
} }
pub fn initialize_block_start_margin(&mut self, pub fn initialize_block_start_margin(&mut self,
fragment: &Fragment, fragment: &Fragment,
can_collapse_block_start_margin_with_kids: bool) { can_collapse_block_start_margin_with_kids: bool) {
if !can_collapse_block_start_margin_with_kids { if !can_collapse_block_start_margin_with_kids {
self.state = MarginCollapseState::AccumulatingMarginIn self.state = MarginCollapseState::AccumulatingMarginIn
} }
@ -239,25 +239,31 @@ impl MarginCollapseInfo {
/// Adds the child's potentially collapsible block-end margin to the current margin state and /// Adds the child's potentially collapsible block-end margin to the current margin state and
/// advances the Y offset by the appropriate amount to handle that margin. Returns the amount /// advances the Y offset by the appropriate amount to handle that margin. Returns the amount
/// that should be added to the Y offset during block layout. /// that should be added to the Y offset during block layout.
pub fn advance_block_end_margin(&mut self, child_collapsible_margins: &CollapsibleMargins) -> Au { pub fn advance_block_end_margin(&mut self, child_collapsible_margins: &CollapsibleMargins)
-> Au {
match (self.state, *child_collapsible_margins) { match (self.state, *child_collapsible_margins) {
(MarginCollapseState::AccumulatingCollapsibleTopMargin, CollapsibleMargins::None(..)) | (MarginCollapseState::AccumulatingCollapsibleTopMargin, CollapsibleMargins::None(..)) |
(MarginCollapseState::AccumulatingCollapsibleTopMargin, CollapsibleMargins::Collapse(..)) => { (MarginCollapseState::AccumulatingCollapsibleTopMargin,
CollapsibleMargins::Collapse(..)) => {
// Can't happen because the state will have been replaced with // Can't happen because the state will have been replaced with
// `MarginCollapseState::AccumulatingMarginIn` above. // `MarginCollapseState::AccumulatingMarginIn` above.
panic!("should not be accumulating collapsible block_start margins anymore!") panic!("should not be accumulating collapsible block_start margins anymore!")
} }
(MarginCollapseState::AccumulatingCollapsibleTopMargin, CollapsibleMargins::CollapseThrough(margin)) => { (MarginCollapseState::AccumulatingCollapsibleTopMargin,
CollapsibleMargins::CollapseThrough(margin)) => {
self.block_start_margin.union(margin); self.block_start_margin.union(margin);
Au(0) Au(0)
} }
(MarginCollapseState::AccumulatingMarginIn, CollapsibleMargins::None(_, block_end)) => { (MarginCollapseState::AccumulatingMarginIn,
CollapsibleMargins::None(_, block_end)) => {
assert_eq!(self.margin_in.most_positive, Au(0)); assert_eq!(self.margin_in.most_positive, Au(0));
assert_eq!(self.margin_in.most_negative, Au(0)); assert_eq!(self.margin_in.most_negative, Au(0));
block_end block_end
} }
(MarginCollapseState::AccumulatingMarginIn, CollapsibleMargins::Collapse(_, block_end)) | (MarginCollapseState::AccumulatingMarginIn,
(MarginCollapseState::AccumulatingMarginIn, CollapsibleMargins::CollapseThrough(block_end)) => { CollapsibleMargins::Collapse(_, block_end)) |
(MarginCollapseState::AccumulatingMarginIn,
CollapsibleMargins::CollapseThrough(block_end)) => {
self.margin_in.union(block_end); self.margin_in.union(block_end);
Au(0) Au(0)
} }