diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2016-03-18 15:23:08 -0700 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2016-03-25 18:39:16 -0700 |
commit | b29719e36bdf2867b1391bbc3b017675975e27ae (patch) | |
tree | d45bd79776dc8c60df8868627e4c7c73bd8c2f26 /components/layout/sequential.rs | |
parent | 9b2ae3a62faafceb3149dc455fc6123de2b306f7 (diff) | |
download | servo-b29719e36bdf2867b1391bbc3b017675975e27ae.tar.gz servo-b29719e36bdf2867b1391bbc3b017675975e27ae.zip |
layout: Rewrite the block formatting context/float inline-size
speculation code.
The old code tried to do the speculation as a single bottom-up pass
after intrinsic inline-size calculation, which was unable to handle
cases like this:
<div>
<div style="float: left">Foo</div>
</div>
<div>
<div style="overflow: hidden">Bar</div>
</div>
No single bottom-up pass could possibly handle this case, because the
inline-size of the float flowing out of the "Foo" block could never make
it down to the "Bar" block, where it is needed for speculation.
On the pages I tried, this regresses layout performance by 1%-2%.
I first noticed this breaking some pages, like the Google SERPs, several
months ago.
Diffstat (limited to 'components/layout/sequential.rs')
-rw-r--r-- | components/layout/sequential.rs | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs index dbf469db082..f63e2a8bfcd 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -8,17 +8,18 @@ use app_units::Au; use context::{LayoutContext, SharedLayoutContext}; use display_list_builder::DisplayListBuildState; use euclid::point::Point2D; +use floats::SpeculatedFloatPlacement; use flow::{PostorderFlowTraversal, PreorderFlowTraversal}; use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils}; use flow_ref::{self, FlowRef}; use fragment::FragmentBorderBoxIterator; use generated_content::ResolveGeneratedContent; use gfx::display_list::{DisplayListEntry, StackingContext}; -use incremental::STORE_OVERFLOW; +use incremental::{REFLOW, STORE_OVERFLOW}; use style::dom::TNode; use style::traversal::DomTraversalContext; -use traversal::{AssignBSizes, AssignISizes}; -use traversal::{BubbleISizes, BuildDisplayList, ComputeAbsolutePositions, PostorderNodeMutTraversal}; +use traversal::{AssignBSizes, AssignISizes, BubbleISizes, BuildDisplayList}; +use traversal::{ComputeAbsolutePositions, PostorderNodeMutTraversal}; use util::opts; pub use style::sequential::traverse_dom; @@ -133,3 +134,22 @@ pub fn store_overflow(layout_context: &LayoutContext, flow: &mut Flow) { flow::mut_base(flow).restyle_damage.remove(STORE_OVERFLOW); } +/// Guesses how much inline size will be taken up by floats on the left and right sides of the +/// given flow. This is needed to speculatively calculate the inline sizes of block formatting +/// contexts. The speculation typically succeeds, but if it doesn't we have to lay it out again. +pub fn guess_float_placement(flow: &mut Flow) { + if !flow::base(flow).restyle_damage.intersects(REFLOW) { + return + } + + let mut floats_in = SpeculatedFloatPlacement::compute_floats_in_for_first_child(flow); + for kid in flow::mut_base(flow).child_iter() { + floats_in.compute_floats_in(kid); + flow::mut_base(kid).speculated_float_placement_in = floats_in; + guess_float_placement(kid); + floats_in = flow::base(kid).speculated_float_placement_out; + } + floats_in.compute_floats_out(flow); + flow::mut_base(flow).speculated_float_placement_out = floats_in +} + |