Merge pull request #3467 from pcwalton/enhance-block-formatting-context-guess

layout: Enhance the heuristic that guesses the inline size of block formatting contexts.

Reviewed-by: glennw
This commit is contained in:
bors-servo 2014-09-25 19:24:30 -06:00
commit 20f5fdd000
4 changed files with 151 additions and 30 deletions

View file

@ -510,9 +510,13 @@ pub struct BlockFlow {
/// Static y offset of an absolute flow from its CB.
pub static_b_offset: Au,
/// The inline-size of the last float prior to this block. This is used to speculatively lay out
/// block formatting contexts.
previous_float_inline_size: Option<Au>,
/// The sum of the inline-sizes of all logically left floats that precede this block. This is
/// used to speculatively lay out block formatting contexts.
inline_size_of_preceding_left_floats: Au,
/// The sum of the inline-sizes of all logically right floats that precede this block. This is
/// used to speculatively lay out block formatting contexts.
inline_size_of_preceding_right_floats: Au,
/// Additional floating flow members.
pub float: Option<Box<FloatedBlockInfo>>
@ -525,7 +529,8 @@ impl BlockFlow {
fragment: Fragment::new(constructor, node),
is_root: false,
static_b_offset: Au::new(0),
previous_float_inline_size: None,
inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0),
float: None
}
}
@ -536,7 +541,8 @@ impl BlockFlow {
fragment: fragment,
is_root: false,
static_b_offset: Au::new(0),
previous_float_inline_size: None,
inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0),
float: None
}
}
@ -550,7 +556,8 @@ impl BlockFlow {
fragment: Fragment::new(constructor, node),
is_root: false,
static_b_offset: Au::new(0),
previous_float_inline_size: None,
inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0),
float: Some(box FloatedBlockInfo::new(float_kind)),
base: base,
}
@ -565,7 +572,8 @@ impl BlockFlow {
fragment: fragment,
is_root: false,
static_b_offset: Au::new(0),
previous_float_inline_size: None,
inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0),
float: Some(box FloatedBlockInfo::new(float_kind)),
base: base,
}
@ -1321,11 +1329,17 @@ impl BlockFlow {
// This value is used only for table cells.
let mut inline_start_margin_edge = inline_start_content_edge;
// The inline-size of the last float, if there was one. This is used for estimating the
// inline-sizes of block formatting contexts. (We estimate that the inline-size of any
// block formatting context that we see will be based on the inline-size of the containing
// block as well as the last float seen before it.)
let mut last_float_inline_size = None;
// Remember the inline-sizes of the last left and right floats, if there were any. These
// are used for estimating the inline-sizes of block formatting contexts. (We estimate that
// the inline-size of any block formatting context that we see will be based on the
// inline-size of the containing block as well as the last float seen before it in each
// direction.)
let mut inline_size_of_preceding_left_floats = Au(0);
let mut inline_size_of_preceding_right_floats = Au(0);
if self.formatting_context_type() == NonformattingContext {
inline_size_of_preceding_left_floats = self.inline_size_of_preceding_left_floats;
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();
@ -1345,29 +1359,44 @@ impl BlockFlow {
let kid_block = kid.as_block();
kid_block.base.absolute_static_i_offset = absolute_static_i_offset;
kid_block.base.fixed_static_i_offset = fixed_static_i_offset;
}
if kid_block.is_float() {
last_float_inline_size = Some(kid_block.base.intrinsic_inline_sizes.preferred_inline_size)
} else {
kid_block.previous_float_inline_size = last_float_inline_size
match kid.float_kind() {
float::none => {}
float::left => {
inline_size_of_preceding_left_floats = inline_size_of_preceding_left_floats +
flow::base(kid).intrinsic_inline_sizes.preferred_inline_size;
}
float::right => {
inline_size_of_preceding_right_floats = inline_size_of_preceding_right_floats +
flow::base(kid).intrinsic_inline_sizes.preferred_inline_size;
}
}
// The inline-start margin edge of the child flow is at our inline-start content edge, and its inline-size
// is our content inline-size.
// The inline-start margin edge of the child flow is at our inline-start content edge,
// and its inline-size is our content inline-size.
flow::mut_base(kid).position.start.i = inline_start_content_edge;
flow::mut_base(kid).position.size.inline = content_inline_size;
// Determine float impaction.
match kid.float_clearance() {
clear::none => {}
clear::left => inline_start_floats_impact_child = false,
clear::right => inline_end_floats_impact_child = false,
clear::left => {
inline_start_floats_impact_child = false;
inline_size_of_preceding_left_floats = Au(0);
}
clear::right => {
inline_end_floats_impact_child = false;
inline_size_of_preceding_right_floats = Au(0);
}
clear::both => {
inline_start_floats_impact_child = false;
inline_end_floats_impact_child = false;
inline_size_of_preceding_left_floats = Au(0);
inline_size_of_preceding_right_floats = Au(0);
}
}
{
let kid_base = flow::mut_base(kid);
inline_start_floats_impact_child = inline_start_floats_impact_child ||
@ -1378,6 +1407,14 @@ impl BlockFlow {
kid_base.flags.set_impacted_by_right_floats(inline_end_floats_impact_child);
}
if kid.is_block_flow() {
let kid_block = kid.as_block();
kid_block.inline_size_of_preceding_left_floats =
inline_size_of_preceding_left_floats;
kid_block.inline_size_of_preceding_right_floats =
inline_size_of_preceding_right_floats;
}
// Handle tables.
match opt_col_inline_sizes {
Some(ref col_inline_sizes) => {
@ -1591,16 +1628,13 @@ impl Flow for BlockFlow {
self.base.flags.set_impacted_by_left_floats(false);
self.base.flags.set_impacted_by_right_floats(false);
// We can't actually compute the inline-size of this block now, because floats might
// affect it. Speculate that its inline-size is equal to the inline-size computed above minus
// the inline-size of the previous float.
match self.previous_float_inline_size {
None => {}
Some(previous_float_inline_size) => {
self.fragment.border_box.size.inline =
self.fragment.border_box.size.inline - previous_float_inline_size
}
}
// We can't actually compute the inline-size of this block now, because floats
// might affect it. Speculate that its inline-size is equal to the inline-size
// computed above minus the inline-size of the previous left and/or right floats.
self.fragment.border_box.size.inline =
self.fragment.border_box.size.inline -
self.inline_size_of_preceding_left_floats -
self.inline_size_of_preceding_right_floats;
}
OtherFormattingContext => {
self.base.flags.set_impacted_by_left_floats(false);

View file

@ -146,3 +146,4 @@ flaky_gpu,flaky_linux == acid2_noscroll.html acid2_ref_broken.html
== block_formatting_context_translation_a.html block_formatting_context_translation_ref.html
== floated_table_with_margin_a.html floated_table_with_margin_ref.html
== margins_inside_floats_a.html margins_inside_floats_ref.html
== block_formatting_context_complex_a.html block_formatting_context_complex_ref.html

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<style>
.a {
height: 999999px;
color: white;
}
</style>
</head>
<body>
<div class=a style="float: right; width: 200px; background: blue;">Meow</div>
<div class=a style="float: left; width: 50px; background: orange;">Mimi</div>
<div class=a style="float: left; width: 50px; background: green;">the</div>
<div class=a style="float: left; width: 50px; background: violet;">cat</div>
<div style="overflow: hidden;">
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
</div>
</body>
</html>

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<style>
.a {
height: 999999px;
color: white;
}
</style>
</head>
<body>
<div class=a style="float: right; width: 200px; background: blue;">Meow</div>
<div class=a style="float: left; width: 50px; background: orange;">Mimi</div>
<div class=a style="float: left; width: 50px; background: green;">the</div>
<div class=a style="float: left; width: 50px; background: violet;">cat</div>
<div>
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
There once was an engine named Servo
</div>
</body>
</html>