Refactor flow construction to make float less of a special case.

This commit is contained in:
Simon Sapin 2015-04-16 16:51:27 +02:00
parent cc4749373a
commit 544a02a250
11 changed files with 48 additions and 125 deletions

View file

@ -562,33 +562,20 @@ impl Encodable for BlockFlowFlags {
} }
impl BlockFlow { impl BlockFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> BlockFlow { pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
fragment: Fragment,
float_kind: Option<FloatKind>)
-> BlockFlow {
let writing_mode = node.style().writing_mode; let writing_mode = node.style().writing_mode;
BlockFlow { BlockFlow {
base: BaseFlow::new(Some((*node).clone()), base: BaseFlow::new(Some((*node).clone()), writing_mode, match float_kind {
writing_mode, Some(_) => ForceNonfloatedFlag::FloatIfNecessary,
ForceNonfloatedFlag::ForceNonfloated), None => ForceNonfloatedFlag::ForceNonfloated,
}),
fragment: fragment, fragment: fragment,
inline_size_of_preceding_left_floats: Au(0), inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0), inline_size_of_preceding_right_floats: Au(0),
float: None, float: float_kind.map(|kind| box FloatedBlockInfo::new(kind)),
flags: BlockFlowFlags::empty(),
}
}
pub fn float_from_node_and_fragment(node: &ThreadSafeLayoutNode,
fragment: Fragment,
float_kind: FloatKind)
-> BlockFlow {
let writing_mode = node.style().writing_mode;
BlockFlow {
base: BaseFlow::new(Some((*node).clone()),
writing_mode,
ForceNonfloatedFlag::FloatIfNecessary),
fragment: fragment,
inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0),
float: Some(box FloatedBlockInfo::new(float_kind)),
flags: BlockFlowFlags::empty(), flags: BlockFlowFlags::empty(),
} }
} }

View file

