diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2014-03-28 13:19:58 -0700 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2014-04-03 14:50:56 -0700 |
commit | 98bf325e76137f01fda7df7333b2cb9b7b319474 (patch) | |
tree | e9525c20a378c0402a3e9917074fb956f6c5b194 /src/components/main/layout/construct.rs | |
parent | 4fd950eae04a5a8516e4f2ac1541f5154fd509e5 (diff) | |
download | servo-98bf325e76137f01fda7df7333b2cb9b7b319474.tar.gz servo-98bf325e76137f01fda7df7333b2cb9b7b319474.zip |
layout: Support multiple boxes per node; don't store fixed/absolute
descendant links separately
Diffstat (limited to 'src/components/main/layout/construct.rs')
-rw-r--r-- | src/components/main/layout/construct.rs | 129 |
1 files changed, 67 insertions, 62 deletions
diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs index 8b25937c624..7d786e8fb77 100644 --- a/src/components/main/layout/construct.rs +++ b/src/components/main/layout/construct.rs @@ -22,14 +22,14 @@ use css::node_style::StyledNode; use layout::block::BlockFlow; -use layout::box_::{Box, GenericBox, IframeBox, IframeBoxInfo, ImageBox, ImageBoxInfo, TableBox}; -use layout::box_::{TableCellBox, TableColumnBox, TableColumnBoxInfo, TableRowBox, TableWrapperBox}; -use layout::box_::{InlineInfo, InlineParentInfo, SpecificBoxInfo, UnscannedTextBox}; -use layout::box_::{UnscannedTextBoxInfo}; +use layout::box_::{Box, GenericBox, IframeBox, IframeBoxInfo, ImageBox, ImageBoxInfo}; +use layout::box_::{InlineInfo, InlineParentInfo, MainBoxKind, SpecificBoxInfo, SubBoxKind}; +use layout::box_::{TableBox, TableCellBox, TableColumnBox, TableColumnBoxInfo, TableRowBox}; +use layout::box_::{TableWrapperBox, UnscannedTextBox, UnscannedTextBoxInfo}; use layout::context::LayoutContext; use layout::floats::FloatKind; use layout::flow::{Flow, ImmutableFlowUtils, MutableOwnedFlowUtils}; -use layout::flow::{Descendants, AbsDescendants, FixedDescendants}; +use layout::flow::{Descendants, AbsDescendants}; use layout::flow_list::{Rawlink}; use layout::inline::InlineFlow; use layout::table_wrapper::TableWrapperFlow; @@ -40,31 +40,34 @@ use layout::table_rowgroup::TableRowGroupFlow; use layout::table_row::TableRowFlow; use layout::table_cell::TableCellFlow; use layout::text::TextRunScanner; -use layout::util::{LayoutDataAccess, OpaqueNode}; +use layout::util::{LayoutDataAccess, OpaqueNodeMethods}; use layout::wrapper::{PostorderNodeMutTraversal, TLayoutNode, ThreadSafeLayoutNode}; +use layout::wrapper::{Before, BeforeBlock, After, AfterBlock, Normal}; +use extra::url::Url; +use gfx::display_list::OpaqueNode; use gfx::font_context::FontContext; use script::dom::bindings::codegen::InheritTypes::TextCast; use script::dom::bindings::js::JS; -use script::dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId, HTMLObjectElementTypeId}; -use script::dom::element::{HTMLTableElementTypeId, HTMLTableSectionElementTypeId}; -use script::dom::element::{HTMLTableDataCellElementTypeId, HTMLTableHeaderCellElementTypeId}; -use script::dom::element::{HTMLTableColElementTypeId, HTMLTableRowElementTypeId}; +use script::dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId}; +use script::dom::element::{HTMLObjectElementTypeId, HTMLPseudoElementTypeId}; +use script::dom::element::{HTMLTableColElementTypeId, HTMLTableDataCellElementTypeId}; +use script::dom::element::{HTMLTableElementTypeId, HTMLTableHeaderCellElementTypeId}; +use script::dom::element::{HTMLTableRowElementTypeId, HTMLTableSectionElementTypeId}; use script::dom::node::{CommentNodeTypeId, DoctypeNodeTypeId, DocumentFragmentNodeTypeId}; use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId}; use script::dom::node::{TextNodeTypeId}; use script::dom::text::Text; -use style::computed_values::{display, position, float, white_space}; -use style::ComputedValues; +use servo_util::geometry::Au; use servo_util::namespace; -use servo_util::url::parse_url; -use servo_util::url::is_image_data; +use servo_util::smallvec::SmallVec; use servo_util::str::is_whitespace; - -use extra::url::Url; -use sync::Arc; +use servo_util::url::{is_image_data, parse_url}; use std::mem; use std::num::Zero; +use style::ComputedValues; +use style::computed_values::{display, position, float, white_space}; +use sync::Arc; /// The results of flow construction for a DOM node. pub enum ConstructionResult { @@ -75,7 +78,7 @@ pub enum ConstructionResult { /// This node contributed a flow at the proper position in the tree. /// Nothing more needs to be done for this node. It has bubbled up fixed /// and absolute descendant flows that have a CB above it. - FlowConstructionResult(~Flow, AbsDescendants, FixedDescendants), + FlowConstructionResult(~Flow, AbsDescendants), /// This node contributed some object or objects that will be needed to construct a proper flow /// later up the tree, but these objects have not yet found their home. @@ -86,7 +89,7 @@ impl ConstructionResult { fn destroy(&mut self) { match *self { NoConstructionResult => {} - FlowConstructionResult(ref mut flow, _, _) => flow.destroy(), + FlowConstructionResult(ref mut flow, _) => flow.destroy(), ConstructionItemConstructionResult(ref mut item) => item.destroy(), } } @@ -132,9 +135,6 @@ struct InlineBoxesConstructionResult { /// Any absolute descendants that we're bubbling up. abs_descendants: AbsDescendants, - - /// Any fixed descendants that we're bubbling up. - fixed_descendants: FixedDescendants, } /// Represents an {ib} split that has not yet found the containing block that it belongs to. This @@ -493,16 +493,13 @@ impl<'a> FlowConstructor<'a> { flow.set_abs_descendants(abs_descendants); abs_descendants = Descendants::new(); - if is_fixed_positioned { - // Send itself along with the other fixed descendants. - fixed_descendants.push(Rawlink::some(flow)); - } else if is_absolutely_positioned { + if is_fixed_positioned || is_absolutely_positioned { // This is now the only absolute flow in the subtree which hasn't yet // reached its CB. abs_descendants.push(Rawlink::some(flow)); } } - FlowConstructionResult(flow, abs_descendants, fixed_descendants) + FlowConstructionResult(flow, abs_descendants) } /// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly @@ -521,7 +518,6 @@ impl<'a> FlowConstructor<'a> { self.build_flow_using_children(flow, node) } - /// Concatenates the boxes of kids, adding in our own borders/padding/margins if necessary. /// Returns the `InlineBoxesConstructionResult`, if any. There will be no /// `InlineBoxesConstructionResult` if this node consisted entirely of ignorable whitespace. @@ -530,13 +526,12 @@ impl<'a> FlowConstructor<'a> { let mut opt_inline_block_splits = None; let mut opt_box_accumulator = None; let mut abs_descendants = Descendants::new(); - let mut fixed_descendants = Descendants::new(); // Concatenate all the boxes of our kids, creating {ib} splits as necessary. for kid in node.children() { match kid.swap_out_construction_result() { NoConstructionResult => {} - FlowConstructionResult(flow, kid_abs_descendants, kid_fixed_descendants) => { + FlowConstructionResult(flow, kid_abs_descendants) => { // {ib} split. Flush the accumulator to our new split and make a new // accumulator to hold any subsequent boxes we come across. let split = InlineBlockSplit { @@ -545,14 +540,12 @@ impl<'a> FlowConstructor<'a> { }; opt_inline_block_splits.push(split); abs_descendants.push_descendants(kid_abs_descendants); - fixed_descendants.push_descendants(kid_fixed_descendants); } ConstructionItemConstructionResult(InlineBoxesConstructionItem( InlineBoxesConstructionResult { splits: opt_splits, boxes: boxes, abs_descendants: kid_abs_descendants, - fixed_descendants: kid_fixed_descendants, })) => { // Bubble up {ib} splits. @@ -579,7 +572,6 @@ impl<'a> FlowConstructor<'a> { // Push residual boxes. opt_box_accumulator.push_all_move(boxes); abs_descendants.push_descendants(kid_abs_descendants); - fixed_descendants.push_descendants(kid_fixed_descendants); } ConstructionItemConstructionResult(WhitespaceConstructionItem(whitespace_node, whitespace_style)) @@ -612,7 +604,7 @@ impl<'a> FlowConstructor<'a> { for box_ in boxes.iter() { total.push(box_); } - self.set_inline_info_for_inline_child(&total, node); + self.set_inline_info_for_inline_child(total, node); }, None => { @@ -622,7 +614,7 @@ impl<'a> FlowConstructor<'a> { total.push(box_); } } - self.set_inline_info_for_inline_child(&total, node); + self.set_inline_info_for_inline_child(total, node); } } }, @@ -633,7 +625,7 @@ impl<'a> FlowConstructor<'a> { for box_ in boxes.iter() { total.push(box_); } - self.set_inline_info_for_inline_child(&total, node); + self.set_inline_info_for_inline_child(total, node); }, None => {} } @@ -648,7 +640,6 @@ impl<'a> FlowConstructor<'a> { splits: opt_inline_block_splits, boxes: opt_box_accumulator.to_vec(), abs_descendants: abs_descendants, - fixed_descendants: fixed_descendants, }); ConstructionItemConstructionResult(construction_item) } else { @@ -656,10 +647,11 @@ impl<'a> FlowConstructor<'a> { } } + // FIXME(pcwalton): Why does this function create a box only to throw it away??? fn set_inline_info_for_inline_child(&mut self, - boxes: &~[&Box], + boxes: &[&Box], parent_node: &ThreadSafeLayoutNode) { - let parent_box = Box::new(self, parent_node); + let parent_box = Box::new(self, parent_node, MainBoxKind); let font_style = parent_box.font_style(); let font_group = self.font_context().get_resolved_font_for_style(&font_style); let (font_ascent,font_descent) = font_group.borrow().with_mut( |fg| { @@ -671,33 +663,38 @@ impl<'a> FlowConstructor<'a> { let boxes_len = boxes.len(); parent_box.compute_borders(parent_box.style()); + // FIXME(pcwalton): I suspect that `Au(0)` is not correct for the containing block width. + parent_box.compute_padding(parent_box.style(), Au(0)); + for (i, box_) in boxes.iter().enumerate() { if box_.inline_info.with( |data| data.is_none() ) { box_.inline_info.set(Some(InlineInfo::new())); } let mut border = parent_box.border.get(); + let mut padding = parent_box.padding.get(); if i != 0 { border.left = Zero::zero(); + padding.left = Zero::zero() } if i != (boxes_len - 1) { border.right = Zero::zero(); + padding.right = Zero::zero() } let mut info = box_.inline_info.borrow_mut(); match info.get() { &Some(ref mut info) => { - // TODO(ksh8281) compute margin,padding - info.parent_info.push( - InlineParentInfo { - padding: Zero::zero(), - border: border, - margin: Zero::zero(), - style: parent_box.style.clone(), - font_ascent: font_ascent, - font_descent: font_descent, - node: OpaqueNode::from_thread_safe_layout_node(parent_node), - }); + // TODO(ksh8281): Compute margins. + info.parent_info.push(InlineParentInfo { + padding: padding, + border: border, + margin: Zero::zero(), + style: parent_box.style.clone(), + font_ascent: font_ascent, + font_descent: font_descent, + node: OpaqueNodeMethods::from_thread_safe_layout_node(parent_node), + }) }, &None => {} } @@ -712,20 +709,22 @@ impl<'a> FlowConstructor<'a> { } // If this node is ignorable whitespace, bail out now. + // + // FIXME(pcwalton): Don't do this if there's padding or borders. if node.is_ignorable_whitespace() { - let opaque_node = OpaqueNode::from_thread_safe_layout_node(node); + let opaque_node = OpaqueNodeMethods::from_thread_safe_layout_node(node); return ConstructionItemConstructionResult(WhitespaceConstructionItem( opaque_node, node.style().clone())) } + let mut opt_box_accumulator = None; + opt_box_accumulator.push(Box::new(self, node, MainBoxKind)); + let construction_item = InlineBoxesConstructionItem(InlineBoxesConstructionResult { splits: None, - boxes: ~[ - Box::new(self, node) - ], + boxes: opt_box_accumulator.to_vec(), abs_descendants: Descendants::new(), - fixed_descendants: Descendants::new(), }); ConstructionItemConstructionResult(construction_item) } @@ -750,7 +749,7 @@ impl<'a> FlowConstructor<'a> { for kid in node.children() { match kid.swap_out_construction_result() { NoConstructionResult | ConstructionItemConstructionResult(_) => {} - FlowConstructionResult(kid_flow, _, _) => { + FlowConstructionResult(kid_flow, _) => { // Only kid flows with table-caption are matched here. assert!(kid_flow.is_table_caption()); table_wrapper_flow.add_new_child(kid_flow); @@ -761,8 +760,10 @@ impl<'a> FlowConstructor<'a> { /// Generates an anonymous table flow according to CSS 2.1 § 17.2.1, step 2. /// If necessary, generate recursively another anonymous table flow. - fn generate_anonymous_missing_child(&mut self, child_flows: ~[~Flow], - flow: &mut ~Flow, node: &ThreadSafeLayoutNode) { + fn generate_anonymous_missing_child(&mut self, + child_flows: ~[~Flow], + flow: &mut ~Flow, + node: &ThreadSafeLayoutNode) { let mut anonymous_flow = flow.generate_missing_child_flow(node); let mut consecutive_siblings = ~[]; for kid_flow in child_flows.move_iter() { @@ -805,10 +806,9 @@ impl<'a> FlowConstructor<'a> { // NOTE: The order of captions and table are not the same order as in the DOM tree. // All caption blocks are placed before the table flow match construction_result { - FlowConstructionResult(table_flow, table_abs_descendants, table_fixed_descendants) => { + FlowConstructionResult(table_flow, table_abs_descendants) => { wrapper_flow.add_new_child(table_flow); abs_descendants.push_descendants(table_abs_descendants); - fixed_descendants.push_descendants(table_fixed_descendants); } _ => {} } @@ -832,7 +832,7 @@ impl<'a> FlowConstructor<'a> { abs_descendants.push(Rawlink::some(wrapper_flow)); } } - FlowConstructionResult(wrapper_flow, abs_descendants, fixed_descendants) + FlowConstructionResult(wrapper_flow, abs_descendants) } /// Builds a flow for a node with `display: table-caption`. This yields a `TableCaptionFlow` @@ -904,7 +904,7 @@ impl<'a> FlowConstructor<'a> { let mut flow = ~TableColGroupFlow::from_node_and_boxes(node, box_, col_boxes) as ~Flow; flow.finish(self.layout_context); - FlowConstructionResult(flow, Descendants::new(), Descendants::new()) + FlowConstructionResult(flow, Descendants::new()) } } @@ -922,6 +922,10 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> { fn process(&mut self, node: &ThreadSafeLayoutNode) -> bool { // Get the `display` property for this node, and determine whether this node is floated. let (display, float, positioning) = match node.type_id() { + ElementNodeTypeId(HTMLPseudoElementTypeId) => { + let style = node.style().get(); + (display::inline, style.Box.get().float, style.Box.get().position) + } ElementNodeTypeId(_) => { let style = node.style().get(); (style.Box.get().display, style.Box.get().float, style.Box.get().position) @@ -1050,6 +1054,7 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> { DoctypeNodeTypeId | DocumentFragmentNodeTypeId | DocumentNodeTypeId | + ElementNodeTypeId(HTMLPseudoElementTypeId) | ElementNodeTypeId(HTMLImageElementTypeId) => true, ElementNodeTypeId(HTMLObjectElementTypeId) => self.has_object_data(), ElementNodeTypeId(_) => false, |