diff --git a/components/layout/block.rs b/components/layout/block.rs index 456ee73d09b..77c60b25b3d 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -27,7 +27,6 @@ #![deny(unsafe_blocks)] -use construct::FlowConstructor; use context::LayoutContext; use css::node_style::StyledNode; use display_list_builder::{BlockFlowDisplayListBuilding, FragmentDisplayListBuilding}; @@ -50,12 +49,8 @@ use wrapper::ThreadSafeLayoutNode; use geom::{Point2D, Rect, Size2D}; use gfx::display_list::{ClippingRegion, DisplayList}; -use rustc_serialize::{Encoder, Encodable}; use msg::compositor_msg::LayerId; -use msg::constellation_msg::ConstellationChan; -use util::geometry::{Au, MAX_AU}; -use util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode}; -use util::opts; +use rustc_serialize::{Encoder, Encodable}; use std::cmp::{max, min}; use std::fmt; use style::computed_values::{overflow_x, overflow_y, position, box_sizing, display, float}; @@ -63,6 +58,9 @@ use style::properties::ComputedValues; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; use style::values::computed::{LengthOrPercentageOrNone}; use std::sync::Arc; +use util::geometry::{Au, MAX_AU}; +use util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode}; +use util::opts; /// Information specific to floated blocks. #[derive(Clone, RustcEncodable)] @@ -570,20 +568,6 @@ impl Encodable for BlockFlowFlags { } 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, ForceNonfloatedFlag::ForceNonfloated), - fragment: Fragment::new(constructor, node), - static_b_offset: Au::new(0), - inline_size_of_preceding_left_floats: Au(0), - inline_size_of_preceding_right_floats: Au(0), - hypothetical_position: LogicalPoint::new(writing_mode, Au(0), Au(0)), - float: None, - flags: BlockFlowFlags::empty(), - } - } - pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> BlockFlow { let writing_mode = node.style().writing_mode; BlockFlow { @@ -598,23 +582,6 @@ impl BlockFlow { } } - pub fn float_from_node(constructor: &mut FlowConstructor, - node: &ThreadSafeLayoutNode, - float_kind: FloatKind) - -> BlockFlow { - let writing_mode = node.style().writing_mode; - BlockFlow { - base: BaseFlow::new(Some((*node).clone()), writing_mode, ForceNonfloatedFlag::FloatIfNecessary), - fragment: Fragment::new(constructor, node), - static_b_offset: Au::new(0), - inline_size_of_preceding_left_floats: Au(0), - inline_size_of_preceding_right_floats: Au(0), - hypothetical_position: LogicalPoint::new(writing_mode, Au(0), Au(0)), - float: Some(box FloatedBlockInfo::new(float_kind)), - flags: BlockFlowFlags::empty(), - } - } - pub fn float_from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment, float_kind: FloatKind) @@ -1950,8 +1917,8 @@ impl Flow for BlockFlow { .translate(stacking_context_position)); } - fn remove_compositor_layers(&self, constellation_chan: ConstellationChan) { - self.fragment.remove_compositor_layers(constellation_chan); + fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) { + (*mutator)(&mut self.fragment) } } diff --git a/components/layout/construct.rs b/components/layout/construct.rs index b8dd5a8415e..b29b6507c2d 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -16,23 +16,23 @@ use block::BlockFlow; use context::LayoutContext; use css::node_style::StyledNode; +use data::{HAS_NEWLY_CONSTRUCTED_FLOW, LayoutDataAccess, LayoutDataWrapper}; use floats::FloatKind; use flow::{Descendants, AbsDescendants}; use flow::{Flow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use flow::{IS_ABSOLUTELY_POSITIONED}; use flow; use flow_ref::FlowRef; +use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo}; use fragment::CanvasFragmentInfo; use fragment::ImageFragmentInfo; use fragment::InlineAbsoluteHypotheticalFragmentInfo; use fragment::TableColumnFragmentInfo; use fragment::UnscannedTextFragmentInfo; -use fragment::{Fragment, IframeFragmentInfo}; use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo}; use incremental::{RECONSTRUCT_FLOW, RestyleDamage}; use inline::InlineFlow; -use data::{HAS_NEWLY_CONSTRUCTED_FLOW, LayoutDataAccess, LayoutDataWrapper}; -use list_item::{self, ListItemFlow}; +use list_item::{ListItemFlow, ListStyleTypeContent}; use opaque_node::OpaqueNodeMethods; use parallel; use table::TableFlow; @@ -55,9 +55,10 @@ use std::borrow::ToOwned; use std::collections::DList; use std::mem; use std::sync::atomic::Ordering; +use style::computed_values::content::ContentItem; use style::computed_values::{caption_side, display, empty_cells, float, list_style_position}; use style::computed_values::{position}; -use style::properties::{ComputedValues, make_inline}; +use style::properties::{self, ComputedValues}; use std::sync::Arc; use url::Url; @@ -265,41 +266,51 @@ impl<'a> FlowConstructor<'a> { } } - /// Builds specific `Fragment` info for the given node. - /// - /// This does *not* construct the text for generated content (but, for generated content with - /// `display: block`, it does construct the generic fragment corresponding to the block). - /// Construction of the text fragment is done specially by `build_flow_using_children()` and - /// `build_fragments_for_replaced_inline_content()`. - pub fn build_specific_fragment_info_for_node(&mut self, node: &ThreadSafeLayoutNode) - -> SpecificFragmentInfo { - match node.type_id() { - Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLIFrameElement))) => { + /// Builds the fragment for the given block or subclass thereof. + fn build_fragment_for_block(&mut self, node: &ThreadSafeLayoutNode) -> Fragment { + let specific_fragment_info = match node.type_id() { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLIFrameElement))) => { SpecificFragmentInfo::Iframe(box IframeFragmentInfo::new(node)) } - Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement))) => { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLImageElement))) => { self.build_fragment_info_for_image(node, node.image_url()) } - Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement))) => { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLObjectElement))) => { let data = node.get_object_data(); self.build_fragment_info_for_image(node, data) } - Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableElement))) => SpecificFragmentInfo::TableWrapper, - Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableColElement))) => { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLTableElement))) => { + SpecificFragmentInfo::TableWrapper + } + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLTableColElement))) => { SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node)) } - Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableCellElement(_)))) => SpecificFragmentInfo::TableCell, - Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement))) | - Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableSectionElement))) => SpecificFragmentInfo::TableRow, - Some(NodeTypeId::Text) => SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::new(node)), - Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement))) => { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLTableCellElement(_)))) => { + SpecificFragmentInfo::TableCell + } + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLTableRowElement))) | + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLTableSectionElement))) => { + SpecificFragmentInfo::TableRow + } + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLCanvasElement))) => { SpecificFragmentInfo::Canvas(box CanvasFragmentInfo::new(node)) } _ => { // This includes pseudo-elements. SpecificFragmentInfo::Generic } - } + }; + + Fragment::new(node, specific_fragment_info) } /// Creates an inline flow from a set of inline fragments, then adds it as a child of the given @@ -339,7 +350,9 @@ impl<'a> FlowConstructor<'a> { let mut inline_block_flows = vec!(); for f in fragments.iter() { match f.specific { - SpecificFragmentInfo::InlineBlock(ref info) => inline_block_flows.push(info.flow_ref.clone()), + SpecificFragmentInfo::InlineBlock(ref info) => { + inline_block_flows.push(info.flow_ref.clone()) + } SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => { inline_block_flows.push(info.flow_ref.clone()) } @@ -473,8 +486,8 @@ impl<'a> FlowConstructor<'a> { whitespace_damage)) => { // Add whitespace results. They will be stripped out later on when // between block elements, and retained when between inline elements. - let fragment_info = - SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::from_text(" ".to_owned())); + let fragment_info = SpecificFragmentInfo::UnscannedText( + UnscannedTextFragmentInfo::from_text(" ".to_owned())); let fragment = Fragment::from_opaque_node_and_style(whitespace_node, whitespace_style, whitespace_damage, @@ -488,25 +501,20 @@ impl<'a> FlowConstructor<'a> { } } - /// Constructs a block flow, beginning with the given `initial_fragment` if present and then + /// Constructs a block flow, beginning with the given `initial_fragments` 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 { + fn build_flow_for_block_starting_with_fragments(&mut self, + mut flow: FlowRef, + node: &ThreadSafeLayoutNode, + mut initial_fragments: DList) + -> 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 = match initial_fragment { - None => true, - Some(initial_fragment) => { - inline_fragment_accumulator.fragments.push_back(initial_fragment); - false - } - }; + inline_fragment_accumulator.fragments.append(&mut initial_fragments); + let mut first_fragment = inline_fragment_accumulator.fragments.is_empty(); // List of absolute descendants, in tree order. let mut abs_descendants = Descendants::new(); @@ -558,7 +566,7 @@ impl<'a> FlowConstructor<'a> { /// 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 + /// `build_flow_for_block_starting_with_fragments`. Currently the following kinds of flows get /// initial content: /// /// * Generated content gets the initial content specified by the `content` attribute of the @@ -569,32 +577,60 @@ impl<'a> FlowConstructor<'a> { /// `