diff options
Diffstat (limited to 'src/components/main/layout/construct.rs')
-rw-r--r-- | src/components/main/layout/construct.rs | 441 |
1 files changed, 251 insertions, 190 deletions
diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs index 8b25937c624..e24805f687a 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, SpecificBoxInfo}; +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}; +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 @@ -281,7 +281,8 @@ impl<'a> FlowConstructor<'a> { } /// Builds the `ImageBoxInfo` for the given image. This is out of line to guide inlining. - fn build_box_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>) -> SpecificBoxInfo { + fn build_box_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>) + -> SpecificBoxInfo { match url { None => GenericBox, Some(url) => { @@ -296,19 +297,25 @@ impl<'a> FlowConstructor<'a> { pub fn build_specific_box_info_for_node(&mut self, node: &ThreadSafeLayoutNode) -> SpecificBoxInfo { match node.type_id() { - ElementNodeTypeId(HTMLImageElementTypeId) => self.build_box_info_for_image(node, node.image_url()), - ElementNodeTypeId(HTMLIFrameElementTypeId) => IframeBox(IframeBoxInfo::new(node)), - ElementNodeTypeId(HTMLObjectElementTypeId) => { + Some(ElementNodeTypeId(HTMLImageElementTypeId)) => { + self.build_box_info_for_image(node, node.image_url()) + } + Some(ElementNodeTypeId(HTMLIFrameElementTypeId)) => { + IframeBox(IframeBoxInfo::new(node)) + } + Some(ElementNodeTypeId(HTMLObjectElementTypeId)) => { let data = node.get_object_data(&self.layout_context.url); self.build_box_info_for_image(node, data) } - ElementNodeTypeId(HTMLTableElementTypeId) => TableWrapperBox, - ElementNodeTypeId(HTMLTableColElementTypeId) => TableColumnBox(TableColumnBoxInfo::new(node)), - ElementNodeTypeId(HTMLTableDataCellElementTypeId) | - ElementNodeTypeId(HTMLTableHeaderCellElementTypeId) => TableCellBox, - ElementNodeTypeId(HTMLTableRowElementTypeId) | - ElementNodeTypeId(HTMLTableSectionElementTypeId) => TableRowBox, - TextNodeTypeId => UnscannedTextBox(UnscannedTextBoxInfo::new(node)), + Some(ElementNodeTypeId(HTMLTableElementTypeId)) => TableWrapperBox, + Some(ElementNodeTypeId(HTMLTableColElementTypeId)) => { + TableColumnBox(TableColumnBoxInfo::new(node)) + } + Some(ElementNodeTypeId(HTMLTableDataCellElementTypeId)) | + Some(ElementNodeTypeId(HTMLTableHeaderCellElementTypeId)) => TableCellBox, + Some(ElementNodeTypeId(HTMLTableRowElementTypeId)) | + Some(ElementNodeTypeId(HTMLTableSectionElementTypeId)) => TableRowBox, + None | Some(TextNodeTypeId) => UnscannedTextBox(UnscannedTextBoxInfo::new(node)), _ => GenericBox, } } @@ -352,6 +359,115 @@ impl<'a> FlowConstructor<'a> { } } + fn build_block_flow_using_children_construction_result(&mut self, + flow: &mut ~Flow, + consecutive_siblings: &mut ~[~Flow], + node: &ThreadSafeLayoutNode, + kid: ThreadSafeLayoutNode, + opt_boxes_for_inline_flow: &mut Option<~[Box]>, + abs_descendants: &mut Descendants, + first_box: &mut bool) { + match kid.swap_out_construction_result() { + NoConstructionResult => {} + FlowConstructionResult(kid_flow, kid_abs_descendants) => { + // If kid_flow is TableCaptionFlow, kid_flow should be added under + // TableWrapperFlow. + if flow.is_table() && kid_flow.is_table_caption() { + kid.set_flow_construction_result(FlowConstructionResult( + kid_flow, + Descendants::new())) + } else if flow.need_anonymous_flow(kid_flow) { + consecutive_siblings.push(kid_flow) + } else { + // Strip ignorable whitespace from the start of this flow per CSS 2.1 § + // 9.2.1.1. + if flow.is_table_kind() || *first_box { + strip_ignorable_whitespace_from_start(opt_boxes_for_inline_flow); + *first_box = false + } + + // Flush any inline boxes that we were gathering up. This allows us to handle + // {ib} splits. + debug!("flushing {} inline box(es) to flow A", + opt_boxes_for_inline_flow.as_ref() + .map_or(0, |boxes| boxes.len())); + self.flush_inline_boxes_to_flow_or_list_if_necessary( + opt_boxes_for_inline_flow, + flow, + consecutive_siblings, + node); + if !consecutive_siblings.is_empty() { + let consecutive_siblings = mem::replace(consecutive_siblings, ~[]); + self.generate_anonymous_missing_child(consecutive_siblings, + flow, + node); + } + flow.add_new_child(kid_flow); + } + abs_descendants.push_descendants(kid_abs_descendants); + } + ConstructionItemConstructionResult(InlineBoxesConstructionItem( + InlineBoxesConstructionResult { + splits: opt_splits, + boxes: boxes, + abs_descendants: kid_abs_descendants, + })) => { + // Add any {ib} splits. + match opt_splits { + None => {} + Some(splits) => { + for split in splits.move_iter() { + // Pull apart the {ib} split object and push its predecessor boxes + // onto the list. + let InlineBlockSplit { + predecessor_boxes: predecessor_boxes, + flow: kid_flow + } = split; + opt_boxes_for_inline_flow.push_all_move(predecessor_boxes); + + // If this is the first box in flow, then strip ignorable + // whitespace per CSS 2.1 § 9.2.1.1. + if *first_box { + strip_ignorable_whitespace_from_start( + opt_boxes_for_inline_flow); + *first_box = false + } + + // Flush any inline boxes that we were gathering up. + debug!("flushing {} inline box(es) to flow A", + opt_boxes_for_inline_flow.as_ref() + .map_or(0, |boxes| boxes.len())); + self.flush_inline_boxes_to_flow_or_list_if_necessary( + opt_boxes_for_inline_flow, + flow, + consecutive_siblings, + node); + + // Push the flow generated by the {ib} split onto our list of + // flows. + if flow.need_anonymous_flow(kid_flow) { + consecutive_siblings.push(kid_flow) + } else { + flow.add_new_child(kid_flow) + } + } + } + } + + // Add the boxes to the list we're maintaining. + opt_boxes_for_inline_flow.push_all_move(boxes); + abs_descendants.push_descendants(kid_abs_descendants); + } + ConstructionItemConstructionResult(WhitespaceConstructionItem(..)) => { + // Nothing to do here. + } + ConstructionItemConstructionResult(TableColumnBoxConstructionItem(_)) => { + // TODO: Implement anonymous table objects for missing parents + // CSS 2.1 § 17.2.1, step 3-2 + } + } + } + /// Build block flow for current node using information from children nodes. /// /// Consume results from children and combine them, handling {ib} splits. @@ -367,109 +483,22 @@ impl<'a> FlowConstructor<'a> { let mut opt_boxes_for_inline_flow = None; let mut consecutive_siblings = ~[]; let mut first_box = true; + // List of absolute descendants, in tree order. let mut abs_descendants = Descendants::new(); - let mut fixed_descendants = Descendants::new(); for kid in node.children() { - match kid.swap_out_construction_result() { - NoConstructionResult => {} - FlowConstructionResult(kid_flow, kid_abs_descendants, kid_fixed_descendants) => { - // If kid_flow is TableCaptionFlow, kid_flow should be added under TableWrapperFlow. - if flow.is_table() && kid_flow.is_table_caption() { - kid.set_flow_construction_result(FlowConstructionResult(kid_flow, - Descendants::new(), - Descendants::new())) - } else if flow.need_anonymous_flow(kid_flow) { - consecutive_siblings.push(kid_flow) - } else { - // Strip ignorable whitespace from the start of this flow per CSS 2.1 § - // 9.2.1.1. - if flow.is_table_kind() || first_box { - strip_ignorable_whitespace_from_start(&mut opt_boxes_for_inline_flow); - first_box = false - } - - // Flush any inline boxes that we were gathering up. This allows us to handle - // {ib} splits. - debug!("flushing {} inline box(es) to flow A", - opt_boxes_for_inline_flow.as_ref() - .map_or(0, |boxes| boxes.len())); - self.flush_inline_boxes_to_flow_or_list_if_necessary(&mut opt_boxes_for_inline_flow, - &mut flow, - &mut consecutive_siblings, - node); - if !consecutive_siblings.is_empty() { - self.generate_anonymous_missing_child(consecutive_siblings, &mut flow, node); - consecutive_siblings = ~[]; - } - flow.add_new_child(kid_flow); - } - 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, - })) => { - // Add any {ib} splits. - match opt_splits { - None => {} - Some(splits) => { - for split in splits.move_iter() { - // Pull apart the {ib} split object and push its predecessor boxes - // onto the list. - let InlineBlockSplit { - predecessor_boxes: predecessor_boxes, - flow: kid_flow - } = split; - opt_boxes_for_inline_flow.push_all_move(predecessor_boxes); - - // If this is the first box in flow, then strip ignorable - // whitespace per CSS 2.1 § 9.2.1.1. - if first_box { - strip_ignorable_whitespace_from_start( - &mut opt_boxes_for_inline_flow); - first_box = false - } - - // Flush any inline boxes that we were gathering up. - debug!("flushing {} inline box(es) to flow A", - opt_boxes_for_inline_flow.as_ref() - .map_or(0, - |boxes| boxes.len())); - self.flush_inline_boxes_to_flow_or_list_if_necessary( - &mut opt_boxes_for_inline_flow, - &mut flow, - &mut consecutive_siblings, - node); - - // Push the flow generated by the {ib} split onto our list of - // flows. - if flow.need_anonymous_flow(kid_flow) { - consecutive_siblings.push(kid_flow) - } else { - flow.add_new_child(kid_flow) - } - } - } - } - - // Add the boxes to the list we're maintaining. - opt_boxes_for_inline_flow.push_all_move(boxes); - abs_descendants.push_descendants(kid_abs_descendants); - fixed_descendants.push_descendants(kid_fixed_descendants); - } - ConstructionItemConstructionResult(WhitespaceConstructionItem(..)) => { - // Nothing to do here. - } - ConstructionItemConstructionResult(TableColumnBoxConstructionItem(_)) => { - // TODO: Implement anonymous table objects for missing parents - // CSS 2.1 § 17.2.1, step 3-2 - } + if kid.get_element_type() != Normal { + self.process(&kid); } + + self.build_block_flow_using_children_construction_result( + &mut flow, + &mut consecutive_siblings, + node, + kid, + &mut opt_boxes_for_inline_flow, + &mut abs_descendants, + &mut first_box); } // Perform a final flush of any inline boxes that we were gathering up to handle {ib} @@ -493,16 +522,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 +547,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 +555,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 +569,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 +601,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 +633,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 +643,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 +654,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 +669,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,8 +676,9 @@ impl<'a> FlowConstructor<'a> { } } + // FIXME(#1999, 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 font_style = parent_box.font_style(); @@ -671,33 +692,39 @@ impl<'a> FlowConstructor<'a> { let boxes_len = boxes.len(); parent_box.compute_borders(parent_box.style()); + // FIXME(#2000, 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 +739,22 @@ impl<'a> FlowConstructor<'a> { } // If this node is ignorable whitespace, bail out now. + // + // FIXME(#2001, 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)); + 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 +779,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 +790,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 +836,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 +862,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 +934,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,16 +952,23 @@ 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(_) => { + None => { + // Pseudo-element. + let style = node.style().get(); + (display::inline, style.Box.get().float, style.Box.get().position) + } + Some(ElementNodeTypeId(_)) => { let style = node.style().get(); (style.Box.get().display, style.Box.get().float, style.Box.get().position) } - TextNodeTypeId => (display::inline, float::none, position::static_), - CommentNodeTypeId | - DoctypeNodeTypeId | - DocumentFragmentNodeTypeId | - DocumentNodeTypeId | - ProcessingInstructionNodeTypeId => (display::none, float::none, position::static_), + Some(TextNodeTypeId) => (display::inline, float::none, position::static_), + Some(CommentNodeTypeId) | + Some(DoctypeNodeTypeId) | + Some(DocumentFragmentNodeTypeId) | + Some(DocumentNodeTypeId) | + Some(ProcessingInstructionNodeTypeId) => { + (display::none, float::none, position::static_) + } }; debug!("building flow for node: {:?} {:?}", display, float); @@ -1044,21 +1081,22 @@ trait NodeUtils { impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> { fn is_replaced_content(&self) -> bool { match self.type_id() { - TextNodeTypeId | - ProcessingInstructionNodeTypeId | - CommentNodeTypeId | - DoctypeNodeTypeId | - DocumentFragmentNodeTypeId | - DocumentNodeTypeId | - ElementNodeTypeId(HTMLImageElementTypeId) => true, - ElementNodeTypeId(HTMLObjectElementTypeId) => self.has_object_data(), - ElementNodeTypeId(_) => false, + Some(TextNodeTypeId) | + Some(ProcessingInstructionNodeTypeId) | + Some(CommentNodeTypeId) | + Some(DoctypeNodeTypeId) | + Some(DocumentFragmentNodeTypeId) | + Some(DocumentNodeTypeId) | + None | + Some(ElementNodeTypeId(HTMLImageElementTypeId)) => true, + Some(ElementNodeTypeId(HTMLObjectElementTypeId)) => self.has_object_data(), + Some(ElementNodeTypeId(_)) => false, } } fn is_ignorable_whitespace(&self) -> bool { match self.type_id() { - TextNodeTypeId => { + Some(TextNodeTypeId) => { unsafe { let text: JS<Text> = TextCast::to(self.get_jsmanaged()).unwrap(); if !is_whitespace(text.get().characterdata.data) { @@ -1085,7 +1123,17 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> { fn set_flow_construction_result(&self, result: ConstructionResult) { let mut layout_data_ref = self.mutate_layout_data(); match *layout_data_ref.get() { - Some(ref mut layout_data) => layout_data.data.flow_construction_result = result, + Some(ref mut layout_data) =>{ + match self.get_element_type() { + Before | BeforeBlock => { + layout_data.data.before_flow_construction_result = result + }, + After | AfterBlock => { + layout_data.data.after_flow_construction_result = result + }, + Normal => layout_data.data.flow_construction_result = result, + } + }, None => fail!("no layout data"), } } @@ -1095,7 +1143,20 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> { let mut layout_data_ref = self.mutate_layout_data(); match *layout_data_ref.get() { Some(ref mut layout_data) => { - mem::replace(&mut layout_data.data.flow_construction_result, NoConstructionResult) + match self.get_element_type() { + Before | BeforeBlock => { + mem::replace(&mut layout_data.data.before_flow_construction_result, + NoConstructionResult) + } + After | AfterBlock => { + mem::replace(&mut layout_data.data.after_flow_construction_result, + NoConstructionResult) + } + Normal => { + mem::replace(&mut layout_data.data.flow_construction_result, + NoConstructionResult) + } + } } None => fail!("no layout data"), } |