layout: Store overflow for flows impacted by floats.

Makes qz.com visible.

In order to work around a compiler bug involving Sized, this patch moves
`store_overflow` to be a virtual method.
This commit is contained in:
Patrick Walton 2015-05-08 15:10:26 -07:00
parent 263b69cf7f
commit b026a8ecf6
6 changed files with 74 additions and 41 deletions

View file

@ -33,7 +33,7 @@ use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use display_list_builder::{FragmentDisplayListBuilding}; use display_list_builder::{FragmentDisplayListBuilding};
use floats::{ClearType, FloatKind, Floats, PlacementInfo}; use floats::{ClearType, FloatKind, Floats, PlacementInfo};
use flow::{self, AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow}; use flow::{self, AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow};
use flow::{ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTraversal}; use flow::{ImmutableFlowUtils, PreorderFlowTraversal};
use flow::{PostorderFlowTraversal, mut_base}; use flow::{PostorderFlowTraversal, mut_base};
use flow::{BLOCK_POSITION_IS_STATIC, HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS}; use flow::{BLOCK_POSITION_IS_STATIC, HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC}; use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC};
@ -1631,6 +1631,7 @@ impl Flow for BlockFlow {
self.base.thread_id = parent_thread_id; self.base.thread_id = parent_thread_id;
if self.base.restyle_damage.intersects(REFLOW_OUT_OF_FLOW | REFLOW) { if self.base.restyle_damage.intersects(REFLOW_OUT_OF_FLOW | REFLOW) {
self.assign_block_size(layout_context); self.assign_block_size(layout_context);
self.store_overflow(layout_context);
// Don't remove the restyle damage; `assign_block_size` decides whether that is // Don't remove the restyle damage; `assign_block_size` decides whether that is
// appropriate (which in the case of e.g. absolutely-positioned flows, it is not). // appropriate (which in the case of e.g. absolutely-positioned flows, it is not).
} }

View file

@ -221,11 +221,55 @@ pub trait Flow: fmt::Debug + Sync {
if impacted { if impacted {
mut_base(self).thread_id = parent_thread_id; mut_base(self).thread_id = parent_thread_id;
self.assign_block_size(layout_context); self.assign_block_size(layout_context);
self.store_overflow(layout_context);
mut_base(self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW); mut_base(self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
} }
impacted impacted
} }
/// Calculate and set overflow for current flow.
///
/// CSS Section 11.1
/// This is the union of rectangles of the flows for which we define the
/// Containing Block.
///
/// FIXME(pcwalton): This should not be a virtual method, but currently is due to a compiler
/// bug ("the trait `Sized` is not implemented for `self`").
///
/// Assumption: This is called in a bottom-up traversal, so kids' overflows have
/// already been set.
/// Assumption: Absolute descendants have had their overflow calculated.
fn store_overflow(&mut self, _: &LayoutContext) {
// Calculate overflow on a per-fragment basis.
let mut overflow = self.compute_overflow();
match self.class() {
FlowClass::Block |
FlowClass::TableCaption |
FlowClass::TableCell if base(self).children.len() != 0 => {
// FIXME(#2795): Get the real container size.
let container_size = Size2D::zero();
for kid in mut_base(self).children.iter_mut() {
if base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
continue
}
let kid_overflow = base(kid).overflow;
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
container_size);
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
}
for kid in mut_base(self).abs_descendants.iter() {
let kid_overflow = base(kid).overflow;
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
container_size);
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
}
}
_ => {}
}
mut_base(self).overflow = overflow;
}
/// Phase 4 of reflow: computes absolute positions. /// Phase 4 of reflow: computes absolute positions.
fn compute_absolute_position(&mut self) { fn compute_absolute_position(&mut self) {
// The default implementation is a no-op. // The default implementation is a no-op.
@ -429,9 +473,6 @@ pub trait MutableFlowUtils {
// Mutators // Mutators
/// Computes the overflow region for this flow.
fn store_overflow(self, _: &LayoutContext);
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of /// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
/// calling them individually, since there is no reason not to perform both operations. /// calling them individually, since there is no reason not to perform both operations.
fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>); fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>);
@ -1228,41 +1269,6 @@ impl<'a> MutableFlowUtils for &'a mut (Flow + 'a) {
} }
} }
/// Calculate and set overflow for current flow.
///
/// CSS Section 11.1
/// This is the union of rectangles of the flows for which we define the
/// Containing Block.
///
/// Assumption: This is called in a bottom-up traversal, so kids' overflows have
/// already been set.
/// Assumption: Absolute descendants have had their overflow calculated.
fn store_overflow(self, _: &LayoutContext) {
// Calculate overflow on a per-fragment basis.
let mut overflow = self.compute_overflow();
if self.is_block_container() {
// FIXME(#2795): Get the real container size.
let container_size = Size2D::zero();
for kid in child_iter(self) {
if base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
continue
}
let kid_overflow = base(kid).overflow;
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
container_size);
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
}
for kid in mut_base(self).abs_descendants.iter() {
let kid_overflow = base(kid).overflow;
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
container_size);
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
}
}
mut_base(self).overflow = overflow;
}
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of /// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
/// calling them individually, since there is no reason not to perform both operations. /// calling them individually, since there is no reason not to perform both operations.

View file

@ -10,9 +10,8 @@ use css::node_style::StyledNode;
use css::matching::{ApplicableDeclarations, MatchMethods, StyleSharingResult}; use css::matching::{ApplicableDeclarations, MatchMethods, StyleSharingResult};
use construct::FlowConstructor; use construct::FlowConstructor;
use context::LayoutContext; use context::LayoutContext;
use flow::{Flow, MutableFlowUtils}; use flow::{self, Flow};
use flow::{PreorderFlowTraversal, PostorderFlowTraversal}; use flow::{PreorderFlowTraversal, PostorderFlowTraversal};
use flow;
use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage}; use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
use script::layout_interface::ReflowGoal; use script::layout_interface::ReflowGoal;
use wrapper::{layout_node_to_unsafe_layout_node, LayoutNode}; use wrapper::{layout_node_to_unsafe_layout_node, LayoutNode};

View file

@ -92,6 +92,7 @@ flaky_cpu == append_style_a.html append_style_b.html
== float_clearance_intrinsic_width_a.html float_clearance_intrinsic_width_ref.html == float_clearance_intrinsic_width_a.html float_clearance_intrinsic_width_ref.html
== float_intrinsic_height.html float_intrinsic_height_ref.html == float_intrinsic_height.html float_intrinsic_height_ref.html
== float_intrinsic_width_a.html float_intrinsic_width_ref.html == float_intrinsic_width_a.html float_intrinsic_width_ref.html
== float_overflow_area_a.html float_overflow_area_ref.html
== float_right_intrinsic_width_a.html float_right_intrinsic_width_ref.html == float_right_intrinsic_width_a.html float_right_intrinsic_width_ref.html
== float_table_a.html float_table_ref.html == float_table_a.html float_table_ref.html
== float_under_top_margin_a.html float_under_top_margin_ref.html == float_under_top_margin_a.html float_under_top_margin_ref.html

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
body, html {
margin: 0;
}
</style>
</head>
<body>
<div style="transformX(0)"><div style="float: left">Y</div></div>
</body>
</html>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<style>
body, html {
margin: 0;
}
</style>
</head>
<body>
<div><div style="float: left">Y</div></div>
</body>
</html>