@ -331,7 +331,7 @@ impl<'a> FlowConstructor<'a> {
if child.is_table() { if child.is_table() {
let fragment = Fragment::new(child_node, SpecificFragmentInfo::TableWrapper); let fragment = Fragment::new(child_node, SpecificFragmentInfo::TableWrapper);
let mut new_child = let mut new_child =
FlowRef::new(box TableWrapperFlow::from_node_and_fragment(child_node, fragment)); FlowRef::new(box TableWrapperFlow::from_node_and_fragment(child_node, fragment, None));
new_child.add_new_child(child.clone()); new_child.add_new_child(child.clone());
child.finish(); child.finish();
*child = new_child *child = new_child
@ -602,7 +602,7 @@ impl<'a> FlowConstructor<'a> {
/// ///
/// FIXME(pcwalton): It is not clear to me that there isn't a cleaner way to handle /// FIXME(pcwalton): It is not clear to me that there isn't a cleaner way to handle
/// `<textarea>`. /// `<textarea>`.
fn build_flow_for_block(&mut self, flow: FlowRef, node: &ThreadSafeLayoutNode) fn build_flow_for_block_like(&mut self, flow: FlowRef, node: &ThreadSafeLayoutNode)
-> ConstructionResult { -> ConstructionResult {
let mut initial_fragments = LinkedList::new(); let mut initial_fragments = LinkedList::new();
if node.get_pseudo_element_type() != PseudoElementType::Normal || if node.get_pseudo_element_type() != PseudoElementType::Normal ||
@ -654,25 +654,15 @@ impl<'a> FlowConstructor<'a> {
/// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly /// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly
/// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed /// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed
/// to happen. /// to happen.
fn build_flow_for_nonfloated_block(&mut self, node: &ThreadSafeLayoutNode) fn build_flow_for_block(&mut self, node: &ThreadSafeLayoutNode, float_kind: Option<FloatKind>)
-> ConstructionResult { -> ConstructionResult {
let fragment = self.build_fragment_for_block(node); let fragment = self.build_fragment_for_block(node);
let flow = if node.style().is_multicol() { let flow = if node.style().is_multicol() {
box MulticolFlow::from_node_and_fragment(node, fragment) as Box<Flow> box MulticolFlow::from_node_and_fragment(node, fragment, float_kind) as Box<Flow>
} else { } else {
box BlockFlow::from_node_and_fragment(node, fragment) as Box<Flow> box BlockFlow::from_node_and_fragment(node, fragment, float_kind) as Box<Flow>
}; };
self.build_flow_for_block(FlowRef::new(flow), node) self.build_flow_for_block_like(FlowRef::new(flow), node)
}
/// Builds the flow for a node with `float: {left|right}`. This yields a float `BlockFlow` with
/// a `BlockFlow` underneath it.
fn build_flow_for_floated_block(&mut self, node: &ThreadSafeLayoutNode, float_kind: FloatKind)
-> ConstructionResult {
let fragment = self.build_fragment_for_block(node);
let flow = box BlockFlow::float_from_node_and_fragment(node, fragment, float_kind) as
Box<Flow>;
self.build_flow_for_block(FlowRef::new(flow), node)
} }
/// Concatenates the fragments of kids, adding in our own borders/padding/margins if necessary. /// Concatenates the fragments of kids, adding in our own borders/padding/margins if necessary.
@ -819,7 +809,7 @@ impl<'a> FlowConstructor<'a> {
fn build_fragment_for_inline_block(&mut self, node: &ThreadSafeLayoutNode) fn build_fragment_for_inline_block(&mut self, node: &ThreadSafeLayoutNode)
-> ConstructionResult { -> ConstructionResult {
let block_flow_result = self.build_flow_for_nonfloated_block(node); let block_flow_result = self.build_flow_for_block(node, None);
let (block_flow, abs_descendants) = match block_flow_result { let (block_flow, abs_descendants) = match block_flow_result {
ConstructionResult::Flow(block_flow, abs_descendants) => (block_flow, abs_descendants), ConstructionResult::Flow(block_flow, abs_descendants) => (block_flow, abs_descendants),
_ => unreachable!() _ => unreachable!()
@ -845,7 +835,7 @@ impl<'a> FlowConstructor<'a> {
/// hypothetical box is inline. /// hypothetical box is inline.
fn build_fragment_for_absolutely_positioned_inline(&mut self, node: &ThreadSafeLayoutNode) fn build_fragment_for_absolutely_positioned_inline(&mut self, node: &ThreadSafeLayoutNode)
-> ConstructionResult { -> ConstructionResult {
let block_flow_result = self.build_flow_for_nonfloated_block(node); let block_flow_result = self.build_flow_for_block(node, None);
let (block_flow, abs_descendants) = match block_flow_result { let (block_flow, abs_descendants) = match block_flow_result {
ConstructionResult::Flow(block_flow, abs_descendants) => (block_flow, abs_descendants), ConstructionResult::Flow(block_flow, abs_descendants) => (block_flow, abs_descendants),
_ => unreachable!() _ => unreachable!()
@ -939,13 +929,8 @@ impl<'a> FlowConstructor<'a> {
fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode, float_value: float::T) fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode, float_value: float::T)
-> ConstructionResult { -> ConstructionResult {
let fragment = Fragment::new(node, SpecificFragmentInfo::TableWrapper); let fragment = Fragment::new(node, SpecificFragmentInfo::TableWrapper);
let wrapper_flow = match float_value { let wrapper_flow = box TableWrapperFlow::from_node_and_fragment(
float::T::none => box TableWrapperFlow::from_node_and_fragment(node, fragment), node, fragment, FloatKind::from_property(float_value));
_ => {
let float_kind = FloatKind::from_property(float_value);
box TableWrapperFlow::float_from_node_and_fragment(node, fragment, float_kind)
}
};
let mut wrapper_flow = FlowRef::new(wrapper_flow as Box<Flow>); let mut wrapper_flow = FlowRef::new(wrapper_flow as Box<Flow>);
let table_fragment = Fragment::new(node, SpecificFragmentInfo::Table); let table_fragment = Fragment::new(node, SpecificFragmentInfo::Table);
@ -953,7 +938,7 @@ impl<'a> FlowConstructor<'a> {
let table_flow = FlowRef::new(table_flow as Box<Flow>); let table_flow = FlowRef::new(table_flow as Box<Flow>);
// First populate the table flow with its children. // First populate the table flow with its children.
let construction_result = self.build_flow_for_block(table_flow, node); let construction_result = self.build_flow_for_block_like(table_flow, node);
let mut abs_descendants = Descendants::new(); let mut abs_descendants = Descendants::new();
let mut fixed_descendants = Descendants::new(); let mut fixed_descendants = Descendants::new();
@ -1008,7 +993,7 @@ impl<'a> FlowConstructor<'a> {
fn build_flow_for_table_caption(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult { fn build_flow_for_table_caption(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
let fragment = self.build_fragment_for_block(node); let fragment = self.build_fragment_for_block(node);
let flow = box TableCaptionFlow::from_node_and_fragment(node, fragment) as Box<Flow>; let flow = box TableCaptionFlow::from_node_and_fragment(node, fragment) as Box<Flow>;
self.build_flow_for_block(FlowRef::new(flow), node) self.build_flow_for_block_like(FlowRef::new(flow), node)
} }
/// Builds a flow for a node with `display: table-row-group`. This yields a `TableRowGroupFlow` /// Builds a flow for a node with `display: table-row-group`. This yields a `TableRowGroupFlow`
@ -1018,7 +1003,7 @@ impl<'a> FlowConstructor<'a> {
let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow); let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow);
let flow = box TableRowGroupFlow::from_node_and_fragment(node, fragment); let flow = box TableRowGroupFlow::from_node_and_fragment(node, fragment);
let flow = flow as Box<Flow>; let flow = flow as Box<Flow>;
self.build_flow_for_block(FlowRef::new(flow), node) self.build_flow_for_block_like(FlowRef::new(flow), node)
} }
/// Builds a flow for a node with `display: table-row`. This yields a `TableRowFlow` with /// Builds a flow for a node with `display: table-row`. This yields a `TableRowFlow` with
@ -1026,7 +1011,7 @@ impl<'a> FlowConstructor<'a> {
fn build_flow_for_table_row(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult { fn build_flow_for_table_row(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow); let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow);
let flow = box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow>; let flow = box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow>;
self.build_flow_for_block(FlowRef::new(flow), node) self.build_flow_for_block_like(FlowRef::new(flow), node)
} }
/// Builds a flow for a node with `display: table-cell`. This yields a `TableCellFlow` with /// Builds a flow for a node with `display: table-cell`. This yields a `TableCellFlow` with
@ -1047,17 +1032,14 @@ impl<'a> FlowConstructor<'a> {
let flow = box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide) let flow = box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide)
as Box<Flow>; as Box<Flow>;
self.build_flow_for_block(FlowRef::new(flow), node) self.build_flow_for_block_like(FlowRef::new(flow), node)
} }
/// Builds a flow for a node with `display: list-item`. This yields a `ListItemFlow` with /// Builds a flow for a node with `display: list-item`. This yields a `ListItemFlow` with
/// possibly other `BlockFlow`s or `InlineFlow`s underneath it. /// possibly other `BlockFlow`s or `InlineFlow`s underneath it.
fn build_flow_for_list_item(&mut self, node: &ThreadSafeLayoutNode, flotation: float::T) fn build_flow_for_list_item(&mut self, node: &ThreadSafeLayoutNode, flotation: float::T)
-> ConstructionResult { -> ConstructionResult {
let flotation = match flotation { let flotation = FloatKind::from_property(flotation);
float::T::none => None,
flotation => Some(FloatKind::from_property(flotation)),
};
let marker_fragment = match node.style().get_list().list_style_image { let marker_fragment = match node.style().get_list().list_style_image {
Some(ref url) => { Some(ref url) => {
let image_info = box ImageFragmentInfo::new(node, let image_info = box ImageFragmentInfo::new(node,
@ -1294,7 +1276,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
// below. // below.
(display::T::block, _, position::T::absolute) | (display::T::block, _, position::T::absolute) |
(_, _, position::T::fixed) => { (_, _, position::T::fixed) => {
let construction_result = self.build_flow_for_nonfloated_block(node); let construction_result = self.build_flow_for_block(node, None);
self.set_flow_construction_result(node, construction_result) self.set_flow_construction_result(node, construction_result)
} }
@ -1369,15 +1351,9 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
// TODO(pcwalton): Make this only trigger for blocks and handle the other `display` // TODO(pcwalton): Make this only trigger for blocks and handle the other `display`
// properties separately. // properties separately.
(_, float::T::none, _) => {
let construction_result = self.build_flow_for_nonfloated_block(node);
self.set_flow_construction_result(node, construction_result)
}
// Floated flows contribute float flow construction results.
(_, float_value, _) => { (_, float_value, _) => {
let float_kind = FloatKind::from_property(float_value); let float_kind = FloatKind::from_property(float_value);
let construction_result = self.build_flow_for_floated_block(node, float_kind); let construction_result = self.build_flow_for_block(node, float_kind);
self.set_flow_construction_result(node, construction_result) self.set_flow_construction_result(node, construction_result)
} }
} }

View file

@ -19,11 +19,11 @@ pub enum FloatKind {
} }
impl FloatKind { impl FloatKind {
pub fn from_property(property: float::T) -> FloatKind { pub fn from_property(property: float::T) -> Option<FloatKind> {
match property { match property {
float::T::none => panic!("can't create a float type from an unfloated property"), float::T::none => None,
float::T::left => FloatKind::Left, float::T::left => Some(FloatKind::Left),
float::T::right => FloatKind::Right, float::T::right => Some(FloatKind::Right),
} }
} }
} }

View file

@ -45,11 +45,7 @@ impl ListItemFlow {
flotation: Option<FloatKind>) flotation: Option<FloatKind>)
-> ListItemFlow { -> ListItemFlow {
let mut this = ListItemFlow { let mut this = ListItemFlow {
block_flow: if let Some(flotation) = flotation { block_flow: BlockFlow::from_node_and_fragment(node, main_fragment, flotation),
BlockFlow::float_from_node_and_fragment(node, main_fragment, flotation)
} else {
BlockFlow::from_node_and_fragment(node, main_fragment)
},
marker: marker_fragment, marker: marker_fragment,
}; };

View file

@ -4,10 +4,11 @@
//! CSS Multi-column layout http://dev.w3.org/csswg/css-multicol/ //! CSS Multi-column layout http://dev.w3.org/csswg/css-multicol/
#![deny(unsafe_blocks)] #![deny(unsafe_code)]
use block::BlockFlow; use block::BlockFlow;
use context::LayoutContext; use context::LayoutContext;
use floats::FloatKind;
use flow::{FlowClass, Flow}; use flow::{FlowClass, Flow};
use fragment::{Fragment, FragmentBorderBoxIterator}; use fragment::{Fragment, FragmentBorderBoxIterator};
use wrapper::ThreadSafeLayoutNode; use wrapper::ThreadSafeLayoutNode;
@ -24,10 +25,12 @@ pub struct MulticolFlow {
} }
impl MulticolFlow { impl MulticolFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
fragment: Fragment,
float_kind: Option<FloatKind>)
-> MulticolFlow { -> MulticolFlow {
MulticolFlow { MulticolFlow {
block_flow: BlockFlow::from_node_and_fragment(node, fragment) block_flow: BlockFlow::from_node_and_fragment(node, fragment, float_kind)
} }
} }
} }

View file

@ -10,7 +10,6 @@ use block::{self, BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
use block::{ISizeConstraintInput, ISizeConstraintSolution}; use block::{ISizeConstraintInput, ISizeConstraintSolution};
use context::LayoutContext; use context::LayoutContext;
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use floats::FloatKind;
use flow::{self, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS}; use flow::{self, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
use flow::{ImmutableFlowUtils}; use flow::{ImmutableFlowUtils};
use fragment::{Fragment, FragmentBorderBoxIterator}; use fragment::{Fragment, FragmentBorderBoxIterator};
@ -66,28 +65,7 @@ impl TableFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
fragment: Fragment) fragment: Fragment)
-> TableFlow { -> TableFlow {
let mut block_flow = BlockFlow::from_node_and_fragment(node, fragment); let mut block_flow = BlockFlow::from_node_and_fragment(node, fragment, None);
let table_layout =
if block_flow.fragment().style().get_table().table_layout == table_layout::T::fixed {
TableLayout::Fixed
} else {
TableLayout::Auto
};
TableFlow {
block_flow: block_flow,
column_intrinsic_inline_sizes: Vec::new(),
column_computed_inline_sizes: Vec::new(),
collapsed_inline_direction_border_widths_for_table: Vec::new(),
collapsed_block_direction_border_widths_for_table: Vec::new(),
table_layout: table_layout
}
}
pub fn float_from_node_and_fragment(node: &ThreadSafeLayoutNode,
fragment: Fragment,
float_kind: FloatKind)
-> TableFlow {
let mut block_flow = BlockFlow::float_from_node_and_fragment(node, fragment, float_kind);
let table_layout = let table_layout =
if block_flow.fragment().style().get_table().table_layout == table_layout::T::fixed { if block_flow.fragment().style().get_table().table_layout == table_layout::T::fixed {
TableLayout::Fixed TableLayout::Fixed

View file

@ -28,7 +28,7 @@ impl TableCaptionFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment)
-> TableCaptionFlow { -> TableCaptionFlow {
TableCaptionFlow { TableCaptionFlow {
block_flow: BlockFlow::from_node_and_fragment(node, fragment) block_flow: BlockFlow::from_node_and_fragment(node, fragment, None)
} }
} }
} }

View file

@ -52,7 +52,7 @@ impl TableCellFlow {
visible: bool) visible: bool)
-> TableCellFlow { -> TableCellFlow {
TableCellFlow { TableCellFlow {
block_flow: BlockFlow::from_node_and_fragment(node, fragment), block_flow: BlockFlow::from_node_and_fragment(node, fragment, None),
collapsed_borders: CollapsedBordersForCell::new(), collapsed_borders: CollapsedBordersForCell::new(),
column_span: node.get_unsigned_integer_attribute(UnsignedIntegerAttribute::ColSpan) column_span: node.get_unsigned_integer_attribute(UnsignedIntegerAttribute::ColSpan)
.unwrap_or(1), .unwrap_or(1),

View file

@ -79,7 +79,7 @@ impl TableRowFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment)
-> TableRowFlow { -> TableRowFlow {
TableRowFlow { TableRowFlow {
block_flow: BlockFlow::from_node_and_fragment(node, fragment), block_flow: BlockFlow::from_node_and_fragment(node, fragment, None),
cell_intrinsic_inline_sizes: Vec::new(), cell_intrinsic_inline_sizes: Vec::new(),
column_computed_inline_sizes: Vec::new(), column_computed_inline_sizes: Vec::new(),
spacing: border_spacing::T { spacing: border_spacing::T {

View file

@ -62,7 +62,7 @@ impl TableRowGroupFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment)
-> TableRowGroupFlow { -> TableRowGroupFlow {
TableRowGroupFlow { TableRowGroupFlow {
block_flow: BlockFlow::from_node_and_fragment(node, fragment), block_flow: BlockFlow::from_node_and_fragment(node, fragment, None),
column_intrinsic_inline_sizes: Vec::new(), column_intrinsic_inline_sizes: Vec::new(),
column_computed_inline_sizes: Vec::new(), column_computed_inline_sizes: Vec::new(),
spacing: border_spacing::T { spacing: border_spacing::T {

View file

@ -56,9 +56,11 @@ pub struct TableWrapperFlow {
} }
impl TableWrapperFlow { impl TableWrapperFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
fragment: Fragment,
float_kind: Option<FloatKind>)
-> TableWrapperFlow { -> TableWrapperFlow {
let mut block_flow = BlockFlow::from_node_and_fragment(node, fragment); let mut block_flow = BlockFlow::from_node_and_fragment(node, fragment, float_kind);
let table_layout = if block_flow.fragment().style().get_table().table_layout == let table_layout = if block_flow.fragment().style().get_table().table_layout ==
table_layout::T::fixed { table_layout::T::fixed {
TableLayout::Fixed TableLayout::Fixed
@ -71,25 +73,6 @@ impl TableWrapperFlow {
table_layout: table_layout table_layout: table_layout
} }
} }
pub fn float_from_node_and_fragment(node: &ThreadSafeLayoutNode,
fragment: Fragment,
float_kind: FloatKind)
-> TableWrapperFlow {
let mut block_flow = BlockFlow::float_from_node_and_fragment(node, fragment, float_kind);
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
table_layout::T::fixed {
TableLayout::Fixed
} else {
TableLayout::Auto
};
TableWrapperFlow {
block_flow: block_flow,
column_intrinsic_inline_sizes: vec!(),
table_layout: table_layout
}
}
fn border_padding_and_spacing(&mut self) -> (Au, Au) { fn border_padding_and_spacing(&mut self) -> (Au, Au) {
let (mut table_border_padding, mut spacing) = (Au(0), Au(0)); let (mut table_border_padding, mut spacing) = (Au(0), Au(0));
for kid in self.block_flow.base.child_iter() { for kid in self.block_flow.base.child_iter() {