diff --git a/components/layout/block.rs b/components/layout/block.rs index 61fff95ec09..079a1961073 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -30,7 +30,7 @@ use construct::FlowConstructor; use context::LayoutContext; use css::node_style::StyledNode; -use display_list_builder::{BlockFlowDisplayListBuilding, BlockLevel, FragmentDisplayListBuilding}; +use display_list_builder::{BlockFlowDisplayListBuilding, FragmentDisplayListBuilding}; use floats::{ClearBoth, ClearLeft, ClearRight, FloatKind, FloatLeft, Floats, PlacementInfo}; use flow::{AbsolutePositionInfo, BaseFlow, BlockFlowClass, FloatIfNecessary, FlowClass, Flow}; use flow::{ForceNonfloated, ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTraversal}; @@ -51,6 +51,7 @@ use table::ColumnComputedInlineSize; use wrapper::ThreadSafeLayoutNode; use geom::Size2D; +use gfx::display_list::DisplayList; use serialize::{Encoder, Encodable}; use servo_msg::compositor_msg::LayerId; use servo_util::geometry::{Au, MAX_AU, MAX_RECT, ZERO_POINT}; @@ -1853,16 +1854,7 @@ impl Flow for BlockFlow { } fn build_display_list(&mut self, layout_context: &LayoutContext) { - if self.base.flags.is_float() { - // TODO(#2009, pcwalton): This is a pseudo-stacking context. We need to merge `z-index: - // auto` kids into the parent stacking context, when that is supported. - self.build_display_list_for_floating_block(layout_context) - } else if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) { - self.build_display_list_for_absolutely_positioned_block(layout_context) - } else { - self.build_display_list_for_block(layout_context, BlockLevel) - } - + self.build_display_list_for_block(box DisplayList::new(), layout_context); if opts::get().validate_display_list_geometry { self.base.validate_display_list_geometry(); } diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 21a24af7efb..ec8533058cd 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -30,6 +30,7 @@ use fragment::{TableColumnFragment, TableColumnFragmentInfo, TableFragment, Tabl use fragment::{TableWrapperFragment, UnscannedTextFragment, UnscannedTextFragmentInfo}; use incremental::{RECONSTRUCT_FLOW, RestyleDamage}; use inline::InlineFlow; +use list_item::{mod, ListItemFlow}; use parallel; use table_wrapper::TableWrapperFlow; use table::TableFlow; @@ -59,7 +60,7 @@ use std::collections::DList; use std::mem; use std::sync::atomic::Relaxed; use style::ComputedValues; -use style::computed_values::{display, position, float}; +use style::computed_values::{display, position, float, list_style_position}; use sync::Arc; use url::Url; @@ -471,38 +472,25 @@ impl<'a> FlowConstructor<'a> { } } - /// Build block flow for current node using information from children nodes. - /// - /// Consume results from children and combine them, handling {ib} splits. - /// Block flows and inline flows thus created will become the children of - /// this block flow. - /// Also, deal with the absolute and fixed descendants bubbled up by - /// children nodes. - fn build_flow_for_block(&mut self, mut flow: FlowRef, node: &ThreadSafeLayoutNode) - -> ConstructionResult { + /// Constructs a block flow, beginning with the given `initial_fragment` if present and then + /// appending the construction results of children to the child list of the block flow. {ib} + /// splits and absolutely-positioned descendants are handled correctly. + fn build_flow_for_block_starting_with_fragment(&mut self, + mut flow: FlowRef, + node: &ThreadSafeLayoutNode, + initial_fragment: Option) + -> ConstructionResult { // Gather up fragments for the inline flows we might need to create. let mut inline_fragment_accumulator = InlineFragmentsAccumulator::new(); let mut consecutive_siblings = vec!(); - let mut first_fragment = true; - // Special case: If this is generated content, then we need to initialize the accumulator - // with the fragment corresponding to that content. - if node.get_pseudo_element_type() != Normal || - node.type_id() == Some(ElementNodeTypeId(HTMLInputElementTypeId)) || - node.type_id() == Some(ElementNodeTypeId(HTMLTextAreaElementTypeId)) { - // A TextArea's text contents are displayed through the input text - // box, so don't construct them. - // TODO Maybe this belongs somewhere else? - if node.type_id() == Some(ElementNodeTypeId(HTMLTextAreaElementTypeId)) { - for kid in node.children() { - kid.set_flow_construction_result(NoConstructionResult) - } + let mut first_fragment = match initial_fragment { + None => true, + Some(initial_fragment) => { + inline_fragment_accumulator.fragments.push_back(initial_fragment); + false } - let fragment_info = UnscannedTextFragment(UnscannedTextFragmentInfo::new(node)); - let fragment = Fragment::new_from_specific_info(node, fragment_info); - inline_fragment_accumulator.fragments.push_back(fragment); - first_fragment = false; - } + }; // List of absolute descendants, in tree order. let mut abs_descendants = Descendants::new(); @@ -552,6 +540,39 @@ impl<'a> FlowConstructor<'a> { FlowConstructionResult(flow, abs_descendants) } + /// Constructs a flow for the given block node and its children. This method creates an + /// initial fragment as appropriate and then dispatches to + /// `build_flow_for_block_starting_with_fragment`. Currently the following kinds of flows get + /// initial content: + /// + /// * Generated content gets the initial content specified by the `content` attribute of the + /// CSS. + /// * `` and `