Auto merge of #18462 - mrobinson:cleanup-building-state, r=emilio

Do some minor cleanups in display list building

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes do not require tests because they should not change behavior.

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18462)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-09-15 05:30:47 -05:00 committed by GitHub
commit b2df99cb65
17 changed files with 258 additions and 198 deletions

View file

@ -19,23 +19,24 @@ use euclid::Vector2D;
use flex::FlexFlow;
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref::FlowRef;
use fnv::FnvHashMap;
use fragment::{CanvasFragmentSource, CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo};
use fragment::{SpecificFragmentInfo, TruncatedFragmentInfo};
use gfx::display_list;
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails, BorderDisplayItem};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayList, DisplayListSection};
use gfx::display_list::{GradientDisplayItem, IframeDisplayItem, ImageBorder, ImageDisplayItem};
use gfx::display_list::{LineDisplayItem, NormalBorder, OpaqueNode, PushTextShadowDisplayItem};
use gfx::display_list::{PopTextShadowDisplayItem, RadialGradientDisplayItem, ScrollRoot};
use gfx::display_list::{ScrollRootType, SolidColorDisplayItem, StackingContext, StackingContextType};
use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClipScrollNode};
use gfx::display_list::{ClipScrollNodeType, ClippingRegion, DisplayItem, DisplayItemMetadata};
use gfx::display_list::{DisplayList, DisplayListSection, GradientDisplayItem, IframeDisplayItem};
use gfx::display_list::{ImageBorder, ImageDisplayItem, LineDisplayItem, NormalBorder, OpaqueNode};
use gfx::display_list::{PopTextShadowDisplayItem, PushTextShadowDisplayItem};
use gfx::display_list::{RadialGradientDisplayItem, SolidColorDisplayItem, StackingContext};
use gfx::display_list::{StackingContextType, TextDisplayItem, TextOrientation, WebRenderImageInfo};
use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc;
use list_item::ListItemFlow;
use model::{self, MaybeAuto};
use msg::constellation_msg::BrowsingContextId;
use msg::constellation_msg::{BrowsingContextId, PipelineId};
use net_traits::image::base::PixelFormat;
use net_traits::image_cache::UsePlaceholder;
use range::Range;
@ -44,7 +45,6 @@ use servo_config::opts;
use servo_geometry::max_rect;
use servo_url::ServoUrl;
use std::{cmp, f32};
use std::collections::HashMap;
use std::default::Default;
use std::mem;
use std::sync::Arc;
@ -143,14 +143,14 @@ fn get_cyclic<T>(arr: &[T], index: usize) -> &T {
#[derive(Debug)]
struct StackingContextInfo {
children: Vec<StackingContext>,
scroll_roots: Vec<ScrollRoot>,
clip_scroll_nodes: Vec<ClipScrollNode>,
}
impl StackingContextInfo {
fn new() -> StackingContextInfo {
StackingContextInfo {
children: Vec::new(),
scroll_roots: Vec::new(),
clip_scroll_nodes: Vec::new(),
}
}
@ -159,13 +159,18 @@ impl StackingContextInfo {
}
}
pub struct DisplayListBuildState<'a> {
pub layout_context: &'a LayoutContext<'a>,
pub struct StackingContextCollectionState {
/// The PipelineId of this stacking context collection.
pub pipeline_id: PipelineId,
/// The root of the StackingContext tree.
pub root_stacking_context: StackingContext,
pub items: HashMap<StackingContextId, Vec<DisplayItem>>,
stacking_context_info: HashMap<StackingContextId, StackingContextInfo>,
pub scroll_root_parents: HashMap<ClipId, ClipId>,
pub processing_scroll_root_element: bool,
/// StackingContext and ClipScrollNode children for each StackingContext.
stacking_context_info: FnvHashMap<StackingContextId, StackingContextInfo>,
/// A map establishing the parent child relationship of every ClipScrollNode.
pub clip_scroll_node_parents: FnvHashMap<ClipId, ClipId>,
/// The current stacking context id, used to keep track of state when building.
/// recursively building and processing the display list.
@ -183,10 +188,6 @@ pub struct DisplayListBuildState<'a> {
/// by their containing block's scroll root.
pub containing_block_clip_and_scroll_info: ClipAndScrollInfo,
/// Vector containing iframe sizes, used to inform the constellation about
/// new iframe sizes
pub iframe_sizes: Vec<(BrowsingContextId, TypedSize2D<f32, CSSPixel>)>,
/// A stack of clips used to cull display list entries that are outside the
/// rendered region.
pub clip_stack: Vec<Rect<Au>>,
@ -199,32 +200,24 @@ pub struct DisplayListBuildState<'a> {
parent_stacking_relative_content_box: Rect<Au>,
}
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),
items: HashMap::new(),
stacking_context_info: HashMap::new(),
scroll_root_parents: HashMap::new(),
processing_scroll_root_element: false,
impl StackingContextCollectionState {
pub fn new(pipeline_id: PipelineId) -> StackingContextCollectionState {
let root_clip_info = ClipAndScrollInfo::simple(pipeline_id.root_scroll_node());
StackingContextCollectionState {
pipeline_id: pipeline_id,
root_stacking_context: StackingContext::root(pipeline_id),
stacking_context_info: FnvHashMap::default(),
clip_scroll_node_parents: FnvHashMap::default(),
current_stacking_context_id: StackingContextId::root(),
current_real_stacking_context_id: StackingContextId::root(),
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(),
parent_stacking_relative_content_box: Rect::zero(),
}
}
fn add_display_item(&mut self, display_item: DisplayItem) {
let items = self.items.entry(display_item.stacking_context_id()).or_insert(Vec::new());
items.push(display_item);
}
fn add_stacking_context(&mut self,
parent_id: StackingContextId,
stacking_context: StackingContext) {
@ -234,35 +227,92 @@ impl<'a> DisplayListBuildState<'a> {
info.children.push(stacking_context);
}
fn has_scroll_root(&mut self, id: ClipId) -> bool {
self.scroll_root_parents.contains_key(&id)
fn has_clip_scroll_node(&mut self, id: ClipId) -> bool {
self.clip_scroll_node_parents.contains_key(&id)
}
fn add_scroll_root(&mut self, scroll_root: ScrollRoot) {
// We want the scroll root to be defined by another other possible item that could use it,
fn add_clip_scroll_node(&mut self, clip_scroll_node: ClipScrollNode) {
// We want the scroll root to be defined before any possible item that could use it,
// so we make sure that it is added to the beginning of the parent "real" (non-pseudo)
// stacking context. This ensures that item reordering will not result in an item using
// the scroll root before it is defined.
self.scroll_root_parents.insert(scroll_root.id, scroll_root.parent_id);
self.clip_scroll_node_parents.insert(clip_scroll_node.id, clip_scroll_node.parent_id);
let info = self.stacking_context_info
.entry(self.current_real_stacking_context_id)
.or_insert(StackingContextInfo::new());
info.scroll_roots.push(scroll_root);
info.clip_scroll_nodes.push(clip_scroll_node);
}
}
pub struct DisplayListBuildState<'a> {
/// A LayoutContext reference important for creating WebRender images.
pub layout_context: &'a LayoutContext<'a>,
/// The root of the StackingContext tree.
pub root_stacking_context: StackingContext,
/// StackingContext and ClipScrollNode children for each StackingContext.
stacking_context_info: FnvHashMap<StackingContextId, StackingContextInfo>,
/// A map establishing the parent child relationship of every ClipScrollNode.
pub clip_scroll_node_parents: FnvHashMap<ClipId, ClipId>,
/// The items in this display list.
pub items: FnvHashMap<StackingContextId, Vec<DisplayItem>>,
/// Whether or not we are processing an element that establishes scrolling overflow. Used
/// to determine what ClipScrollNode to place backgrounds and borders into.
pub processing_scrolling_overflow_element: bool,
/// The current stacking context id, used to keep track of state when building.
/// recursively building and processing the display list.
pub current_stacking_context_id: StackingContextId,
/// The current clip and scroll info, used to keep track of state when
/// recursively building and processing the display list.
pub current_clip_and_scroll_info: ClipAndScrollInfo,
/// Vector containing iframe sizes, used to inform the constellation about
/// new iframe sizes
pub iframe_sizes: Vec<(BrowsingContextId, TypedSize2D<f32, CSSPixel>)>,
}
impl<'a> DisplayListBuildState<'a> {
pub fn new(layout_context: &'a LayoutContext,
state: StackingContextCollectionState)
-> DisplayListBuildState<'a> {
let root_clip_info = ClipAndScrollInfo::simple(layout_context.id.root_scroll_node());
DisplayListBuildState {
layout_context: layout_context,
root_stacking_context: state.root_stacking_context,
items: FnvHashMap::default(),
stacking_context_info: state.stacking_context_info,
clip_scroll_node_parents: state.clip_scroll_node_parents,
processing_scrolling_overflow_element: false,
current_stacking_context_id: StackingContextId::root(),
current_clip_and_scroll_info: root_clip_info,
iframe_sizes: Vec::new(),
}
}
fn parent_scroll_root_id(&self, scroll_root_id: ClipId) -> ClipId {
if scroll_root_id.is_root_scroll_node() {
return scroll_root_id;
fn add_display_item(&mut self, display_item: DisplayItem) {
let items = self.items.entry(display_item.stacking_context_id()).or_insert(Vec::new());
items.push(display_item);
}
fn parent_clip_scroll_node_id(&self, clip_scroll_node_id: ClipId) -> ClipId {
if clip_scroll_node_id.is_root_scroll_node() {
return clip_scroll_node_id;
}
debug_assert!(self.scroll_root_parents.contains_key(&scroll_root_id));
*self.scroll_root_parents.get(&scroll_root_id).unwrap()
debug_assert!(self.clip_scroll_node_parents.contains_key(&clip_scroll_node_id));
*self.clip_scroll_node_parents.get(&clip_scroll_node_id).unwrap()
}
fn is_background_or_border_of_scroll_root(&self, section: DisplayListSection) -> bool {
fn is_background_or_border_of_clip_scroll_node(&self, section: DisplayListSection) -> bool {
(section == DisplayListSection::BackgroundAndBorders ||
section == DisplayListSection::BlockBackgroundsAndBorders) &&
self.processing_scroll_root_element
self.processing_scrolling_overflow_element
}
fn create_base_display_item(&self,
@ -272,8 +322,8 @@ impl<'a> DisplayListBuildState<'a> {
cursor: Option<Cursor>,
section: DisplayListSection)
-> BaseDisplayItem {
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))
let clip_and_scroll_info = if self.is_background_or_border_of_clip_scroll_node(section) {
ClipAndScrollInfo::simple(self.parent_clip_scroll_node_id(self.current_clip_and_scroll_info.scroll_node_id))
} else {
self.current_clip_and_scroll_info
};
@ -315,12 +365,12 @@ impl<'a> DisplayListBuildState<'a> {
let pipeline_id = self.layout_context.id;
if stacking_context.context_type != StackingContextType::Real {
list.extend(info.scroll_roots.into_iter().map(|root| root.to_define_item(pipeline_id)));
list.extend(info.clip_scroll_nodes.into_iter().map(|root| root.to_define_item(pipeline_id)));
self.to_display_list_for_items(list, child_items, info.children);
} else {
let (push_item, pop_item) = stacking_context.to_display_list_items(pipeline_id);
list.push(push_item);
list.extend(info.scroll_roots.into_iter().map(|root| root.to_define_item(pipeline_id)));
list.extend(info.clip_scroll_nodes.into_iter().map(|root| root.to_define_item(pipeline_id)));
self.to_display_list_for_items(list, child_items, info.children);
list.push(pop_item);
}
@ -2270,47 +2320,47 @@ pub enum EstablishContainingBlock {
pub trait BlockFlowDisplayListBuilding {
fn collect_stacking_contexts_for_block(&mut self,
state: &mut DisplayListBuildState,
state: &mut StackingContextCollectionState,
can_establish_containing_block: EstablishContainingBlock);
fn transform_clip_to_coordinate_space(&mut self,
state: &mut DisplayListBuildState,
preserved_state: &mut PreservedDisplayListState);
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState);
fn setup_clipping_for_block(&mut self,
state: &mut DisplayListBuildState,
preserved_state: &mut PreservedDisplayListState,
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState,
stacking_context_type: BlockStackingContextType,
can_establish_containing_block: EstablishContainingBlock)
-> ClipAndScrollInfo;
fn setup_scroll_root_for_position(&mut self,
state: &mut DisplayListBuildState,
border_box: &Rect<Au>);
fn setup_scroll_root_for_overflow(&mut self,
state: &mut DisplayListBuildState,
border_box: &Rect<Au>);
fn setup_scroll_root_for_css_clip(&mut self,
state: &mut DisplayListBuildState,
preserved_state: &mut PreservedDisplayListState,
stacking_relative_border_box: &Rect<Au>);
fn setup_clip_scroll_node_for_position(&mut self,
state: &mut StackingContextCollectionState,
border_box: &Rect<Au>);
fn setup_clip_scroll_node_for_overflow(&mut self,
state: &mut StackingContextCollectionState,
border_box: &Rect<Au>);
fn setup_clip_scroll_node_for_css_clip(&mut self,
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState,
stacking_relative_border_box: &Rect<Au>);
fn create_pseudo_stacking_context_for_block(&mut self,
parent_stacking_context_id: StackingContextId,
parent_clip_and_scroll_info: ClipAndScrollInfo,
state: &mut DisplayListBuildState);
state: &mut StackingContextCollectionState);
fn create_real_stacking_context_for_block(&mut self,
parent_stacking_context_id: StackingContextId,
parent_clip_and_scroll_info: ClipAndScrollInfo,
state: &mut DisplayListBuildState);
state: &mut StackingContextCollectionState);
fn build_display_list_for_block(&mut self,
state: &mut DisplayListBuildState,
border_painting_mode: BorderPaintingMode);
}
/// This structure manages ensuring that modification to DisplayListBuildState
/// is only temporary. It's useful for moving recursively down the flow tree
/// and ensuring that the state is restored for siblings. To use this structure,
/// we must call PreservedDisplayListState::restore in order to restore the state.
/// This structure manages ensuring that modification to StackingContextCollectionState is
/// only temporary. It's useful for moving recursively down the flow tree and ensuring
/// that the state is restored for siblings. To use this structure, we must call
/// SavedStackingContextCollectionState::restore in order to restore the state.
/// TODO(mrobinson): It would be nice to use RAII here to avoid having to call restore.
pub struct PreservedDisplayListState {
pub struct SavedStackingContextCollectionState {
stacking_context_id: StackingContextId,
real_stacking_context_id: StackingContextId,
clip_and_scroll_info: ClipAndScrollInfo,
@ -2320,9 +2370,9 @@ pub struct PreservedDisplayListState {
stacking_relative_content_box: Rect<Au>,
}
impl PreservedDisplayListState {
fn new(state: &mut DisplayListBuildState) -> PreservedDisplayListState {
PreservedDisplayListState {
impl SavedStackingContextCollectionState {
fn new(state: &mut StackingContextCollectionState) -> SavedStackingContextCollectionState {
SavedStackingContextCollectionState {
stacking_context_id: state.current_stacking_context_id,
real_stacking_context_id: state.current_real_stacking_context_id,
clip_and_scroll_info: state.current_clip_and_scroll_info,
@ -2333,13 +2383,13 @@ impl PreservedDisplayListState {
}
}
fn switch_to_containing_block_clip(&mut self, state: &mut DisplayListBuildState) {
fn switch_to_containing_block_clip(&mut self, state: &mut StackingContextCollectionState) {
let clip = state.containing_block_clip_stack.last().cloned().unwrap_or_else(max_rect);
state.clip_stack.push(clip);
self.clips_pushed += 1;
}
fn restore(self, state: &mut DisplayListBuildState) {
fn restore(self, state: &mut StackingContextCollectionState) {
state.current_stacking_context_id = self.stacking_context_id;
state.current_real_stacking_context_id = self.real_stacking_context_id;
state.current_clip_and_scroll_info = self.clip_and_scroll_info;
@ -2355,7 +2405,7 @@ impl PreservedDisplayListState {
}
fn push_clip(&mut self,
state: &mut DisplayListBuildState,
state: &mut StackingContextCollectionState,
clip: &Rect<Au>,
positioning: position::T) {
let mut clip = *clip;
@ -2377,8 +2427,8 @@ impl PreservedDisplayListState {
impl BlockFlowDisplayListBuilding for BlockFlow {
fn transform_clip_to_coordinate_space(&mut self,
state: &mut DisplayListBuildState,
preserved_state: &mut PreservedDisplayListState) {
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState) {
if state.clip_stack.is_empty() {
return;
}
@ -2436,9 +2486,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}
fn collect_stacking_contexts_for_block(&mut self,
state: &mut DisplayListBuildState,
state: &mut StackingContextCollectionState,
can_establish_containing_block: EstablishContainingBlock) {
let mut preserved_state = PreservedDisplayListState::new(state);
let mut preserved_state = SavedStackingContextCollectionState::new(state);
let block_stacking_context_type = self.block_stacking_context_type();
self.base.stacking_context_id = match block_stacking_context_type {
@ -2487,8 +2537,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}
fn setup_clipping_for_block(&mut self,
state: &mut DisplayListBuildState,
preserved_state: &mut PreservedDisplayListState,
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState,
stacking_context_type: BlockStackingContextType,
can_establish_containing_block: EstablishContainingBlock)
-> ClipAndScrollInfo {
@ -2518,9 +2568,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
self.transform_clip_to_coordinate_space(state, preserved_state);
}
self.setup_scroll_root_for_position(state, &stacking_relative_border_box);
self.setup_scroll_root_for_overflow(state, &stacking_relative_border_box);
self.setup_scroll_root_for_css_clip(state, preserved_state, &stacking_relative_border_box);
self.setup_clip_scroll_node_for_position(state, &stacking_relative_border_box);
self.setup_clip_scroll_node_for_overflow(state, &stacking_relative_border_box);
self.setup_clip_scroll_node_for_css_clip(state, preserved_state, &stacking_relative_border_box);
self.base.clip = state.clip_stack.last().cloned().unwrap_or_else(max_rect);
// We keep track of our position so that any stickily positioned elements can
@ -2544,8 +2594,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
containing_clip_and_scroll_info
}
fn setup_scroll_root_for_position(&mut self,
state: &mut DisplayListBuildState,
fn setup_clip_scroll_node_for_position(&mut self,
state: &mut StackingContextCollectionState,
border_box: &Rect<Au>) {
if self.positioning() != position::T::sticky {
return;
@ -2592,28 +2642,28 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
to_sticky_info(sticky_position.left,
to_max_offset(constraint_rect.max_x(), border_box_in_parent.max_x())));
let new_scroll_root_id = ClipId::new(self.fragment.unique_id(IdType::OverflowClip),
state.layout_context.id.to_webrender());
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,
let new_clip_scroll_node_id = ClipId::new(self.fragment.unique_id(IdType::OverflowClip),
state.pipeline_id.to_webrender());
let parent_id = self.clip_and_scroll_info(state.pipeline_id).scroll_node_id;
state.add_clip_scroll_node(
ClipScrollNode {
id: new_clip_scroll_node_id,
parent_id: parent_id,
clip: ClippingRegion::from_rect(border_box),
content_rect: Rect::zero(),
root_type: ScrollRootType::StickyFrame(sticky_frame_info),
node_type: ClipScrollNodeType::StickyFrame(sticky_frame_info),
},
);
let new_clip_and_scroll_info = ClipAndScrollInfo::simple(new_scroll_root_id);
let new_clip_and_scroll_info = ClipAndScrollInfo::simple(new_clip_scroll_node_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 setup_scroll_root_for_overflow(&mut self,
state: &mut DisplayListBuildState,
border_box: &Rect<Au>) {
if !self.overflow_style_may_require_scroll_root() {
fn setup_clip_scroll_node_for_overflow(&mut self,
state: &mut StackingContextCollectionState,
border_box: &Rect<Au>) {
if !self.overflow_style_may_require_clip_scroll_node() {
return;
}
@ -2633,9 +2683,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
// If we already have a scroll root for this flow, just return. This can happen
// when fragments map to more than one flow, such as in the case of table
// wrappers. We just accept the first scroll root in that case.
let new_scroll_root_id = ClipId::new(self.fragment.unique_id(IdType::OverflowClip),
state.layout_context.id.to_webrender());
if state.has_scroll_root(new_scroll_root_id) {
let new_clip_scroll_node_id = ClipId::new(self.fragment.unique_id(IdType::OverflowClip),
state.pipeline_id.to_webrender());
if state.has_clip_scroll_node(new_clip_scroll_node_id) {
return;
}
@ -2656,28 +2706,28 @@ 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.clip_and_scroll_info(state.layout_context.id).scroll_node_id;
state.add_scroll_root(
ScrollRoot {
id: new_scroll_root_id,
let parent_id = self.clip_and_scroll_info(state.pipeline_id).scroll_node_id;
state.add_clip_scroll_node(
ClipScrollNode {
id: new_clip_scroll_node_id,
parent_id: parent_id,
clip: clip,
content_rect: Rect::new(content_box.origin, content_size),
root_type: ScrollRootType::ScrollFrame(sensitivity),
node_type: ClipScrollNodeType::ScrollFrame(sensitivity),
},
);
let new_clip_and_scroll_info = ClipAndScrollInfo::simple(new_scroll_root_id);
let new_clip_and_scroll_info = ClipAndScrollInfo::simple(new_clip_scroll_node_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
/// per CSS 2.1 § 11.1.2.
fn setup_scroll_root_for_css_clip(&mut self,
state: &mut DisplayListBuildState,
preserved_state: &mut PreservedDisplayListState,
stacking_relative_border_box: &Rect<Au>) {
fn setup_clip_scroll_node_for_css_clip(&mut self,
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState,
stacking_relative_border_box: &Rect<Au>) {
// Account for `clip` per CSS 2.1 § 11.1.2.
let style_clip_rect = match self.fragment.style().get_effects().clip {
Either::First(style_clip_rect) => style_clip_rect,
@ -2704,32 +2754,33 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
// We use the node id to create scroll roots for overflow properties, so we
// use the fragment address to do the same for CSS clipping.
// TODO(mrobinson): This should be more resilient while maintaining the space
// efficiency of ScrollRootId.
let new_scroll_root_id = ClipId::new(self.fragment.unique_id(IdType::CSSClip),
state.layout_context.id.to_webrender());
// efficiency of ClipScrollNode.
let new_clip_scroll_node_id = ClipId::new(self.fragment.unique_id(IdType::CSSClip),
state.pipeline_id.to_webrender());
// If we already have a scroll root for this flow, just return. This can happen
// when fragments map to more than one flow, such as in the case of table
// wrappers. We just accept the first scroll root in that case.
if state.has_scroll_root(new_scroll_root_id) {
if state.has_clip_scroll_node(new_clip_scroll_node_id) {
return;
}
let clip_rect = Rect::new(clip_origin, clip_size);
preserved_state.push_clip(state, &clip_rect, self.positioning());
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,
let parent_id = self.clip_and_scroll_info(state.pipeline_id).scroll_node_id;
state.add_clip_scroll_node(
ClipScrollNode {
id: new_clip_scroll_node_id,
parent_id: parent_id,
clip: ClippingRegion::from_rect(&clip_rect),
content_rect: Rect::zero(), // content_rect isn't important for clips.
root_type: ScrollRootType::Clip,
node_type: ClipScrollNodeType::Clip,
},
);
let new_clip_and_scroll_info = ClipAndScrollInfo::new(new_scroll_root_id, new_scroll_root_id);
let new_clip_and_scroll_info = ClipAndScrollInfo::new(new_clip_scroll_node_id,
new_clip_scroll_node_id);
self.base.clip_and_scroll_info = Some(new_clip_and_scroll_info);
state.current_clip_and_scroll_info = new_clip_and_scroll_info;
}
@ -2737,7 +2788,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
fn create_pseudo_stacking_context_for_block(&mut self,
parent_stacking_context_id: StackingContextId,
parent_clip_and_scroll_info: ClipAndScrollInfo,
state: &mut DisplayListBuildState) {
state: &mut StackingContextCollectionState) {
let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
self.fragment.style.get_box().position != position::T::static_ {
StackingContextType::PseudoPositioned
@ -2771,7 +2822,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
fn create_real_stacking_context_for_block(&mut self,
parent_stacking_context_id: StackingContextId,
parent_clip_and_scroll_info: ClipAndScrollInfo,
state: &mut DisplayListBuildState) {
state: &mut StackingContextCollectionState) {
let scroll_policy = if self.is_fixed() {
ScrollPolicy::Fixed
} else {
@ -2804,7 +2855,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
DisplayListSection::BlockBackgroundsAndBorders
};
state.processing_scroll_root_element = self.has_scrolling_overflow();
state.processing_scrolling_overflow_element = self.has_scrolling_overflow();
// Add the box that starts the block context.
self.fragment
@ -2822,13 +2873,13 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
self.base.build_display_items_for_debugging_tint(state, self.fragment.node);
state.processing_scroll_root_element = false;
state.processing_scrolling_overflow_element = false;
}
}
pub trait InlineFlowDisplayListBuilding {
fn collect_stacking_contexts_for_inline(&mut self, state: &mut DisplayListBuildState);
fn collect_stacking_contexts_for_inline(&mut self, state: &mut StackingContextCollectionState);
fn build_display_list_for_inline_fragment_at_index(&mut self,
state: &mut DisplayListBuildState,
index: usize);
@ -2836,7 +2887,7 @@ pub trait InlineFlowDisplayListBuilding {
}
impl InlineFlowDisplayListBuilding for InlineFlow {
fn collect_stacking_contexts_for_inline(&mut self, state: &mut DisplayListBuildState) {
fn collect_stacking_contexts_for_inline(&mut self, state: &mut StackingContextCollectionState) {
self.base.stacking_context_id = state.current_stacking_context_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);