aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/block.rs79
-rw-r--r--components/layout/flow.rs32
-rw-r--r--components/layout/inline.rs4
-rw-r--r--components/layout/table.rs4
-rw-r--r--components/layout/table_colgroup.rs4
-rw-r--r--components/layout/table_row.rs5
-rw-r--r--components/layout/table_rowgroup.rs5
-rw-r--r--components/layout/table_wrapper.rs4
-rw-r--r--tests/ref/basic.list1
-rw-r--r--tests/ref/incremental_float_a.html36
-rw-r--r--tests/ref/incremental_float_ref.html31
11 files changed, 157 insertions, 48 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs
index e3d03f22c0c..8d2438de783 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -32,8 +32,9 @@ use context::LayoutContext;
use css::node_style::StyledNode;
use display_list_builder::{BlockFlowDisplayListBuilding, BlockLevel, FragmentDisplayListBuilding};
use floats::{ClearBoth, ClearLeft, ClearRight, FloatKind, FloatLeft, Floats, PlacementInfo};
-use flow::{AbsolutePositionInfo, BaseFlow, BlockFlowClass, FlowClass, Flow, ImmutableFlowUtils};
-use flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal, mut_base};
+use flow::{AbsolutePositionInfo, BaseFlow, BlockFlowClass, FloatIfNecessary, FlowClass, Flow};
+use flow::{ForceNonfloated, ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTraversal};
+use flow::{PostorderFlowTraversal, mut_base};
use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
@@ -569,7 +570,7 @@ impl BlockFlow {
pub fn from_node(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> BlockFlow {
let writing_mode = node.style().writing_mode;
BlockFlow {
- base: BaseFlow::new(Some((*node).clone()), writing_mode),
+ base: BaseFlow::new(Some((*node).clone()), writing_mode, ForceNonfloated),
fragment: Fragment::new(constructor, node),
static_b_offset: Au::new(0),
inline_size_of_preceding_left_floats: Au(0),
@@ -583,7 +584,7 @@ impl BlockFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> BlockFlow {
let writing_mode = node.style().writing_mode;
BlockFlow {
- base: BaseFlow::new(Some((*node).clone()), writing_mode),
+ base: BaseFlow::new(Some((*node).clone()), writing_mode, ForceNonfloated),
fragment: fragment,
static_b_offset: Au::new(0),
inline_size_of_preceding_left_floats: Au(0),
@@ -600,7 +601,7 @@ impl BlockFlow {
-> BlockFlow {
let writing_mode = node.style().writing_mode;
BlockFlow {
- base: BaseFlow::new(Some((*node).clone()), writing_mode),
+ base: BaseFlow::new(Some((*node).clone()), writing_mode, FloatIfNecessary),
fragment: Fragment::new(constructor, node),
static_b_offset: Au::new(0),
inline_size_of_preceding_left_floats: Au(0),
@@ -617,7 +618,7 @@ impl BlockFlow {
-> BlockFlow {
let writing_mode = node.style().writing_mode;
BlockFlow {
- base: BaseFlow::new(Some((*node).clone()), writing_mode),
+ base: BaseFlow::new(Some((*node).clone()), writing_mode, FloatIfNecessary),
fragment: fragment,
static_b_offset: Au::new(0),
inline_size_of_preceding_left_floats: Au(0),
@@ -866,7 +867,10 @@ impl BlockFlow {
// Assume that the *hypothetical box* for an absolute flow starts immediately
// after the block-end border edge of the previous flow.
kid.as_block().hypothetical_position.b = cur_b;
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ kid.place_float_if_applicable(layout_context);
+ if !flow::base(kid).flags.is_float() {
+ kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ }
propagate_layer_flag_from_child(&mut layers_needed_for_descendants, kid);
// Skip the collapsing and float processing for absolute flow kids and continue
@@ -885,10 +889,7 @@ impl BlockFlow {
margin_collapse_info.current_float_ceiling();
}
propagate_layer_flag_from_child(&mut layers_needed_for_descendants, kid);
-
- let need_to_process_child_floats =
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
- assert!(need_to_process_child_floats); // As it was a float itself...
+ kid.place_float_if_applicable(layout_context);
let kid_base = flow::mut_base(kid);
floats = kid_base.floats.clone();
@@ -907,8 +908,12 @@ impl BlockFlow {
}
// Lay the child out if this was an in-order traversal.
- let need_to_process_child_floats =
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ let need_to_process_child_floats = if flow::base(kid).flags.is_float() {
+ kid.place_float_if_applicable(layout_context);
+ true
+ } else {
+ kid.assign_block_size_for_inorder_child_if_necessary(layout_context)
+ };
// Mark flows for layerization if necessary to handle painting order correctly.
propagate_layer_flag_from_child(&mut layers_needed_for_descendants, kid);
@@ -1066,8 +1071,9 @@ impl BlockFlow {
// has not been calculated yet. (See `calculate_absolute_block_size_and_margins` for that.)
// Also don't remove the dirty bits if we're a block formatting context since our inline
// size has not yet been computed. (See `assign_inline_position_for_formatting_context()`.)
- if !self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
- self.formatting_context_type() == NonformattingContext {
+ if (self.base.flags.is_float() ||
+ self.formatting_context_type() == NonformattingContext) &&
+ !self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
self.base.restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
}
}
@@ -1113,8 +1119,13 @@ impl BlockFlow {
self.fragment.margin.block_start);
if !self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
- self.base.position = self.base.position.translate(&float_offset)
- .translate(&margin_offset);
+ let mut origin = LogicalPoint::new(self.base.writing_mode,
+ self.hypothetical_position.i,
+ self.base.position.start.b);
+ origin = origin.add_point(&float_offset).add_point(&margin_offset);
+ self.base.position = LogicalRect::from_point_size(self.base.writing_mode,
+ origin,
+ self.base.position.size);
}
}
@@ -1321,7 +1332,8 @@ impl BlockFlow {
// and its inline-size is our content inline-size.
{
let kid_base = flow::mut_base(kid);
- if !kid_base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
+ if !kid_base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
+ !kid_base.flags.is_float() {
kid_base.position.start.i = inline_start_content_edge
}
kid_base.block_container_inline_size = content_inline_size;
@@ -1414,11 +1426,11 @@ impl BlockFlow {
}
let info = PlacementInfo {
- size: LogicalSize::new(
- self.fragment.style.writing_mode,
- self.base.position.size.inline + self.fragment.margin.inline_start_end() +
- self.fragment.border_padding.inline_start_end(),
- self.fragment.border_box.size.block),
+ size: LogicalSize::new(self.fragment.style.writing_mode,
+ self.base.position.size.inline +
+ self.fragment.margin.inline_start_end() +
+ self.fragment.border_padding.inline_start_end(),
+ self.fragment.border_box.size.block),
ceiling: self.base.position.start.b,
max_inline_size: MAX_AU,
kind: FloatLeft,
@@ -1426,10 +1438,12 @@ impl BlockFlow {
// Offset our position by whatever displacement is needed to not impact the floats.
let rect = self.base.floats.place_between_floats(&info);
- self.base.position.start.i = self.base.position.start.i + rect.start.i;
+ self.base.position.start.i = self.hypothetical_position.i + rect.start.i;
// TODO(pcwalton): If the inline-size of this flow is different from the size we estimated
// earlier, lay it out again.
+
+ self.base.restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
}
fn is_inline_block(&self) -> bool {
@@ -1602,19 +1616,17 @@ impl Flow for BlockFlow {
None);
}
- /// Assigns block-sizes in-order; or, if this is a float, places the float. The default
- /// implementation simply assigns block-sizes if this flow is impacted by floats. Returns true
- /// if this child affected the floats in the flow somehow or false otherwise; thus, if true,
- /// then the parent flow is expected to take the `floats` member of this flow into account.
- ///
- /// This is called on child flows by the parent. Hence, we can assume that `assign_block_size`
- /// has already been called on the child (because of the bottom-up traversal).
+ fn place_float_if_applicable<'a>(&mut self, _: &'a LayoutContext<'a>) {
+ if self.base.flags.is_float() {
+ self.place_float();
+ }
+ }
+
fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self,
layout_context: &'a LayoutContext<'a>)
-> bool {
if self.base.flags.is_float() {
- self.place_float();
- return true
+ return false
}
let is_formatting_context = self.formatting_context_type() != NonformattingContext;
@@ -2010,7 +2022,6 @@ pub trait ISizeAndMarginsComputer {
// We also resize the block itself, to ensure that overflow is not calculated
// as the inline-size of our parent. We might be smaller and we might be larger if we
// overflow.
-
flow::mut_base(block).position.size.inline = inline_size + extra_inline_size_from_margin;
}
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index 0049d77eb8e..d95154a6746 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -191,6 +191,9 @@ pub trait Flow: fmt::Show + ToString + Sync {
panic!("assign_block_size not yet implemented")
}
+ /// If this is a float, places it. The default implementation does nothing.
+ fn place_float_if_applicable<'a>(&mut self, _: &'a LayoutContext<'a>) {}
+
/// Assigns block-sizes in-order; or, if this is a float, places the float. The default
/// implementation simply assigns block-sizes if this flow is impacted by floats. Returns true
/// if this child was impacted by floats or false otherwise.
@@ -568,7 +571,7 @@ impl FlowFlags {
#[inline]
pub fn is_float(&self) -> bool {
- self.floats_left() || self.floats_right()
+ self.contains(FLOATS_LEFT) || self.contains(FLOATS_RIGHT)
}
#[inline]
@@ -835,9 +838,22 @@ impl Drop for BaseFlow {
}
}
+/// Whether a base flow should be forced to be nonfloated. This can affect e.g. `TableFlow`, which
+/// is never floated because the table wrapper flow is the floated one.
+#[deriving(Clone, PartialEq)]
+pub enum ForceNonfloatedFlag {
+ /// The flow should be floated if the node has a `float` property.
+ FloatIfNecessary,
+ /// The flow should be forced to be nonfloated.
+ ForceNonfloated,
+}
+
impl BaseFlow {
#[inline]
- pub fn new(node: Option<ThreadSafeLayoutNode>, writing_mode: WritingMode) -> BaseFlow {
+ pub fn new(node: Option<ThreadSafeLayoutNode>,
+ writing_mode: WritingMode,
+ force_nonfloated: ForceNonfloatedFlag)
+ -> BaseFlow {
let mut flags = FlowFlags::empty();
match node {
None => {}
@@ -849,11 +865,15 @@ impl BaseFlow {
}
_ => {}
}
- match node_style.get_box().float {
- float::none => {}
- float::left => flags.insert(FLOATS_LEFT),
- float::right => flags.insert(FLOATS_RIGHT),
+
+ if force_nonfloated == FloatIfNecessary {
+ match node_style.get_box().float {
+ float::none => {}
+ float::left => flags.insert(FLOATS_LEFT),
+ float::right => flags.insert(FLOATS_RIGHT),
+ }
}
+
match node_style.get_box().clear {
clear::none => {}
clear::left => flags.insert(CLEARS_LEFT),
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index 31ca89d3c75..73332023d5d 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -8,7 +8,7 @@ use css::node_style::StyledNode;
use context::LayoutContext;
use display_list_builder::{ContentLevel, DisplayListResult, FragmentDisplayListBuilding};
use floats::{FloatLeft, Floats, PlacementInfo};
-use flow::{BaseFlow, FlowClass, Flow, InlineFlowClass, MutableFlowUtils};
+use flow::{BaseFlow, FlowClass, Flow, ForceNonfloated, InlineFlowClass, MutableFlowUtils};
use flow::{IS_ABSOLUTELY_POSITIONED};
use flow;
use fragment::{Fragment, InlineAbsoluteHypotheticalFragment, InlineBlockFragment};
@@ -706,7 +706,7 @@ pub struct InlineFlow {
impl InlineFlow {
pub fn from_fragments(fragments: InlineFragments, writing_mode: WritingMode) -> InlineFlow {
InlineFlow {
- base: BaseFlow::new(None, writing_mode),
+ base: BaseFlow::new(None, writing_mode, ForceNonfloated),
fragments: fragments,
lines: Vec::new(),
minimum_block_size_above_baseline: Au(0),
diff --git a/components/layout/table.rs b/components/layout/table.rs
index 773e18faf05..72f11d66fbf 100644
--- a/components/layout/table.rs
+++ b/components/layout/table.rs
@@ -11,8 +11,8 @@ use block::{ISizeConstraintInput, ISizeConstraintSolution};
use construct::FlowConstructor;
use context::LayoutContext;
use floats::FloatKind;
-use flow::{TableFlowClass, FlowClass, Flow, ImmutableFlowUtils};
-use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
+use flow::{Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, ImmutableFlowUtils};
+use flow::{TableFlowClass};
use fragment::{Fragment, FragmentBoundsIterator};
use layout_debug;
use model::{IntrinsicISizes, IntrinsicISizesContribution};
diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs
index dbc826db9f2..e8caa10e88d 100644
--- a/components/layout/table_colgroup.rs
+++ b/components/layout/table_colgroup.rs
@@ -8,7 +8,7 @@
use context::LayoutContext;
use css::node_style::StyledNode;
-use flow::{BaseFlow, TableColGroupFlowClass, FlowClass, Flow};
+use flow::{BaseFlow, ForceNonfloated, TableColGroupFlowClass, FlowClass, Flow};
use fragment::{Fragment, FragmentBoundsIterator, TableColumnFragment};
use layout_debug;
use wrapper::ThreadSafeLayoutNode;
@@ -44,7 +44,7 @@ impl TableColGroupFlow {
-> TableColGroupFlow {
let writing_mode = node.style().writing_mode;
TableColGroupFlow {
- base: BaseFlow::new(Some((*node).clone()), writing_mode),
+ base: BaseFlow::new(Some((*node).clone()), writing_mode, ForceNonfloated),
fragment: Some(fragment),
cols: fragments,
inline_sizes: vec!(),
diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs
index d834ecd144f..4c12ef1ef87 100644
--- a/components/layout/table_row.rs
+++ b/components/layout/table_row.rs
@@ -79,7 +79,10 @@ impl TableRowFlow {
// cells).
let mut max_y = Au(0);
for kid in self.block_flow.base.child_iter() {
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ kid.place_float_if_applicable(layout_context);
+ if !flow::base(kid).flags.is_float() {
+ kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ }
{
let child_fragment = kid.as_table_cell().fragment();
diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs
index 50e35e40c73..865c0a3c081 100644
--- a/components/layout/table_rowgroup.rs
+++ b/components/layout/table_rowgroup.rs
@@ -74,7 +74,10 @@ impl TableRowGroupFlow {
let mut cur_y = block_start_offset;
for kid in self.block_flow.base.child_iter() {
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ kid.place_float_if_applicable(layout_context);
+ if !flow::base(kid).flags.is_float() {
+ kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ }
let child_node = flow::mut_base(kid);
child_node.position.start.b = cur_y;
diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs
index 78d050351bc..7ec0ed874a4 100644
--- a/components/layout/table_wrapper.rs
+++ b/components/layout/table_wrapper.rs
@@ -301,6 +301,10 @@ impl Flow for TableWrapperFlow {
self.block_flow.compute_absolute_position()
}
+ fn place_float_if_applicable<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
+ self.block_flow.place_float_if_applicable(layout_context)
+ }
+
fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self,
layout_context: &'a LayoutContext<'a>)
-> bool {
diff --git a/tests/ref/basic.list b/tests/ref/basic.list
index c4d7c923c4c..b1480e1d856 100644
--- a/tests/ref/basic.list
+++ b/tests/ref/basic.list
@@ -184,3 +184,4 @@ fragment=top != ../html/acid2.html acid2_ref.html
== linear_gradients_reverse_a.html linear_gradients_reverse_ref.html
!= linear_gradients_corners_a.html linear_gradients_corners_ref.html
== linear_gradients_lengths_a.html linear_gradients_lengths_ref.html
+== incremental_float_a.html incremental_float_ref.html
diff --git a/tests/ref/incremental_float_a.html b/tests/ref/incremental_float_a.html
new file mode 100644
index 00000000000..02e762b82e9
--- /dev/null
+++ b/tests/ref/incremental_float_a.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+nav.floaty {
+ float: left;
+}
+section {
+ clear: both;
+ position: relative;
+}
+</style>
+</head>
+<body>
+<section>
+<nav>This floats</nav>
+<div>This doesn't</div>
+</section>
+<section>
+<nav>This floats</nav>
+<div style="overflow: hidden;">This is a block formatting context</div>
+</section>
+<section>
+<nav>This floats</nav>
+<div style="position: absolute; top: 0; left: 0; width: 100px; height: 100px;">
+ This is abspos
+</div>
+</section>
+<script>
+var elements = document.getElementsByTagName('nav');
+for (var i = 0; i < elements.length; i++)
+ elements[i].setAttribute('class', 'floaty');
+</script>
+</body>
+</html>
+
diff --git a/tests/ref/incremental_float_ref.html b/tests/ref/incremental_float_ref.html
new file mode 100644
index 00000000000..7b52f8a8f49
--- /dev/null
+++ b/tests/ref/incremental_float_ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+nav {
+ float: left;
+}
+section {
+ clear: both;
+ position: relative;
+}
+</style>
+</head>
+<body>
+<section>
+<nav>This floats</nav>
+<div>This doesn't</div>
+</section>
+<section>
+<nav>This floats</nav>
+<div style="overflow: hidden;">This is a block formatting context</div>
+</section>
+<section>
+<nav>This floats</nav>
+<div style="position: absolute; top: 0; left: 0; width: 100px; height: 100px;">
+ This is abspos
+</div>
+</section>
+</body>
+</html>
+