mirror of
https://github.com/servo/servo.git
synced 2025-07-03 13:33:39 +01:00
Auto merge of #18951 - mrobinson:later-id-assignment-for-clip-scroll-nodes, r=glennw,emilio
Wait as late as possible to assign ClipIds <!-- 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/18951) <!-- Reviewable:end -->
This commit is contained in:
commit
f26aa3b016
8 changed files with 365 additions and 274 deletions
|
@ -33,9 +33,8 @@ use style::values::computed::Filter;
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
use text::TextRun;
|
use text::TextRun;
|
||||||
use text::glyph::ByteIndex;
|
use text::glyph::ByteIndex;
|
||||||
use webrender_api::{self, ClipAndScrollInfo, ClipId, ColorF, GradientStop, LocalClip};
|
use webrender_api::{self, ClipId, ColorF, GradientStop, LocalClip, MixBlendMode, ScrollPolicy};
|
||||||
use webrender_api::{MixBlendMode, ScrollPolicy, ScrollSensitivity, StickyFrameInfo};
|
use webrender_api::{ScrollSensitivity, StickyFrameInfo, TransformStyle};
|
||||||
use webrender_api::TransformStyle;
|
|
||||||
|
|
||||||
pub use style::dom::OpaqueNode;
|
pub use style::dom::OpaqueNode;
|
||||||
|
|
||||||
|
@ -43,9 +42,54 @@ pub use style::dom::OpaqueNode;
|
||||||
/// items that involve a blur. This ensures that the display item boundaries include all the ink.
|
/// items that involve a blur. This ensures that the display item boundaries include all the ink.
|
||||||
pub static BLUR_INFLATION_FACTOR: i32 = 3;
|
pub static BLUR_INFLATION_FACTOR: i32 = 3;
|
||||||
|
|
||||||
|
/// An index into the vector of ClipScrollNodes. During WebRender conversion these nodes
|
||||||
|
/// are given ClipIds.
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||||
|
pub struct ClipScrollNodeIndex(pub usize);
|
||||||
|
|
||||||
|
impl ClipScrollNodeIndex {
|
||||||
|
pub fn is_root_scroll_node(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
ClipScrollNodeIndex(0) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_define_item(&self) -> DisplayItem {
|
||||||
|
DisplayItem::DefineClipScrollNode(Box::new(DefineClipScrollNodeItem {
|
||||||
|
base: BaseDisplayItem::empty(),
|
||||||
|
node_index: *self,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A set of indices into the clip scroll node vector for a given item.
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||||
|
pub struct ClippingAndScrolling {
|
||||||
|
pub scrolling: ClipScrollNodeIndex,
|
||||||
|
pub clipping: Option<ClipScrollNodeIndex>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClippingAndScrolling {
|
||||||
|
pub fn simple(scrolling: ClipScrollNodeIndex) -> ClippingAndScrolling {
|
||||||
|
ClippingAndScrolling {
|
||||||
|
scrolling,
|
||||||
|
clipping: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(scrolling: ClipScrollNodeIndex, clipping: ClipScrollNodeIndex) -> ClippingAndScrolling {
|
||||||
|
ClippingAndScrolling {
|
||||||
|
scrolling,
|
||||||
|
clipping: Some(clipping),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, MallocSizeOf, Serialize)]
|
#[derive(Deserialize, MallocSizeOf, Serialize)]
|
||||||
pub struct DisplayList {
|
pub struct DisplayList {
|
||||||
pub list: Vec<DisplayItem>,
|
pub list: Vec<DisplayItem>,
|
||||||
|
pub clip_scroll_nodes: Vec<ClipScrollNode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DisplayList {
|
impl DisplayList {
|
||||||
|
@ -84,12 +128,19 @@ impl DisplayList {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_with_tree(&self, print_tree: &mut PrintTree) {
|
pub fn print_with_tree(&self, print_tree: &mut PrintTree) {
|
||||||
|
print_tree.new_level("ClipScrollNodes".to_owned());
|
||||||
|
for node in &self.clip_scroll_nodes {
|
||||||
|
print_tree.add_item(format!("{:?}", node));
|
||||||
|
}
|
||||||
|
print_tree.end_level();
|
||||||
|
|
||||||
print_tree.new_level("Items".to_owned());
|
print_tree.new_level("Items".to_owned());
|
||||||
for item in &self.list {
|
for item in &self.list {
|
||||||
print_tree.add_item(format!("{:?} StackingContext: {:?} {:?}",
|
print_tree.add_item(format!("{:?} StackingContext: {:?} {:?}",
|
||||||
item,
|
item,
|
||||||
item.base().stacking_context_id,
|
item.base().stacking_context_id,
|
||||||
item.clip_and_scroll_info()));
|
item.clipping_and_scrolling())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
print_tree.end_level();
|
print_tree.end_level();
|
||||||
}
|
}
|
||||||
|
@ -150,7 +201,7 @@ pub struct StackingContext {
|
||||||
pub scroll_policy: ScrollPolicy,
|
pub scroll_policy: ScrollPolicy,
|
||||||
|
|
||||||
/// The clip and scroll info for this StackingContext.
|
/// The clip and scroll info for this StackingContext.
|
||||||
pub parent_clip_and_scroll_info: ClipAndScrollInfo,
|
pub parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackingContext {
|
impl StackingContext {
|
||||||
|
@ -167,27 +218,28 @@ impl StackingContext {
|
||||||
transform_style: TransformStyle,
|
transform_style: TransformStyle,
|
||||||
perspective: Option<Transform3D<f32>>,
|
perspective: Option<Transform3D<f32>>,
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
parent_clip_and_scroll_info: ClipAndScrollInfo)
|
parent_clipping_and_scrolling: ClippingAndScrolling)
|
||||||
-> StackingContext {
|
-> StackingContext {
|
||||||
StackingContext {
|
StackingContext {
|
||||||
id: id,
|
id,
|
||||||
context_type: context_type,
|
context_type,
|
||||||
bounds: *bounds,
|
bounds: *bounds,
|
||||||
overflow: *overflow,
|
overflow: *overflow,
|
||||||
z_index: z_index,
|
z_index,
|
||||||
filters: filters,
|
filters,
|
||||||
mix_blend_mode: mix_blend_mode,
|
mix_blend_mode,
|
||||||
transform: transform,
|
transform,
|
||||||
transform_style: transform_style,
|
transform_style,
|
||||||
perspective: perspective,
|
perspective,
|
||||||
scroll_policy: scroll_policy,
|
scroll_policy,
|
||||||
parent_clip_and_scroll_info: parent_clip_and_scroll_info,
|
parent_clipping_and_scrolling,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn root(pipeline_id: PipelineId) -> StackingContext {
|
pub fn root() -> StackingContext {
|
||||||
StackingContext::new(StackingContextId::root(),
|
StackingContext::new(
|
||||||
|
StackingContextId::root(),
|
||||||
StackingContextType::Real,
|
StackingContextType::Real,
|
||||||
&Rect::zero(),
|
&Rect::zero(),
|
||||||
&Rect::zero(),
|
&Rect::zero(),
|
||||||
|
@ -198,13 +250,14 @@ impl StackingContext {
|
||||||
TransformStyle::Flat,
|
TransformStyle::Flat,
|
||||||
None,
|
None,
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
pipeline_id.root_clip_and_scroll_info())
|
ClippingAndScrolling::simple(ClipScrollNodeIndex(0))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_display_list_items(self, pipeline_id: PipelineId) -> (DisplayItem, DisplayItem) {
|
pub fn to_display_list_items(self) -> (DisplayItem, DisplayItem) {
|
||||||
let mut base_item = BaseDisplayItem::empty(pipeline_id);
|
let mut base_item = BaseDisplayItem::empty();
|
||||||
base_item.stacking_context_id = self.id;
|
base_item.stacking_context_id = self.id;
|
||||||
base_item.clip_and_scroll_info = self.parent_clip_and_scroll_info;
|
base_item.clipping_and_scrolling = self.parent_clipping_and_scrolling;
|
||||||
|
|
||||||
let pop_item = DisplayItem::PopStackingContext(Box::new(
|
let pop_item = DisplayItem::PopStackingContext(Box::new(
|
||||||
PopStackingContextItem {
|
PopStackingContextItem {
|
||||||
|
@ -280,10 +333,10 @@ pub enum ClipScrollNodeType {
|
||||||
pub struct ClipScrollNode {
|
pub struct ClipScrollNode {
|
||||||
/// The WebRender clip id of this scroll root based on the source of this clip
|
/// The WebRender clip id of this scroll root based on the source of this clip
|
||||||
/// and information about the fragment.
|
/// and information about the fragment.
|
||||||
pub id: ClipId,
|
pub id: Option<ClipId>,
|
||||||
|
|
||||||
/// The unique ID of the parent of this ClipScrollNode.
|
/// The index of the parent of this ClipScrollNode.
|
||||||
pub parent_id: ClipId,
|
pub parent_index: ClipScrollNodeIndex,
|
||||||
|
|
||||||
/// The position of this scroll root's frame in the parent stacking context.
|
/// The position of this scroll root's frame in the parent stacking context.
|
||||||
pub clip: ClippingRegion,
|
pub clip: ClippingRegion,
|
||||||
|
@ -295,16 +348,6 @@ pub struct ClipScrollNode {
|
||||||
pub node_type: ClipScrollNodeType,
|
pub node_type: ClipScrollNodeType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClipScrollNode {
|
|
||||||
pub fn to_define_item(&self, pipeline_id: PipelineId) -> DisplayItem {
|
|
||||||
DisplayItem::DefineClipScrollNode(Box::new(DefineClipScrollNodeItem {
|
|
||||||
base: BaseDisplayItem::empty(pipeline_id),
|
|
||||||
node: self.clone(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// One drawing command in the list.
|
/// One drawing command in the list.
|
||||||
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
|
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
|
||||||
pub enum DisplayItem {
|
pub enum DisplayItem {
|
||||||
|
@ -343,7 +386,7 @@ pub struct BaseDisplayItem {
|
||||||
pub stacking_context_id: StackingContextId,
|
pub stacking_context_id: StackingContextId,
|
||||||
|
|
||||||
/// The clip and scroll info for this item.
|
/// The clip and scroll info for this item.
|
||||||
pub clip_and_scroll_info: ClipAndScrollInfo,
|
pub clipping_and_scrolling: ClippingAndScrolling,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseDisplayItem {
|
impl BaseDisplayItem {
|
||||||
|
@ -353,7 +396,7 @@ impl BaseDisplayItem {
|
||||||
local_clip: LocalClip,
|
local_clip: LocalClip,
|
||||||
section: DisplayListSection,
|
section: DisplayListSection,
|
||||||
stacking_context_id: StackingContextId,
|
stacking_context_id: StackingContextId,
|
||||||
clip_and_scroll_info: ClipAndScrollInfo)
|
clipping_and_scrolling: ClippingAndScrolling)
|
||||||
-> BaseDisplayItem {
|
-> BaseDisplayItem {
|
||||||
BaseDisplayItem {
|
BaseDisplayItem {
|
||||||
bounds: *bounds,
|
bounds: *bounds,
|
||||||
|
@ -361,12 +404,12 @@ impl BaseDisplayItem {
|
||||||
local_clip: local_clip,
|
local_clip: local_clip,
|
||||||
section: section,
|
section: section,
|
||||||
stacking_context_id: stacking_context_id,
|
stacking_context_id: stacking_context_id,
|
||||||
clip_and_scroll_info: clip_and_scroll_info,
|
clipping_and_scrolling: clipping_and_scrolling,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn empty(pipeline_id: PipelineId) -> BaseDisplayItem {
|
pub fn empty() -> BaseDisplayItem {
|
||||||
BaseDisplayItem {
|
BaseDisplayItem {
|
||||||
bounds: TypedRect::zero(),
|
bounds: TypedRect::zero(),
|
||||||
metadata: DisplayItemMetadata {
|
metadata: DisplayItemMetadata {
|
||||||
|
@ -376,7 +419,7 @@ impl BaseDisplayItem {
|
||||||
local_clip: LocalClip::from(max_rect().to_rectf()),
|
local_clip: LocalClip::from(max_rect().to_rectf()),
|
||||||
section: DisplayListSection::Content,
|
section: DisplayListSection::Content,
|
||||||
stacking_context_id: StackingContextId::root(),
|
stacking_context_id: StackingContextId::root(),
|
||||||
clip_and_scroll_info: pipeline_id.root_clip_and_scroll_info(),
|
clipping_and_scrolling: ClippingAndScrolling::simple(ClipScrollNodeIndex(0)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -929,7 +972,7 @@ pub struct DefineClipScrollNodeItem {
|
||||||
pub base: BaseDisplayItem,
|
pub base: BaseDisplayItem,
|
||||||
|
|
||||||
/// The scroll root that this item starts.
|
/// The scroll root that this item starts.
|
||||||
pub node: ClipScrollNode,
|
pub node_index: ClipScrollNodeIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How a box shadow should be clipped.
|
/// How a box shadow should be clipped.
|
||||||
|
@ -963,12 +1006,12 @@ impl DisplayItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scroll_node_id(&self) -> ClipId {
|
pub fn scroll_node_index(&self) -> ClipScrollNodeIndex {
|
||||||
self.base().clip_and_scroll_info.scroll_node_id
|
self.base().clipping_and_scrolling.scrolling
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clip_and_scroll_info(&self) -> ClipAndScrollInfo {
|
pub fn clipping_and_scrolling(&self) -> ClippingAndScrolling {
|
||||||
self.base().clip_and_scroll_info
|
self.base().clipping_and_scrolling
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stacking_context_id(&self) -> StackingContextId {
|
pub fn stacking_context_id(&self) -> StackingContextId {
|
||||||
|
@ -1003,7 +1046,7 @@ impl fmt::Debug for DisplayItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let DisplayItem::DefineClipScrollNode(ref item) = *self {
|
if let DisplayItem::DefineClipScrollNode(ref item) = *self {
|
||||||
return write!(f, "DefineClipScrollNode({:?}", item.node);
|
return write!(f, "DefineClipScrollNode({:?}", item.node_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "{} @ {:?} {:?}",
|
write!(f, "{} @ {:?} {:?}",
|
||||||
|
|
|
@ -14,8 +14,7 @@ use app_units::{AU_PER_PX, Au};
|
||||||
use block::{BlockFlow, BlockStackingContextType};
|
use block::{BlockFlow, BlockStackingContextType};
|
||||||
use canvas_traits::canvas::{CanvasMsg, FromLayoutMsg};
|
use canvas_traits::canvas::{CanvasMsg, FromLayoutMsg};
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, TypedSize2D};
|
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, TypedRect, TypedSize2D, Vector2D};
|
||||||
use euclid::Vector2D;
|
|
||||||
use flex::FlexFlow;
|
use flex::FlexFlow;
|
||||||
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
|
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
|
@ -25,9 +24,10 @@ use fragment::SpecificFragmentInfo;
|
||||||
use gfx::display_list;
|
use gfx::display_list;
|
||||||
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails, BorderDisplayItem};
|
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails, BorderDisplayItem};
|
||||||
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClipScrollNode};
|
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClipScrollNode};
|
||||||
use gfx::display_list::{ClipScrollNodeType, ClippingRegion, DisplayItem, DisplayItemMetadata};
|
use gfx::display_list::{ClipScrollNodeIndex, ClippingAndScrolling, ClipScrollNodeType};
|
||||||
use gfx::display_list::{DisplayList, DisplayListSection, GradientDisplayItem, IframeDisplayItem};
|
use gfx::display_list::{ClippingRegion, DisplayItem, DisplayItemMetadata, DisplayList};
|
||||||
use gfx::display_list::{ImageBorder, ImageDisplayItem, LineDisplayItem, NormalBorder, OpaqueNode};
|
use gfx::display_list::{DisplayListSection, GradientDisplayItem, IframeDisplayItem, ImageBorder};
|
||||||
|
use gfx::display_list::{ImageDisplayItem, LineDisplayItem, NormalBorder, OpaqueNode};
|
||||||
use gfx::display_list::{PopAllTextShadowsDisplayItem, PushTextShadowDisplayItem};
|
use gfx::display_list::{PopAllTextShadowsDisplayItem, PushTextShadowDisplayItem};
|
||||||
use gfx::display_list::{RadialGradientDisplayItem, SolidColorDisplayItem, StackingContext};
|
use gfx::display_list::{RadialGradientDisplayItem, SolidColorDisplayItem, StackingContext};
|
||||||
use gfx::display_list::{StackingContextType, TextDisplayItem, TextOrientation, WebRenderImageInfo};
|
use gfx::display_list::{StackingContextType, TextDisplayItem, TextOrientation, WebRenderImageInfo};
|
||||||
|
@ -71,8 +71,8 @@ use style_traits::CSSPixel;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
use table_cell::CollapsedBordersForCell;
|
use table_cell::CollapsedBordersForCell;
|
||||||
use webrender_api::{ClipAndScrollInfo, ClipId, ClipMode, ColorF, ComplexClipRegion, GradientStop};
|
use webrender_api::{ClipId, ClipMode, ColorF, ComplexClipRegion, GradientStop, LineStyle};
|
||||||
use webrender_api::{LineStyle, LocalClip, RepeatMode, ScrollPolicy, ScrollSensitivity, StickyFrameInfo};
|
use webrender_api::{LocalClip, RepeatMode, ScrollPolicy, ScrollSensitivity, StickyFrameInfo};
|
||||||
use webrender_api::StickySideConstraint;
|
use webrender_api::StickySideConstraint;
|
||||||
use webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle};
|
use webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle};
|
||||||
|
|
||||||
|
@ -146,8 +146,9 @@ pub struct InlineNodeBorderInfo {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct StackingContextInfo {
|
struct StackingContextInfo {
|
||||||
children: Vec<StackingContext>,
|
children: Vec<StackingContext>,
|
||||||
clip_scroll_nodes: Vec<ClipScrollNode>,
|
clip_scroll_nodes: Vec<ClipScrollNodeIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackingContextInfo {
|
impl StackingContextInfo {
|
||||||
fn new() -> StackingContextInfo {
|
fn new() -> StackingContextInfo {
|
||||||
StackingContextInfo {
|
StackingContextInfo {
|
||||||
|
@ -171,8 +172,7 @@ pub struct StackingContextCollectionState {
|
||||||
/// StackingContext and ClipScrollNode children for each StackingContext.
|
/// StackingContext and ClipScrollNode children for each StackingContext.
|
||||||
stacking_context_info: FnvHashMap<StackingContextId, StackingContextInfo>,
|
stacking_context_info: FnvHashMap<StackingContextId, StackingContextInfo>,
|
||||||
|
|
||||||
/// A map establishing the parent child relationship of every ClipScrollNode.
|
pub clip_scroll_nodes: Vec<ClipScrollNode>,
|
||||||
pub clip_scroll_node_parents: FnvHashMap<ClipId, ClipId>,
|
|
||||||
|
|
||||||
/// The current stacking context id, used to keep track of state when building.
|
/// The current stacking context id, used to keep track of state when building.
|
||||||
/// recursively building and processing the display list.
|
/// recursively building and processing the display list.
|
||||||
|
@ -186,12 +186,12 @@ pub struct StackingContextCollectionState {
|
||||||
|
|
||||||
/// The current clip and scroll info, 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.
|
/// recursively building and processing the display list.
|
||||||
pub current_clip_and_scroll_info: ClipAndScrollInfo,
|
pub current_clipping_and_scrolling: ClippingAndScrolling,
|
||||||
|
|
||||||
/// The clip and scroll info 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
|
/// This is necessary because absolutely positioned items should be clipped
|
||||||
/// by their containing block's scroll root.
|
/// by their containing block's scroll root.
|
||||||
pub containing_block_clip_and_scroll_info: ClipAndScrollInfo,
|
pub containing_block_clipping_and_scrolling: ClippingAndScrolling,
|
||||||
|
|
||||||
/// A stack of clips used to cull display list entries that are outside the
|
/// A stack of clips used to cull display list entries that are outside the
|
||||||
/// rendered region.
|
/// rendered region.
|
||||||
|
@ -207,17 +207,28 @@ pub struct StackingContextCollectionState {
|
||||||
|
|
||||||
impl StackingContextCollectionState {
|
impl StackingContextCollectionState {
|
||||||
pub fn new(pipeline_id: PipelineId) -> StackingContextCollectionState {
|
pub fn new(pipeline_id: PipelineId) -> StackingContextCollectionState {
|
||||||
let root_clip_info = ClipAndScrollInfo::simple(pipeline_id.root_scroll_node());
|
let root_clip_indices = ClippingAndScrolling::simple(ClipScrollNodeIndex(0));
|
||||||
|
|
||||||
|
// This is just a dummy node to take up a slot in the array. WebRender
|
||||||
|
// takes care of adding this root node and it can be ignored during DL conversion.
|
||||||
|
let root_node = ClipScrollNode {
|
||||||
|
id: Some(ClipId::root_scroll_node(pipeline_id.to_webrender())),
|
||||||
|
parent_index: ClipScrollNodeIndex(0),
|
||||||
|
clip: ClippingRegion::from_rect(&TypedRect::zero()),
|
||||||
|
content_rect: Rect::zero(),
|
||||||
|
node_type: ClipScrollNodeType::ScrollFrame(ScrollSensitivity::ScriptAndInputEvents),
|
||||||
|
};
|
||||||
|
|
||||||
StackingContextCollectionState {
|
StackingContextCollectionState {
|
||||||
pipeline_id: pipeline_id,
|
pipeline_id: pipeline_id,
|
||||||
root_stacking_context: StackingContext::root(pipeline_id),
|
root_stacking_context: StackingContext::root(),
|
||||||
stacking_context_info: FnvHashMap::default(),
|
stacking_context_info: FnvHashMap::default(),
|
||||||
clip_scroll_node_parents: FnvHashMap::default(),
|
clip_scroll_nodes: vec![root_node],
|
||||||
current_stacking_context_id: StackingContextId::root(),
|
current_stacking_context_id: StackingContextId::root(),
|
||||||
current_real_stacking_context_id: StackingContextId::root(),
|
current_real_stacking_context_id: StackingContextId::root(),
|
||||||
next_stacking_context_id: StackingContextId::root().next(),
|
next_stacking_context_id: StackingContextId::root().next(),
|
||||||
current_clip_and_scroll_info: root_clip_info,
|
current_clipping_and_scrolling: root_clip_indices,
|
||||||
containing_block_clip_and_scroll_info: root_clip_info,
|
containing_block_clipping_and_scrolling: root_clip_indices,
|
||||||
clip_stack: Vec::new(),
|
clip_stack: Vec::new(),
|
||||||
containing_block_clip_stack: Vec::new(),
|
containing_block_clip_stack: Vec::new(),
|
||||||
parent_stacking_relative_content_box: Rect::zero(),
|
parent_stacking_relative_content_box: Rect::zero(),
|
||||||
|
@ -238,20 +249,18 @@ impl StackingContextCollectionState {
|
||||||
info.children.push(stacking_context);
|
info.children.push(stacking_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_clip_scroll_node(&mut self, id: ClipId) -> bool {
|
fn add_clip_scroll_node(&mut self, clip_scroll_node: ClipScrollNode) -> ClipScrollNodeIndex {
|
||||||
self.clip_scroll_node_parents.contains_key(&id)
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
// 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)
|
// 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
|
// stacking context. This ensures that item reordering will not result in an item using
|
||||||
// the scroll root before it is defined.
|
// the scroll root before it is defined.
|
||||||
self.clip_scroll_node_parents.insert(clip_scroll_node.id, clip_scroll_node.parent_id);
|
self.clip_scroll_nodes.push(clip_scroll_node);
|
||||||
|
let index = ClipScrollNodeIndex(self.clip_scroll_nodes.len() - 1);
|
||||||
let info = self.stacking_context_info
|
let info = self.stacking_context_info
|
||||||
.entry(self.current_real_stacking_context_id)
|
.entry(self.current_real_stacking_context_id)
|
||||||
.or_insert(StackingContextInfo::new());
|
.or_insert(StackingContextInfo::new());
|
||||||
info.clip_scroll_nodes.push(clip_scroll_node);
|
info.clip_scroll_nodes.push(index);
|
||||||
|
index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,8 +274,8 @@ pub struct DisplayListBuildState<'a> {
|
||||||
/// StackingContext and ClipScrollNode children for each StackingContext.
|
/// StackingContext and ClipScrollNode children for each StackingContext.
|
||||||
stacking_context_info: FnvHashMap<StackingContextId, StackingContextInfo>,
|
stacking_context_info: FnvHashMap<StackingContextId, StackingContextInfo>,
|
||||||
|
|
||||||
/// A map establishing the parent child relationship of every ClipScrollNode.
|
/// A vector of ClipScrollNodes which will be given ids during WebRender DL conversion.
|
||||||
pub clip_scroll_node_parents: FnvHashMap<ClipId, ClipId>,
|
pub clip_scroll_nodes: Vec<ClipScrollNode>,
|
||||||
|
|
||||||
/// The items in this display list.
|
/// The items in this display list.
|
||||||
pub items: FnvHashMap<StackingContextId, Vec<DisplayItem>>,
|
pub items: FnvHashMap<StackingContextId, Vec<DisplayItem>>,
|
||||||
|
@ -281,7 +290,7 @@ pub struct DisplayListBuildState<'a> {
|
||||||
|
|
||||||
/// The current clip and scroll info, 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.
|
/// recursively building and processing the display list.
|
||||||
pub current_clip_and_scroll_info: ClipAndScrollInfo,
|
pub current_clipping_and_scrolling: ClippingAndScrolling,
|
||||||
|
|
||||||
/// Vector containing iframe sizes, used to inform the constellation about
|
/// Vector containing iframe sizes, used to inform the constellation about
|
||||||
/// new iframe sizes
|
/// new iframe sizes
|
||||||
|
@ -292,16 +301,16 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
pub fn new(layout_context: &'a LayoutContext,
|
pub fn new(layout_context: &'a LayoutContext,
|
||||||
state: StackingContextCollectionState)
|
state: StackingContextCollectionState)
|
||||||
-> DisplayListBuildState<'a> {
|
-> DisplayListBuildState<'a> {
|
||||||
let root_clip_info = ClipAndScrollInfo::simple(layout_context.id.root_scroll_node());
|
let root_clip_indices = ClippingAndScrolling::simple(ClipScrollNodeIndex(0));
|
||||||
DisplayListBuildState {
|
DisplayListBuildState {
|
||||||
layout_context: layout_context,
|
layout_context: layout_context,
|
||||||
root_stacking_context: state.root_stacking_context,
|
root_stacking_context: state.root_stacking_context,
|
||||||
items: FnvHashMap::default(),
|
items: FnvHashMap::default(),
|
||||||
stacking_context_info: state.stacking_context_info,
|
stacking_context_info: state.stacking_context_info,
|
||||||
clip_scroll_node_parents: state.clip_scroll_node_parents,
|
clip_scroll_nodes: state.clip_scroll_nodes,
|
||||||
processing_scrolling_overflow_element: false,
|
processing_scrolling_overflow_element: false,
|
||||||
current_stacking_context_id: StackingContextId::root(),
|
current_stacking_context_id: StackingContextId::root(),
|
||||||
current_clip_and_scroll_info: root_clip_info,
|
current_clipping_and_scrolling: root_clip_indices,
|
||||||
iframe_sizes: Vec::new(),
|
iframe_sizes: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,13 +320,12 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
items.push(display_item);
|
items.push(display_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parent_clip_scroll_node_id(&self, clip_scroll_node_id: ClipId) -> ClipId {
|
fn parent_clip_scroll_node_index(&self, index: ClipScrollNodeIndex) -> ClipScrollNodeIndex {
|
||||||
if clip_scroll_node_id.is_root_scroll_node() {
|
if index.is_root_scroll_node() {
|
||||||
return clip_scroll_node_id;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(self.clip_scroll_node_parents.contains_key(&clip_scroll_node_id));
|
self.clip_scroll_nodes[index.0].parent_index
|
||||||
*self.clip_scroll_node_parents.get(&clip_scroll_node_id).unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_background_or_border_of_clip_scroll_node(&self, section: DisplayListSection) -> bool {
|
fn is_background_or_border_of_clip_scroll_node(&self, section: DisplayListSection) -> bool {
|
||||||
|
@ -333,10 +341,11 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
cursor: Option<Cursor>,
|
cursor: Option<Cursor>,
|
||||||
section: DisplayListSection)
|
section: DisplayListSection)
|
||||||
-> BaseDisplayItem {
|
-> BaseDisplayItem {
|
||||||
let clip_and_scroll_info = if self.is_background_or_border_of_clip_scroll_node(section) {
|
let clipping_and_scrolling = 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))
|
ClippingAndScrolling::simple(
|
||||||
|
self.parent_clip_scroll_node_index(self.current_clipping_and_scrolling.scrolling))
|
||||||
} else {
|
} else {
|
||||||
self.current_clip_and_scroll_info
|
self.current_clipping_and_scrolling
|
||||||
};
|
};
|
||||||
|
|
||||||
BaseDisplayItem::new(&bounds,
|
BaseDisplayItem::new(&bounds,
|
||||||
|
@ -347,18 +356,18 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
clip,
|
clip,
|
||||||
section,
|
section,
|
||||||
self.current_stacking_context_id,
|
self.current_stacking_context_id,
|
||||||
clip_and_scroll_info)
|
clipping_and_scrolling)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_display_list(mut self) -> DisplayList {
|
pub fn to_display_list(mut self) -> DisplayList {
|
||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
let root_context = mem::replace(&mut self.root_stacking_context,
|
let root_context = mem::replace(&mut self.root_stacking_context, StackingContext::root());
|
||||||
StackingContext::root(self.layout_context.id));
|
|
||||||
|
|
||||||
self.to_display_list_for_stacking_context(&mut list, root_context);
|
self.to_display_list_for_stacking_context(&mut list, root_context);
|
||||||
|
|
||||||
DisplayList {
|
DisplayList {
|
||||||
list: list,
|
list: list,
|
||||||
|
clip_scroll_nodes: self.clip_scroll_nodes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,14 +383,13 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
|
|
||||||
info.children.sort();
|
info.children.sort();
|
||||||
|
|
||||||
let pipeline_id = self.layout_context.id;
|
|
||||||
if stacking_context.context_type != StackingContextType::Real {
|
if stacking_context.context_type != StackingContextType::Real {
|
||||||
list.extend(info.clip_scroll_nodes.into_iter().map(|root| root.to_define_item(pipeline_id)));
|
list.extend(info.clip_scroll_nodes.into_iter().map(|index| index.to_define_item()));
|
||||||
self.to_display_list_for_items(list, child_items, info.children);
|
self.to_display_list_for_items(list, child_items, info.children);
|
||||||
} else {
|
} else {
|
||||||
let (push_item, pop_item) = stacking_context.to_display_list_items(pipeline_id);
|
let (push_item, pop_item) = stacking_context.to_display_list_items();
|
||||||
list.push(push_item);
|
list.push(push_item);
|
||||||
list.extend(info.clip_scroll_nodes.into_iter().map(|root| root.to_define_item(pipeline_id)));
|
list.extend(info.clip_scroll_nodes.into_iter().map(|index| index.to_define_item()));
|
||||||
self.to_display_list_for_items(list, child_items, info.children);
|
self.to_display_list_for_items(list, child_items, info.children);
|
||||||
list.push(pop_item);
|
list.push(pop_item);
|
||||||
}
|
}
|
||||||
|
@ -612,13 +620,14 @@ pub trait FragmentDisplayListBuilding {
|
||||||
clip: &Rect<Au>);
|
clip: &Rect<Au>);
|
||||||
|
|
||||||
/// Creates a stacking context for associated fragment.
|
/// Creates a stacking context for associated fragment.
|
||||||
fn create_stacking_context(&self,
|
fn create_stacking_context(
|
||||||
|
&self,
|
||||||
id: StackingContextId,
|
id: StackingContextId,
|
||||||
base_flow: &BaseFlow,
|
base_flow: &BaseFlow,
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
context_type: StackingContextType,
|
context_type: StackingContextType,
|
||||||
parent_clip_and_scroll_info: ClipAndScrollInfo)
|
parent_clipping_and_scrolling: ClippingAndScrolling
|
||||||
-> StackingContext;
|
) -> StackingContext;
|
||||||
|
|
||||||
fn unique_id(&self, id_type: IdType) -> u64;
|
fn unique_id(&self, id_type: IdType) -> u64;
|
||||||
|
|
||||||
|
@ -2175,13 +2184,14 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_stacking_context(&self,
|
fn create_stacking_context(
|
||||||
|
&self,
|
||||||
id: StackingContextId,
|
id: StackingContextId,
|
||||||
base_flow: &BaseFlow,
|
base_flow: &BaseFlow,
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
context_type: StackingContextType,
|
context_type: StackingContextType,
|
||||||
parent_clip_and_scroll_info: ClipAndScrollInfo)
|
parent_clipping_and_scrolling: ClippingAndScrolling
|
||||||
-> StackingContext {
|
) -> StackingContext {
|
||||||
let border_box =
|
let border_box =
|
||||||
self.stacking_relative_border_box(&base_flow.stacking_relative_position,
|
self.stacking_relative_border_box(&base_flow.stacking_relative_position,
|
||||||
&base_flow.early_absolute_position_info
|
&base_flow.early_absolute_position_info
|
||||||
|
@ -2203,7 +2213,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
filters.push(Filter::Opacity(effects.opacity.into()))
|
filters.push(Filter::Opacity(effects.opacity.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
StackingContext::new(id,
|
StackingContext::new(
|
||||||
|
id,
|
||||||
context_type,
|
context_type,
|
||||||
&border_box,
|
&border_box,
|
||||||
&overflow,
|
&overflow,
|
||||||
|
@ -2214,7 +2225,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
self.style().get_used_transform_style().to_transform_style(),
|
self.style().get_used_transform_style().to_transform_style(),
|
||||||
self.perspective_matrix(&border_box),
|
self.perspective_matrix(&border_box),
|
||||||
scroll_policy,
|
scroll_policy,
|
||||||
parent_clip_and_scroll_info)
|
parent_clipping_and_scrolling
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list_for_text_fragment(&self,
|
fn build_display_list_for_text_fragment(&self,
|
||||||
|
@ -2417,7 +2429,7 @@ pub trait BlockFlowDisplayListBuilding {
|
||||||
preserved_state: &mut SavedStackingContextCollectionState,
|
preserved_state: &mut SavedStackingContextCollectionState,
|
||||||
stacking_context_type: BlockStackingContextType,
|
stacking_context_type: BlockStackingContextType,
|
||||||
flags: StackingContextCollectionFlags)
|
flags: StackingContextCollectionFlags)
|
||||||
-> ClipAndScrollInfo;
|
-> ClippingAndScrolling;
|
||||||
fn setup_clip_scroll_node_for_position(&mut self,
|
fn setup_clip_scroll_node_for_position(&mut self,
|
||||||
state: &mut StackingContextCollectionState,
|
state: &mut StackingContextCollectionState,
|
||||||
border_box: &Rect<Au>);
|
border_box: &Rect<Au>);
|
||||||
|
@ -2428,14 +2440,18 @@ pub trait BlockFlowDisplayListBuilding {
|
||||||
state: &mut StackingContextCollectionState,
|
state: &mut StackingContextCollectionState,
|
||||||
preserved_state: &mut SavedStackingContextCollectionState,
|
preserved_state: &mut SavedStackingContextCollectionState,
|
||||||
stacking_relative_border_box: &Rect<Au>);
|
stacking_relative_border_box: &Rect<Au>);
|
||||||
fn create_pseudo_stacking_context_for_block(&mut self,
|
fn create_pseudo_stacking_context_for_block(
|
||||||
|
&mut self,
|
||||||
parent_stacking_context_id: StackingContextId,
|
parent_stacking_context_id: StackingContextId,
|
||||||
parent_clip_and_scroll_info: ClipAndScrollInfo,
|
parent_clip_and_scroll_info: ClippingAndScrolling,
|
||||||
state: &mut StackingContextCollectionState);
|
state: &mut StackingContextCollectionState
|
||||||
fn create_real_stacking_context_for_block(&mut self,
|
);
|
||||||
|
fn create_real_stacking_context_for_block(
|
||||||
|
&mut self,
|
||||||
parent_stacking_context_id: StackingContextId,
|
parent_stacking_context_id: StackingContextId,
|
||||||
parent_clip_and_scroll_info: ClipAndScrollInfo,
|
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||||
state: &mut StackingContextCollectionState);
|
state: &mut StackingContextCollectionState
|
||||||
|
);
|
||||||
fn build_display_list_for_block(&mut self,
|
fn build_display_list_for_block(&mut self,
|
||||||
state: &mut DisplayListBuildState,
|
state: &mut DisplayListBuildState,
|
||||||
border_painting_mode: BorderPaintingMode);
|
border_painting_mode: BorderPaintingMode);
|
||||||
|
@ -2454,8 +2470,8 @@ pub trait BlockFlowDisplayListBuilding {
|
||||||
pub struct SavedStackingContextCollectionState {
|
pub struct SavedStackingContextCollectionState {
|
||||||
stacking_context_id: StackingContextId,
|
stacking_context_id: StackingContextId,
|
||||||
real_stacking_context_id: StackingContextId,
|
real_stacking_context_id: StackingContextId,
|
||||||
clip_and_scroll_info: ClipAndScrollInfo,
|
clipping_and_scrolling: ClippingAndScrolling,
|
||||||
containing_block_clip_and_scroll_info: ClipAndScrollInfo,
|
containing_block_clipping_and_scrolling: ClippingAndScrolling,
|
||||||
clips_pushed: usize,
|
clips_pushed: usize,
|
||||||
containing_block_clips_pushed: usize,
|
containing_block_clips_pushed: usize,
|
||||||
stacking_relative_content_box: Rect<Au>,
|
stacking_relative_content_box: Rect<Au>,
|
||||||
|
@ -2466,8 +2482,8 @@ impl SavedStackingContextCollectionState {
|
||||||
SavedStackingContextCollectionState {
|
SavedStackingContextCollectionState {
|
||||||
stacking_context_id: state.current_stacking_context_id,
|
stacking_context_id: state.current_stacking_context_id,
|
||||||
real_stacking_context_id: state.current_real_stacking_context_id,
|
real_stacking_context_id: state.current_real_stacking_context_id,
|
||||||
clip_and_scroll_info: state.current_clip_and_scroll_info,
|
clipping_and_scrolling: state.current_clipping_and_scrolling,
|
||||||
containing_block_clip_and_scroll_info: state.containing_block_clip_and_scroll_info,
|
containing_block_clipping_and_scrolling: state.containing_block_clipping_and_scrolling,
|
||||||
clips_pushed: 0,
|
clips_pushed: 0,
|
||||||
containing_block_clips_pushed: 0,
|
containing_block_clips_pushed: 0,
|
||||||
stacking_relative_content_box: state.parent_stacking_relative_content_box,
|
stacking_relative_content_box: state.parent_stacking_relative_content_box,
|
||||||
|
@ -2483,8 +2499,8 @@ impl SavedStackingContextCollectionState {
|
||||||
fn restore(self, state: &mut StackingContextCollectionState) {
|
fn restore(self, state: &mut StackingContextCollectionState) {
|
||||||
state.current_stacking_context_id = self.stacking_context_id;
|
state.current_stacking_context_id = self.stacking_context_id;
|
||||||
state.current_real_stacking_context_id = self.real_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;
|
state.current_clipping_and_scrolling = self.clipping_and_scrolling;
|
||||||
state.containing_block_clip_and_scroll_info = self.containing_block_clip_and_scroll_info;
|
state.containing_block_clipping_and_scrolling = self.containing_block_clipping_and_scrolling;
|
||||||
state.parent_stacking_relative_content_box = self.stacking_relative_content_box;
|
state.parent_stacking_relative_content_box = self.stacking_relative_content_box;
|
||||||
|
|
||||||
let truncate_length = state.clip_stack.len() - self.clips_pushed;
|
let truncate_length = state.clip_stack.len() - self.clips_pushed;
|
||||||
|
@ -2594,17 +2610,17 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are getting the id of the scroll root that contains us here, not the id of
|
// 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
|
// any scroll root that we create. If we create a scroll root, its index will be
|
||||||
// stored in state.current_clip_and_scroll_info. If we create a stacking context,
|
// stored in state.current_clipping_and_scrolling. If we create a stacking context,
|
||||||
// we don't want it to be contained by its own scroll root.
|
// we don't want it to be contained by its own scroll root.
|
||||||
let containing_clip_and_scroll_info =
|
let containing_clipping_and_scrolling =
|
||||||
self.setup_clipping_for_block(state,
|
self.setup_clipping_for_block(state,
|
||||||
&mut preserved_state,
|
&mut preserved_state,
|
||||||
block_stacking_context_type,
|
block_stacking_context_type,
|
||||||
flags);
|
flags);
|
||||||
|
|
||||||
if establishes_containing_block_for_absolute(flags, self.positioning()) {
|
if establishes_containing_block_for_absolute(flags, self.positioning()) {
|
||||||
state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info;
|
state.containing_block_clipping_and_scrolling = state.current_clipping_and_scrolling;
|
||||||
}
|
}
|
||||||
|
|
||||||
match block_stacking_context_type {
|
match block_stacking_context_type {
|
||||||
|
@ -2612,14 +2628,18 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
self.base.collect_stacking_contexts_for_children(state);
|
self.base.collect_stacking_contexts_for_children(state);
|
||||||
}
|
}
|
||||||
BlockStackingContextType::PseudoStackingContext => {
|
BlockStackingContextType::PseudoStackingContext => {
|
||||||
self.create_pseudo_stacking_context_for_block(preserved_state.stacking_context_id,
|
self.create_pseudo_stacking_context_for_block(
|
||||||
containing_clip_and_scroll_info,
|
preserved_state.stacking_context_id,
|
||||||
state);
|
containing_clipping_and_scrolling,
|
||||||
|
state
|
||||||
|
);
|
||||||
}
|
}
|
||||||
BlockStackingContextType::StackingContext => {
|
BlockStackingContextType::StackingContext => {
|
||||||
self.create_real_stacking_context_for_block(preserved_state.stacking_context_id,
|
self.create_real_stacking_context_for_block(
|
||||||
containing_clip_and_scroll_info,
|
preserved_state.stacking_context_id,
|
||||||
state);
|
containing_clipping_and_scrolling,
|
||||||
|
state
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2631,22 +2651,22 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
preserved_state: &mut SavedStackingContextCollectionState,
|
preserved_state: &mut SavedStackingContextCollectionState,
|
||||||
stacking_context_type: BlockStackingContextType,
|
stacking_context_type: BlockStackingContextType,
|
||||||
flags: StackingContextCollectionFlags)
|
flags: StackingContextCollectionFlags)
|
||||||
-> ClipAndScrollInfo {
|
-> ClippingAndScrolling {
|
||||||
// If this block is absolutely positioned, we should be clipped and positioned by
|
// 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.
|
// the scroll root of our nearest ancestor that establishes a containing block.
|
||||||
let containing_clip_and_scroll_info = match self.positioning() {
|
let containing_clipping_and_scrolling = match self.positioning() {
|
||||||
position::T::absolute => {
|
position::T::absolute => {
|
||||||
preserved_state.switch_to_containing_block_clip(state);
|
preserved_state.switch_to_containing_block_clip(state);
|
||||||
state.current_clip_and_scroll_info = state.containing_block_clip_and_scroll_info;
|
state.current_clipping_and_scrolling = state.containing_block_clipping_and_scrolling;
|
||||||
state.containing_block_clip_and_scroll_info
|
state.containing_block_clipping_and_scrolling
|
||||||
}
|
}
|
||||||
position::T::fixed => {
|
position::T::fixed => {
|
||||||
preserved_state.push_clip(state, &max_rect(), position::T::fixed);
|
preserved_state.push_clip(state, &max_rect(), position::T::fixed);
|
||||||
state.current_clip_and_scroll_info
|
state.current_clipping_and_scrolling
|
||||||
}
|
}
|
||||||
_ => state.current_clip_and_scroll_info,
|
_ => state.current_clipping_and_scrolling,
|
||||||
};
|
};
|
||||||
self.base.clip_and_scroll_info = Some(containing_clip_and_scroll_info);
|
self.base.clipping_and_scrolling = Some(containing_clipping_and_scrolling);
|
||||||
|
|
||||||
let stacking_relative_border_box = if self.fragment.establishes_stacking_context() {
|
let stacking_relative_border_box = if self.fragment.establishes_stacking_context() {
|
||||||
self.stacking_relative_border_box(CoordinateSystem::Own)
|
self.stacking_relative_border_box(CoordinateSystem::Own)
|
||||||
|
@ -2680,11 +2700,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
|
|
||||||
match self.positioning() {
|
match self.positioning() {
|
||||||
position::T::absolute | position::T::relative | position::T::fixed =>
|
position::T::absolute | position::T::relative | position::T::fixed =>
|
||||||
state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info,
|
state.containing_block_clipping_and_scrolling = state.current_clipping_and_scrolling,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
containing_clip_and_scroll_info
|
containing_clipping_and_scrolling
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_clip_scroll_node_for_position(&mut self,
|
fn setup_clip_scroll_node_for_position(&mut self,
|
||||||
|
@ -2735,25 +2755,19 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
to_sticky_info(sticky_position.left,
|
to_sticky_info(sticky_position.left,
|
||||||
to_max_offset(constraint_rect.max_x(), border_box_in_parent.max_x())));
|
to_max_offset(constraint_rect.max_x(), border_box_in_parent.max_x())));
|
||||||
|
|
||||||
let new_clip_scroll_node_id = ClipId::new(self.fragment.unique_id(IdType::OverflowClip),
|
let new_clip_scroll_index = state.add_clip_scroll_node(
|
||||||
state.pipeline_id.to_webrender());
|
|
||||||
if state.has_clip_scroll_node(new_clip_scroll_node_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let parent_id = self.clip_and_scroll_info(state.pipeline_id).scroll_node_id;
|
|
||||||
state.add_clip_scroll_node(
|
|
||||||
ClipScrollNode {
|
ClipScrollNode {
|
||||||
id: new_clip_scroll_node_id,
|
id: None,
|
||||||
parent_id: parent_id,
|
parent_index: self.clipping_and_scrolling().scrolling,
|
||||||
clip: ClippingRegion::from_rect(border_box),
|
clip: ClippingRegion::from_rect(border_box),
|
||||||
content_rect: Rect::zero(),
|
content_rect: Rect::zero(),
|
||||||
node_type: ClipScrollNodeType::StickyFrame(sticky_frame_info),
|
node_type: ClipScrollNodeType::StickyFrame(sticky_frame_info),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let new_clip_and_scroll_info = ClipAndScrollInfo::simple(new_clip_scroll_node_id);
|
let new_clipping_and_scrolling = ClippingAndScrolling::simple(new_clip_scroll_index);
|
||||||
self.base.clip_and_scroll_info = Some(new_clip_and_scroll_info);
|
self.base.clipping_and_scrolling = Some(new_clipping_and_scrolling);
|
||||||
state.current_clip_and_scroll_info = new_clip_and_scroll_info;
|
state.current_clipping_and_scrolling = new_clipping_and_scrolling;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_clip_scroll_node_for_overflow(&mut self,
|
fn setup_clip_scroll_node_for_overflow(&mut self,
|
||||||
|
@ -2781,9 +2795,6 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
// wrappers. We just accept the first scroll root in that case.
|
// wrappers. We just accept the first scroll root in that case.
|
||||||
let new_clip_scroll_node_id = ClipId::new(self.fragment.unique_id(IdType::OverflowClip),
|
let new_clip_scroll_node_id = ClipId::new(self.fragment.unique_id(IdType::OverflowClip),
|
||||||
state.pipeline_id.to_webrender());
|
state.pipeline_id.to_webrender());
|
||||||
if state.has_clip_scroll_node(new_clip_scroll_node_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sensitivity = if overflow_x::T::hidden == self.fragment.style.get_box().overflow_x &&
|
let sensitivity = if overflow_x::T::hidden == self.fragment.style.get_box().overflow_x &&
|
||||||
overflow_x::T::hidden == self.fragment.style.get_box().overflow_y {
|
overflow_x::T::hidden == self.fragment.style.get_box().overflow_y {
|
||||||
|
@ -2802,20 +2813,19 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
let content_size = self.base.overflow.scroll.origin + self.base.overflow.scroll.size;
|
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 content_size = Size2D::new(content_size.x, content_size.y);
|
||||||
|
|
||||||
let parent_id = self.clip_and_scroll_info(state.pipeline_id).scroll_node_id;
|
let new_clip_scroll_index = state.add_clip_scroll_node(
|
||||||
state.add_clip_scroll_node(
|
|
||||||
ClipScrollNode {
|
ClipScrollNode {
|
||||||
id: new_clip_scroll_node_id,
|
id: Some(new_clip_scroll_node_id),
|
||||||
parent_id: parent_id,
|
parent_index: self.clipping_and_scrolling().scrolling,
|
||||||
clip: clip,
|
clip: clip,
|
||||||
content_rect: Rect::new(content_box.origin, content_size),
|
content_rect: Rect::new(content_box.origin, content_size),
|
||||||
node_type: ClipScrollNodeType::ScrollFrame(sensitivity),
|
node_type: ClipScrollNodeType::ScrollFrame(sensitivity),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let new_clip_and_scroll_info = ClipAndScrollInfo::simple(new_clip_scroll_node_id);
|
let new_clipping_and_scrolling = ClippingAndScrolling::simple(new_clip_scroll_index);
|
||||||
self.base.clip_and_scroll_info = Some(new_clip_and_scroll_info);
|
self.base.clipping_and_scrolling = Some(new_clipping_and_scrolling);
|
||||||
state.current_clip_and_scroll_info = new_clip_and_scroll_info;
|
state.current_clipping_and_scrolling = new_clipping_and_scrolling;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a scroll root for a block to take the `clip` property into account
|
/// Adds a scroll root for a block to take the `clip` property into account
|
||||||
|
@ -2847,44 +2857,30 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
.unwrap_or(stacking_relative_border_box.size.height);
|
.unwrap_or(stacking_relative_border_box.size.height);
|
||||||
let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
|
let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
|
||||||
|
|
||||||
// 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 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_clip_scroll_node(new_clip_scroll_node_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let clip_rect = Rect::new(clip_origin, clip_size);
|
let clip_rect = Rect::new(clip_origin, clip_size);
|
||||||
preserved_state.push_clip(state, &clip_rect, self.positioning());
|
preserved_state.push_clip(state, &clip_rect, self.positioning());
|
||||||
|
|
||||||
let parent_id = self.clip_and_scroll_info(state.pipeline_id).scroll_node_id;
|
let new_index = state.add_clip_scroll_node(
|
||||||
state.add_clip_scroll_node(
|
|
||||||
ClipScrollNode {
|
ClipScrollNode {
|
||||||
id: new_clip_scroll_node_id,
|
id: None,
|
||||||
parent_id: parent_id,
|
parent_index: self.clipping_and_scrolling().scrolling,
|
||||||
clip: ClippingRegion::from_rect(&clip_rect),
|
clip: ClippingRegion::from_rect(&clip_rect),
|
||||||
content_rect: Rect::zero(), // content_rect isn't important for clips.
|
content_rect: Rect::zero(), // content_rect isn't important for clips.
|
||||||
node_type: ClipScrollNodeType::Clip,
|
node_type: ClipScrollNodeType::Clip,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let new_clip_and_scroll_info = ClipAndScrollInfo::new(new_clip_scroll_node_id,
|
let new_indices = ClippingAndScrolling::new(new_index, new_index);
|
||||||
new_clip_scroll_node_id);
|
self.base.clipping_and_scrolling = Some(new_indices);
|
||||||
self.base.clip_and_scroll_info = Some(new_clip_and_scroll_info);
|
state.current_clipping_and_scrolling = new_indices;
|
||||||
state.current_clip_and_scroll_info = new_clip_and_scroll_info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_pseudo_stacking_context_for_block(&mut self,
|
fn create_pseudo_stacking_context_for_block(
|
||||||
|
&mut self,
|
||||||
parent_stacking_context_id: StackingContextId,
|
parent_stacking_context_id: StackingContextId,
|
||||||
parent_clip_and_scroll_info: ClipAndScrollInfo,
|
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||||
state: &mut StackingContextCollectionState) {
|
state: &mut StackingContextCollectionState
|
||||||
|
) {
|
||||||
let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
|
let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
|
||||||
self.fragment.style.get_box().position != position::T::static_ {
|
self.fragment.style.get_box().position != position::T::static_ {
|
||||||
StackingContextType::PseudoPositioned
|
StackingContextType::PseudoPositioned
|
||||||
|
@ -2897,7 +2893,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
&self.base,
|
&self.base,
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
creation_mode,
|
creation_mode,
|
||||||
parent_clip_and_scroll_info);
|
parent_clipping_and_scrolling);
|
||||||
state.add_stacking_context(parent_stacking_context_id, new_context);
|
state.add_stacking_context(parent_stacking_context_id, new_context);
|
||||||
|
|
||||||
self.base.collect_stacking_contexts_for_children(state);
|
self.base.collect_stacking_contexts_for_children(state);
|
||||||
|
@ -2915,10 +2911,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_real_stacking_context_for_block(&mut self,
|
fn create_real_stacking_context_for_block(
|
||||||
|
&mut self,
|
||||||
parent_stacking_context_id: StackingContextId,
|
parent_stacking_context_id: StackingContextId,
|
||||||
parent_clip_and_scroll_info: ClipAndScrollInfo,
|
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||||
state: &mut StackingContextCollectionState) {
|
state: &mut StackingContextCollectionState
|
||||||
|
) {
|
||||||
let scroll_policy = if self.is_fixed() {
|
let scroll_policy = if self.is_fixed() {
|
||||||
ScrollPolicy::Fixed
|
ScrollPolicy::Fixed
|
||||||
} else {
|
} else {
|
||||||
|
@ -2930,7 +2928,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
&self.base,
|
&self.base,
|
||||||
scroll_policy,
|
scroll_policy,
|
||||||
StackingContextType::Real,
|
StackingContextType::Real,
|
||||||
parent_clip_and_scroll_info);
|
parent_clipping_and_scrolling
|
||||||
|
);
|
||||||
|
|
||||||
state.add_stacking_context(parent_stacking_context_id, stacking_context);
|
state.add_stacking_context(parent_stacking_context_id, stacking_context);
|
||||||
self.base.collect_stacking_contexts_for_children(state);
|
self.base.collect_stacking_contexts_for_children(state);
|
||||||
|
@ -3012,14 +3011,14 @@ pub trait InlineFlowDisplayListBuilding {
|
||||||
impl InlineFlowDisplayListBuilding for InlineFlow {
|
impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
fn collect_stacking_contexts_for_inline(&mut self, state: &mut StackingContextCollectionState) {
|
fn collect_stacking_contexts_for_inline(&mut self, state: &mut StackingContextCollectionState) {
|
||||||
self.base.stacking_context_id = state.current_stacking_context_id;
|
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.clipping_and_scrolling = Some(state.current_clipping_and_scrolling);
|
||||||
self.base.clip = state.clip_stack.last().cloned().unwrap_or_else(max_rect);
|
self.base.clip = state.clip_stack.last().cloned().unwrap_or_else(max_rect);
|
||||||
|
|
||||||
for fragment in self.fragments.fragments.iter_mut() {
|
for fragment in self.fragments.fragments.iter_mut() {
|
||||||
let previous_cb_clip_scroll_info = state.containing_block_clip_and_scroll_info;
|
let previous_cb_clipping_and_scrolling = state.containing_block_clipping_and_scrolling;
|
||||||
if establishes_containing_block_for_absolute(StackingContextCollectionFlags::empty(),
|
if establishes_containing_block_for_absolute(StackingContextCollectionFlags::empty(),
|
||||||
fragment.style.get_box().position) {
|
fragment.style.get_box().position) {
|
||||||
state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info;
|
state.containing_block_clipping_and_scrolling = state.current_clipping_and_scrolling;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !fragment.collect_stacking_contexts_for_blocklike_fragment(state) {
|
if !fragment.collect_stacking_contexts_for_blocklike_fragment(state) {
|
||||||
|
@ -3027,12 +3026,13 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
fragment.stacking_context_id = state.generate_stacking_context_id();
|
fragment.stacking_context_id = state.generate_stacking_context_id();
|
||||||
|
|
||||||
let current_stacking_context_id = state.current_stacking_context_id;
|
let current_stacking_context_id = state.current_stacking_context_id;
|
||||||
let stacking_context =
|
let stacking_context = fragment.create_stacking_context(
|
||||||
fragment.create_stacking_context(fragment.stacking_context_id,
|
fragment.stacking_context_id,
|
||||||
&self.base,
|
&self.base,
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
StackingContextType::Real,
|
StackingContextType::Real,
|
||||||
state.current_clip_and_scroll_info);
|
state.current_clipping_and_scrolling
|
||||||
|
);
|
||||||
|
|
||||||
state.add_stacking_context(current_stacking_context_id, stacking_context);
|
state.add_stacking_context(current_stacking_context_id, stacking_context);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3040,7 +3040,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.containing_block_clip_and_scroll_info = previous_cb_clip_scroll_info;
|
state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,11 @@ use floats::{Floats, SpeculatedFloatPlacement};
|
||||||
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
||||||
use flow_ref::{FlowRef, WeakFlowRef};
|
use flow_ref::{FlowRef, WeakFlowRef};
|
||||||
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
|
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
|
||||||
|
use gfx::display_list::ClippingAndScrolling;
|
||||||
use gfx_traits::StackingContextId;
|
use gfx_traits::StackingContextId;
|
||||||
use gfx_traits::print_tree::PrintTree;
|
use gfx_traits::print_tree::PrintTree;
|
||||||
use inline::InlineFlow;
|
use inline::InlineFlow;
|
||||||
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
||||||
use msg::constellation_msg::PipelineId;
|
|
||||||
use multicol::MulticolFlow;
|
use multicol::MulticolFlow;
|
||||||
use parallel::FlowParallelInfo;
|
use parallel::FlowParallelInfo;
|
||||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||||
|
@ -63,7 +63,6 @@ use table_colgroup::TableColGroupFlow;
|
||||||
use table_row::TableRowFlow;
|
use table_row::TableRowFlow;
|
||||||
use table_rowgroup::TableRowGroupFlow;
|
use table_rowgroup::TableRowGroupFlow;
|
||||||
use table_wrapper::TableWrapperFlow;
|
use table_wrapper::TableWrapperFlow;
|
||||||
use webrender_api::ClipAndScrollInfo;
|
|
||||||
|
|
||||||
/// This marker trait indicates that a type is a struct with `#[repr(C)]` whose first field
|
/// This marker trait indicates that a type is a struct with `#[repr(C)]` whose first field
|
||||||
/// is of type `BaseFlow` or some type that also implements this trait.
|
/// is of type `BaseFlow` or some type that also implements this trait.
|
||||||
|
@ -444,13 +443,10 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
|
||||||
/// children of this flow.
|
/// children of this flow.
|
||||||
fn print_extra_flow_children(&self, _: &mut PrintTree) { }
|
fn print_extra_flow_children(&self, _: &mut PrintTree) { }
|
||||||
|
|
||||||
fn clip_and_scroll_info(&self, pipeline_id: PipelineId) -> ClipAndScrollInfo {
|
fn clipping_and_scrolling(&self) -> ClippingAndScrolling {
|
||||||
match base(self).clip_and_scroll_info {
|
match base(self).clipping_and_scrolling {
|
||||||
Some(info) => info,
|
Some(info) => info,
|
||||||
None => {
|
None => unreachable!("Tried to access scroll root id on Flow before assignment"),
|
||||||
debug_assert!(false, "Tried to access scroll root id on Flow before assignment");
|
|
||||||
pipeline_id.root_clip_and_scroll_info()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -920,7 +916,9 @@ pub struct BaseFlow {
|
||||||
/// list construction.
|
/// list construction.
|
||||||
pub stacking_context_id: StackingContextId,
|
pub stacking_context_id: StackingContextId,
|
||||||
|
|
||||||
pub clip_and_scroll_info: Option<ClipAndScrollInfo>,
|
/// The indices of this Flow's ClipScrollNode. This is used to place the node's
|
||||||
|
/// display items into scrolling frames and clipping nodes.
|
||||||
|
pub clipping_and_scrolling: Option<ClippingAndScrolling>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for BaseFlow {
|
impl fmt::Debug for BaseFlow {
|
||||||
|
@ -1062,7 +1060,7 @@ impl BaseFlow {
|
||||||
writing_mode: writing_mode,
|
writing_mode: writing_mode,
|
||||||
thread_id: 0,
|
thread_id: 0,
|
||||||
stacking_context_id: StackingContextId::root(),
|
stacking_context_id: StackingContextId::root(),
|
||||||
clip_and_scroll_info: None,
|
clipping_and_scrolling: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ impl Flow for TableColGroupFlow {
|
||||||
|
|
||||||
fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) {
|
fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) {
|
||||||
self.base.stacking_context_id = state.current_stacking_context_id;
|
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.clipping_and_scrolling = Some(state.current_clipping_and_scrolling);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repair_style(&mut self, _: &::ServoArc<ComputedValues>) {}
|
fn repair_style(&mut self, _: &::ServoArc<ComputedValues>) {}
|
||||||
|
|
|
@ -313,9 +313,8 @@ impl<'a> BuildDisplayList<'a> {
|
||||||
let parent_stacking_context_id = self.state.current_stacking_context_id;
|
let parent_stacking_context_id = self.state.current_stacking_context_id;
|
||||||
self.state.current_stacking_context_id = flow::base(flow).stacking_context_id;
|
self.state.current_stacking_context_id = flow::base(flow).stacking_context_id;
|
||||||
|
|
||||||
let parent_clip_and_scroll_info = self.state.current_clip_and_scroll_info;
|
let parent_clipping_and_scrolling = self.state.current_clipping_and_scrolling;
|
||||||
self.state.current_clip_and_scroll_info =
|
self.state.current_clipping_and_scrolling = flow.clipping_and_scrolling();
|
||||||
flow.clip_and_scroll_info(self.state.layout_context.id);
|
|
||||||
|
|
||||||
flow.build_display_list(&mut self.state);
|
flow.build_display_list(&mut self.state);
|
||||||
flow::mut_base(flow).restyle_damage.remove(REPAINT);
|
flow::mut_base(flow).restyle_damage.remove(REPAINT);
|
||||||
|
@ -325,6 +324,6 @@ impl<'a> BuildDisplayList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state.current_stacking_context_id = parent_stacking_context_id;
|
self.state.current_stacking_context_id = parent_stacking_context_id;
|
||||||
self.state.current_clip_and_scroll_info = parent_clip_and_scroll_info;
|
self.state.current_clipping_and_scrolling = parent_clipping_and_scrolling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,15 @@
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use euclid::{Point2D, Vector2D, Rect, SideOffsets2D, Size2D};
|
use euclid::{Point2D, Vector2D, Rect, SideOffsets2D, Size2D};
|
||||||
use gfx::display_list::{BorderDetails, BorderRadii, BoxShadowClipMode, ClipScrollNodeType};
|
use gfx::display_list::{BorderDetails, BorderRadii, BoxShadowClipMode, ClipScrollNode};
|
||||||
use gfx::display_list::{ClippingRegion, DisplayItem, DisplayList, StackingContextType};
|
use gfx::display_list::{ClipScrollNodeIndex, ClipScrollNodeType, ClippingRegion, DisplayItem};
|
||||||
|
use gfx::display_list::{DisplayList, StackingContextType};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use style::computed_values::{image_rendering, mix_blend_mode, transform_style};
|
use style::computed_values::{image_rendering, mix_blend_mode, transform_style};
|
||||||
use style::values::computed::{BorderStyle, Filter};
|
use style::values::computed::{BorderStyle, Filter};
|
||||||
use style::values::generics::effects::Filter as GenericFilter;
|
use style::values::generics::effects::Filter as GenericFilter;
|
||||||
use webrender_api::{self, ClipAndScrollInfo, ComplexClipRegion, DisplayListBuilder};
|
use webrender_api::{self, ClipAndScrollInfo, ClipId, ClipMode, ComplexClipRegion};
|
||||||
use webrender_api::{ClipMode, ExtendMode, LayoutTransform};
|
use webrender_api::{DisplayListBuilder, ExtendMode, LayoutTransform};
|
||||||
|
|
||||||
pub trait WebRenderDisplayListConverter {
|
pub trait WebRenderDisplayListConverter {
|
||||||
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder;
|
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder;
|
||||||
|
@ -24,9 +25,13 @@ pub trait WebRenderDisplayListConverter {
|
||||||
|
|
||||||
trait WebRenderDisplayItemConverter {
|
trait WebRenderDisplayItemConverter {
|
||||||
fn prim_info(&self) -> webrender_api::LayoutPrimitiveInfo;
|
fn prim_info(&self) -> webrender_api::LayoutPrimitiveInfo;
|
||||||
fn convert_to_webrender(&self,
|
fn convert_to_webrender(
|
||||||
|
&self,
|
||||||
builder: &mut DisplayListBuilder,
|
builder: &mut DisplayListBuilder,
|
||||||
current_clip_and_scroll_info: &mut ClipAndScrollInfo);
|
clip_scroll_nodes: &[ClipScrollNode],
|
||||||
|
clip_ids: &mut Vec<Option<ClipId>>,
|
||||||
|
current_clip_and_scroll_info: &mut ClipAndScrollInfo
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ToBorderStyle {
|
trait ToBorderStyle {
|
||||||
|
@ -227,8 +232,17 @@ impl WebRenderDisplayListConverter for DisplayList {
|
||||||
let mut current_clip_and_scroll_info = pipeline_id.root_clip_and_scroll_info();
|
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);
|
builder.push_clip_and_scroll_info(current_clip_and_scroll_info);
|
||||||
|
|
||||||
|
let mut clip_ids = Vec::with_capacity(self.clip_scroll_nodes.len());
|
||||||
|
clip_ids.resize(self.clip_scroll_nodes.len(), None);
|
||||||
|
clip_ids[0] = Some(ClipId::root_scroll_node(pipeline_id.to_webrender()));
|
||||||
|
|
||||||
for item in &self.list {
|
for item in &self.list {
|
||||||
item.convert_to_webrender(&mut builder, &mut current_clip_and_scroll_info);
|
item.convert_to_webrender(
|
||||||
|
&mut builder,
|
||||||
|
&self.clip_scroll_nodes,
|
||||||
|
&mut clip_ids,
|
||||||
|
&mut current_clip_and_scroll_info
|
||||||
|
);
|
||||||
}
|
}
|
||||||
builder
|
builder
|
||||||
}
|
}
|
||||||
|
@ -249,10 +263,27 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_to_webrender(&self,
|
fn convert_to_webrender(
|
||||||
|
&self,
|
||||||
builder: &mut DisplayListBuilder,
|
builder: &mut DisplayListBuilder,
|
||||||
current_clip_and_scroll_info: &mut ClipAndScrollInfo) {
|
clip_scroll_nodes: &[ClipScrollNode],
|
||||||
let clip_and_scroll_info = self.base().clip_and_scroll_info;
|
clip_ids: &mut Vec<Option<ClipId>>,
|
||||||
|
current_clip_and_scroll_info: &mut ClipAndScrollInfo
|
||||||
|
) {
|
||||||
|
let get_id = |clip_ids: &[Option<ClipId>], index: ClipScrollNodeIndex| -> ClipId {
|
||||||
|
match clip_ids[index.0] {
|
||||||
|
Some(id) => id,
|
||||||
|
None => unreachable!("Tried to use WebRender ClipId before it was defined."),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let clip_and_scroll_indices = self.base().clipping_and_scrolling;
|
||||||
|
let scrolling_id = get_id(clip_ids, clip_and_scroll_indices.scrolling);
|
||||||
|
let clip_and_scroll_info = match clip_and_scroll_indices.clipping {
|
||||||
|
None => ClipAndScrollInfo::simple(scrolling_id),
|
||||||
|
Some(index) => ClipAndScrollInfo::new(scrolling_id, get_id(clip_ids, index)),
|
||||||
|
};
|
||||||
|
|
||||||
if clip_and_scroll_info != *current_clip_and_scroll_info {
|
if clip_and_scroll_info != *current_clip_and_scroll_info {
|
||||||
builder.pop_clip_id();
|
builder.pop_clip_id();
|
||||||
builder.push_clip_and_scroll_info(clip_and_scroll_info);
|
builder.push_clip_and_scroll_info(clip_and_scroll_info);
|
||||||
|
@ -487,32 +518,42 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
}
|
}
|
||||||
DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(),
|
DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(),
|
||||||
DisplayItem::DefineClipScrollNode(ref item) => {
|
DisplayItem::DefineClipScrollNode(ref item) => {
|
||||||
builder.push_clip_id(item.node.parent_id);
|
let node = &clip_scroll_nodes[item.node_index.0];
|
||||||
|
let parent_id = get_id(clip_ids, node.parent_index);
|
||||||
|
let item_rect = node.clip.main.to_rectf();
|
||||||
|
|
||||||
let our_id = item.node.id;
|
let webrender_id = match node.node_type {
|
||||||
let item_rect = item.node.clip.main.to_rectf();
|
|
||||||
let webrender_id = match item.node.node_type {
|
|
||||||
ClipScrollNodeType::Clip => {
|
ClipScrollNodeType::Clip => {
|
||||||
builder.define_clip(Some(our_id),
|
builder.define_clip_with_parent(
|
||||||
|
node.id,
|
||||||
|
parent_id,
|
||||||
item_rect,
|
item_rect,
|
||||||
item.node.clip.get_complex_clips(),
|
node.clip.get_complex_clips(),
|
||||||
None)
|
None
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ClipScrollNodeType::ScrollFrame(scroll_sensitivity) => {
|
ClipScrollNodeType::ScrollFrame(scroll_sensitivity) => {
|
||||||
builder.define_scroll_frame(Some(our_id),
|
builder.define_scroll_frame_with_parent(
|
||||||
item.node.content_rect.to_rectf(),
|
node.id,
|
||||||
item.node.clip.main.to_rectf(),
|
parent_id,
|
||||||
item.node.clip.get_complex_clips(),
|
node.content_rect.to_rectf(),
|
||||||
|
node.clip.main.to_rectf(),
|
||||||
|
node.clip.get_complex_clips(),
|
||||||
None,
|
None,
|
||||||
scroll_sensitivity)
|
scroll_sensitivity
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ClipScrollNodeType::StickyFrame(sticky_frame_info) => {
|
ClipScrollNodeType::StickyFrame(sticky_frame_info) => {
|
||||||
builder.define_sticky_frame(Some(our_id), item_rect, sticky_frame_info)
|
// TODO: Add define_sticky_frame_with_parent to WebRender.
|
||||||
|
builder.push_clip_id(parent_id);
|
||||||
|
let id = builder.define_sticky_frame(node.id, item_rect, sticky_frame_info);
|
||||||
|
builder.pop_clip_id();
|
||||||
|
id
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug_assert!(our_id == webrender_id);
|
|
||||||
|
|
||||||
builder.pop_clip_id();
|
debug_assert!(node.id.is_none() || node.id == Some(webrender_id));
|
||||||
|
clip_ids[item.node_index.0] = Some(webrender_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,6 +189,11 @@ svg > * {
|
||||||
position: static;
|
position: static;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
counter-increment: none;
|
counter-increment: none;
|
||||||
|
|
||||||
|
/* We don't want anonymous table parts to inherit hidden overflow, because
|
||||||
|
* they will create extra unnecessary ClipScrollNodes which also throws
|
||||||
|
* off assignment of contained flows. */
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
*|*::-servo-anonymous-table {
|
*|*::-servo-anonymous-table {
|
||||||
|
@ -197,6 +202,7 @@ svg > * {
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
counter-increment: none;
|
counter-increment: none;
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
*|*::-servo-anonymous-table-row {
|
*|*::-servo-anonymous-table-row {
|
||||||
|
@ -204,6 +210,7 @@ svg > * {
|
||||||
position: static;
|
position: static;
|
||||||
border: none;
|
border: none;
|
||||||
counter-increment: none;
|
counter-increment: none;
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
*|*::-servo-anonymous-table-cell {
|
*|*::-servo-anonymous-table-cell {
|
||||||
|
@ -211,6 +218,7 @@ svg > * {
|
||||||
position: static;
|
position: static;
|
||||||
border: none;
|
border: none;
|
||||||
counter-increment: none;
|
counter-increment: none;
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
*|*::-servo-anonymous-block {
|
*|*::-servo-anonymous-block {
|
||||||
|
|
|
@ -61,7 +61,8 @@ fn test_common(display_list: &DisplayList, epoch: Epoch) -> PaintTimeMetrics {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_first_paint_setter() {
|
fn test_first_paint_setter() {
|
||||||
let empty_display_list = DisplayList {
|
let empty_display_list = DisplayList {
|
||||||
list: Vec::new()
|
list: Vec::new(),
|
||||||
|
clip_scroll_nodes: Vec::new(),
|
||||||
};
|
};
|
||||||
let epoch = Epoch(0);
|
let epoch = Epoch(0);
|
||||||
let mut paint_time_metrics = test_common(&empty_display_list, epoch);
|
let mut paint_time_metrics = test_common(&empty_display_list, epoch);
|
||||||
|
@ -74,7 +75,7 @@ fn test_first_paint_setter() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_first_contentful_paint_setter() {
|
fn test_first_contentful_paint_setter() {
|
||||||
let image = DisplayItem::Image(Box::new(ImageDisplayItem {
|
let image = DisplayItem::Image(Box::new(ImageDisplayItem {
|
||||||
base: BaseDisplayItem::empty(TEST_PIPELINE_ID),
|
base: BaseDisplayItem::empty(),
|
||||||
webrender_image: WebRenderImageInfo {
|
webrender_image: WebRenderImageInfo {
|
||||||
width: 1,
|
width: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
|
@ -87,7 +88,8 @@ fn test_first_contentful_paint_setter() {
|
||||||
image_rendering: image_rendering::T::auto,
|
image_rendering: image_rendering::T::auto,
|
||||||
}));
|
}));
|
||||||
let display_list = DisplayList {
|
let display_list = DisplayList {
|
||||||
list: vec![image]
|
list: vec![image],
|
||||||
|
clip_scroll_nodes: Vec::new(),
|
||||||
};
|
};
|
||||||
let epoch = Epoch(0);
|
let epoch = Epoch(0);
|
||||||
let mut paint_time_metrics = test_common(&display_list, epoch);
|
let mut paint_time_metrics = test_common(&display_list, epoch);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue