mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Auto merge of #14084 - mrobinson:scroll_root_2, r=glennw
Don't promote all scrollable regions to stacking contexts <!-- Please describe your changes on the following line: --> Don't promote all scrollable regions to stacking contexts Instead annotate all flows with their owning ScrollRoots. When processing the display list items into a flattened display list, we add PushScrollRoot and PopScrollRoot to signal when scrolling regions start and end. It is possible for content from different scrolling regions to intersect and when they do, the stack of scrolling regions is duplicated. When these duplicated scrolling regions stacks reach WebRender, it will scroll them in tandem. The PushScrollRoot and PopScrollRoot items are currently represented as StackingContexts in WebRender, but eventually these will be replaced with special WebRender display items. --- <!-- 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 - [x] These changes fix #13529 and #13298. (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- 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/14084) <!-- Reviewable:end -->
This commit is contained in:
commit
ef5ca14283
22 changed files with 454 additions and 181 deletions
|
@ -81,7 +81,15 @@ impl DisplayList {
|
||||||
scroll_offsets,
|
scroll_offsets,
|
||||||
result);
|
result);
|
||||||
}
|
}
|
||||||
&DisplayItem::PopStackingContext(_) => return,
|
&DisplayItem::PushScrollRoot(ref item) => {
|
||||||
|
self.hit_test_scroll_root(traversal,
|
||||||
|
&item.scroll_root,
|
||||||
|
*translated_point,
|
||||||
|
client_point,
|
||||||
|
scroll_offsets,
|
||||||
|
result);
|
||||||
|
}
|
||||||
|
&DisplayItem::PopStackingContext(_) | &DisplayItem::PopScrollRoot(_) => return,
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(meta) = item.hit_test(*translated_point) {
|
if let Some(meta) = item.hit_test(*translated_point) {
|
||||||
result.push(meta);
|
result.push(meta);
|
||||||
|
@ -91,6 +99,26 @@ impl DisplayList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hit_test_scroll_root<'a>(&self,
|
||||||
|
traversal: &mut DisplayListTraversal<'a>,
|
||||||
|
scroll_root: &ScrollRoot,
|
||||||
|
mut translated_point: Point2D<Au>,
|
||||||
|
client_point: &Point2D<Au>,
|
||||||
|
scroll_offsets: &ScrollOffsetMap,
|
||||||
|
result: &mut Vec<DisplayItemMetadata>) {
|
||||||
|
// Adjust the translated point to account for the scroll offset if
|
||||||
|
// necessary. This can only happen when WebRender is in use.
|
||||||
|
//
|
||||||
|
// We don't perform this adjustment on the root stacking context because
|
||||||
|
// the DOM-side code has already translated the point for us (e.g. in
|
||||||
|
// `Window::hit_test_query()`) by now.
|
||||||
|
if let Some(scroll_offset) = scroll_offsets.get(&scroll_root.id) {
|
||||||
|
translated_point.x -= Au::from_f32_px(scroll_offset.x);
|
||||||
|
translated_point.y -= Au::from_f32_px(scroll_offset.y);
|
||||||
|
}
|
||||||
|
self.hit_test_contents(traversal, &translated_point, client_point, scroll_offsets, result);
|
||||||
|
}
|
||||||
|
|
||||||
fn hit_test_stacking_context<'a>(&self,
|
fn hit_test_stacking_context<'a>(&self,
|
||||||
traversal: &mut DisplayListTraversal<'a>,
|
traversal: &mut DisplayListTraversal<'a>,
|
||||||
stacking_context: &StackingContext,
|
stacking_context: &StackingContext,
|
||||||
|
@ -102,7 +130,7 @@ impl DisplayList {
|
||||||
// stacking context isn't fixed. If it's fixed, we need to use the client point anyway.
|
// stacking context isn't fixed. If it's fixed, we need to use the client point anyway.
|
||||||
debug_assert!(stacking_context.context_type == StackingContextType::Real);
|
debug_assert!(stacking_context.context_type == StackingContextType::Real);
|
||||||
let is_fixed = stacking_context.scroll_policy == ScrollPolicy::FixedPosition;
|
let is_fixed = stacking_context.scroll_policy == ScrollPolicy::FixedPosition;
|
||||||
let mut translated_point = if is_fixed {
|
let translated_point = if is_fixed {
|
||||||
*client_point
|
*client_point
|
||||||
} else {
|
} else {
|
||||||
let point = *translated_point - stacking_context.bounds.origin;
|
let point = *translated_point - stacking_context.bounds.origin;
|
||||||
|
@ -112,21 +140,6 @@ impl DisplayList {
|
||||||
Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y))
|
Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y))
|
||||||
};
|
};
|
||||||
|
|
||||||
// Adjust the translated point to account for the scroll offset if
|
|
||||||
// necessary. This can only happen when WebRender is in use.
|
|
||||||
//
|
|
||||||
// We don't perform this adjustment on the root stacking context because
|
|
||||||
// the DOM-side code has already translated the point for us (e.g. in
|
|
||||||
// `Window::hit_test_query()`) by now.
|
|
||||||
if !is_fixed && stacking_context.id != StackingContextId::root() {
|
|
||||||
if let Some(scroll_root_id) = stacking_context.overflow_scroll_id {
|
|
||||||
if let Some(scroll_offset) = scroll_offsets.get(&scroll_root_id) {
|
|
||||||
translated_point.x -= Au::from_f32_px(scroll_offset.x);
|
|
||||||
translated_point.y -= Au::from_f32_px(scroll_offset.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.hit_test_contents(traversal, &translated_point, client_point, scroll_offsets, result);
|
self.hit_test_contents(traversal, &translated_point, client_point, scroll_offsets, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +151,10 @@ 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("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: {:?} ScrollRoot: {:?}",
|
||||||
item,
|
item,
|
||||||
item.base().stacking_context_id));
|
item.base().stacking_context_id,
|
||||||
|
item.scroll_root_id()));
|
||||||
}
|
}
|
||||||
print_tree.end_level();
|
print_tree.end_level();
|
||||||
}
|
}
|
||||||
|
@ -250,6 +264,7 @@ pub enum StackingContextType {
|
||||||
Real,
|
Real,
|
||||||
PseudoPositioned,
|
PseudoPositioned,
|
||||||
PseudoFloat,
|
PseudoFloat,
|
||||||
|
PseudoScrollingArea,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
||||||
|
@ -291,8 +306,8 @@ pub struct StackingContext {
|
||||||
/// Children of this StackingContext.
|
/// Children of this StackingContext.
|
||||||
pub children: Vec<StackingContext>,
|
pub children: Vec<StackingContext>,
|
||||||
|
|
||||||
/// If this StackingContext scrolls its overflow area, this will contain the id.
|
/// The id of the parent scrolling area that contains this StackingContext.
|
||||||
pub overflow_scroll_id: Option<ScrollRootId>,
|
pub parent_scroll_id: ScrollRootId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackingContext {
|
impl StackingContext {
|
||||||
|
@ -309,7 +324,7 @@ impl StackingContext {
|
||||||
perspective: Matrix4D<f32>,
|
perspective: Matrix4D<f32>,
|
||||||
establishes_3d_context: bool,
|
establishes_3d_context: bool,
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
scroll_root_id: Option<ScrollRootId>)
|
parent_scroll_id: ScrollRootId)
|
||||||
-> StackingContext {
|
-> StackingContext {
|
||||||
StackingContext {
|
StackingContext {
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -324,7 +339,7 @@ impl StackingContext {
|
||||||
establishes_3d_context: establishes_3d_context,
|
establishes_3d_context: establishes_3d_context,
|
||||||
scroll_policy: scroll_policy,
|
scroll_policy: scroll_policy,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
overflow_scroll_id: scroll_root_id,
|
parent_scroll_id: parent_scroll_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +356,7 @@ impl StackingContext {
|
||||||
Matrix4D::identity(),
|
Matrix4D::identity(),
|
||||||
true,
|
true,
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
None)
|
ScrollRootId::root())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_child(&mut self, mut child: StackingContext) {
|
pub fn add_child(&mut self, mut child: StackingContext) {
|
||||||
|
@ -453,21 +468,40 @@ impl fmt::Debug for StackingContext {
|
||||||
"Pseudo-StackingContext"
|
"Pseudo-StackingContext"
|
||||||
};
|
};
|
||||||
|
|
||||||
let scrollable_string = if self.overflow_scroll_id.is_some() {
|
write!(f, "{} at {:?} with overflow {:?}: {:?}",
|
||||||
" (scrolls overflow area)"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(f, "{}{} at {:?} with overflow {:?}: {:?}",
|
|
||||||
type_string,
|
type_string,
|
||||||
scrollable_string,
|
|
||||||
self.bounds,
|
self.bounds,
|
||||||
self.overflow,
|
self.overflow,
|
||||||
self.id)
|
self.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a stacking context.
|
||||||
|
#[derive(Clone, Debug, HeapSizeOf, Deserialize, Serialize)]
|
||||||
|
pub struct ScrollRoot {
|
||||||
|
/// The unique ID of this ScrollRoot.
|
||||||
|
pub id: ScrollRootId,
|
||||||
|
|
||||||
|
/// The unique ID of the parent of this ScrollRoot.
|
||||||
|
pub parent_id: ScrollRootId,
|
||||||
|
|
||||||
|
/// The position of this scroll root's frame in the parent stacking context.
|
||||||
|
pub clip: Rect<Au>,
|
||||||
|
|
||||||
|
/// The size of the contents that can be scrolled inside of the scroll root.
|
||||||
|
pub size: Size2D<Au>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScrollRoot {
|
||||||
|
pub fn to_push(&self) -> DisplayItem {
|
||||||
|
DisplayItem::PushScrollRoot(box PushScrollRootItem {
|
||||||
|
base: BaseDisplayItem::empty(),
|
||||||
|
scroll_root: self.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// One drawing command in the list.
|
/// One drawing command in the list.
|
||||||
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
|
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
|
||||||
pub enum DisplayItem {
|
pub enum DisplayItem {
|
||||||
|
@ -482,6 +516,8 @@ pub enum DisplayItem {
|
||||||
Iframe(Box<IframeDisplayItem>),
|
Iframe(Box<IframeDisplayItem>),
|
||||||
PushStackingContext(Box<PushStackingContextItem>),
|
PushStackingContext(Box<PushStackingContextItem>),
|
||||||
PopStackingContext(Box<PopStackingContextItem>),
|
PopStackingContext(Box<PopStackingContextItem>),
|
||||||
|
PushScrollRoot(Box<PushScrollRootItem>),
|
||||||
|
PopScrollRoot(Box<BaseDisplayItem>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information common to all display items.
|
/// Information common to all display items.
|
||||||
|
@ -501,6 +537,9 @@ pub struct BaseDisplayItem {
|
||||||
|
|
||||||
/// The id of the stacking context this item belongs to.
|
/// The id of the stacking context this item belongs to.
|
||||||
pub stacking_context_id: StackingContextId,
|
pub stacking_context_id: StackingContextId,
|
||||||
|
|
||||||
|
/// The id of the scroll root this item belongs to.
|
||||||
|
pub scroll_root_id: ScrollRootId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseDisplayItem {
|
impl BaseDisplayItem {
|
||||||
|
@ -509,7 +548,8 @@ impl BaseDisplayItem {
|
||||||
metadata: DisplayItemMetadata,
|
metadata: DisplayItemMetadata,
|
||||||
clip: &ClippingRegion,
|
clip: &ClippingRegion,
|
||||||
section: DisplayListSection,
|
section: DisplayListSection,
|
||||||
stacking_context_id: StackingContextId)
|
stacking_context_id: StackingContextId,
|
||||||
|
scroll_root_id: ScrollRootId)
|
||||||
-> BaseDisplayItem {
|
-> BaseDisplayItem {
|
||||||
// Detect useless clipping regions here and optimize them to `ClippingRegion::max()`.
|
// Detect useless clipping regions here and optimize them to `ClippingRegion::max()`.
|
||||||
// The painting backend may want to optimize out clipping regions and this makes it easier
|
// The painting backend may want to optimize out clipping regions and this makes it easier
|
||||||
|
@ -524,6 +564,7 @@ impl BaseDisplayItem {
|
||||||
},
|
},
|
||||||
section: section,
|
section: section,
|
||||||
stacking_context_id: stacking_context_id,
|
stacking_context_id: stacking_context_id,
|
||||||
|
scroll_root_id: scroll_root_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,6 +579,7 @@ impl BaseDisplayItem {
|
||||||
clip: ClippingRegion::max(),
|
clip: ClippingRegion::max(),
|
||||||
section: DisplayListSection::Content,
|
section: DisplayListSection::Content,
|
||||||
stacking_context_id: StackingContextId::root(),
|
stacking_context_id: StackingContextId::root(),
|
||||||
|
scroll_root_id: ScrollRootId::root(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -981,6 +1023,15 @@ pub struct PopStackingContextItem {
|
||||||
pub stacking_context_id: StackingContextId,
|
pub stacking_context_id: StackingContextId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Starts a group of items inside a particular scroll root.
|
||||||
|
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
||||||
|
pub struct PushScrollRootItem {
|
||||||
|
/// Fields common to all display items.
|
||||||
|
pub base: BaseDisplayItem,
|
||||||
|
|
||||||
|
/// The scroll root that this item starts.
|
||||||
|
pub scroll_root: ScrollRoot,
|
||||||
|
}
|
||||||
|
|
||||||
/// How a box shadow should be clipped.
|
/// How a box shadow should be clipped.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, HeapSizeOf, Deserialize, Serialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, HeapSizeOf, Deserialize, Serialize)]
|
||||||
|
@ -1009,9 +1060,15 @@ impl DisplayItem {
|
||||||
DisplayItem::Iframe(ref iframe) => &iframe.base,
|
DisplayItem::Iframe(ref iframe) => &iframe.base,
|
||||||
DisplayItem::PushStackingContext(ref stacking_context) => &stacking_context.base,
|
DisplayItem::PushStackingContext(ref stacking_context) => &stacking_context.base,
|
||||||
DisplayItem::PopStackingContext(ref item) => &item.base,
|
DisplayItem::PopStackingContext(ref item) => &item.base,
|
||||||
|
DisplayItem::PushScrollRoot(ref item) => &item.base,
|
||||||
|
DisplayItem::PopScrollRoot(ref base) => &base,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_root_id(&self) -> ScrollRootId {
|
||||||
|
self.base().scroll_root_id
|
||||||
|
}
|
||||||
|
|
||||||
pub fn stacking_context_id(&self) -> StackingContextId {
|
pub fn stacking_context_id(&self) -> StackingContextId {
|
||||||
self.base().stacking_context_id
|
self.base().stacking_context_id
|
||||||
}
|
}
|
||||||
|
@ -1090,6 +1147,14 @@ impl fmt::Debug for DisplayItem {
|
||||||
return write!(f, "PopStackingContext({:?}", item.stacking_context_id);
|
return write!(f, "PopStackingContext({:?}", item.stacking_context_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let DisplayItem::PushScrollRoot(ref item) = *self {
|
||||||
|
return write!(f, "PushScrollRoot({:?}", item.scroll_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let DisplayItem::PopScrollRoot(_) = *self {
|
||||||
|
return write!(f, "PopScrollRoot");
|
||||||
|
}
|
||||||
|
|
||||||
write!(f, "{} @ {:?} {:?}",
|
write!(f, "{} @ {:?} {:?}",
|
||||||
match *self {
|
match *self {
|
||||||
DisplayItem::SolidColor(ref solid_color) =>
|
DisplayItem::SolidColor(ref solid_color) =>
|
||||||
|
@ -1106,8 +1171,10 @@ impl fmt::Debug for DisplayItem {
|
||||||
DisplayItem::Line(_) => "Line".to_owned(),
|
DisplayItem::Line(_) => "Line".to_owned(),
|
||||||
DisplayItem::BoxShadow(_) => "BoxShadow".to_owned(),
|
DisplayItem::BoxShadow(_) => "BoxShadow".to_owned(),
|
||||||
DisplayItem::Iframe(_) => "Iframe".to_owned(),
|
DisplayItem::Iframe(_) => "Iframe".to_owned(),
|
||||||
DisplayItem::PushStackingContext(_) => "".to_owned(),
|
DisplayItem::PushStackingContext(_) |
|
||||||
DisplayItem::PopStackingContext(_) => "".to_owned(),
|
DisplayItem::PopStackingContext(_) |
|
||||||
|
DisplayItem::PushScrollRoot(_) |
|
||||||
|
DisplayItem::PopScrollRoot(_) => "".to_owned(),
|
||||||
},
|
},
|
||||||
self.bounds(),
|
self.bounds(),
|
||||||
self.base().clip
|
self.base().clip
|
||||||
|
|
|
@ -211,6 +211,11 @@ impl ScrollRootId {
|
||||||
pub fn fragment_type(&self) -> FragmentType {
|
pub fn fragment_type(&self) -> FragmentType {
|
||||||
FragmentType::from_usize(self.0 & 3)
|
FragmentType::from_usize(self.0 & 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn to_stacking_context_id(&self) -> StackingContextId {
|
||||||
|
StackingContextId(self.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type of fragment that a stacking context represents.
|
/// The type of fragment that a stacking context represents.
|
||||||
|
|
|
@ -1941,17 +1941,6 @@ impl Flow for BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
||||||
// `overflow: auto` and `overflow: scroll` force creation of layers, since we can only
|
|
||||||
// scroll layers.
|
|
||||||
match (self.fragment.style().get_box().overflow_x,
|
|
||||||
self.fragment.style().get_box().overflow_y.0) {
|
|
||||||
(overflow_x::T::auto, _) | (overflow_x::T::scroll, _) |
|
|
||||||
(_, overflow_x::T::auto) | (_, overflow_x::T::scroll) => {
|
|
||||||
self.base.clip = ClippingRegion::max();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let position_start = self.base.position.start.to_physical(self.base.writing_mode,
|
let position_start = self.base.position.start.to_physical(self.base.writing_mode,
|
||||||
container_size);
|
container_size);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ use block::{BlockFlow, BlockStackingContextType};
|
||||||
use canvas_traits::{CanvasData, CanvasMsg, FromLayoutMsg};
|
use canvas_traits::{CanvasData, CanvasMsg, FromLayoutMsg};
|
||||||
use context::SharedLayoutContext;
|
use context::SharedLayoutContext;
|
||||||
use euclid::{Matrix4D, Point2D, Radians, Rect, SideOffsets2D, Size2D};
|
use euclid::{Matrix4D, Point2D, Radians, Rect, SideOffsets2D, Size2D};
|
||||||
|
use euclid::point::TypedPoint2D;
|
||||||
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,7 +26,7 @@ use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, Cl
|
||||||
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayList, DisplayListSection};
|
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayList, DisplayListSection};
|
||||||
use gfx::display_list::{GradientDisplayItem, IframeDisplayItem, ImageDisplayItem};
|
use gfx::display_list::{GradientDisplayItem, IframeDisplayItem, ImageDisplayItem};
|
||||||
use gfx::display_list::{LineDisplayItem, OpaqueNode};
|
use gfx::display_list::{LineDisplayItem, OpaqueNode};
|
||||||
use gfx::display_list::{SolidColorDisplayItem, StackingContext, StackingContextType};
|
use gfx::display_list::{SolidColorDisplayItem, ScrollRoot, StackingContext, StackingContextType};
|
||||||
use gfx::display_list::{TextDisplayItem, TextOrientation, WebGLDisplayItem, WebRenderImageInfo};
|
use gfx::display_list::{TextDisplayItem, TextOrientation, WebGLDisplayItem, WebRenderImageInfo};
|
||||||
use gfx_traits::{ScrollPolicy, ScrollRootId, StackingContextId};
|
use gfx_traits::{ScrollPolicy, ScrollRootId, StackingContextId};
|
||||||
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
|
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
|
||||||
|
@ -42,8 +43,8 @@ use std::mem;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style::computed_values::{background_attachment, background_clip, background_origin};
|
use style::computed_values::{background_attachment, background_clip, background_origin};
|
||||||
use style::computed_values::{background_repeat, background_size, border_style};
|
use style::computed_values::{background_repeat, background_size, border_style};
|
||||||
use style::computed_values::{cursor, image_rendering, overflow_x, pointer_events, position};
|
use style::computed_values::{cursor, image_rendering, overflow_x};
|
||||||
use style::computed_values::{transform, transform_style, visibility};
|
use style::computed_values::{pointer_events, position, transform, transform_style, visibility};
|
||||||
use style::computed_values::_servo_overflow_clip_box as overflow_clip_box;
|
use style::computed_values::_servo_overflow_clip_box as overflow_clip_box;
|
||||||
use style::computed_values::filter::Filter;
|
use style::computed_values::filter::Filter;
|
||||||
use style::computed_values::text_shadow::TextShadow;
|
use style::computed_values::text_shadow::TextShadow;
|
||||||
|
@ -95,6 +96,7 @@ pub struct DisplayListBuildState<'a> {
|
||||||
pub shared_layout_context: &'a SharedLayoutContext,
|
pub shared_layout_context: &'a SharedLayoutContext,
|
||||||
pub root_stacking_context: StackingContext,
|
pub root_stacking_context: StackingContext,
|
||||||
pub items: HashMap<StackingContextId, Vec<DisplayItem>>,
|
pub items: HashMap<StackingContextId, Vec<DisplayItem>>,
|
||||||
|
pub scroll_roots: HashMap<ScrollRootId, ScrollRoot>,
|
||||||
pub stacking_context_id_stack: Vec<StackingContextId>,
|
pub stacking_context_id_stack: Vec<StackingContextId>,
|
||||||
pub scroll_root_id_stack: Vec<ScrollRootId>,
|
pub scroll_root_id_stack: Vec<ScrollRootId>,
|
||||||
}
|
}
|
||||||
|
@ -107,6 +109,7 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
shared_layout_context: shared_layout_context,
|
shared_layout_context: shared_layout_context,
|
||||||
root_stacking_context: StackingContext::root(),
|
root_stacking_context: StackingContext::root(),
|
||||||
items: HashMap::new(),
|
items: HashMap::new(),
|
||||||
|
scroll_roots: HashMap::new(),
|
||||||
stacking_context_id_stack: vec!(stacking_context_id),
|
stacking_context_id_stack: vec!(stacking_context_id),
|
||||||
scroll_root_id_stack: vec!(ScrollRootId::root()),
|
scroll_root_id_stack: vec!(ScrollRootId::root()),
|
||||||
}
|
}
|
||||||
|
@ -117,6 +120,11 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
items.push(display_item);
|
items.push(display_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_scroll_root(&mut self, scroll_root: ScrollRoot) {
|
||||||
|
debug_assert!(!self.scroll_roots.contains_key(&scroll_root.id));
|
||||||
|
self.scroll_roots.insert(scroll_root.id, scroll_root);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn stacking_context_id(&self) -> StackingContextId {
|
pub fn stacking_context_id(&self) -> StackingContextId {
|
||||||
self.stacking_context_id_stack.last().unwrap().clone()
|
self.stacking_context_id_stack.last().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
@ -126,14 +134,19 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_stacking_context_id(&mut self) {
|
pub fn pop_stacking_context_id(&mut self) {
|
||||||
self.stacking_context_id_stack.pop();
|
|
||||||
assert!(!self.stacking_context_id_stack.is_empty());
|
assert!(!self.stacking_context_id_stack.is_empty());
|
||||||
|
self.stacking_context_id_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scroll_root_id(&mut self) -> ScrollRootId {
|
pub fn scroll_root_id(&self) -> ScrollRootId {
|
||||||
self.scroll_root_id_stack.last().unwrap().clone()
|
self.scroll_root_id_stack.last().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parent_scroll_root_id(&self) -> ScrollRootId {
|
||||||
|
debug_assert!(self.scroll_root_id_stack.len() > 1);
|
||||||
|
self.scroll_root_id_stack[self.scroll_root_id_stack.len() - 2]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push_scroll_root_id(&mut self, id: ScrollRootId) {
|
pub fn push_scroll_root_id(&mut self, id: ScrollRootId) {
|
||||||
self.scroll_root_id_stack.push(id);
|
self.scroll_root_id_stack.push(id);
|
||||||
}
|
}
|
||||||
|
@ -157,14 +170,18 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
},
|
},
|
||||||
&clip,
|
&clip,
|
||||||
section,
|
section,
|
||||||
self.stacking_context_id())
|
self.stacking_context_id(),
|
||||||
|
self.scroll_root_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_display_list(mut self) -> DisplayList {
|
pub fn to_display_list(mut self) -> DisplayList {
|
||||||
|
let mut scroll_root_stack = Vec::new();
|
||||||
|
scroll_root_stack.push(ScrollRootId::root());
|
||||||
|
|
||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
let root_context = mem::replace(&mut self.root_stacking_context, StackingContext::root());
|
let root_context = mem::replace(&mut self.root_stacking_context, StackingContext::root());
|
||||||
|
|
||||||
self.to_display_list_for_stacking_context(&mut list, root_context);
|
self.to_display_list_for_stacking_context(&mut list, root_context, &mut scroll_root_stack);
|
||||||
|
|
||||||
DisplayList {
|
DisplayList {
|
||||||
list: list,
|
list: list,
|
||||||
|
@ -173,7 +190,8 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
|
|
||||||
fn to_display_list_for_stacking_context(&mut self,
|
fn to_display_list_for_stacking_context(&mut self,
|
||||||
list: &mut Vec<DisplayItem>,
|
list: &mut Vec<DisplayItem>,
|
||||||
mut stacking_context: StackingContext) {
|
mut stacking_context: StackingContext,
|
||||||
|
scroll_root_stack: &mut Vec<ScrollRootId>) {
|
||||||
let mut child_items = self.items.remove(&stacking_context.id).unwrap_or(Vec::new());
|
let mut child_items = self.items.remove(&stacking_context.id).unwrap_or(Vec::new());
|
||||||
child_items.sort_by(|a, b| a.base().section.cmp(&b.base().section));
|
child_items.sort_by(|a, b| a.base().section.cmp(&b.base().section));
|
||||||
child_items.reverse();
|
child_items.reverse();
|
||||||
|
@ -186,63 +204,114 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
if !real_stacking_context {
|
if !real_stacking_context {
|
||||||
self.to_display_list_for_items(list,
|
self.to_display_list_for_items(list,
|
||||||
child_items,
|
child_items,
|
||||||
child_stacking_contexts);
|
child_stacking_contexts,
|
||||||
|
scroll_root_stack);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut scroll_root_stack = Vec::new();
|
||||||
|
scroll_root_stack.push(stacking_context.parent_scroll_id);
|
||||||
|
|
||||||
let (push_item, pop_item) = stacking_context.to_display_list_items();
|
let (push_item, pop_item) = stacking_context.to_display_list_items();
|
||||||
list.push(push_item);
|
list.push(push_item);
|
||||||
self.to_display_list_for_items(list,
|
self.to_display_list_for_items(list,
|
||||||
child_items,
|
child_items,
|
||||||
child_stacking_contexts);
|
child_stacking_contexts,
|
||||||
|
&mut scroll_root_stack);
|
||||||
list.push(pop_item);
|
list.push(pop_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_display_list_for_items(&mut self,
|
fn to_display_list_for_items(&mut self,
|
||||||
list: &mut Vec<DisplayItem>,
|
list: &mut Vec<DisplayItem>,
|
||||||
mut child_items: Vec<DisplayItem>,
|
mut child_items: Vec<DisplayItem>,
|
||||||
child_stacking_contexts: Vec<StackingContext>) {
|
child_stacking_contexts: Vec<StackingContext>,
|
||||||
|
scroll_root_stack: &mut Vec<ScrollRootId>) {
|
||||||
// Properly order display items that make up a stacking context. "Steps" here
|
// Properly order display items that make up a stacking context. "Steps" here
|
||||||
// refer to the steps in CSS 2.1 Appendix E.
|
// refer to the steps in CSS 2.1 Appendix E.
|
||||||
// Steps 1 and 2: Borders and background for the root.
|
// Steps 1 and 2: Borders and background for the root.
|
||||||
while child_items.last().map_or(false,
|
while child_items.last().map_or(false,
|
||||||
|child| child.section() == DisplayListSection::BackgroundAndBorders) {
|
|child| child.section() == DisplayListSection::BackgroundAndBorders) {
|
||||||
list.push(child_items.pop().unwrap());
|
let item = child_items.pop().unwrap();
|
||||||
|
self.switch_scroll_roots(list, item.scroll_root_id(), scroll_root_stack);
|
||||||
|
list.push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Positioned descendants with negative z-indices.
|
// Step 3: Positioned descendants with negative z-indices.
|
||||||
let mut child_stacking_contexts = child_stacking_contexts.into_iter().peekable();
|
let mut child_stacking_contexts = child_stacking_contexts.into_iter().peekable();
|
||||||
while child_stacking_contexts.peek().map_or(false, |child| child.z_index < 0) {
|
while child_stacking_contexts.peek().map_or(false, |child| child.z_index < 0) {
|
||||||
let context = child_stacking_contexts.next().unwrap();
|
let context = child_stacking_contexts.next().unwrap();
|
||||||
self.to_display_list_for_stacking_context(list, context);
|
self.switch_scroll_roots(list, context.parent_scroll_id, scroll_root_stack);
|
||||||
|
self.to_display_list_for_stacking_context(list, context, scroll_root_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: Block backgrounds and borders.
|
// Step 4: Block backgrounds and borders.
|
||||||
while child_items.last().map_or(false,
|
while child_items.last().map_or(false,
|
||||||
|child| child.section() == DisplayListSection::BlockBackgroundsAndBorders) {
|
|child| child.section() == DisplayListSection::BlockBackgroundsAndBorders) {
|
||||||
list.push(child_items.pop().unwrap());
|
let item = child_items.pop().unwrap();
|
||||||
|
self.switch_scroll_roots(list, item.scroll_root_id(), scroll_root_stack);
|
||||||
|
list.push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5: Floats.
|
// Step 5: Floats.
|
||||||
while child_stacking_contexts.peek().map_or(false,
|
while child_stacking_contexts.peek().map_or(false,
|
||||||
|child| child.context_type == StackingContextType::PseudoFloat) {
|
|child| child.context_type == StackingContextType::PseudoFloat) {
|
||||||
let context = child_stacking_contexts.next().unwrap();
|
let context = child_stacking_contexts.next().unwrap();
|
||||||
self.to_display_list_for_stacking_context(list, context);
|
self.switch_scroll_roots(list, context.parent_scroll_id, scroll_root_stack);
|
||||||
|
self.to_display_list_for_stacking_context(list, context, scroll_root_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6 & 7: Content and inlines that generate stacking contexts.
|
// Step 6 & 7: Content and inlines that generate stacking contexts.
|
||||||
while child_items.last().map_or(false,
|
while child_items.last().map_or(false,
|
||||||
|child| child.section() == DisplayListSection::Content) {
|
|child| child.section() == DisplayListSection::Content) {
|
||||||
list.push(child_items.pop().unwrap());
|
let item = child_items.pop().unwrap();
|
||||||
|
self.switch_scroll_roots(list, item.scroll_root_id(), scroll_root_stack);
|
||||||
|
list.push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 8 & 9: Positioned descendants with nonnegative, numeric z-indices.
|
// Step 8 & 9: Positioned descendants with nonnegative, numeric z-indices.
|
||||||
for child in child_stacking_contexts {
|
for child in child_stacking_contexts {
|
||||||
self.to_display_list_for_stacking_context(list, child);
|
self.switch_scroll_roots(list, child.parent_scroll_id, scroll_root_stack);
|
||||||
|
self.to_display_list_for_stacking_context(list, child, scroll_root_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 10: Outlines.
|
// Step 10: Outlines.
|
||||||
list.extend(child_items);
|
for item in child_items.drain(..) {
|
||||||
|
self.switch_scroll_roots(list, item.scroll_root_id(), scroll_root_stack);
|
||||||
|
list.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in scroll_root_stack.drain(1..) {
|
||||||
|
list.push(DisplayItem::PopScrollRoot(Box::new(BaseDisplayItem::empty())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn switch_scroll_roots(&self,
|
||||||
|
list: &mut Vec<DisplayItem>,
|
||||||
|
new_id: ScrollRootId,
|
||||||
|
scroll_root_stack: &mut Vec<ScrollRootId>) {
|
||||||
|
if new_id == *scroll_root_stack.last().unwrap() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if new_id == *scroll_root_stack.first().unwrap() {
|
||||||
|
for _ in scroll_root_stack.drain(1..) {
|
||||||
|
list.push(DisplayItem::PopScrollRoot(Box::new(BaseDisplayItem::empty())));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We never want to reach the root of the ScrollRoot tree without encountering the
|
||||||
|
// containing scroll root of this StackingContext. If this does happen we've tried to
|
||||||
|
// switch to a ScrollRoot that does not contain our current stacking context or isn't
|
||||||
|
// itself a direct child of our current stacking context. This should never happen
|
||||||
|
// due to CSS stacking rules.
|
||||||
|
debug_assert!(new_id != ScrollRootId::root());
|
||||||
|
|
||||||
|
let scroll_root = self.scroll_roots.get(&new_id).unwrap();
|
||||||
|
self.switch_scroll_roots(list, scroll_root.parent_id, scroll_root_stack);
|
||||||
|
|
||||||
|
scroll_root_stack.push(new_id);
|
||||||
|
list.push(scroll_root.to_push());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +488,7 @@ pub trait FragmentDisplayListBuilding {
|
||||||
base_flow: &BaseFlow,
|
base_flow: &BaseFlow,
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
mode: StackingContextCreationMode,
|
mode: StackingContextCreationMode,
|
||||||
scroll_root_id: Option<ScrollRootId>)
|
parent_scroll_id: ScrollRootId)
|
||||||
-> StackingContext;
|
-> StackingContext;
|
||||||
|
|
||||||
/// Returns the 4D matrix representing this fragment's transform.
|
/// Returns the 4D matrix representing this fragment's transform.
|
||||||
|
@ -1476,9 +1545,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
base_flow: &BaseFlow,
|
base_flow: &BaseFlow,
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
mode: StackingContextCreationMode,
|
mode: StackingContextCreationMode,
|
||||||
scroll_root_id: Option<ScrollRootId>)
|
parent_scroll_id: ScrollRootId)
|
||||||
-> StackingContext {
|
-> StackingContext {
|
||||||
let scrolls_overflow_area = mode == StackingContextCreationMode::ScrollWrapper;
|
|
||||||
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
|
||||||
|
@ -1486,16 +1554,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
base_flow.early_absolute_position_info
|
base_flow.early_absolute_position_info
|
||||||
.relative_containing_block_mode,
|
.relative_containing_block_mode,
|
||||||
CoordinateSystem::Parent);
|
CoordinateSystem::Parent);
|
||||||
let overflow = if scrolls_overflow_area {
|
// First, compute the offset of our border box (including relative positioning)
|
||||||
Rect::new(Point2D::zero(), base_flow.overflow.scroll.size)
|
// from our flow origin, since that is what `BaseFlow::overflow` is relative to.
|
||||||
} else {
|
let border_box_offset =
|
||||||
// First, compute the offset of our border box (including relative positioning)
|
border_box.translate(&-base_flow.stacking_relative_position).origin;
|
||||||
// from our flow origin, since that is what `BaseFlow::overflow` is relative to.
|
// Then, using that, compute our overflow region relative to our border box.
|
||||||
let border_box_offset =
|
let overflow = base_flow.overflow.paint.translate(&-border_box_offset);
|
||||||
border_box.translate(&-base_flow.stacking_relative_position).origin;
|
|
||||||
// Then, using that, compute our overflow region relative to our border box.
|
|
||||||
base_flow.overflow.paint.translate(&-border_box_offset)
|
|
||||||
};
|
|
||||||
|
|
||||||
let transform = self.transform_matrix(&border_box);
|
let transform = self.transform_matrix(&border_box);
|
||||||
let perspective = match self.style().get_effects().perspective {
|
let perspective = match self.style().get_effects().perspective {
|
||||||
|
@ -1531,8 +1595,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
let transform_style = self.style().get_used_transform_style();
|
let transform_style = self.style().get_used_transform_style();
|
||||||
let establishes_3d_context = scrolls_overflow_area ||
|
let establishes_3d_context = transform_style == transform_style::T::flat;
|
||||||
transform_style == transform_style::T::flat;
|
|
||||||
|
|
||||||
let context_type = match mode {
|
let context_type = match mode {
|
||||||
StackingContextCreationMode::PseudoFloat => StackingContextType::PseudoFloat,
|
StackingContextCreationMode::PseudoFloat => StackingContextType::PseudoFloat,
|
||||||
|
@ -1551,7 +1614,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
perspective,
|
perspective,
|
||||||
establishes_3d_context,
|
establishes_3d_context,
|
||||||
scroll_policy,
|
scroll_policy,
|
||||||
scroll_root_id)
|
parent_scroll_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adjust_clipping_region_for_children(&self,
|
fn adjust_clipping_region_for_children(&self,
|
||||||
|
@ -1829,18 +1892,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
fn collect_stacking_contexts_for_block(&mut self,
|
fn collect_stacking_contexts_for_block(&mut self,
|
||||||
parent: &mut StackingContext,
|
parent: &mut StackingContext,
|
||||||
parent_scroll_root_id: ScrollRootId) {
|
parent_scroll_root_id: ScrollRootId) {
|
||||||
let block_stacking_context_type = self.block_stacking_context_type();
|
let scroll_root_id = if self.has_scrolling_overflow() {
|
||||||
if block_stacking_context_type == BlockStackingContextType::NonstackingContext {
|
|
||||||
self.base.stacking_context_id = parent.id;
|
|
||||||
self.base.collect_stacking_contexts_for_children(parent, parent_scroll_root_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let stacking_context_id = StackingContextId::new_of_type(self.fragment.node.id() as usize,
|
|
||||||
self.fragment.fragment_type());
|
|
||||||
|
|
||||||
let has_scrolling_overflow = self.has_scrolling_overflow();
|
|
||||||
let scroll_root_id = if has_scrolling_overflow {
|
|
||||||
ScrollRootId::new_of_type(self.fragment.node.id() as usize,
|
ScrollRootId::new_of_type(self.fragment.node.id() as usize,
|
||||||
self.fragment.fragment_type())
|
self.fragment.fragment_type())
|
||||||
} else {
|
} else {
|
||||||
|
@ -1848,7 +1900,15 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
};
|
};
|
||||||
self.base.scroll_root_id = scroll_root_id;
|
self.base.scroll_root_id = scroll_root_id;
|
||||||
|
|
||||||
|
let block_stacking_context_type = self.block_stacking_context_type();
|
||||||
|
if block_stacking_context_type == BlockStackingContextType::NonstackingContext {
|
||||||
|
self.base.stacking_context_id = parent.id;
|
||||||
|
self.base.collect_stacking_contexts_for_children(parent, scroll_root_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let stacking_context_id = StackingContextId::new_of_type(self.fragment.node.id() as usize,
|
||||||
|
self.fragment.fragment_type());
|
||||||
self.base.stacking_context_id = stacking_context_id;
|
self.base.stacking_context_id = stacking_context_id;
|
||||||
|
|
||||||
if block_stacking_context_type == BlockStackingContextType::PseudoStackingContext {
|
if block_stacking_context_type == BlockStackingContextType::PseudoStackingContext {
|
||||||
|
@ -1864,7 +1924,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
&self.base,
|
&self.base,
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
creation_mode,
|
creation_mode,
|
||||||
None);
|
parent_scroll_root_id);
|
||||||
self.base.collect_stacking_contexts_for_children(&mut new_context, scroll_root_id);
|
self.base.collect_stacking_contexts_for_children(&mut new_context, scroll_root_id);
|
||||||
let new_children: Vec<StackingContext> = new_context.children.drain(..).collect();
|
let new_children: Vec<StackingContext> = new_context.children.drain(..).collect();
|
||||||
|
|
||||||
|
@ -1888,20 +1948,13 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
ScrollPolicy::Scrollable
|
ScrollPolicy::Scrollable
|
||||||
};
|
};
|
||||||
|
|
||||||
let (creation_mode, internal_id) = if has_scrolling_overflow {
|
|
||||||
(StackingContextCreationMode::ScrollWrapper, Some(self.base.scroll_root_id))
|
|
||||||
} else {
|
|
||||||
(StackingContextCreationMode::Normal, None)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut stacking_context = self.fragment.create_stacking_context(
|
let mut stacking_context = self.fragment.create_stacking_context(
|
||||||
stacking_context_id,
|
stacking_context_id,
|
||||||
&self.base,
|
&self.base,
|
||||||
scroll_policy,
|
scroll_policy,
|
||||||
creation_mode,
|
StackingContextCreationMode::Normal,
|
||||||
internal_id);
|
parent_scroll_root_id);
|
||||||
self.base.collect_stacking_contexts_for_children(&mut stacking_context, scroll_root_id);
|
self.base.collect_stacking_contexts_for_children(&mut stacking_context, scroll_root_id);
|
||||||
|
|
||||||
parent.add_child(stacking_context);
|
parent.add_child(stacking_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1921,6 +1974,28 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
DisplayListSection::BlockBackgroundsAndBorders
|
DisplayListSection::BlockBackgroundsAndBorders
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if self.has_scrolling_overflow() {
|
||||||
|
let size = self.base.overflow.scroll.size;
|
||||||
|
let mut clip = self.fragment.stacking_relative_border_box(
|
||||||
|
&self.base.stacking_relative_position,
|
||||||
|
&self.base.early_absolute_position_info.relative_containing_block_size,
|
||||||
|
self.base.early_absolute_position_info.relative_containing_block_mode,
|
||||||
|
CoordinateSystem::Parent);
|
||||||
|
if establishes_stacking_context {
|
||||||
|
clip = Rect::new(TypedPoint2D::zero(), clip.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent_id = state.parent_scroll_root_id();
|
||||||
|
state.add_scroll_root(
|
||||||
|
ScrollRoot {
|
||||||
|
id: self.base.scroll_root_id,
|
||||||
|
parent_id: parent_id,
|
||||||
|
clip: clip,
|
||||||
|
size: size,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Add the box that starts the block context.
|
// Add the box that starts the block context.
|
||||||
self.fragment
|
self.fragment
|
||||||
.build_display_list(state,
|
.build_display_list(state,
|
||||||
|
@ -2025,7 +2100,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
&self.base,
|
&self.base,
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
StackingContextCreationMode::Normal,
|
StackingContextCreationMode::Normal,
|
||||||
None));
|
parent_scroll_root_id));
|
||||||
}
|
}
|
||||||
_ => fragment.stacking_context_id = parent.id,
|
_ => fragment.stacking_context_id = parent.id,
|
||||||
}
|
}
|
||||||
|
@ -2229,7 +2304,6 @@ pub enum BorderPaintingMode<'a> {
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum StackingContextCreationMode {
|
pub enum StackingContextCreationMode {
|
||||||
Normal,
|
Normal,
|
||||||
ScrollWrapper,
|
|
||||||
PseudoPositioned,
|
PseudoPositioned,
|
||||||
PseudoFloat,
|
PseudoFloat,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2595,8 +2595,6 @@ impl Fragment {
|
||||||
transform_style::T::auto => {}
|
transform_style::T::auto => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): Don't unconditionally form stacking contexts for `overflow_x: scroll`
|
|
||||||
// and `overflow_y: scroll`. This needs multiple layers per stacking context.
|
|
||||||
match (self.style().get_box().position,
|
match (self.style().get_box().position,
|
||||||
self.style().get_position().z_index,
|
self.style().get_position().z_index,
|
||||||
self.style().get_box().overflow_x,
|
self.style().get_box().overflow_x,
|
||||||
|
@ -2615,11 +2613,7 @@ impl Fragment {
|
||||||
overflow_x::T::visible) => false,
|
overflow_x::T::visible) => false,
|
||||||
(position::T::absolute, _, _, _) |
|
(position::T::absolute, _, _, _) |
|
||||||
(position::T::fixed, _, _, _) |
|
(position::T::fixed, _, _, _) |
|
||||||
(position::T::relative, _, _, _) |
|
(position::T::relative, _, _, _) => true,
|
||||||
(_, _, overflow_x::T::auto, _) |
|
|
||||||
(_, _, overflow_x::T::scroll, _) |
|
|
||||||
(_, _, _, overflow_x::T::auto) |
|
|
||||||
(_, _, _, overflow_x::T::scroll) => true,
|
|
||||||
(position::T::static_, _, _, _) => false
|
(position::T::static_, _, _, _) => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,34 +271,34 @@ pub struct BuildDisplayList<'a> {
|
||||||
impl<'a> BuildDisplayList<'a> {
|
impl<'a> BuildDisplayList<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn traverse(&mut self, flow: &mut Flow) {
|
pub fn traverse(&mut self, flow: &mut Flow) {
|
||||||
|
let new_stacking_context =
|
||||||
|
flow::base(flow).stacking_context_id != self.state.stacking_context_id();
|
||||||
|
if new_stacking_context {
|
||||||
|
self.state.push_stacking_context_id(flow::base(flow).stacking_context_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_scroll_root =
|
||||||
|
flow::base(flow).scroll_root_id != self.state.scroll_root_id();
|
||||||
|
if new_scroll_root {
|
||||||
|
self.state.push_scroll_root_id(flow::base(flow).scroll_root_id);
|
||||||
|
}
|
||||||
|
|
||||||
if self.should_process() {
|
if self.should_process() {
|
||||||
let new_stacking_context =
|
|
||||||
flow::base(flow).stacking_context_id != self.state.stacking_context_id();
|
|
||||||
if new_stacking_context {
|
|
||||||
self.state.push_stacking_context_id(flow::base(flow).stacking_context_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
let new_scroll_root =
|
|
||||||
flow::base(flow).scroll_root_id != self.state.scroll_root_id();
|
|
||||||
if new_scroll_root {
|
|
||||||
self.state.push_scroll_root_id(flow::base(flow).scroll_root_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);
|
||||||
|
|
||||||
if new_stacking_context {
|
|
||||||
self.state.pop_stacking_context_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_scroll_root {
|
|
||||||
self.state.pop_scroll_root_id();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for kid in flow::child_iter_mut(flow) {
|
for kid in flow::child_iter_mut(flow) {
|
||||||
self.traverse(kid);
|
self.traverse(kid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if new_stacking_context {
|
||||||
|
self.state.pop_stacking_context_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
if new_scroll_root {
|
||||||
|
self.state.pop_scroll_root_id();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// completely converting layout to directly generate WebRender display lists, for example.
|
// completely converting layout to directly generate WebRender display lists, for example.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use euclid::{Point2D, Rect, Size2D};
|
use euclid::{Matrix4D, Point2D, Rect, Size2D, TypedRect};
|
||||||
use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion};
|
use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion};
|
||||||
use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal};
|
use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal};
|
||||||
use gfx::display_list::{StackingContext, StackingContextType};
|
use gfx::display_list::{StackingContext, StackingContextType};
|
||||||
|
@ -24,7 +24,8 @@ trait WebRenderStackingContextConverter {
|
||||||
api: &mut webrender_traits::RenderApi,
|
api: &mut webrender_traits::RenderApi,
|
||||||
pipeline_id: webrender_traits::PipelineId,
|
pipeline_id: webrender_traits::PipelineId,
|
||||||
epoch: webrender_traits::Epoch,
|
epoch: webrender_traits::Epoch,
|
||||||
frame_builder: &mut WebRenderFrameBuilder)
|
frame_builder: &mut WebRenderFrameBuilder,
|
||||||
|
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
|
||||||
-> webrender_traits::StackingContextId;
|
-> webrender_traits::StackingContextId;
|
||||||
|
|
||||||
fn convert_children_to_webrender<'a>(&self,
|
fn convert_children_to_webrender<'a>(&self,
|
||||||
|
@ -235,17 +236,39 @@ impl WebRenderStackingContextConverter for StackingContext {
|
||||||
&DisplayItem::PushStackingContext(ref stacking_context_item) => {
|
&DisplayItem::PushStackingContext(ref stacking_context_item) => {
|
||||||
let stacking_context = &stacking_context_item.stacking_context;
|
let stacking_context = &stacking_context_item.stacking_context;
|
||||||
debug_assert!(stacking_context.context_type == StackingContextType::Real);
|
debug_assert!(stacking_context.context_type == StackingContextType::Real);
|
||||||
|
builder.push_stacking_context(
|
||||||
let stacking_context_id =
|
|
||||||
stacking_context.convert_to_webrender(traversal,
|
stacking_context.convert_to_webrender(traversal,
|
||||||
api,
|
api,
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
epoch,
|
epoch,
|
||||||
frame_builder);
|
frame_builder,
|
||||||
builder.push_stacking_context(stacking_context_id);
|
None));
|
||||||
|
|
||||||
}
|
}
|
||||||
&DisplayItem::PopStackingContext(_) => return,
|
&DisplayItem::PushScrollRoot(ref item) => {
|
||||||
|
let stacking_context = StackingContext::new(
|
||||||
|
StackingContextId::new(0),
|
||||||
|
StackingContextType::Real,
|
||||||
|
&item.scroll_root.clip,
|
||||||
|
&TypedRect::new(Point2D::zero(), item.scroll_root.size),
|
||||||
|
0,
|
||||||
|
filter::T::new(Vec::new()),
|
||||||
|
mix_blend_mode::T::normal,
|
||||||
|
Matrix4D::identity(),
|
||||||
|
Matrix4D::identity(),
|
||||||
|
true,
|
||||||
|
ScrollPolicy::Scrollable,
|
||||||
|
ScrollRootId::root());
|
||||||
|
let scroll_layer_id =
|
||||||
|
Some(frame_builder.next_scroll_layer_id(item.scroll_root.id));
|
||||||
|
builder.push_stacking_context(
|
||||||
|
stacking_context.convert_to_webrender(traversal,
|
||||||
|
api,
|
||||||
|
pipeline_id,
|
||||||
|
epoch,
|
||||||
|
frame_builder,
|
||||||
|
scroll_layer_id));
|
||||||
|
}
|
||||||
|
&DisplayItem::PopStackingContext(_) | &DisplayItem::PopScrollRoot(_) => return,
|
||||||
_ => item.convert_to_webrender(builder, frame_builder),
|
_ => item.convert_to_webrender(builder, frame_builder),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,21 +279,14 @@ impl WebRenderStackingContextConverter for StackingContext {
|
||||||
api: &mut webrender_traits::RenderApi,
|
api: &mut webrender_traits::RenderApi,
|
||||||
pipeline_id: webrender_traits::PipelineId,
|
pipeline_id: webrender_traits::PipelineId,
|
||||||
epoch: webrender_traits::Epoch,
|
epoch: webrender_traits::Epoch,
|
||||||
frame_builder: &mut WebRenderFrameBuilder)
|
frame_builder: &mut WebRenderFrameBuilder,
|
||||||
|
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
|
||||||
-> webrender_traits::StackingContextId {
|
-> webrender_traits::StackingContextId {
|
||||||
let webrender_scroll_policy = match self.scroll_policy {
|
let webrender_scroll_policy = match self.scroll_policy {
|
||||||
ScrollPolicy::Scrollable => webrender_traits::ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable => webrender_traits::ScrollPolicy::Scrollable,
|
||||||
ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed,
|
ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed,
|
||||||
};
|
};
|
||||||
|
|
||||||
let scroll_layer_id = if let Some(scroll_root_id) = self.overflow_scroll_id {
|
|
||||||
Some(frame_builder.next_scroll_layer_id(scroll_root_id))
|
|
||||||
} else if self.id == StackingContextId::root() {
|
|
||||||
Some(frame_builder.next_scroll_layer_id(ScrollRootId::root()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut sc =
|
let mut sc =
|
||||||
webrender_traits::StackingContext::new(scroll_layer_id,
|
webrender_traits::StackingContext::new(scroll_layer_id,
|
||||||
webrender_scroll_policy,
|
webrender_scroll_policy,
|
||||||
|
@ -310,11 +326,14 @@ impl WebRenderDisplayListConverter for DisplayList {
|
||||||
match item {
|
match item {
|
||||||
Some(&DisplayItem::PushStackingContext(ref stacking_context_item)) => {
|
Some(&DisplayItem::PushStackingContext(ref stacking_context_item)) => {
|
||||||
let stacking_context = &stacking_context_item.stacking_context;
|
let stacking_context = &stacking_context_item.stacking_context;
|
||||||
|
let scroll_layer_id =
|
||||||
|
Some(frame_builder.next_scroll_layer_id(ScrollRootId::root()));
|
||||||
stacking_context.convert_to_webrender(&mut traversal,
|
stacking_context.convert_to_webrender(&mut traversal,
|
||||||
api,
|
api,
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
epoch,
|
epoch,
|
||||||
frame_builder)
|
frame_builder,
|
||||||
|
scroll_layer_id)
|
||||||
}
|
}
|
||||||
_ => unreachable!("DisplayList did not start with StackingContext."),
|
_ => unreachable!("DisplayList did not start with StackingContext."),
|
||||||
|
|
||||||
|
@ -453,7 +472,11 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
item.base.clip.to_clip_region(frame_builder),
|
item.base.clip.to_clip_region(frame_builder),
|
||||||
pipeline_id);
|
pipeline_id);
|
||||||
}
|
}
|
||||||
DisplayItem::PushStackingContext(_) | DisplayItem::PopStackingContext(_) => {}
|
DisplayItem::PushStackingContext(_) |
|
||||||
|
DisplayItem::PopStackingContext(_) |
|
||||||
|
DisplayItem::PushScrollRoot(_) |
|
||||||
|
DisplayItem::PopScrollRoot(_) =>
|
||||||
|
unreachable!("Tried to convert a scroll root or stacking context structure item."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,8 @@ use euclid::rect::Rect;
|
||||||
use euclid::scale_factor::ScaleFactor;
|
use euclid::scale_factor::ScaleFactor;
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use fnv::FnvHasher;
|
use fnv::FnvHasher;
|
||||||
use gfx::display_list::{ClippingRegion, OpaqueNode, WebRenderImageInfo};
|
use gfx::display_list::{ClippingRegion, OpaqueNode};
|
||||||
|
use gfx::display_list::WebRenderImageInfo;
|
||||||
use gfx::font;
|
use gfx::font;
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use gfx::font_context;
|
use gfx::font_context;
|
||||||
|
@ -905,8 +906,8 @@ impl LayoutThread {
|
||||||
match (data.goal, display_list_needed) {
|
match (data.goal, display_list_needed) {
|
||||||
(ReflowGoal::ForDisplay, _) | (ReflowGoal::ForScriptQuery, true) => {
|
(ReflowGoal::ForDisplay, _) | (ReflowGoal::ForScriptQuery, true) => {
|
||||||
let mut build_state =
|
let mut build_state =
|
||||||
sequential::build_display_list_for_subtree(layout_root,
|
sequential::build_display_list_for_subtree(layout_root,
|
||||||
shared_layout_context);
|
shared_layout_context);
|
||||||
|
|
||||||
debug!("Done building display list.");
|
debug!("Done building display list.");
|
||||||
|
|
||||||
|
|
4
components/servo/Cargo.lock
generated
4
components/servo/Cargo.lock
generated
|
@ -2832,7 +2832,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webrender"
|
name = "webrender"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "git+https://github.com/servo/webrender#8b53081a3de714f8c1296e20658fabe4e75a6244"
|
source = "git+https://github.com/servo/webrender#c5eb15a9b8030bbad15809aba7dd1b5906d96397"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2857,7 +2857,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webrender_traits"
|
name = "webrender_traits"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "git+https://github.com/servo/webrender#8b53081a3de714f8c1296e20658fabe4e75a6244"
|
source = "git+https://github.com/servo/webrender#c5eb15a9b8030bbad15809aba7dd1b5906d96397"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
4
ports/cef/Cargo.lock
generated
4
ports/cef/Cargo.lock
generated
|
@ -2690,7 +2690,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webrender"
|
name = "webrender"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "git+https://github.com/servo/webrender#8b53081a3de714f8c1296e20658fabe4e75a6244"
|
source = "git+https://github.com/servo/webrender#c5eb15a9b8030bbad15809aba7dd1b5906d96397"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2715,7 +2715,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webrender_traits"
|
name = "webrender_traits"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "git+https://github.com/servo/webrender#8b53081a3de714f8c1296e20658fabe4e75a6244"
|
source = "git+https://github.com/servo/webrender#c5eb15a9b8030bbad15809aba7dd1b5906d96397"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -9,7 +9,7 @@ flat varying vec4 vClipMaskUvRect;
|
||||||
flat varying vec4 vClipMaskLocalRect;
|
flat varying vec4 vClipMaskLocalRect;
|
||||||
|
|
||||||
#ifdef WR_VERTEX_SHADER
|
#ifdef WR_VERTEX_SHADER
|
||||||
void write_clip(ClipInfo clip) {
|
void write_clip(ClipData clip) {
|
||||||
vClipRect = vec4(clip.rect.rect.xy, clip.rect.rect.xy + clip.rect.rect.zw);
|
vClipRect = vec4(clip.rect.rect.xy, clip.rect.rect.xy + clip.rect.rect.zw);
|
||||||
vClipRadius = vec4(clip.top_left.outer_inner_radius.x,
|
vClipRadius = vec4(clip.top_left.outer_inner_radius.x,
|
||||||
clip.top_right.outer_inner_radius.x,
|
clip.top_right.outer_inner_radius.x,
|
||||||
|
@ -17,8 +17,8 @@ void write_clip(ClipInfo clip) {
|
||||||
clip.bottom_left.outer_inner_radius.x);
|
clip.bottom_left.outer_inner_radius.x);
|
||||||
//TODO: interpolate the final mask UV
|
//TODO: interpolate the final mask UV
|
||||||
vec2 texture_size = textureSize(sMask, 0);
|
vec2 texture_size = textureSize(sMask, 0);
|
||||||
vClipMaskUvRect = clip.mask_info.uv_rect / texture_size.xyxy;
|
vClipMaskUvRect = clip.mask_data.uv_rect / texture_size.xyxy;
|
||||||
vClipMaskLocalRect = clip.mask_info.local_rect; //TODO: transform
|
vClipMaskLocalRect = clip.mask_data.local_rect; //TODO: transform
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -347,13 +347,13 @@ ClipRect fetch_clip_rect(int index) {
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ImageMaskInfo {
|
struct ImageMaskData {
|
||||||
vec4 uv_rect;
|
vec4 uv_rect;
|
||||||
vec4 local_rect;
|
vec4 local_rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageMaskInfo fetch_mask_info(int index) {
|
ImageMaskData fetch_mask_data(int index) {
|
||||||
ImageMaskInfo info;
|
ImageMaskData info;
|
||||||
|
|
||||||
ivec2 uv = get_fetch_uv_2(index);
|
ivec2 uv = get_fetch_uv_2(index);
|
||||||
|
|
||||||
|
@ -379,24 +379,24 @@ ClipCorner fetch_clip_corner(int index) {
|
||||||
return corner;
|
return corner;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ClipInfo {
|
struct ClipData {
|
||||||
ClipRect rect;
|
ClipRect rect;
|
||||||
ClipCorner top_left;
|
ClipCorner top_left;
|
||||||
ClipCorner top_right;
|
ClipCorner top_right;
|
||||||
ClipCorner bottom_left;
|
ClipCorner bottom_left;
|
||||||
ClipCorner bottom_right;
|
ClipCorner bottom_right;
|
||||||
ImageMaskInfo mask_info;
|
ImageMaskData mask_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
ClipInfo fetch_clip(int index) {
|
ClipData fetch_clip(int index) {
|
||||||
ClipInfo clip;
|
ClipData clip;
|
||||||
|
|
||||||
clip.rect = fetch_clip_rect(index + 0);
|
clip.rect = fetch_clip_rect(index + 0);
|
||||||
clip.top_left = fetch_clip_corner(index + 1);
|
clip.top_left = fetch_clip_corner(index + 1);
|
||||||
clip.top_right = fetch_clip_corner(index + 2);
|
clip.top_right = fetch_clip_corner(index + 2);
|
||||||
clip.bottom_left = fetch_clip_corner(index + 3);
|
clip.bottom_left = fetch_clip_corner(index + 3);
|
||||||
clip.bottom_right = fetch_clip_corner(index + 4);
|
clip.bottom_right = fetch_clip_corner(index + 4);
|
||||||
clip.mask_info = fetch_mask_info(index + 5);
|
clip.mask_data = fetch_mask_data(index + 5);
|
||||||
|
|
||||||
return clip;
|
return clip;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,6 @@ void main(void) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipInfo clip = fetch_clip(prim.clip_index);
|
ClipData clip = fetch_clip(prim.clip_index);
|
||||||
write_clip(clip);
|
write_clip(clip);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ void main(void) {
|
||||||
vLocalPos = vi.local_clamped_pos;
|
vLocalPos = vi.local_clamped_pos;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ClipInfo clip = fetch_clip(prim.clip_index);
|
ClipData clip = fetch_clip(prim.clip_index);
|
||||||
write_clip(clip);
|
write_clip(clip);
|
||||||
|
|
||||||
// vUv will contain how many times this image has wrapped around the image size.
|
// vUv will contain how many times this image has wrapped around the image size.
|
||||||
|
|
|
@ -22,6 +22,6 @@ void main(void) {
|
||||||
vPos = vi.local_clamped_pos;
|
vPos = vi.local_clamped_pos;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ClipInfo clip = fetch_clip(prim.clip_index);
|
ClipData clip = fetch_clip(prim.clip_index);
|
||||||
write_clip(clip);
|
write_clip(clip);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[abspos-overflow-010.htm]
|
|
||||||
type: reftest
|
|
||||||
expected:
|
|
||||||
if os == "linux": FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[abspos-overflow-011.htm]
|
|
||||||
type: reftest
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[max-width-106.htm]
|
|
||||||
type: reftest
|
|
||||||
expected: FAIL
|
|
|
@ -5016,6 +5016,30 @@
|
||||||
"url": "/_mozilla/css/stacking_context_rtl.html"
|
"url": "/_mozilla/css/stacking_context_rtl.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"css/stacking_order_overflow_auto.html": [
|
||||||
|
{
|
||||||
|
"path": "css/stacking_order_overflow_auto.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/stacking_order_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/stacking_order_overflow_auto.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"css/stacking_order_overflow_scroll.html": [
|
||||||
|
{
|
||||||
|
"path": "css/stacking_order_overflow_scroll.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/stacking_order_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/stacking_order_overflow_scroll.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"css/style_is_in_doc.html": [
|
"css/style_is_in_doc.html": [
|
||||||
{
|
{
|
||||||
"path": "css/style_is_in_doc.html",
|
"path": "css/style_is_in_doc.html",
|
||||||
|
@ -19848,6 +19872,30 @@
|
||||||
"url": "/_mozilla/css/stacking_context_rtl.html"
|
"url": "/_mozilla/css/stacking_context_rtl.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"css/stacking_order_overflow_auto.html": [
|
||||||
|
{
|
||||||
|
"path": "css/stacking_order_overflow_auto.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/stacking_order_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/stacking_order_overflow_auto.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"css/stacking_order_overflow_scroll.html": [
|
||||||
|
{
|
||||||
|
"path": "css/stacking_order_overflow_scroll.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/stacking_order_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/stacking_order_overflow_scroll.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"css/style_is_in_doc.html": [
|
"css/style_is_in_doc.html": [
|
||||||
{
|
{
|
||||||
"path": "css/style_is_in_doc.html",
|
"path": "css/style_is_in_doc.html",
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>The position:absolute element should be on top of the overflow:auto element</title>
|
||||||
|
<link rel='match' href='stacking_order_ref.html'>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbox {
|
||||||
|
margin: 50px;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
overflow: auto;
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
left: 50px;
|
||||||
|
top: 50px;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="overlay"></div>
|
||||||
|
<div class="scrollbox"></div>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>The position:absolute element should be on top of the overflow:scroll element</title>
|
||||||
|
<link rel='match' href='stacking_order_ref.html'>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbox {
|
||||||
|
margin: 50px;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
overflow: scroll;
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
left: 50px;
|
||||||
|
top: 50px;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="overlay"></div>
|
||||||
|
<div class="scrollbox"></div>
|
20
tests/wpt/mozilla/tests/css/stacking_order_ref.html
Normal file
20
tests/wpt/mozilla/tests/css/stacking_order_ref.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
position: absolute;
|
||||||
|
left: 50px;
|
||||||
|
top: 50px;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="box"></div>
|
Loading…
Add table
Add a link
Reference in a new issue