diff --git a/src/components/main/layout/float.rs b/src/components/main/layout/float.rs index df97ebf9112..8aee9e4837a 100644 --- a/src/components/main/layout/float.rs +++ b/src/components/main/layout/float.rs @@ -302,6 +302,7 @@ impl FlowContext for FloatFlow { position.size.height = height; } + } fn collapse_margins(&mut self, diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs index 472950b4a96..35e06902f8f 100644 --- a/src/components/main/layout/flow.rs +++ b/src/components/main/layout/flow.rs @@ -90,12 +90,12 @@ pub trait FlowContext { fail!("assign_widths not yet implemented") } - /// Pass 3 of reflow: computes height. + /// Pass 3a of reflow: computes height. fn assign_height(&mut self, _ctx: &mut LayoutContext) { fail!("assign_height not yet implemented") } - /// In-order version of pass 3 of reflow: computes heights with floats present. + /// In-order version of pass 3a of reflow: computes heights with floats present. fn assign_height_inorder(&mut self, _ctx: &mut LayoutContext) { fail!("assign_height_inorder not yet implemented") } @@ -190,6 +190,9 @@ pub trait MutableFlowUtils { /// Removes the last child of this flow and destroys it. fn remove_last(self); + /// Computes the overflow region for this flow. + fn store_overflow(self, _: &mut LayoutContext); + /// Builds a display list for this flow and its children. fn build_display_list( self, @@ -315,7 +318,15 @@ pub struct FlowData { // layout; maybe combine into a single enum to save space. min_width: Au, pref_width: Au, + + /// The position of the upper left corner of the border box of this flow, relative to the + /// containing block. position: Rect, + + /// The amount of overflow of this flow, relative to the containing block. Must include all the + /// pixels of all the display list items for correct invalidation. + overflow: Rect, + floats_in: FloatContext, floats_out: FloatContext, num_floats: uint, @@ -353,6 +364,7 @@ impl FlowData { min_width: Au::new(0), pref_width: Au::new(0), position: Au::zero_rect(), + overflow: Au::zero_rect(), floats_in: Invalid, floats_out: Invalid, num_floats: 0, @@ -467,6 +479,17 @@ impl<'self> MutableFlowUtils for &'self mut FlowContext { let _ = mut_base(self).children.pop_back(); } + fn store_overflow(self, _: &mut LayoutContext) { + let my_position = mut_base(self).position; + let mut overflow = my_position; + for kid in mut_base(self).child_iter() { + let mut kid_overflow = base(*kid).overflow; + kid_overflow = kid_overflow.translate(&my_position.origin); + overflow = overflow.union(&kid_overflow) + } + mut_base(self).overflow = overflow + } + fn build_display_list( self, builder: &DisplayListBuilder, diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index cb029942710..046f2518ffe 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -138,15 +138,16 @@ impl<'self> PreorderFlowTraversal for AssignWidthsTraversal<'self> { } } -/// The assign-heights traversal, the last (and most expensive) part of layout computation. -/// Determines the final heights for all layout objects. In Gecko this corresponds to -/// `FinishAndStoreOverflow`. -struct AssignHeightsTraversal<'self>(&'self mut LayoutContext); +/// The assign-heights-and-store-overflow traversal, the last (and most expensive) part of layout +/// computation. Determines the final heights for all layout objects, computes positions, and +/// computes overflow regions. In Gecko this corresponds to `FinishAndStoreOverflow`. +struct AssignHeightsAndStoreOverflowTraversal<'self>(&'self mut LayoutContext); -impl<'self> PostorderFlowTraversal for AssignHeightsTraversal<'self> { +impl<'self> PostorderFlowTraversal for AssignHeightsAndStoreOverflowTraversal<'self> { #[inline] fn process(&mut self, flow: &mut FlowContext) -> bool { flow.assign_height(**self); + flow.store_overflow(**self); true } @@ -296,6 +297,29 @@ impl LayoutTask { self.stylist.add_stylesheet(sheet, AuthorOrigin); } + /// Performs layout constraint solving. + /// + /// This corresponds to `Reflow()` in Gecko and `layout()` in WebKit/Blink and should be + /// benchmarked against those two. It is marked `#[inline(never)]` to aid profiling. + #[inline(never)] + fn solve_constraints(&mut self, + layout_root: &mut FlowContext, + layout_context: &mut LayoutContext) { + let _ = layout_root.traverse_postorder(&mut BubbleWidthsTraversal(layout_context)); + + // FIXME(kmc): We want to do + // for flow in layout_root.traverse_preorder_prune(|f| + // f.restyle_damage().lacks(Reflow)) + // but FloatContext values can't be reused, so we need to recompute them every time. + // NOTE: this currently computes borders, so any pruning should separate that operation out. + let _ = layout_root.traverse_preorder(&mut AssignWidthsTraversal(layout_context)); + + // For now, this is an inorder traversal + // FIXME: prune this traversal as well + let _ = layout_root.traverse_postorder(&mut + AssignHeightsAndStoreOverflowTraversal(layout_context)); + } + /// The high-level routine that performs layout tasks. fn handle_reflow(&mut self, data: &Reflow) { // FIXME: Isolate this transmutation into a "bridge" module. @@ -365,17 +389,7 @@ impl LayoutTask { // Perform the primary layout passes over the flow tree to compute the locations of all // the boxes. do profile(time::LayoutMainCategory, self.profiler_chan.clone()) { - let _ = layout_root.traverse_postorder(&mut BubbleWidthsTraversal(&mut layout_ctx)); - - // FIXME(kmc): We want to do - // for flow in layout_root.traverse_preorder_prune(|f| f.restyle_damage().lacks(Reflow)) - // but FloatContext values can't be reused, so we need to recompute them every time. - // NOTE: this currently computes borders, so any pruning should separate that operation out. - let _ = layout_root.traverse_preorder(&mut AssignWidthsTraversal(&mut layout_ctx)); - - // For now, this is an inorder traversal - // FIXME: prune this traversal as well - let _ = layout_root.traverse_postorder(&mut AssignHeightsTraversal(&mut layout_ctx)); + self.solve_constraints(layout_root, &mut layout_ctx) } // Build the display list if necessary, and send it to the renderer. diff --git a/src/components/util/geometry.rs b/src/components/util/geometry.rs index d67fae0c003..febb33660f4 100644 --- a/src/components/util/geometry.rs +++ b/src/components/util/geometry.rs @@ -8,9 +8,16 @@ use geom::size::Size2D; use std::num::{NumCast, One, Zero}; -#[deriving(Clone)] pub struct Au(i32); +// We don't use #[deriving] here for inlining. +impl Clone for Au { + #[inline] + fn clone(&self) -> Au { + Au(**self) + } +} + impl Eq for Au { #[inline] fn eq(&self, other: &Au) -> bool { diff --git a/src/support/geom/rust-geom b/src/support/geom/rust-geom index 82d56dfc632..6e4db1ea746 160000 --- a/src/support/geom/rust-geom +++ b/src/support/geom/rust-geom @@ -1 +1 @@ -Subproject commit 82d56dfc632fe458d126d049fd5abe856170f48d +Subproject commit 6e4db1ea746f38fe8156bc285c89ad5c12b124a9