diff options
Diffstat (limited to 'components/layout')
-rw-r--r-- | components/layout/block.rs | 84 | ||||
-rw-r--r-- | components/layout/construct.rs | 63 | ||||
-rw-r--r-- | components/layout/display_list_builder.rs | 461 | ||||
-rw-r--r-- | components/layout/flow.rs | 27 | ||||
-rw-r--r-- | components/layout/fragment.rs | 115 | ||||
-rw-r--r-- | components/layout/inline.rs | 106 | ||||
-rw-r--r-- | components/layout/layout_task.rs | 42 | ||||
-rw-r--r-- | components/layout/list_item.rs | 10 | ||||
-rw-r--r-- | components/layout/sequential.rs | 33 | ||||
-rw-r--r-- | components/layout/table.rs | 10 | ||||
-rw-r--r-- | components/layout/table_caption.rs | 10 | ||||
-rw-r--r-- | components/layout/table_cell.rs | 10 | ||||
-rw-r--r-- | components/layout/table_colgroup.rs | 9 | ||||
-rw-r--r-- | components/layout/table_row.rs | 10 | ||||
-rw-r--r-- | components/layout/table_rowgroup.rs | 10 | ||||
-rw-r--r-- | components/layout/table_wrapper.rs | 10 |
16 files changed, 561 insertions, 449 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs index eec1f945d1c..3f7fd4be823 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -32,7 +32,7 @@ use context::LayoutContext; use css::node_style::StyledNode; use display_list_builder::{BlockFlowDisplayListBuilding, FragmentDisplayListBuilding}; use floats::{ClearType, FloatKind, Floats, PlacementInfo}; -use flow::{AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow}; +use flow::{mod, AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow}; use flow::{ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTraversal}; use flow::{PostorderFlowTraversal, mut_base}; use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS}; @@ -40,8 +40,7 @@ use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS}; use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER}; use flow::{IS_ABSOLUTELY_POSITIONED}; use flow::{CLEARS_LEFT, CLEARS_RIGHT}; -use flow; -use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo}; +use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; use incremental::{REFLOW, REFLOW_OUT_OF_FLOW}; use layout_debug; use model::{IntrinsicISizes, MarginCollapseInfo}; @@ -49,11 +48,11 @@ use model::{MaybeAuto, CollapsibleMargins, specified, specified_or_none}; use table::ColumnComputedInlineSize; use wrapper::ThreadSafeLayoutNode; -use geom::{Rect, Size2D}; +use geom::{Point2D, Rect, Size2D}; use gfx::display_list::{ClippingRegion, DisplayList}; use serialize::{Encoder, Encodable}; use servo_msg::compositor_msg::LayerId; -use servo_util::geometry::{Au, MAX_AU, ZERO_POINT}; +use servo_util::geometry::{Au, MAX_AU}; use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize}; use servo_util::opts; use std::cmp::{max, min}; @@ -1769,23 +1768,40 @@ impl Flow for BlockFlow { }; // Compute the origin and clipping rectangle for children. - let origin_for_children = if self.fragment.establishes_stacking_context() { - ZERO_POINT + let relative_offset = relative_offset.to_physical(self.base.writing_mode); + let origin_for_children; + let clip_in_child_coordinate_system; + if self.fragment.establishes_stacking_context() { + // We establish a stacking context, so the position of our children is vertically + // correct, but has to be adjusted to accommodate horizontal margins. (Note the + // calculation involving `position` below and recall that inline-direction flow + // positions are relative to the edges of the margin box.) + // + // FIXME(pcwalton): Is this vertical-writing-direction-safe? + let margin = self.fragment.margin.to_physical(self.base.writing_mode); + origin_for_children = Point2D(-margin.left, Au(0)) + relative_offset; + clip_in_child_coordinate_system = + self.base.clip.translate(&-self.base.stacking_relative_position) } else { - self.base.stacking_relative_position - }; - let clip = self.fragment.clipping_region_for_children(&self.base.clip, - &origin_for_children); + origin_for_children = self.base.stacking_relative_position + relative_offset; + clip_in_child_coordinate_system = self.base.clip.clone() + } + let stacking_relative_border_box = + self.fragment + .stacking_relative_border_box(&self.base.stacking_relative_position, + &self.base + .absolute_position_info + .relative_containing_block_size, + CoordinateSystem::Self); + let clip = self.fragment.clipping_region_for_children(&clip_in_child_coordinate_system, + &stacking_relative_border_box); // Process children. - let writing_mode = self.base.writing_mode; for kid in self.base.child_iter() { if !flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) { let kid_base = flow::mut_base(kid); - kid_base.stacking_relative_position = - origin_for_children - + kid_base.position.start.to_physical(kid_base.writing_mode, container_size) - + relative_offset.to_physical(writing_mode); + kid_base.stacking_relative_position = origin_for_children + + kid_base.position.start.to_physical(kid_base.writing_mode, container_size); } flow::mut_base(kid).absolute_position_info = absolute_position_info_for_children; @@ -1832,16 +1848,20 @@ impl Flow for BlockFlow { fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) && - self.fragment.style().logical_position().inline_start == LengthOrPercentageOrAuto::Auto && - self.fragment.style().logical_position().inline_end == LengthOrPercentageOrAuto::Auto { + self.fragment.style().logical_position().inline_start == + LengthOrPercentageOrAuto::Auto && + self.fragment.style().logical_position().inline_end == + LengthOrPercentageOrAuto::Auto { self.base.position.start.i = inline_position } } fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) { if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) && - self.fragment.style().logical_position().block_start == LengthOrPercentageOrAuto::Auto && - self.fragment.style().logical_position().block_end == LengthOrPercentageOrAuto::Auto { + self.fragment.style().logical_position().block_start == + LengthOrPercentageOrAuto::Auto && + self.fragment.style().logical_position().block_end == + LengthOrPercentageOrAuto::Auto { self.base.position.start.b = block_position } } @@ -1861,16 +1881,32 @@ impl Flow for BlockFlow { self.fragment.compute_overflow() } - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { - if iterator.should_process(&self.fragment) { - iterator.process(&self.fragment, self.fragment.compute_overflow()); + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + if !iterator.should_process(&self.fragment) { + return } + + iterator.process(&self.fragment, + &self.fragment + .stacking_relative_border_box(&self.base.stacking_relative_position, + &self.base + .absolute_position_info + .relative_containing_block_size, + CoordinateSystem::Parent) + .translate(stacking_context_position)); } } impl fmt::Show for BlockFlow { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} - {:x}: frag={} ({})", self.class(), self.base.debug_id(), self.fragment, self.base) + write!(f, + "{} - {:x}: frag={} ({})", + self.class(), + self.base.debug_id(), + self.fragment, + self.base) } } diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 94605e103ec..c2911b13640 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -52,9 +52,9 @@ use servo_util::opts; use std::collections::DList; use std::mem; use std::sync::atomic::Relaxed; -use style::ComputedValues; use style::computed_values::{caption_side, display, empty_cells, float, list_style_position}; use style::computed_values::{position}; +use style::{mod, ComputedValues}; use sync::Arc; use url::Url; @@ -681,7 +681,7 @@ impl<'a> FlowConstructor<'a> { /// doesn't render its children, so this just nukes a child's fragments and creates a /// `Fragment`. fn build_fragments_for_replaced_inline_content(&mut self, node: &ThreadSafeLayoutNode) - -> ConstructionResult { + -> ConstructionResult { for kid in node.children() { kid.set_flow_construction_result(ConstructionResult::None) } @@ -697,24 +697,42 @@ impl<'a> FlowConstructor<'a> { node.restyle_damage())) } + // If the value of `display` property is not `inline`, then we have a situation like + // `<div style="position:absolute">foo bar baz</div>`. The fragments for `foo`, `bar`, and + // `baz` had better not be absolutely positioned! + let mut style = (*node.style()).clone(); + if style.get_box().display != display::inline { + style = Arc::new(style::make_inline(&*style)) + } + // If this is generated content, then we need to initialize the accumulator with the // fragment corresponding to that content. Otherwise, just initialize with the ordinary // fragment that needs to be generated for this inline node. let fragment = if node.get_pseudo_element_type() != PseudoElementType::Normal { - let fragment_info = SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::new(node)); - Fragment::new_from_specific_info(node, fragment_info) + let fragment_info = + SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::new(node)); + Fragment::from_opaque_node_and_style( + OpaqueNodeMethods::from_thread_safe_layout_node(node), + style, + node.restyle_damage(), + fragment_info) } else { - Fragment::new(self, node) + Fragment::from_opaque_node_and_style( + OpaqueNodeMethods::from_thread_safe_layout_node(node), + style, + node.restyle_damage(), + self.build_specific_fragment_info_for_node(node)) }; let mut fragments = DList::new(); fragments.push_back(fragment); - let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { - splits: DList::new(), - fragments: fragments, - abs_descendants: Descendants::new(), - }); + let construction_item = + ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { + splits: DList::new(), + fragments: fragments, + abs_descendants: Descendants::new(), + }); ConstructionResult::ConstructionItem(construction_item) } @@ -726,17 +744,19 @@ impl<'a> FlowConstructor<'a> { _ => unreachable!() }; - let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(block_flow)); + let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new( + block_flow)); let fragment = Fragment::new_from_specific_info(node, fragment_info); let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node); fragment_accumulator.fragments.push_back(fragment); - let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { - splits: DList::new(), - fragments: fragment_accumulator.to_dlist(), - abs_descendants: abs_descendants, - }); + let construction_item = + ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { + splits: DList::new(), + fragments: fragment_accumulator.to_dlist(), + abs_descendants: abs_descendants, + }); ConstructionResult::ConstructionItem(construction_item) } @@ -757,11 +777,12 @@ impl<'a> FlowConstructor<'a> { let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node); fragment_accumulator.fragments.push_back(fragment); - let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { - splits: DList::new(), - fragments: fragment_accumulator.to_dlist(), - abs_descendants: abs_descendants, - }); + let construction_item = + ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { + splits: DList::new(), + fragments: fragment_accumulator.to_dlist(), + abs_descendants: abs_descendants, + }); ConstructionResult::ConstructionItem(construction_item) } diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 2696bcc3dc5..80877ffaaf9 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -13,8 +13,9 @@ use block::BlockFlow; use context::LayoutContext; use flow::{mod, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER}; -use fragment::{Fragment, SpecificFragmentInfo, IframeFragmentInfo, ImageFragmentInfo}; -use fragment::ScannedTextFragmentInfo; +use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo}; +use fragment::{ScannedTextFragmentInfo, SpecificFragmentInfo}; +use inline::InlineFlow; use list_item::ListItemFlow; use model; use util::{OpaqueNodeMethods, ToGfxColor}; @@ -36,8 +37,8 @@ use servo_msg::constellation_msg::Msg as ConstellationMsg; use servo_msg::constellation_msg::ConstellationChan; use servo_net::image::holder::ImageHolder; use servo_util::cursor::{DefaultCursor, TextCursor, VerticalTextCursor}; -use servo_util::geometry::{mod, Au, ZERO_POINT}; -use servo_util::logical_geometry::{LogicalRect, WritingMode}; +use servo_util::geometry::{mod, Au}; +use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize}; use servo_util::opts; use std::default::Default; use std::num::FloatMath; @@ -133,16 +134,19 @@ pub trait FragmentDisplayListBuilding { absolute_bounds: &Rect<Au>, clip: &ClippingRegion); + /// Adds display items necessary to draw debug boxes around a scanned text fragment. fn build_debug_borders_around_text_fragments(&self, style: &ComputedValues, display_list: &mut DisplayList, - flow_origin: Point2D<Au>, + stacking_relative_border_box: &Rect<Au>, + stacking_relative_content_box: &Rect<Au>, text_fragment: &ScannedTextFragmentInfo, clip: &ClippingRegion); + /// Adds display items necessary to draw debug boxes around this fragment. fn build_debug_borders_around_fragment(&self, display_list: &mut DisplayList, - flow_origin: Point2D<Au>, + stacking_relative_border_box: &Rect<Au>, clip: &ClippingRegion); /// Adds the display items for this fragment to the given display list. @@ -152,12 +156,16 @@ pub trait FragmentDisplayListBuilding { /// * `display_list`: The display list to add display items to. /// * `layout_context`: The layout context. /// * `dirty`: The dirty rectangle in the coordinate system of the owning flow. - /// * `flow_origin`: Position of the origin of the owning flow wrt the display list root flow. + /// * `stacking_relative_flow_origin`: Position of the origin of the owning flow with respect + /// to its nearest ancestor stacking context. + /// * `relative_containing_block_size`: The size of the containing block that + /// `position: relative` makes use of. /// * `clip`: The region to clip the display items to. fn build_display_list(&mut self, display_list: &mut DisplayList, layout_context: &LayoutContext, - flow_origin: Point2D<Au>, + stacking_relative_flow_origin: &Point2D<Au>, + relative_containing_block_size: &LogicalSize<Au>, background_and_border_level: BackgroundAndBorderLevel, clip: &ClippingRegion); @@ -168,12 +176,17 @@ pub trait FragmentDisplayListBuilding { offset: Point2D<Au>, layout_context: &LayoutContext); - fn clipping_region_for_children(&self, current_clip: &ClippingRegion, flow_origin: &Point2D<Au>) + /// Returns the appropriate clipping region for descendants of this flow. + fn clipping_region_for_children(&self, + current_clip: &ClippingRegion, + stacking_relative_border_box: &Rect<Au>) -> ClippingRegion; /// Calculates the clipping rectangle for a fragment, taking the `clip` property into account /// per CSS 2.1 § 11.1.2. - fn calculate_style_specified_clip(&self, parent_clip: &ClippingRegion, origin: &Point2D<Au>) + fn calculate_style_specified_clip(&self, + parent_clip: &ClippingRegion, + stacking_relative_border_box: &Rect<Au>) -> ClippingRegion; /// Creates the text display item for one text fragment. @@ -181,23 +194,20 @@ pub trait FragmentDisplayListBuilding { display_list: &mut DisplayList, text_fragment: &ScannedTextFragmentInfo, text_color: RGBA, - offset: &Point2D<Au>, - flow_origin: &Point2D<Au>, + stacking_relative_content_box: &Rect<Au>, clip: &ClippingRegion); /// Creates the display item for a text decoration: underline, overline, or line-through. fn build_display_list_for_text_decoration(&self, display_list: &mut DisplayList, - color: RGBA, - flow_origin: &Point2D<Au>, - clip: &ClippingRegion, - logical_bounds: &LogicalRect<Au>, - offset: &Point2D<Au>); + color: &RGBA, + stacking_relative_box: &LogicalRect<Au>, + clip: &ClippingRegion); /// A helper method that `build_display_list` calls to create per-fragment-type display items. fn build_fragment_type_specific_display_items(&mut self, display_list: &mut DisplayList, - flow_origin: Point2D<Au>, + stacking_relative_border_box: &Rect<Au>, clip: &ClippingRegion); } @@ -580,20 +590,16 @@ impl FragmentDisplayListBuilding for Fragment { fn build_debug_borders_around_text_fragments(&self, style: &ComputedValues, display_list: &mut DisplayList, - flow_origin: Point2D<Au>, + stacking_relative_border_box: &Rect<Au>, + stacking_relative_content_box: &Rect<Au>, text_fragment: &ScannedTextFragmentInfo, clip: &ClippingRegion) { - // FIXME(#2795): Get the real container size + // FIXME(pcwalton, #2795): Get the real container size. let container_size = Size2D::zero(); - // Fragment position wrt to the owning flow. - let fragment_bounds = self.border_box.to_physical(self.style.writing_mode, container_size); - let absolute_fragment_bounds = Rect( - fragment_bounds.origin + flow_origin, - fragment_bounds.size); // Compute the text fragment bounds and draw a border surrounding them. display_list.content.push_back(DisplayItem::BorderClass(box BorderDisplayItem { - base: BaseDisplayItem::new(absolute_fragment_bounds, + base: BaseDisplayItem::new(*stacking_relative_border_box, DisplayItemMetadata::new(self.node, style, DefaultCursor), (*clip).clone()), border_widths: SideOffsets2D::new_all_same(Au::from_px(1)), @@ -603,12 +609,12 @@ impl FragmentDisplayListBuilding for Fragment { })); // Draw a rectangle representing the baselines. - let ascent = text_fragment.run.ascent(); - let mut baseline = self.border_box.clone(); - baseline.start.b = baseline.start.b + ascent; + let mut baseline = LogicalRect::from_physical(self.style.writing_mode, + *stacking_relative_content_box, + container_size); + baseline.start.b = baseline.start.b + text_fragment.run.ascent(); baseline.size.block = Au(0); - let mut baseline = baseline.to_physical(self.style.writing_mode, container_size); - baseline.origin = baseline.origin + flow_origin; + let baseline = baseline.to_physical(self.style.writing_mode, container_size); let line_display_item = box LineDisplayItem { base: BaseDisplayItem::new(baseline, @@ -622,19 +628,11 @@ impl FragmentDisplayListBuilding for Fragment { fn build_debug_borders_around_fragment(&self, display_list: &mut DisplayList, - flow_origin: Point2D<Au>, + stacking_relative_border_box: &Rect<Au>, clip: &ClippingRegion) { - // FIXME(#2795): Get the real container size - let container_size = Size2D::zero(); - // Fragment position wrt to the owning flow. - let fragment_bounds = self.border_box.to_physical(self.style.writing_mode, container_size); - let absolute_fragment_bounds = Rect( - fragment_bounds.origin + flow_origin, - fragment_bounds.size); - // This prints a debug border around the border of this fragment. display_list.content.push_back(DisplayItem::BorderClass(box BorderDisplayItem { - base: BaseDisplayItem::new(absolute_fragment_bounds, + base: BaseDisplayItem::new(*stacking_relative_border_box, DisplayItemMetadata::new(self.node, &*self.style, DefaultCursor), @@ -646,7 +644,9 @@ impl FragmentDisplayListBuilding for Fragment { })); } - fn calculate_style_specified_clip(&self, parent_clip: &ClippingRegion, origin: &Point2D<Au>) + fn calculate_style_specified_clip(&self, + parent_clip: &ClippingRegion, + stacking_relative_border_box: &Rect<Au>) -> ClippingRegion { // Account for `clip` per CSS 2.1 § 11.1.2. let style_clip_rect = match (self.style().get_box().position, @@ -656,54 +656,49 @@ impl FragmentDisplayListBuilding for Fragment { }; // FIXME(pcwalton, #2795): Get the real container size. - let border_box = self.border_box.to_physical(self.style.writing_mode, Size2D::zero()); - let clip_origin = Point2D(border_box.origin.x + style_clip_rect.left, - border_box.origin.y + style_clip_rect.top); - let new_clip_rect = - Rect(clip_origin + *origin, - Size2D(style_clip_rect.right.unwrap_or(border_box.size.width) - clip_origin.x, - style_clip_rect.bottom.unwrap_or(border_box.size.height) - clip_origin.y)); - (*parent_clip).clone().intersect_rect(&new_clip_rect) + let clip_origin = Point2D(stacking_relative_border_box.origin.x + style_clip_rect.left, + stacking_relative_border_box.origin.y + style_clip_rect.top); + let right = style_clip_rect.right.unwrap_or(stacking_relative_border_box.size.width); + let bottom = style_clip_rect.bottom.unwrap_or(stacking_relative_border_box.size.height); + let clip_size = Size2D(right - clip_origin.x, bottom - clip_origin.y); + (*parent_clip).clone().intersect_rect(&Rect(clip_origin, clip_size)) } fn build_display_list(&mut self, display_list: &mut DisplayList, layout_context: &LayoutContext, - flow_origin: Point2D<Au>, + stacking_relative_flow_origin: &Point2D<Au>, + relative_containing_block_size: &LogicalSize<Au>, background_and_border_level: BackgroundAndBorderLevel, clip: &ClippingRegion) { // Compute the fragment position relative to the parent stacking context. If the fragment // itself establishes a stacking context, then the origin of its position will be (0, 0) // for the purposes of this computation. - let stacking_relative_flow_origin = if self.establishes_stacking_context() { - ZERO_POINT - } else { - flow_origin - }; - let absolute_fragment_bounds = - self.stacking_relative_bounds(&stacking_relative_flow_origin); + let stacking_relative_border_box = + self.stacking_relative_border_box(stacking_relative_flow_origin, + relative_containing_block_size, + CoordinateSystem::Self); - debug!("Fragment::build_display_list at rel={}, abs={}: {}", + debug!("Fragment::build_display_list at rel={}, abs={}, dirty={}, flow origin={}: {}", self.border_box, - absolute_fragment_bounds, - self); - debug!("Fragment::build_display_list: dirty={}, flow_origin={}", + stacking_relative_border_box, layout_context.shared.dirty, - flow_origin); + stacking_relative_flow_origin, + self); if self.style().get_inheritedbox().visibility != visibility::visible { return } - if !absolute_fragment_bounds.intersects(&layout_context.shared.dirty) { + if !stacking_relative_border_box.intersects(&layout_context.shared.dirty) { debug!("Fragment::build_display_list: Did not intersect..."); return } // Calculate the clip rect. If there's nothing to render at all, don't even construct // display list items. - let clip = self.calculate_style_specified_clip(clip, &absolute_fragment_bounds.origin); - if !clip.might_intersect_rect(&absolute_fragment_bounds) { + let clip = self.calculate_style_specified_clip(clip, &stacking_relative_border_box); + if !clip.might_intersect_rect(&stacking_relative_border_box) { return; } @@ -713,15 +708,34 @@ impl FragmentDisplayListBuilding for Fragment { let level = StackingLevel::from_background_and_border_level(background_and_border_level); - // Add a shadow to the list, if applicable. + // Add shadows, background, borders, and outlines, if applicable. if let Some(ref inline_context) = self.inline_context { for style in inline_context.styles.iter().rev() { - self.build_display_list_for_box_shadow_if_applicable(&**style, - display_list, - layout_context, - level, - &absolute_fragment_bounds, - &clip); + self.build_display_list_for_box_shadow_if_applicable( + &**style, + display_list, + layout_context, + level, + &stacking_relative_border_box, + &clip); + self.build_display_list_for_background_if_applicable( + &**style, + display_list, + layout_context, + level, + &stacking_relative_border_box, + &clip); + self.build_display_list_for_borders_if_applicable( + &**style, + display_list, + &stacking_relative_border_box, + level, + &clip); + self.build_display_list_for_outline_if_applicable( + &**style, + display_list, + &stacking_relative_border_box, + &clip); } } if !self.is_scanned_text_fragment() { @@ -729,62 +743,35 @@ impl FragmentDisplayListBuilding for Fragment { display_list, layout_context, level, - &absolute_fragment_bounds, + &stacking_relative_border_box, &clip); - } - - // Add the background to the list, if applicable. - if let Some(ref inline_context) = self.inline_context { - for style in inline_context.styles.iter().rev() { - self.build_display_list_for_background_if_applicable(&**style, - display_list, - layout_context, - level, - &absolute_fragment_bounds, - &clip); - } - } - if !self.is_scanned_text_fragment() { self.build_display_list_for_background_if_applicable(&*self.style, display_list, layout_context, level, - &absolute_fragment_bounds, + &stacking_relative_border_box, &clip); - } - - // Add a border and outlines, if applicable. - if let Some(ref inline_context) = self.inline_context { - for style in inline_context.styles.iter().rev() { - self.build_display_list_for_borders_if_applicable(&**style, - display_list, - &absolute_fragment_bounds, - level, - &clip); - self.build_display_list_for_outline_if_applicable(&**style, - display_list, - &absolute_fragment_bounds, - &clip); - } - } - if !self.is_scanned_text_fragment() { self.build_display_list_for_borders_if_applicable(&*self.style, display_list, - &absolute_fragment_bounds, + &stacking_relative_border_box, level, &clip); self.build_display_list_for_outline_if_applicable(&*self.style, display_list, - &absolute_fragment_bounds, + &stacking_relative_border_box, &clip); } } // Create special per-fragment-type display items. - self.build_fragment_type_specific_display_items(display_list, flow_origin, &clip); + self.build_fragment_type_specific_display_items(display_list, + &stacking_relative_border_box, + &clip); if opts::get().show_debug_fragment_borders { - self.build_debug_borders_around_fragment(display_list, flow_origin, &clip) + self.build_debug_borders_around_fragment(display_list, + &stacking_relative_border_box, + &clip) } // If this is an iframe, then send its position and size up to the constellation. @@ -799,31 +786,18 @@ impl FragmentDisplayListBuilding for Fragment { // the iframe is actually going to be displayed. if let SpecificFragmentInfo::Iframe(ref iframe_fragment) = self.specific { self.finalize_position_and_size_of_iframe(&**iframe_fragment, - absolute_fragment_bounds.origin, + stacking_relative_border_box.origin, layout_context) } } fn build_fragment_type_specific_display_items(&mut self, display_list: &mut DisplayList, - flow_origin: Point2D<Au>, + stacking_relative_border_box: &Rect<Au>, clip: &ClippingRegion) { - // Compute the fragment position relative to the parent stacking context. If the fragment - // itself establishes a stacking context, then the origin of its position will be (0, 0) - // for the purposes of this computation. - let stacking_relative_flow_origin = if self.establishes_stacking_context() { - ZERO_POINT - } else { - flow_origin - }; - - // FIXME(#2795): Get the real container size. - let content_box = self.content_box(); - let container_size = Size2D::zero(); - let rect_to_absolute = |writing_mode: WritingMode, logical_rect: LogicalRect<Au>| { - let physical_rect = logical_rect.to_physical(writing_mode, container_size); - Rect(physical_rect.origin + stacking_relative_flow_origin, physical_rect.size) - }; + // Compute the context box position relative to the parent stacking context. + let stacking_relative_content_box = + self.stacking_relative_content_box(stacking_relative_border_box); match self.specific { SpecificFragmentInfo::UnscannedText(_) => { @@ -838,16 +812,16 @@ impl FragmentDisplayListBuilding for Fragment { self.build_display_list_for_text_fragment(display_list, &**text_fragment, text_color, - &flow_origin, - &Point2D(Au(0), Au(0)), + &stacking_relative_content_box, clip); if opts::get().show_debug_fragment_borders { self.build_debug_borders_around_text_fragments(self.style(), display_list, - flow_origin, + stacking_relative_border_box, + &stacking_relative_content_box, &**text_fragment, - clip); + clip) } } SpecificFragmentInfo::Generic | @@ -859,25 +833,25 @@ impl FragmentDisplayListBuilding for Fragment { SpecificFragmentInfo::InlineBlock(_) | SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => { if opts::get().show_debug_fragment_borders { - self.build_debug_borders_around_fragment(display_list, flow_origin, clip); + self.build_debug_borders_around_fragment(display_list, + stacking_relative_border_box, + clip); } } SpecificFragmentInfo::Image(ref mut image_fragment) => { let image_ref = &mut image_fragment.image; if let Some(image) = image_ref.get_image(self.node.to_untrusted_node_address()) { debug!("(building display list) building image fragment"); - let absolute_content_box = rect_to_absolute(self.style.writing_mode, - content_box); // Place the image into the display list. display_list.content.push_back(DisplayItem::ImageClass(box ImageDisplayItem { - base: BaseDisplayItem::new(absolute_content_box, + base: BaseDisplayItem::new(stacking_relative_content_box, DisplayItemMetadata::new(self.node, &*self.style, DefaultCursor), (*clip).clone()), image: image.clone(), - stretch_size: absolute_content_box.size, + stretch_size: stacking_relative_content_box.size, })); } else { // No image data at all? Do nothing. @@ -910,7 +884,9 @@ impl FragmentDisplayListBuilding for Fragment { iframe_rect)); } - fn clipping_region_for_children(&self, current_clip: &ClippingRegion, flow_origin: &Point2D<Au>) + fn clipping_region_for_children(&self, + current_clip: &ClippingRegion, + stacking_relative_border_box: &Rect<Au>) -> ClippingRegion { // Don't clip if we're text. if self.is_scanned_text_fragment() { @@ -918,27 +894,24 @@ impl FragmentDisplayListBuilding for Fragment { } // Account for style-specified `clip`. - let current_clip = self.calculate_style_specified_clip(current_clip, flow_origin); + let current_clip = self.calculate_style_specified_clip(current_clip, + stacking_relative_border_box); // Only clip if `overflow` tells us to. match self.style.get_box().overflow { - overflow::hidden | overflow::auto | overflow::scroll => {} - _ => return current_clip, + overflow::hidden | overflow::auto | overflow::scroll => { + // Create a new clip rect. + current_clip.intersect_rect(stacking_relative_border_box) + } + _ => current_clip, } - - // Create a new clip rect. - // - // FIXME(#2795): Get the real container size. - let physical_rect = self.border_box.to_physical(self.style.writing_mode, Size2D::zero()); - current_clip.intersect_rect(&Rect(physical_rect.origin + *flow_origin, physical_rect.size)) } fn build_display_list_for_text_fragment(&self, display_list: &mut DisplayList, text_fragment: &ScannedTextFragmentInfo, text_color: RGBA, - flow_origin: &Point2D<Au>, - offset: &Point2D<Au>, + stacking_relative_content_box: &Rect<Au>, clip: &ClippingRegion) { // Determine the orientation and cursor to use. let (orientation, cursor) = if self.style.writing_mode.is_vertical() { @@ -955,29 +928,16 @@ impl FragmentDisplayListBuilding for Fragment { // // FIXME(pcwalton): Get the real container size. let container_size = Size2D::zero(); - let content_box = self.content_box(); let metrics = &text_fragment.run.font_metrics; - let baseline_origin = { - let mut content_box_start = content_box.start; - content_box_start.b = content_box_start.b + metrics.ascent; - content_box_start.to_physical(self.style.writing_mode, container_size) + *flow_origin + - *offset - }; - let stacking_relative_flow_origin = if self.establishes_stacking_context() { - ZERO_POINT - } else { - *flow_origin - }; - let rect_to_absolute = |writing_mode: WritingMode, logical_rect: LogicalRect<Au>| { - let physical_rect = logical_rect.to_physical(writing_mode, container_size); - Rect(physical_rect.origin + stacking_relative_flow_origin, physical_rect.size) - }; - let content_rect = rect_to_absolute(self.style.writing_mode, - content_box).translate(offset); + let baseline_origin = stacking_relative_content_box.origin + + LogicalPoint::new(self.style.writing_mode, + Au(0), + metrics.ascent).to_physical(self.style.writing_mode, + container_size); // Create the text display item. display_list.content.push_back(DisplayItem::TextClass(box TextDisplayItem { - base: BaseDisplayItem::new(content_rect, + base: BaseDisplayItem::new(*stacking_relative_content_box, DisplayItemMetadata::new(self.node, self.style(), cursor), (*clip).clone()), text_run: text_fragment.run.clone(), @@ -989,63 +949,55 @@ impl FragmentDisplayListBuilding for Fragment { // Create display items for text decorations. let text_decorations = self.style().get_inheritedtext()._servo_text_decorations_in_effect; - if let Some(underline_color) = text_decorations.underline { - let mut rect = content_box.clone(); - rect.start.b = rect.start.b + metrics.ascent - metrics.underline_offset; - rect.size.block = metrics.underline_size; + let stacking_relative_content_box = + LogicalRect::from_physical(self.style.writing_mode, + *stacking_relative_content_box, + container_size); + if let Some(ref underline_color) = text_decorations.underline { + let mut stacking_relative_box = stacking_relative_content_box; + stacking_relative_box.start.b = stacking_relative_content_box.start.b + + metrics.ascent - metrics.underline_offset; + stacking_relative_box.size.block = metrics.underline_size; self.build_display_list_for_text_decoration(display_list, underline_color, - flow_origin, - clip, - &rect, - offset) + &stacking_relative_box, + clip) } - if let Some(overline_color) = text_decorations.overline { - let mut rect = content_box.clone(); - rect.size.block = metrics.underline_size; + if let Some(ref overline_color) = text_decorations.overline { + let mut stacking_relative_box = stacking_relative_content_box; + stacking_relative_box.size.block = metrics.underline_size; self.build_display_list_for_text_decoration(display_list, overline_color, - flow_origin, - clip, - &rect, - offset) + &stacking_relative_box, + clip) } - if let Some(line_through_color) = text_decorations.line_through { - let mut rect = content_box.clone(); - rect.start.b = rect.start.b + metrics.ascent - metrics.strikeout_offset; - rect.size.block = metrics.strikeout_size; + if let Some(ref line_through_color) = text_decorations.line_through { + let mut stacking_relative_box = stacking_relative_content_box; + stacking_relative_box.start.b = stacking_relative_box.start.b + metrics.ascent - + metrics.strikeout_offset; + stacking_relative_box.size.block = metrics.strikeout_size; self.build_display_list_for_text_decoration(display_list, line_through_color, - flow_origin, - clip, - &rect, - offset) + &stacking_relative_box, + clip) } } fn build_display_list_for_text_decoration(&self, display_list: &mut DisplayList, - color: RGBA, - flow_origin: &Point2D<Au>, - clip: &ClippingRegion, - logical_bounds: &LogicalRect<Au>, - offset: &Point2D<Au>) { - // FIXME(pcwalton): Get the real container size. + color: &RGBA, + stacking_relative_box: &LogicalRect<Au>, + clip: &ClippingRegion) { + // FIXME(pcwalton, #2795): Get the real container size. let container_size = Size2D::zero(); - let stacking_relative_flow_origin = if self.establishes_stacking_context() { - ZERO_POINT - } else { - *flow_origin - }; - let physical_rect = logical_bounds.to_physical(self.style.writing_mode, container_size); + let stacking_relative_box = stacking_relative_box.to_physical(self.style.writing_mode, + container_size); - let bounds = Rect(physical_rect.origin + stacking_relative_flow_origin, - physical_rect.size).translate(offset); let metadata = DisplayItemMetadata::new(self.node, &*self.style, DefaultCursor); display_list.content.push_back(DisplayItem::SolidColorClass(box SolidColorDisplayItem { - base: BaseDisplayItem::new(bounds, metadata, (*clip).clone()), + base: BaseDisplayItem::new(stacking_relative_box, metadata, (*clip).clone()), color: color.to_gfx_color(), })) } @@ -1081,14 +1033,16 @@ impl BlockFlowDisplayListBuilding for BlockFlow { layout_context: &LayoutContext, background_border_level: BackgroundAndBorderLevel) { // Add the box that starts the block context. - let stacking_relative_fragment_origin = - self.base.stacking_relative_position_of_child_fragment(&self.fragment); self.fragment.build_display_list(display_list, layout_context, - stacking_relative_fragment_origin, + &self.base.stacking_relative_position, + &self.base + .absolute_position_info + .relative_containing_block_size, background_border_level, &self.base.clip); + // Add children. for kid in self.base.children.iter_mut() { flow::mut_base(kid).display_list_building_result.add_to(display_list); } @@ -1180,19 +1134,70 @@ impl BlockFlowDisplayListBuilding for BlockFlow { display_list: Box<DisplayList>, layer: Option<Arc<PaintLayer>>) -> Arc<StackingContext> { - let size = self.base.position.size.to_physical(self.base.writing_mode); - let bounds = Rect(self.base.stacking_relative_position, size); - let z_index = self.fragment.style().get_box().z_index.number_or_zero(); - let opacity = self.fragment.style().get_effects().opacity as f32; + debug_assert!(self.fragment.establishes_stacking_context()); + let border_box = self.fragment + .stacking_relative_border_box(&self.base.stacking_relative_position, + &self.base + .absolute_position_info + .relative_containing_block_size, + CoordinateSystem::Parent); + + // FIXME(pcwalton): Is this vertical-writing-direction-safe? + let margin = self.fragment.margin.to_physical(self.base.writing_mode); + let overflow = self.base.overflow.translate(&-Point2D(margin.left, Au(0))); + Arc::new(StackingContext::new(display_list, - &bounds, - &self.base.overflow, - z_index, - opacity, + &border_box, + &overflow, + self.fragment.style().get_box().z_index.number_or_zero(), + self.fragment.style().get_effects().opacity as f32, layer)) } } +pub trait InlineFlowDisplayListBuilding { + fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext); +} + +impl InlineFlowDisplayListBuilding for InlineFlow { + fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext) { + // TODO(#228): Once we form lines and have their cached bounds, we can be smarter and + // not recurse on a line if nothing in it can intersect the dirty region. + debug!("Flow: building display list for {:u} inline fragments", self.fragments.len()); + + let mut display_list = box DisplayList::new(); + for fragment in self.fragments.fragments.iter_mut() { + fragment.build_display_list(&mut *display_list, + layout_context, + &self.base.stacking_relative_position, + &self.base + .absolute_position_info + .relative_containing_block_size, + BackgroundAndBorderLevel::Content, + &self.base.clip); + match fragment.specific { + SpecificFragmentInfo::InlineBlock(ref mut block_flow) => { + let block_flow = block_flow.flow_ref.deref_mut(); + flow::mut_base(block_flow).display_list_building_result + .add_to(&mut *display_list) + } + SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => { + let block_flow = block_flow.flow_ref.deref_mut(); + flow::mut_base(block_flow).display_list_building_result + .add_to(&mut *display_list) + } + _ => {} + } + } + + self.base.display_list_building_result = DisplayListBuildingResult::Normal(display_list); + + if opts::get().validate_display_list_geometry { + self.base.validate_display_list_geometry(); + } + } +} + pub trait ListItemFlowDisplayListBuilding { fn build_display_list_for_list_item(&mut self, display_list: Box<DisplayList>, @@ -1204,17 +1209,16 @@ impl ListItemFlowDisplayListBuilding for ListItemFlow { mut display_list: Box<DisplayList>, layout_context: &LayoutContext) { // Draw the marker, if applicable. - match self.marker { - None => {} - Some(ref mut marker) => { - let stacking_relative_fragment_origin = - self.block_flow.base.stacking_relative_position_of_child_fragment(marker); - marker.build_display_list(&mut *display_list, - layout_context, - stacking_relative_fragment_origin, - BackgroundAndBorderLevel::Content, - &self.block_flow.base.clip); - } + if let Some(ref mut marker) = self.marker { + marker.build_display_list(&mut *display_list, + layout_context, + &self.block_flow.base.stacking_relative_position, + &self.block_flow + .base + .absolute_position_info + .relative_containing_block_size, + BackgroundAndBorderLevel::Content, + &self.block_flow.base.clip); } // Draw the rest of the block. @@ -1292,3 +1296,4 @@ impl StackingContextConstruction for DisplayList { } } } + diff --git a/components/layout/flow.rs b/components/layout/flow.rs index f20d5a0c128..d252a93269b 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -32,7 +32,7 @@ use display_list_builder::DisplayListBuildingResult; use floats::Floats; use flow_list::{FlowList, FlowListIterator, MutFlowListIterator}; use flow_ref::FlowRef; -use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo}; +use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage}; use inline::InlineFlow; use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo}; @@ -223,8 +223,10 @@ pub trait Flow: fmt::Show + ToString + Sync { /// Returns the union of all overflow rects of all of this flow's fragments. fn compute_overflow(&self) -> Rect<Au>; - /// Iterates through overflow rects of all of this flow's fragments. - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator); + /// Iterates through border boxes of all of this flow's fragments. + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>); fn compute_collapsible_block_start_margin(&mut self, _layout_context: &mut LayoutContext, @@ -958,17 +960,6 @@ impl BaseFlow { } } } - - /// Returns the position of the given fragment relative to the start of the nearest ancestor - /// stacking context. The fragment must be a child fragment of this flow. - pub fn stacking_relative_position_of_child_fragment(&self, fragment: &Fragment) - -> Point2D<Au> { - let relative_offset = - fragment.relative_position(&self - .absolute_position_info - .relative_containing_block_size); - self.stacking_relative_position.add_size(&relative_offset.to_physical(self.writing_mode)) - } } impl<'a> ImmutableFlowUtils for &'a Flow + 'a { @@ -1065,14 +1056,14 @@ impl<'a> ImmutableFlowUtils for &'a Flow + 'a { let flow = match self.class() { FlowClass::Table | FlowClass::TableRowGroup => { let fragment = - Fragment::new_anonymous_table_fragment(node, - SpecificFragmentInfo::TableRow); + Fragment::new_anonymous_from_specific_info(node, + SpecificFragmentInfo::TableRow); box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow> }, FlowClass::TableRow => { let fragment = - Fragment::new_anonymous_table_fragment(node, - SpecificFragmentInfo::TableCell); + Fragment::new_anonymous_from_specific_info(node, + SpecificFragmentInfo::TableCell); let hide = node.style().get_inheritedtable().empty_cells == empty_cells::hide; box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide) as Box<Flow> diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index c66087364ed..cfc2ab8b1a5 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -31,8 +31,7 @@ use serialize::{Encodable, Encoder}; use servo_msg::constellation_msg::{PipelineId, SubpageId}; use servo_net::image::holder::ImageHolder; use servo_net::local_image_cache::LocalImageCache; -use servo_util::geometry::Au; -use servo_util::geometry; +use servo_util::geometry::{mod, Au, ZERO_POINT}; use servo_util::logical_geometry::{LogicalRect, LogicalSize, LogicalMargin}; use servo_util::range::*; use servo_util::smallvec::SmallVec; @@ -62,8 +61,8 @@ use url::Url; /// positioned as if it were a block fragment, but its children are positioned according to /// inline flow. /// -/// A `SpecificFragmentInfo::Generic` is an empty fragment that contributes only borders, margins, padding, and -/// backgrounds. It is analogous to a CSS nonreplaced content box. +/// A `SpecificFragmentInfo::Generic` is an empty fragment that contributes only borders, margins, +/// padding, and backgrounds. It is analogous to a CSS nonreplaced content box. /// /// A fragment's type influences how its styles are interpreted during layout. For example, /// replaced content such as images are resized differently from tables, text, or other content. @@ -83,8 +82,10 @@ pub struct Fragment { /// The CSS style of this fragment. pub style: Arc<ComputedValues>, - /// The position of this fragment relative to its owning flow. - /// The size includes padding and border, but not margin. + /// The position of this fragment relative to its owning flow. The size includes padding and + /// border, but not margin. + /// + /// NB: This does not account for relative positioning. pub border_box: LogicalRect<Au>, /// The sum of border and padding; i.e. the distance from the edge of the border box to the @@ -520,10 +521,28 @@ impl Fragment { } } + /// Constructs a new `Fragment` instance for an anonymous object. + pub fn new_anonymous(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) + -> Fragment { + let node_style = cascade_anonymous(&**node.style()); + let writing_mode = node_style.writing_mode; + Fragment { + node: OpaqueNodeMethods::from_thread_safe_layout_node(node), + style: Arc::new(node_style), + restyle_damage: node.restyle_damage(), + border_box: LogicalRect::zero(writing_mode), + border_padding: LogicalMargin::zero(writing_mode), + margin: LogicalMargin::zero(writing_mode), + specific: constructor.build_specific_fragment_info_for_node(node), + inline_context: None, + debug_id: layout_debug::generate_unique_debug_id(), + } + } + /// Constructs a new `Fragment` instance for an anonymous table object. - pub fn new_anonymous_table_fragment(node: &ThreadSafeLayoutNode, - specific: SpecificFragmentInfo) - -> Fragment { + pub fn new_anonymous_from_specific_info(node: &ThreadSafeLayoutNode, + specific: SpecificFragmentInfo) + -> Fragment { // CSS 2.1 § 17.2.1 This is for non-inherited properties on anonymous table fragments // example: // @@ -1508,10 +1527,17 @@ impl Fragment { /// because the corresponding table flow is the primary fragment. pub fn is_primary_fragment(&self) -> bool { match self.specific { - SpecificFragmentInfo::InlineBlock(_) | SpecificFragmentInfo::InlineAbsoluteHypothetical(_) | + SpecificFragmentInfo::InlineBlock(_) | + SpecificFragmentInfo::InlineAbsoluteHypothetical(_) | SpecificFragmentInfo::TableWrapper => false, - SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | - SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableColumn(_) | SpecificFragmentInfo::TableRow | + SpecificFragmentInfo::Generic | + SpecificFragmentInfo::Iframe(_) | + SpecificFragmentInfo::Image(_) | + SpecificFragmentInfo::ScannedText(_) | + SpecificFragmentInfo::Table | + SpecificFragmentInfo::TableCell | + SpecificFragmentInfo::TableColumn(_) | + SpecificFragmentInfo::TableRow | SpecificFragmentInfo::UnscannedText(_) => true, } } @@ -1540,15 +1566,48 @@ impl Fragment { self.style = (*new_style).clone() } - /// Given the stacking-context-relative position of the containing flow, returns the boundaries - /// of this fragment relative to the parent stacking context. - pub fn stacking_relative_bounds(&self, stacking_relative_flow_origin: &Point2D<Au>) - -> Rect<Au> { - // FIXME(#2795): Get the real container size + /// Given the stacking-context-relative position of the containing flow, returns the border box + /// of this fragment relative to the parent stacking context. This takes `position: relative` + /// into account. + /// + /// If `coordinate_system` is `Parent`, this returns the border box in the parent stacking + /// context's coordinate system. Otherwise, if `coordinate_system` is `Self` and this fragment + /// establishes a stacking context itself, this returns a border box anchored at (0, 0). (If + /// this fragment does not establish a stacking context, then it always belongs to its parent + /// stacking context and thus `coordinate_system` is ignored.) + /// + /// This is the method you should use for display list construction as well as + /// `getBoundingClientRect()` and so forth. + pub fn stacking_relative_border_box(&self, + stacking_relative_flow_origin: &Point2D<Au>, + relative_containing_block_size: &LogicalSize<Au>, + coordinate_system: CoordinateSystem) + -> Rect<Au> { + // FIXME(pcwalton, #2795): Get the real container size. let container_size = Size2D::zero(); - self.border_box - .to_physical(self.style.writing_mode, container_size) - .translate(stacking_relative_flow_origin) + let border_box = self.border_box.to_physical(self.style.writing_mode, container_size); + if coordinate_system == CoordinateSystem::Self && self.establishes_stacking_context() { + return Rect(ZERO_POINT, border_box.size) + } + + // FIXME(pcwalton): This can double-count relative position sometimes for inlines (e.g. + // `<div style="position:relative">x</div>`, because the `position:relative` trickles down + // to the inline flow. Possibly we should extend the notion of "primary fragment" to fix + // this. + let relative_position = self.relative_position(relative_containing_block_size); + border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode)) + .translate(stacking_relative_flow_origin) + } + + /// Given the stacking-context-relative border box, returns the stacking-context-relative + /// content box. + pub fn stacking_relative_content_box(&self, stacking_relative_border_box: &Rect<Au>) + -> Rect<Au> { + let border_padding = self.border_padding.to_physical(self.style.writing_mode); + Rect(Point2D(stacking_relative_border_box.origin.x + border_padding.left, + stacking_relative_border_box.origin.y + border_padding.top), + Size2D(stacking_relative_border_box.size.width - border_padding.horizontal(), + stacking_relative_border_box.size.height - border_padding.vertical())) } /// Returns true if this fragment establishes a new stacking context and false otherwise. @@ -1637,13 +1696,23 @@ bitflags! { } } -/// A top-down fragment overflow region iteration handler. -pub trait FragmentOverflowIterator { +/// A top-down fragment border box iteration handler. +pub trait FragmentBorderBoxIterator { /// The operation to perform. - fn process(&mut self, fragment: &Fragment, overflow: Rect<Au>); + fn process(&mut self, fragment: &Fragment, overflow: &Rect<Au>); /// Returns true if this fragment must be processed in-order. If this returns false, /// we skip the operation for this fragment, but continue processing siblings. fn should_process(&mut self, fragment: &Fragment) -> bool; } +/// The coordinate system used in `stacking_relative_border_box()`. See the documentation of that +/// method for details. +#[deriving(Clone, PartialEq, Show)] +pub enum CoordinateSystem { + /// The border box returned is relative to the fragment's parent stacking context. + Parent, + /// The border box returned is relative to the fragment's own stacking context, if applicable. + Self, +} + diff --git a/components/layout/inline.rs b/components/layout/inline.rs index f8a19708d1e..0a2234bfa8b 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -6,13 +6,13 @@ use css::node_style::StyledNode; use context::LayoutContext; -use display_list_builder::{BackgroundAndBorderLevel, DisplayListBuildingResult, FragmentDisplayListBuilding}; +use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBuilding}; use floats::{FloatKind, Floats, PlacementInfo}; use flow::{BaseFlow, FlowClass, Flow, MutableFlowUtils, ForceNonfloatedFlag}; use flow::{IS_ABSOLUTELY_POSITIONED}; use flow; -use fragment::{Fragment, SpecificFragmentInfo}; -use fragment::{FragmentOverflowIterator, ScannedTextFragmentInfo}; +use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, ScannedTextFragmentInfo}; +use fragment::{SpecificFragmentInfo}; use fragment::SplitInfo; use incremental::{REFLOW, REFLOW_OUT_OF_FLOW}; use layout_debug; @@ -20,16 +20,14 @@ use model::IntrinsicISizesContribution; use text; use collections::{RingBuf}; -use geom::{Rect, Size2D}; -use gfx::display_list::DisplayList; +use geom::{Point2D, Rect}; use gfx::font::FontMetrics; use gfx::font_context::FontContext; use gfx::text::glyph::CharIndex; +use servo_util::arc_ptr_eq; use servo_util::geometry::{Au, ZERO_RECT}; use servo_util::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; -use servo_util::opts; use servo_util::range::{Range, RangeIndex}; -use servo_util::arc_ptr_eq; use std::cmp::max; use std::fmt; use std::mem; @@ -1186,44 +1184,29 @@ impl Flow for InlineFlow { fn compute_absolute_position(&mut self) { for fragment in self.fragments.fragments.iter_mut() { - let stacking_relative_position = match fragment.specific { + let stacking_relative_border_box = + fragment.stacking_relative_border_box(&self.base.stacking_relative_position, + &self.base + .absolute_position_info + .relative_containing_block_size, + CoordinateSystem::Self); + let clip = fragment.clipping_region_for_children(&self.base.clip, + &stacking_relative_border_box); + match fragment.specific { SpecificFragmentInfo::InlineBlock(ref mut info) => { + flow::mut_base(info.flow_ref.deref_mut()).clip = clip; let block_flow = info.flow_ref.as_block(); block_flow.base.absolute_position_info = self.base.absolute_position_info; - - // FIXME(#2795): Get the real container size - let container_size = Size2D::zero(); block_flow.base.stacking_relative_position = - self.base.stacking_relative_position + - fragment.border_box.start.to_physical(self.base.writing_mode, - container_size); - block_flow.base.stacking_relative_position + stacking_relative_border_box.origin; } SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { + flow::mut_base(info.flow_ref.deref_mut()).clip = clip; let block_flow = info.flow_ref.as_block(); block_flow.base.absolute_position_info = self.base.absolute_position_info; - - // FIXME(#2795): Get the real container size - let container_size = Size2D::zero(); block_flow.base.stacking_relative_position = - self.base.stacking_relative_position + - fragment.border_box.start.to_physical(self.base.writing_mode, - container_size); - block_flow.base.stacking_relative_position - - } - _ => continue, - }; - - let clip = fragment.clipping_region_for_children(&self.base.clip, - &stacking_relative_position); + stacking_relative_border_box.origin - match fragment.specific { - SpecificFragmentInfo::InlineBlock(ref mut info) => { - flow::mut_base(info.flow_ref.deref_mut()).clip = clip - } - SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { - flow::mut_base(info.flow_ref.deref_mut()).clip = clip } _ => {} } @@ -1235,38 +1218,7 @@ impl Flow for InlineFlow { fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {} fn build_display_list(&mut self, layout_context: &LayoutContext) { - // TODO(#228): Once we form lines and have their cached bounds, we can be smarter and - // not recurse on a line if nothing in it can intersect the dirty region. - debug!("Flow: building display list for {} inline fragments", self.fragments.len()); - - let mut display_list = box DisplayList::new(); - for fragment in self.fragments.fragments.iter_mut() { - let fragment_origin = self.base.stacking_relative_position_of_child_fragment(fragment); - fragment.build_display_list(&mut *display_list, - layout_context, - fragment_origin, - BackgroundAndBorderLevel::Content, - &self.base.clip); - match fragment.specific { - SpecificFragmentInfo::InlineBlock(ref mut block_flow) => { - let block_flow = block_flow.flow_ref.deref_mut(); - flow::mut_base(block_flow).display_list_building_result - .add_to(&mut *display_list) - } - SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => { - let block_flow = block_flow.flow_ref.deref_mut(); - flow::mut_base(block_flow).display_list_building_result - .add_to(&mut *display_list) - } - _ => {} - } - } - - self.base.display_list_building_result = DisplayListBuildingResult::Normal(display_list); - - if opts::get().validate_display_list_geometry { - self.base.validate_display_list_geometry(); - } + self.build_display_list_for_inline(layout_context) } fn repair_style(&mut self, _: &Arc<ComputedValues>) {} @@ -1279,13 +1231,23 @@ impl Flow for InlineFlow { overflow } - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + // FIXME(#2795): Get the real container size. for fragment in self.fragments.fragments.iter() { - if iterator.should_process(fragment) { - let fragment_origin = - self.base.stacking_relative_position_of_child_fragment(fragment); - iterator.process(fragment, fragment.stacking_relative_bounds(&fragment_origin)); + if !iterator.should_process(fragment) { + continue } + + let stacking_relative_position = &self.base.stacking_relative_position; + let relative_containing_block_size = + &self.base.absolute_position_info.relative_containing_block_size; + iterator.process(fragment, + &fragment.stacking_relative_border_box(stacking_relative_position, + relative_containing_block_size, + CoordinateSystem::Parent) + .translate(stacking_context_position)) } } } diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 22e00904c75..3309ff9c28b 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -10,7 +10,7 @@ use construct::ConstructionResult; use context::SharedLayoutContext; use flow::{mod, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; use flow_ref::FlowRef; -use fragment::{Fragment, FragmentOverflowIterator}; +use fragment::{Fragment, FragmentBorderBoxIterator}; use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT}; use layout_debug; use parallel::{mod, UnsafeFlow}; @@ -604,8 +604,8 @@ impl LayoutTask { // FIXME(pcwalton): This has not been updated to handle the stacking context relative // stuff. So the position is wrong in most cases. let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); - let mut iterator = UnioningFragmentOverflowIterator::new(requested_node); - sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator); + let mut iterator = UnioningFragmentBorderBoxIterator::new(requested_node); + sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); rw_data.content_box_response = iterator.rect; } @@ -616,8 +616,8 @@ impl LayoutTask { // FIXME(pcwalton): This has not been updated to handle the stacking context relative // stuff. So the position is wrong in most cases. let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); - let mut iterator = CollectingFragmentOverflowIterator::new(requested_node); - sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator); + let mut iterator = CollectingFragmentBorderBoxIterator::new(requested_node); + sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); rw_data.content_boxes_response = iterator.rects; } @@ -1017,26 +1017,26 @@ impl LayoutRPC for LayoutRPCImpl { } } -struct UnioningFragmentOverflowIterator { +struct UnioningFragmentBorderBoxIterator { node_address: OpaqueNode, rect: Rect<Au>, } -impl UnioningFragmentOverflowIterator { - fn new(node_address: OpaqueNode) -> UnioningFragmentOverflowIterator { - UnioningFragmentOverflowIterator { +impl UnioningFragmentBorderBoxIterator { + fn new(node_address: OpaqueNode) -> UnioningFragmentBorderBoxIterator { + UnioningFragmentBorderBoxIterator { node_address: node_address, rect: Rect::zero(), } } } -impl FragmentOverflowIterator for UnioningFragmentOverflowIterator { - fn process(&mut self, _: &Fragment, bounds: Rect<Au>) { - if self.rect.is_empty() { - self.rect = bounds; +impl FragmentBorderBoxIterator for UnioningFragmentBorderBoxIterator { + fn process(&mut self, _: &Fragment, border_box: &Rect<Au>) { + self.rect = if self.rect.is_empty() { + *border_box } else { - self.rect = self.rect.union(&bounds); + self.rect.union(border_box) } } @@ -1045,23 +1045,23 @@ impl FragmentOverflowIterator for UnioningFragmentOverflowIterator { } } -struct CollectingFragmentOverflowIterator { +struct CollectingFragmentBorderBoxIterator { node_address: OpaqueNode, rects: Vec<Rect<Au>>, } -impl CollectingFragmentOverflowIterator { - fn new(node_address: OpaqueNode) -> CollectingFragmentOverflowIterator { - CollectingFragmentOverflowIterator { +impl CollectingFragmentBorderBoxIterator { + fn new(node_address: OpaqueNode) -> CollectingFragmentBorderBoxIterator { + CollectingFragmentBorderBoxIterator { node_address: node_address, rects: Vec::new(), } } } -impl FragmentOverflowIterator for CollectingFragmentOverflowIterator { - fn process(&mut self, _: &Fragment, bounds: Rect<Au>) { - self.rects.push(bounds); +impl FragmentBorderBoxIterator for CollectingFragmentBorderBoxIterator { + fn process(&mut self, _: &Fragment, border_box: &Rect<Au>) { + self.rects.push(*border_box); } fn should_process(&mut self, fragment: &Fragment) -> bool { diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs index 0d0c71d526c..b13630496c5 100644 --- a/components/layout/list_item.rs +++ b/components/layout/list_item.rs @@ -12,10 +12,10 @@ use construct::FlowConstructor; use context::LayoutContext; use display_list_builder::ListItemFlowDisplayListBuilding; use flow::{Flow, FlowClass}; -use fragment::{Fragment, FragmentOverflowIterator}; +use fragment::{Fragment, FragmentBorderBoxIterator}; use wrapper::ThreadSafeLayoutNode; -use geom::Rect; +use geom::{Point2D, Rect}; use gfx::display_list::DisplayList; use servo_util::geometry::Au; use servo_util::opts; @@ -116,8 +116,10 @@ impl Flow for ListItemFlow { self.block_flow.compute_overflow() } - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { - self.block_flow.iterate_through_fragment_overflow(iterator); + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position) } } diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs index 01ba0c098ed..1be77041113 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -5,11 +5,10 @@ //! Implements sequential traversals over the DOM and flow trees. use context::{LayoutContext, SharedLayoutContext}; -use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal}; -use flow; +use flow::{mod, Flow, ImmutableFlowUtils, MutableFlowUtils, PostorderFlowTraversal}; +use flow::{PreorderFlowTraversal}; use flow_ref::FlowRef; -use fragment::FragmentOverflowIterator; -use servo_util::opts; +use fragment::FragmentBorderBoxIterator; use traversal::{BubbleISizes, RecalcStyleForNode, ConstructFlows}; use traversal::{AssignBSizesAndStoreOverflow, AssignISizes}; use traversal::{ComputeAbsolutePositions, BuildDisplayList}; @@ -17,6 +16,10 @@ use wrapper::LayoutNode; use wrapper::{PostorderNodeMutTraversal}; use wrapper::{PreorderDomTraversal, PostorderDomTraversal}; +use geom::point::Point2D; +use servo_util::geometry::{Au, ZERO_POINT}; +use servo_util::opts; + pub fn traverse_dom_preorder(root: LayoutNode, shared_layout_context: &SharedLayoutContext) { fn doit(node: LayoutNode, recalc_style: RecalcStyleForNode, construct_flows: ConstructFlows) { @@ -94,15 +97,25 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef, doit(root.deref_mut(), compute_absolute_positions, build_display_list); } -pub fn iterate_through_flow_tree_fragment_bounds(root: &mut FlowRef, - iterator: &mut FragmentOverflowIterator) { - fn doit(flow: &mut Flow, iterator: &mut FragmentOverflowIterator) { - flow.iterate_through_fragment_overflow(iterator); +pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef, + iterator: &mut FragmentBorderBoxIterator) { + fn doit(flow: &mut Flow, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position); for kid in flow::mut_base(flow).child_iter() { - doit(kid, iterator); + let stacking_context_position = + if kid.is_block_flow() && kid.as_block().fragment.establishes_stacking_context() { + *stacking_context_position + flow::base(kid).stacking_relative_position + } else { + *stacking_context_position + }; + + // FIXME(#2795): Get the real container size. + doit(kid, iterator, &stacking_context_position); } } - doit(root.deref_mut(), iterator); + doit(root.deref_mut(), iterator, &ZERO_POINT); } diff --git a/components/layout/table.rs b/components/layout/table.rs index 81c9f40d43d..e05abd4d67e 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -13,14 +13,14 @@ use context::LayoutContext; use floats::FloatKind; use flow::{mod, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS}; use flow::ImmutableFlowUtils; -use fragment::{Fragment, FragmentOverflowIterator}; +use fragment::{Fragment, FragmentBorderBoxIterator}; use layout_debug; use model::{IntrinsicISizes, IntrinsicISizesContribution}; use table_row::CellIntrinsicInlineSize; use table_wrapper::TableLayout; use wrapper::ThreadSafeLayoutNode; -use geom::Rect; +use geom::{Point2D, Rect}; use servo_util::geometry::Au; use servo_util::logical_geometry::LogicalRect; use std::cmp::max; @@ -389,8 +389,10 @@ impl Flow for TableFlow { self.block_flow.compute_overflow() } - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { - self.block_flow.iterate_through_fragment_overflow(iterator); + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position) } } diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs index 4864e49096a..1a77cde7092 100644 --- a/components/layout/table_caption.rs +++ b/components/layout/table_caption.rs @@ -10,10 +10,10 @@ use block::BlockFlow; use construct::FlowConstructor; use context::LayoutContext; use flow::{FlowClass, Flow}; -use fragment::FragmentOverflowIterator; +use fragment::FragmentBorderBoxIterator; use wrapper::ThreadSafeLayoutNode; -use geom::Rect; +use geom::{Point2D, Rect}; use servo_util::geometry::Au; use std::fmt; use style::ComputedValues; @@ -86,8 +86,10 @@ impl Flow for TableCaptionFlow { self.block_flow.compute_overflow() } - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { - self.block_flow.iterate_through_fragment_overflow(iterator); + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position) } } diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 583c328f315..b97a12e143d 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -9,13 +9,13 @@ use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag}; use context::LayoutContext; use flow::{Flow, FlowClass}; -use fragment::{Fragment, FragmentOverflowIterator}; +use fragment::{Fragment, FragmentBorderBoxIterator}; use model::{MaybeAuto}; use layout_debug; use table::InternalTable; use wrapper::ThreadSafeLayoutNode; -use geom::Rect; +use geom::{Point2D, Rect}; use servo_util::geometry::Au; use std::fmt; use style::{UnsignedIntegerAttribute, ComputedValues}; @@ -167,8 +167,10 @@ impl Flow for TableCellFlow { self.block_flow.compute_overflow() } - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { - self.block_flow.iterate_through_fragment_overflow(iterator); + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position) } } diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index 4eb1cae8022..5e7b066d206 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -9,11 +9,11 @@ use context::LayoutContext; use css::node_style::StyledNode; use flow::{BaseFlow, FlowClass, Flow, ForceNonfloatedFlag}; -use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo}; +use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; use layout_debug; use wrapper::ThreadSafeLayoutNode; -use geom::Rect; +use geom::{Point2D, Rect}; use servo_util::geometry::{Au, ZERO_RECT}; use std::cmp::max; use std::fmt; @@ -101,8 +101,9 @@ impl Flow for TableColGroupFlow { ZERO_RECT } - fn iterate_through_fragment_overflow(&self, _: &mut FragmentOverflowIterator) { - } + fn iterate_through_fragment_border_boxes(&self, + _: &mut FragmentBorderBoxIterator, + _: &Point2D<Au>) {} } impl fmt::Show for TableColGroupFlow { diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index d27d7d1ffb4..b3e9e1ae7f6 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -12,13 +12,13 @@ use construct::FlowConstructor; use context::LayoutContext; use flow::{FlowClass, Flow, ImmutableFlowUtils}; use flow; -use fragment::{Fragment, FragmentOverflowIterator}; +use fragment::{Fragment, FragmentBorderBoxIterator}; use layout_debug; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable}; use model::MaybeAuto; use wrapper::ThreadSafeLayoutNode; -use geom::Rect; +use geom::{Point2D, Rect}; use servo_util::geometry::Au; use std::cmp::max; use std::fmt; @@ -320,8 +320,10 @@ impl Flow for TableRowFlow { self.block_flow.compute_overflow() } - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { - self.block_flow.iterate_through_fragment_overflow(iterator); + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position) } } diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index 5d3673c1612..2c2847565c7 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -10,12 +10,12 @@ use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag}; use construct::FlowConstructor; use context::LayoutContext; use flow::{FlowClass, Flow}; -use fragment::{Fragment, FragmentOverflowIterator}; +use fragment::{Fragment, FragmentBorderBoxIterator}; use layout_debug; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable}; use wrapper::ThreadSafeLayoutNode; -use geom::Rect; +use geom::{Point2D, Rect}; use servo_util::geometry::Au; use std::fmt; use style::ComputedValues; @@ -155,8 +155,10 @@ impl Flow for TableRowGroupFlow { self.block_flow.compute_overflow() } - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { - self.block_flow.iterate_through_fragment_overflow(iterator); + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position) } } diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index fa8497c46d7..1c68b7fa924 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -19,11 +19,11 @@ use context::LayoutContext; use floats::FloatKind; use flow::{FlowClass, Flow, ImmutableFlowUtils}; use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS}; -use fragment::{Fragment, FragmentOverflowIterator}; +use fragment::{Fragment, FragmentBorderBoxIterator}; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize}; use wrapper::ThreadSafeLayoutNode; -use geom::Rect; +use geom::{Point2D, Rect}; use servo_util::geometry::Au; use std::cmp::{max, min}; use std::fmt; @@ -363,8 +363,10 @@ impl Flow for TableWrapperFlow { self.block_flow.compute_overflow() } - fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { - self.block_flow.iterate_through_fragment_overflow(iterator); + fn iterate_through_fragment_border_boxes(&self, + iterator: &mut FragmentBorderBoxIterator, + stacking_context_position: &Point2D<Au>) { + self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position) } } |