diff options
Diffstat (limited to 'components/layout')
-rw-r--r-- | components/layout/display_list_builder.rs | 130 | ||||
-rw-r--r-- | components/layout/flow.rs | 16 | ||||
-rw-r--r-- | components/layout/table_colgroup.rs | 3 | ||||
-rw-r--r-- | components/layout/traversal.rs | 7 | ||||
-rw-r--r-- | components/layout/webrender_helpers.rs | 25 |
5 files changed, 96 insertions, 85 deletions
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index f8b26899b57..5e238a683fe 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -71,8 +71,8 @@ use style_traits::CSSPixel; use style_traits::ToCss; use style_traits::cursor::Cursor; use table_cell::CollapsedBordersForCell; -use webrender_api::{ClipId, ColorF, ComplexClipRegion, GradientStop, LocalClip, RepeatMode}; -use webrender_api::{LineStyle, ScrollPolicy, ScrollSensitivity, TransformStyle}; +use webrender_api::{ClipAndScrollInfo, ClipId, ColorF, ComplexClipRegion, GradientStop, LineStyle}; +use webrender_api::{LocalClip, RepeatMode, ScrollPolicy, ScrollSensitivity, TransformStyle}; use webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle}; trait ResolvePercentage { @@ -169,14 +169,14 @@ pub struct DisplayListBuildState<'a> { /// recursively building and processing the display list. pub current_stacking_context_id: StackingContextId, - /// The current scroll root id, used to keep track of state when + /// The current clip and scroll info, used to keep track of state when /// recursively building and processing the display list. - pub current_scroll_root_id: ClipId, + pub current_clip_and_scroll_info: ClipAndScrollInfo, - /// The scroll root id of the first ancestor which defines a containing block. + /// The clip and scroll info of the first ancestor which defines a containing block. /// This is necessary because absolutely positioned items should be clipped /// by their containing block's scroll root. - pub containing_block_scroll_root_id: ClipId, + pub containing_block_clip_and_scroll_info: ClipAndScrollInfo, /// Vector containing iframe sizes, used to inform the constellation about /// new iframe sizes @@ -196,6 +196,7 @@ pub struct DisplayListBuildState<'a> { impl<'a> DisplayListBuildState<'a> { pub fn new(layout_context: &'a LayoutContext) -> DisplayListBuildState<'a> { + let root_clip_info = ClipAndScrollInfo::simple(layout_context.id.root_scroll_node()); DisplayListBuildState { layout_context: layout_context, root_stacking_context: StackingContext::root(layout_context.id), @@ -204,8 +205,8 @@ impl<'a> DisplayListBuildState<'a> { scroll_root_parents: HashMap::new(), processing_scroll_root_element: false, current_stacking_context_id: StackingContextId::root(), - current_scroll_root_id: layout_context.id.root_scroll_node(), - containing_block_scroll_root_id: layout_context.id.root_scroll_node(), + current_clip_and_scroll_info: root_clip_info, + containing_block_clip_and_scroll_info: root_clip_info, iframe_sizes: Vec::new(), clip_stack: Vec::new(), containing_block_clip_stack: Vec::new(), @@ -249,6 +250,12 @@ impl<'a> DisplayListBuildState<'a> { *self.scroll_root_parents.get(&scroll_root_id).unwrap() } + fn is_background_or_border_of_scroll_root(&self, section: DisplayListSection) -> bool { + (section == DisplayListSection::BackgroundAndBorders || + section == DisplayListSection::BlockBackgroundsAndBorders) && + self.processing_scroll_root_element + } + fn create_base_display_item(&self, bounds: &Rect<Au>, clip: LocalClip, @@ -256,12 +263,10 @@ impl<'a> DisplayListBuildState<'a> { cursor: Option<Cursor>, section: DisplayListSection) -> BaseDisplayItem { - let scroll_root_id = if (section == DisplayListSection::BackgroundAndBorders || - section == DisplayListSection::BlockBackgroundsAndBorders) && - self.processing_scroll_root_element { - self.parent_scroll_root_id(self.current_scroll_root_id) + let clip_and_scroll_info = if self.is_background_or_border_of_scroll_root(section) { + ClipAndScrollInfo::simple(self.parent_scroll_root_id(self.current_clip_and_scroll_info.scroll_node_id)) } else { - self.current_scroll_root_id + self.current_clip_and_scroll_info }; BaseDisplayItem::new(&bounds, @@ -272,7 +277,7 @@ impl<'a> DisplayListBuildState<'a> { clip, section, self.current_stacking_context_id, - scroll_root_id) + clip_and_scroll_info) } pub fn to_display_list(mut self) -> DisplayList { @@ -548,7 +553,7 @@ pub trait FragmentDisplayListBuilding { base_flow: &BaseFlow, scroll_policy: ScrollPolicy, mode: StackingContextCreationMode, - parent_scroll_id: ClipId) + parent_clip_and_scroll_info: ClipAndScrollInfo) -> StackingContext; @@ -2029,7 +2034,7 @@ impl FragmentDisplayListBuilding for Fragment { base_flow: &BaseFlow, scroll_policy: ScrollPolicy, mode: StackingContextCreationMode, - parent_scroll_id: ClipId) + parent_clip_and_scroll_info: ClipAndScrollInfo) -> StackingContext { let border_box = self.stacking_relative_border_box(&base_flow.stacking_relative_position, @@ -2069,7 +2074,7 @@ impl FragmentDisplayListBuilding for Fragment { self.style().get_used_transform_style().to_transform_style(), self.perspective_matrix(&border_box), scroll_policy, - parent_scroll_id) + parent_clip_and_scroll_info) } fn build_display_list_for_text_fragment(&self, @@ -2255,7 +2260,7 @@ pub trait BlockFlowDisplayListBuilding { state: &mut DisplayListBuildState, preserved_state: &mut PreservedDisplayListState, stacking_context_type: BlockStackingContextType) - -> ClipId; + -> ClipAndScrollInfo; fn setup_scroll_root_for_overflow(&mut self, state: &mut DisplayListBuildState, border_box: &Rect<Au>); @@ -2265,11 +2270,11 @@ pub trait BlockFlowDisplayListBuilding { stacking_relative_border_box: &Rect<Au>); fn create_pseudo_stacking_context_for_block(&mut self, parent_stacking_context_id: StackingContextId, - parent_scroll_root_id: ClipId, + parent_clip_and_scroll_info: ClipAndScrollInfo, state: &mut DisplayListBuildState); fn create_real_stacking_context_for_block(&mut self, parent_stacking_context_id: StackingContextId, - parent_scroll_root_id: ClipId, + parent_clip_and_scroll_info: ClipAndScrollInfo, state: &mut DisplayListBuildState); fn build_display_list_for_block(&mut self, state: &mut DisplayListBuildState, @@ -2283,8 +2288,8 @@ pub trait BlockFlowDisplayListBuilding { /// TODO(mrobinson): It would be nice to use RAII here to avoid having to call restore. pub struct PreservedDisplayListState { stacking_context_id: StackingContextId, - scroll_root_id: ClipId, - containing_block_scroll_root_id: ClipId, + clip_and_scroll_info: ClipAndScrollInfo, + containing_block_clip_and_scroll_info: ClipAndScrollInfo, clips_pushed: usize, containing_block_clips_pushed: usize, transform_style: TransformStyle, @@ -2294,8 +2299,8 @@ impl PreservedDisplayListState { fn new(state: &mut DisplayListBuildState) -> PreservedDisplayListState { PreservedDisplayListState { stacking_context_id: state.current_stacking_context_id, - scroll_root_id: state.current_scroll_root_id, - containing_block_scroll_root_id: state.containing_block_scroll_root_id, + clip_and_scroll_info: state.current_clip_and_scroll_info, + containing_block_clip_and_scroll_info: state.containing_block_clip_and_scroll_info, clips_pushed: 0, containing_block_clips_pushed: 0, transform_style: state.current_transform_style, @@ -2310,8 +2315,8 @@ impl PreservedDisplayListState { fn restore(self, state: &mut DisplayListBuildState) { state.current_stacking_context_id = self.stacking_context_id; - state.current_scroll_root_id = self.scroll_root_id; - state.containing_block_scroll_root_id = self.containing_block_scroll_root_id; + state.current_clip_and_scroll_info = self.clip_and_scroll_info; + state.containing_block_clip_and_scroll_info = self.containing_block_clip_and_scroll_info; let truncate_length = state.clip_stack.len() - self.clips_pushed; state.clip_stack.truncate(truncate_length); @@ -2417,14 +2422,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow { // We are getting the id of the scroll root that contains us here, not the id of // any scroll root that we create. If we create a scroll root, its id will be - // stored in state.current_scroll_root_id. If we should create a stacking context, - // we don't want it to be clipped by its own scroll root. - let containing_scroll_root_id = self.setup_clipping_for_block(state, - &mut preserved_state, - block_stacking_context_type); - + // stored in state.current_clip_and_scroll_info. If we create a stacking context, + // we don't want it to be contained by its own scroll root. + let containing_clip_and_scroll_info = + self.setup_clipping_for_block(state, &mut preserved_state, block_stacking_context_type); if establishes_containing_block_for_absolute(self.positioning()) { - state.containing_block_scroll_root_id = state.current_scroll_root_id; + state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info; } match block_stacking_context_type { @@ -2433,12 +2436,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow { } BlockStackingContextType::PseudoStackingContext => { self.create_pseudo_stacking_context_for_block(preserved_state.stacking_context_id, - containing_scroll_root_id, + containing_clip_and_scroll_info, state); } BlockStackingContextType::StackingContext => { self.create_real_stacking_context_for_block(preserved_state.stacking_context_id, - containing_scroll_root_id, + containing_clip_and_scroll_info, state); } } @@ -2450,22 +2453,22 @@ impl BlockFlowDisplayListBuilding for BlockFlow { state: &mut DisplayListBuildState, preserved_state: &mut PreservedDisplayListState, stacking_context_type: BlockStackingContextType) - -> ClipId { + -> ClipAndScrollInfo { // If this block is absolutely positioned, we should be clipped and positioned by // the scroll root of our nearest ancestor that establishes a containing block. - let containing_scroll_root_id = match self.positioning() { + let containing_clip_and_scroll_info = match self.positioning() { position::T::absolute => { preserved_state.switch_to_containing_block_clip(state); - state.current_scroll_root_id = state.containing_block_scroll_root_id; - state.containing_block_scroll_root_id + state.current_clip_and_scroll_info = state.containing_block_clip_and_scroll_info; + state.containing_block_clip_and_scroll_info } position::T::fixed => { preserved_state.push_clip(state, &max_rect(), position::T::fixed); - state.current_scroll_root_id + state.current_clip_and_scroll_info } - _ => state.current_scroll_root_id, + _ => state.current_clip_and_scroll_info, }; - self.base.scroll_root_id = Some(containing_scroll_root_id); + self.base.clip_and_scroll_info = Some(containing_clip_and_scroll_info); let coordinate_system = if self.fragment.establishes_stacking_context() { CoordinateSystem::Own @@ -2489,11 +2492,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow { match self.positioning() { position::T::absolute | position::T::relative | position::T::fixed => - state.containing_block_scroll_root_id = state.current_scroll_root_id, + state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info, _ => {} } - containing_scroll_root_id + containing_clip_and_scroll_info } fn setup_scroll_root_for_overflow(&mut self, @@ -2542,7 +2545,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { let content_size = self.base.overflow.scroll.origin + self.base.overflow.scroll.size; let content_size = Size2D::new(content_size.x, content_size.y); - let parent_id = self.scroll_root_id(state.layout_context.id); + let parent_id = self.clip_and_scroll_info(state.layout_context.id).scroll_node_id; state.add_scroll_root( ScrollRoot { id: new_scroll_root_id, @@ -2554,8 +2557,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow { self.base.stacking_context_id ); - self.base.scroll_root_id = Some(new_scroll_root_id); - state.current_scroll_root_id = new_scroll_root_id; + let new_clip_and_scroll_info = ClipAndScrollInfo::simple(new_scroll_root_id); + self.base.clip_and_scroll_info = Some(new_clip_and_scroll_info); + state.current_clip_and_scroll_info = new_clip_and_scroll_info; } /// Adds a scroll root for a block to take the `clip` property into account @@ -2570,6 +2574,13 @@ impl BlockFlowDisplayListBuilding for BlockFlow { _ => return, }; + // CSS `clip` should only apply to position:absolute or positione:fixed elements. + // CSS Masking Appendix A: "Applies to: Absolutely positioned elements." + match self.positioning() { + position::T::absolute | position::T::fixed => {} + _ => return, + } + let clip_origin = Point2D::new(stacking_relative_border_box.origin.x + style_clip_rect.left.unwrap_or(Au(0)), stacking_relative_border_box.origin.y + @@ -2595,7 +2606,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { let clip_rect = Rect::new(clip_origin, clip_size); preserved_state.push_clip(state, &clip_rect, self.positioning()); - let parent_id = self.scroll_root_id(state.layout_context.id); + let parent_id = self.clip_and_scroll_info(state.layout_context.id).scroll_node_id; state.add_scroll_root( ScrollRoot { id: new_scroll_root_id, @@ -2607,13 +2618,14 @@ impl BlockFlowDisplayListBuilding for BlockFlow { self.base.stacking_context_id ); - self.base.scroll_root_id = Some(new_scroll_root_id); - state.current_scroll_root_id = new_scroll_root_id; + let new_clip_and_scroll_info = ClipAndScrollInfo::new(new_scroll_root_id, new_scroll_root_id); + self.base.clip_and_scroll_info = Some(new_clip_and_scroll_info); + state.current_clip_and_scroll_info = new_clip_and_scroll_info; } fn create_pseudo_stacking_context_for_block(&mut self, parent_stacking_context_id: StackingContextId, - parent_scroll_root_id: ClipId, + parent_clip_and_scroll_info: ClipAndScrollInfo, state: &mut DisplayListBuildState) { let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) || self.fragment.style.get_box().position != position::T::static_ { @@ -2627,7 +2639,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { &self.base, ScrollPolicy::Scrollable, creation_mode, - parent_scroll_root_id); + parent_clip_and_scroll_info); state.add_stacking_context(parent_stacking_context_id, new_context); self.base.collect_stacking_contexts_for_children(state); @@ -2647,7 +2659,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { fn create_real_stacking_context_for_block(&mut self, parent_stacking_context_id: StackingContextId, - parent_scroll_root_id: ClipId, + parent_clip_and_scroll_info: ClipAndScrollInfo, state: &mut DisplayListBuildState) { let scroll_policy = if self.is_fixed() { ScrollPolicy::Fixed @@ -2660,7 +2672,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { &self.base, scroll_policy, StackingContextCreationMode::Normal, - parent_scroll_root_id); + parent_clip_and_scroll_info); state.add_stacking_context(parent_stacking_context_id, stacking_context); self.base.collect_stacking_contexts_for_children(state); @@ -2715,13 +2727,13 @@ pub trait InlineFlowDisplayListBuilding { impl InlineFlowDisplayListBuilding for InlineFlow { fn collect_stacking_contexts_for_inline(&mut self, state: &mut DisplayListBuildState) { self.base.stacking_context_id = state.current_stacking_context_id; - self.base.scroll_root_id = Some(state.current_scroll_root_id); + self.base.clip_and_scroll_info = Some(state.current_clip_and_scroll_info); self.base.clip = state.clip_stack.last().cloned().unwrap_or_else(max_rect); for mut fragment in self.fragments.fragments.iter_mut() { - let previous_containing_block_scroll_root_id = state.containing_block_scroll_root_id; + let previous_cb_clip_scroll_info = state.containing_block_clip_and_scroll_info; if establishes_containing_block_for_absolute(fragment.style.get_box().position) { - state.containing_block_scroll_root_id = state.current_scroll_root_id; + state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info; } match fragment.specific { @@ -2745,14 +2757,14 @@ impl InlineFlowDisplayListBuilding for InlineFlow { &self.base, ScrollPolicy::Scrollable, StackingContextCreationMode::Normal, - state.current_scroll_root_id); + state.current_clip_and_scroll_info); state.add_stacking_context(current_stacking_context_id, stacking_context); } _ => fragment.stacking_context_id = state.current_stacking_context_id, } - state.containing_block_scroll_root_id = previous_containing_block_scroll_root_id; + state.containing_block_clip_and_scroll_info = previous_cb_clip_scroll_info; } } diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 846b7be8326..3ce36ad1a7c 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -63,7 +63,7 @@ use table_colgroup::TableColGroupFlow; use table_row::TableRowFlow; use table_rowgroup::TableRowGroupFlow; use table_wrapper::TableWrapperFlow; -use webrender_api::ClipId; +use webrender_api::ClipAndScrollInfo; /// Virtual methods that make up a float context. /// @@ -431,12 +431,12 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { /// children of this flow. fn print_extra_flow_children(&self, _: &mut PrintTree) { } - fn scroll_root_id(&self, pipeline_id: PipelineId) -> ClipId { - match base(self).scroll_root_id { - Some(id) => id, + fn clip_and_scroll_info(&self, pipeline_id: PipelineId) -> ClipAndScrollInfo { + match base(self).clip_and_scroll_info { + Some(info) => info, None => { - warn!("Tried to access scroll root id on Flow before assignment"); - pipeline_id.root_scroll_node() + debug_assert!(false, "Tried to access scroll root id on Flow before assignment"); + pipeline_id.root_clip_and_scroll_info() } } } @@ -969,7 +969,7 @@ pub struct BaseFlow { /// list construction. pub stacking_context_id: StackingContextId, - pub scroll_root_id: Option<ClipId>, + pub clip_and_scroll_info: Option<ClipAndScrollInfo>, } impl fmt::Debug for BaseFlow { @@ -1111,7 +1111,7 @@ impl BaseFlow { writing_mode: writing_mode, thread_id: 0, stacking_context_id: StackingContextId::root(), - scroll_root_id: None, + clip_and_scroll_info: None, } } diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index 97d0ef89022..10a87903403 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -94,10 +94,9 @@ impl Flow for TableColGroupFlow { fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) { self.base.stacking_context_id = state.current_stacking_context_id; - self.base.scroll_root_id = Some(state.current_scroll_root_id); + self.base.clip_and_scroll_info = Some(state.current_clip_and_scroll_info); } - fn repair_style(&mut self, _: &::ServoArc<ComputedValues>) {} fn compute_overflow(&self) -> Overflow { diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index f821b4a2806..7ca56d22f9a 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -222,8 +222,9 @@ impl<'a> BuildDisplayList<'a> { let parent_stacking_context_id = self.state.current_stacking_context_id; self.state.current_stacking_context_id = flow::base(flow).stacking_context_id; - let parent_scroll_root_id = self.state.current_scroll_root_id; - self.state.current_scroll_root_id = flow.scroll_root_id(self.state.layout_context.id); + let parent_clip_and_scroll_info = self.state.current_clip_and_scroll_info; + self.state.current_clip_and_scroll_info = + flow.clip_and_scroll_info(self.state.layout_context.id); if self.should_process() { flow.build_display_list(&mut self.state); @@ -235,7 +236,7 @@ impl<'a> BuildDisplayList<'a> { } self.state.current_stacking_context_id = parent_stacking_context_id; - self.state.current_scroll_root_id = parent_scroll_root_id; + self.state.current_clip_and_scroll_info = parent_clip_and_scroll_info; } #[inline] diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index d33638d08d2..13bde487675 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -16,8 +16,8 @@ use msg::constellation_msg::PipelineId; use style::computed_values::{image_rendering, mix_blend_mode, transform_style}; use style::values::computed::{BorderStyle, Filter}; use style::values::generics::effects::Filter as GenericFilter; -use webrender_api::{self, ClipId, ComplexClipRegion, DisplayListBuilder, ExtendMode}; -use webrender_api::LayoutTransform; +use webrender_api::{self, ClipAndScrollInfo, ComplexClipRegion, DisplayListBuilder}; +use webrender_api::{ExtendMode, LayoutTransform}; pub trait WebRenderDisplayListConverter { fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder; @@ -26,7 +26,7 @@ pub trait WebRenderDisplayListConverter { trait WebRenderDisplayItemConverter { fn convert_to_webrender(&self, builder: &mut DisplayListBuilder, - current_scroll_root_id: &mut ClipId); + current_clip_and_scroll_info: &mut ClipAndScrollInfo); } trait ToBorderStyle { @@ -222,16 +222,15 @@ impl ToTransformStyle for transform_style::T { impl WebRenderDisplayListConverter for DisplayList { fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder { let traversal = DisplayListTraversal::new(self); - let webrender_pipeline_id = pipeline_id.to_webrender(); - let mut builder = DisplayListBuilder::with_capacity(webrender_pipeline_id, + let mut builder = DisplayListBuilder::with_capacity(pipeline_id.to_webrender(), self.bounds().size.to_sizef(), 1024 * 1024); // 1 MB of space - let mut current_scroll_root_id = ClipId::root_scroll_node(webrender_pipeline_id); - builder.push_clip_id(current_scroll_root_id); + let mut current_clip_and_scroll_info = pipeline_id.root_clip_and_scroll_info(); + builder.push_clip_and_scroll_info(current_clip_and_scroll_info); for item in traversal { - item.convert_to_webrender(&mut builder, &mut current_scroll_root_id); + item.convert_to_webrender(&mut builder, &mut current_clip_and_scroll_info); } builder } @@ -240,12 +239,12 @@ impl WebRenderDisplayListConverter for DisplayList { impl WebRenderDisplayItemConverter for DisplayItem { fn convert_to_webrender(&self, builder: &mut DisplayListBuilder, - current_scroll_root_id: &mut ClipId) { - let scroll_root_id = self.base().scroll_root_id; - if scroll_root_id != *current_scroll_root_id { + current_clip_and_scroll_info: &mut ClipAndScrollInfo) { + let clip_and_scroll_info = self.base().clip_and_scroll_info; + if clip_and_scroll_info != *current_clip_and_scroll_info { builder.pop_clip_id(); - builder.push_clip_id(scroll_root_id); - *current_scroll_root_id = scroll_root_id; + builder.push_clip_and_scroll_info(clip_and_scroll_info); + *current_clip_and_scroll_info = clip_and_scroll_info; } match *self { |