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,
|
||||
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) {
|
||||
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,
|
||||
traversal: &mut DisplayListTraversal<'a>,
|
||||
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.
|
||||
debug_assert!(stacking_context.context_type == StackingContextType::Real);
|
||||
let is_fixed = stacking_context.scroll_policy == ScrollPolicy::FixedPosition;
|
||||
let mut translated_point = if is_fixed {
|
||||
let translated_point = if is_fixed {
|
||||
*client_point
|
||||
} else {
|
||||
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))
|
||||
};
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -138,9 +151,10 @@ impl DisplayList {
|
|||
pub fn print_with_tree(&self, print_tree: &mut PrintTree) {
|
||||
print_tree.new_level("Items".to_owned());
|
||||
for item in &self.list {
|
||||
print_tree.add_item(format!("{:?} StackingContext: {:?}",
|
||||
print_tree.add_item(format!("{:?} StackingContext: {:?} ScrollRoot: {:?}",
|
||||
item,
|
||||
item.base().stacking_context_id));
|
||||
item.base().stacking_context_id,
|
||||
item.scroll_root_id()));
|
||||
}
|
||||
print_tree.end_level();
|
||||
}
|
||||
|
@ -250,6 +264,7 @@ pub enum StackingContextType {
|
|||
Real,
|
||||
PseudoPositioned,
|
||||
PseudoFloat,
|
||||
PseudoScrollingArea,
|
||||
}
|
||||
|
||||
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
||||
|
@ -291,8 +306,8 @@ pub struct StackingContext {
|
|||
/// Children of this StackingContext.
|
||||
pub children: Vec<StackingContext>,
|
||||
|
||||
/// If this StackingContext scrolls its overflow area, this will contain the id.
|
||||
pub overflow_scroll_id: Option<ScrollRootId>,
|
||||
/// The id of the parent scrolling area that contains this StackingContext.
|
||||
pub parent_scroll_id: ScrollRootId,
|
||||
}
|
||||
|
||||
impl StackingContext {
|
||||
|
@ -309,7 +324,7 @@ impl StackingContext {
|
|||
perspective: Matrix4D<f32>,
|
||||
establishes_3d_context: bool,
|
||||
scroll_policy: ScrollPolicy,
|
||||
scroll_root_id: Option<ScrollRootId>)
|
||||
parent_scroll_id: ScrollRootId)
|
||||
-> StackingContext {
|
||||
StackingContext {
|
||||
id: id,
|
||||
|
@ -324,7 +339,7 @@ impl StackingContext {
|
|||
establishes_3d_context: establishes_3d_context,
|
||||
scroll_policy: scroll_policy,
|
||||
children: Vec::new(),
|
||||
overflow_scroll_id: scroll_root_id,
|
||||
parent_scroll_id: parent_scroll_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,7 +356,7 @@ impl StackingContext {
|
|||
Matrix4D::identity(),
|
||||
true,
|
||||
ScrollPolicy::Scrollable,
|
||||
None)
|
||||
ScrollRootId::root())
|
||||
}
|
||||
|
||||
pub fn add_child(&mut self, mut child: StackingContext) {
|
||||
|
@ -453,21 +468,40 @@ impl fmt::Debug for StackingContext {
|
|||
"Pseudo-StackingContext"
|
||||
};
|
||||
|
||||
let scrollable_string = if self.overflow_scroll_id.is_some() {
|
||||
" (scrolls overflow area)"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
write!(f, "{}{} at {:?} with overflow {:?}: {:?}",
|
||||
write!(f, "{} at {:?} with overflow {:?}: {:?}",
|
||||
type_string,
|
||||
scrollable_string,
|
||||
self.bounds,
|
||||
self.overflow,
|
||||
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.
|
||||
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
|
||||
pub enum DisplayItem {
|
||||
|
@ -482,6 +516,8 @@ pub enum DisplayItem {
|
|||
Iframe(Box<IframeDisplayItem>),
|
||||
PushStackingContext(Box<PushStackingContextItem>),
|
||||
PopStackingContext(Box<PopStackingContextItem>),
|
||||
PushScrollRoot(Box<PushScrollRootItem>),
|
||||
PopScrollRoot(Box<BaseDisplayItem>),
|
||||
}
|
||||
|
||||
/// Information common to all display items.
|
||||
|
@ -501,6 +537,9 @@ pub struct BaseDisplayItem {
|
|||
|
||||
/// The id of the stacking context this item belongs to.
|
||||
pub stacking_context_id: StackingContextId,
|
||||
|
||||
/// The id of the scroll root this item belongs to.
|
||||
pub scroll_root_id: ScrollRootId,
|
||||
}
|
||||
|
||||
impl BaseDisplayItem {
|
||||
|
@ -509,7 +548,8 @@ impl BaseDisplayItem {
|
|||
metadata: DisplayItemMetadata,
|
||||
clip: &ClippingRegion,
|
||||
section: DisplayListSection,
|
||||
stacking_context_id: StackingContextId)
|
||||
stacking_context_id: StackingContextId,
|
||||
scroll_root_id: ScrollRootId)
|
||||
-> BaseDisplayItem {
|
||||
// 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
|
||||
|
@ -524,6 +564,7 @@ impl BaseDisplayItem {
|
|||
},
|
||||
section: section,
|
||||
stacking_context_id: stacking_context_id,
|
||||
scroll_root_id: scroll_root_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,6 +579,7 @@ impl BaseDisplayItem {
|
|||
clip: ClippingRegion::max(),
|
||||
section: DisplayListSection::Content,
|
||||
stacking_context_id: StackingContextId::root(),
|
||||
scroll_root_id: ScrollRootId::root(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -981,6 +1023,15 @@ pub struct PopStackingContextItem {
|
|||
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.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, HeapSizeOf, Deserialize, Serialize)]
|
||||
|
@ -1009,9 +1060,15 @@ impl DisplayItem {
|
|||
DisplayItem::Iframe(ref iframe) => &iframe.base,
|
||||
DisplayItem::PushStackingContext(ref stacking_context) => &stacking_context.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 {
|
||||
self.base().stacking_context_id
|
||||
}
|
||||
|
@ -1090,6 +1147,14 @@ impl fmt::Debug for DisplayItem {
|
|||
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, "{} @ {:?} {:?}",
|
||||
match *self {
|
||||
DisplayItem::SolidColor(ref solid_color) =>
|
||||
|
@ -1106,8 +1171,10 @@ impl fmt::Debug for DisplayItem {
|
|||
DisplayItem::Line(_) => "Line".to_owned(),
|
||||
DisplayItem::BoxShadow(_) => "BoxShadow".to_owned(),
|
||||
DisplayItem::Iframe(_) => "Iframe".to_owned(),
|
||||
DisplayItem::PushStackingContext(_) => "".to_owned(),
|
||||
DisplayItem::PopStackingContext(_) => "".to_owned(),
|
||||
DisplayItem::PushStackingContext(_) |
|
||||
DisplayItem::PopStackingContext(_) |
|
||||
DisplayItem::PushScrollRoot(_) |
|
||||
DisplayItem::PopScrollRoot(_) => "".to_owned(),
|
||||
},
|
||||
self.bounds(),
|
||||
self.base().clip
|
||||
|
|
|
@ -211,6 +211,11 @@ impl ScrollRootId {
|
|||
pub fn fragment_type(&self) -> FragmentType {
|
||||
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.
|
||||
|
|
|
@ -1941,17 +1941,6 @@ impl Flow for BlockFlow {
|
|||
}
|
||||
|
||||
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,
|
||||
container_size);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ use block::{BlockFlow, BlockStackingContextType};
|
|||
use canvas_traits::{CanvasData, CanvasMsg, FromLayoutMsg};
|
||||
use context::SharedLayoutContext;
|
||||
use euclid::{Matrix4D, Point2D, Radians, Rect, SideOffsets2D, Size2D};
|
||||
use euclid::point::TypedPoint2D;
|
||||
use flex::FlexFlow;
|
||||
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
|
||||
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::{GradientDisplayItem, IframeDisplayItem, ImageDisplayItem};
|
||||
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_traits::{ScrollPolicy, ScrollRootId, StackingContextId};
|
||||
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
|
||||
|
@ -42,8 +43,8 @@ use std::mem;
|
|||
use std::sync::Arc;
|
||||
use style::computed_values::{background_attachment, background_clip, background_origin};
|
||||
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::{transform, transform_style, visibility};
|
||||
use style::computed_values::{cursor, image_rendering, overflow_x};
|
||||
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::filter::Filter;
|
||||
use style::computed_values::text_shadow::TextShadow;
|
||||
|
@ -95,6 +96,7 @@ pub struct DisplayListBuildState<'a> {
|
|||
pub shared_layout_context: &'a SharedLayoutContext,
|
||||
pub root_stacking_context: StackingContext,
|
||||
pub items: HashMap<StackingContextId, Vec<DisplayItem>>,
|
||||
pub scroll_roots: HashMap<ScrollRootId, ScrollRoot>,
|
||||
pub stacking_context_id_stack: Vec<StackingContextId>,
|
||||
pub scroll_root_id_stack: Vec<ScrollRootId>,
|
||||
}
|
||||
|
@ -107,6 +109,7 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
shared_layout_context: shared_layout_context,
|
||||
root_stacking_context: StackingContext::root(),
|
||||
items: HashMap::new(),
|
||||
scroll_roots: HashMap::new(),
|
||||
stacking_context_id_stack: vec!(stacking_context_id),
|
||||
scroll_root_id_stack: vec!(ScrollRootId::root()),
|
||||
}
|
||||
|
@ -117,6 +120,11 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
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 {
|
||||
self.stacking_context_id_stack.last().unwrap().clone()
|
||||
}
|
||||
|
@ -126,14 +134,19 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
}
|
||||
|
||||
pub fn pop_stacking_context_id(&mut self) {
|
||||
self.stacking_context_id_stack.pop();
|
||||
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()
|
||||
}
|
||||
|
||||
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) {
|
||||
self.scroll_root_id_stack.push(id);
|
||||
}
|
||||
|
@ -157,14 +170,18 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
},
|
||||
&clip,
|
||||
section,
|
||||
self.stacking_context_id())
|
||||
self.stacking_context_id(),
|
||||
self.scroll_root_id())
|
||||
}
|
||||
|
||||
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 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 {
|
||||
list: list,
|
||||
|
@ -173,7 +190,8 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
|
||||
fn to_display_list_for_stacking_context(&mut self,
|
||||
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());
|
||||
child_items.sort_by(|a, b| a.base().section.cmp(&b.base().section));
|
||||
child_items.reverse();
|
||||
|
@ -186,63 +204,114 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
if !real_stacking_context {
|
||||
self.to_display_list_for_items(list,
|
||||
child_items,
|
||||
child_stacking_contexts);
|
||||
child_stacking_contexts,
|
||||
scroll_root_stack);
|
||||
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();
|
||||
list.push(push_item);
|
||||
self.to_display_list_for_items(list,
|
||||
child_items,
|
||||
child_stacking_contexts);
|
||||
child_stacking_contexts,
|
||||
&mut scroll_root_stack);
|
||||
list.push(pop_item);
|
||||
}
|
||||
|
||||
fn to_display_list_for_items(&mut self,
|
||||
list: &mut 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
|
||||
// refer to the steps in CSS 2.1 Appendix E.
|
||||
// Steps 1 and 2: Borders and background for the root.
|
||||
while child_items.last().map_or(false,
|
||||
|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.
|
||||
let mut child_stacking_contexts = child_stacking_contexts.into_iter().peekable();
|
||||
while child_stacking_contexts.peek().map_or(false, |child| child.z_index < 0) {
|
||||
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.
|
||||
while child_items.last().map_or(false,
|
||||
|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.
|
||||
while child_stacking_contexts.peek().map_or(false,
|
||||
|child| child.context_type == StackingContextType::PseudoFloat) {
|
||||
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.
|
||||
while child_items.last().map_or(false,
|
||||
|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.
|
||||
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.
|
||||
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,
|
||||
scroll_policy: ScrollPolicy,
|
||||
mode: StackingContextCreationMode,
|
||||
scroll_root_id: Option<ScrollRootId>)
|
||||
parent_scroll_id: ScrollRootId)
|
||||
-> StackingContext;
|
||||
|
||||
/// Returns the 4D matrix representing this fragment's transform.
|
||||
|
@ -1476,9 +1545,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
base_flow: &BaseFlow,
|
||||
scroll_policy: ScrollPolicy,
|
||||
mode: StackingContextCreationMode,
|
||||
scroll_root_id: Option<ScrollRootId>)
|
||||
parent_scroll_id: ScrollRootId)
|
||||
-> StackingContext {
|
||||
let scrolls_overflow_area = mode == StackingContextCreationMode::ScrollWrapper;
|
||||
let border_box =
|
||||
self.stacking_relative_border_box(&base_flow.stacking_relative_position,
|
||||
&base_flow.early_absolute_position_info
|
||||
|
@ -1486,16 +1554,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
base_flow.early_absolute_position_info
|
||||
.relative_containing_block_mode,
|
||||
CoordinateSystem::Parent);
|
||||
let overflow = if scrolls_overflow_area {
|
||||
Rect::new(Point2D::zero(), base_flow.overflow.scroll.size)
|
||||
} else {
|
||||
// First, compute the offset of our border box (including relative positioning)
|
||||
// from our flow origin, since that is what `BaseFlow::overflow` is relative to.
|
||||
let 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)
|
||||
};
|
||||
// First, compute the offset of our border box (including relative positioning)
|
||||
// from our flow origin, since that is what `BaseFlow::overflow` is relative to.
|
||||
let border_box_offset =
|
||||
border_box.translate(&-base_flow.stacking_relative_position).origin;
|
||||
// Then, using that, compute our overflow region relative to our border box.
|
||||
let overflow = base_flow.overflow.paint.translate(&-border_box_offset);
|
||||
|
||||
let transform = self.transform_matrix(&border_box);
|
||||
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 establishes_3d_context = scrolls_overflow_area ||
|
||||
transform_style == transform_style::T::flat;
|
||||
let establishes_3d_context = transform_style == transform_style::T::flat;
|
||||
|
||||
let context_type = match mode {
|
||||
StackingContextCreationMode::PseudoFloat => StackingContextType::PseudoFloat,
|
||||
|
@ -1551,7 +1614,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
perspective,
|
||||
establishes_3d_context,
|
||||
scroll_policy,
|
||||
scroll_root_id)
|
||||
parent_scroll_id)
|
||||
}
|
||||
|
||||
fn adjust_clipping_region_for_children(&self,
|
||||
|
@ -1829,18 +1892,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
fn collect_stacking_contexts_for_block(&mut self,
|
||||
parent: &mut StackingContext,
|
||||
parent_scroll_root_id: ScrollRootId) {
|
||||
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, 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 {
|
||||
let scroll_root_id = if self.has_scrolling_overflow() {
|
||||
ScrollRootId::new_of_type(self.fragment.node.id() as usize,
|
||||
self.fragment.fragment_type())
|
||||
} else {
|
||||
|
@ -1848,7 +1900,15 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
};
|
||||
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;
|
||||
|
||||
if block_stacking_context_type == BlockStackingContextType::PseudoStackingContext {
|
||||
|
@ -1864,7 +1924,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
&self.base,
|
||||
ScrollPolicy::Scrollable,
|
||||
creation_mode,
|
||||
None);
|
||||
parent_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();
|
||||
|
||||
|
@ -1888,20 +1948,13 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
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(
|
||||
stacking_context_id,
|
||||
&self.base,
|
||||
scroll_policy,
|
||||
creation_mode,
|
||||
internal_id);
|
||||
StackingContextCreationMode::Normal,
|
||||
parent_scroll_root_id);
|
||||
self.base.collect_stacking_contexts_for_children(&mut stacking_context, scroll_root_id);
|
||||
|
||||
parent.add_child(stacking_context);
|
||||
}
|
||||
|
||||
|
@ -1921,6 +1974,28 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
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.
|
||||
self.fragment
|
||||
.build_display_list(state,
|
||||
|
@ -2025,7 +2100,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
|||
&self.base,
|
||||
ScrollPolicy::Scrollable,
|
||||
StackingContextCreationMode::Normal,
|
||||
None));
|
||||
parent_scroll_root_id));
|
||||
}
|
||||
_ => fragment.stacking_context_id = parent.id,
|
||||
}
|
||||
|
@ -2229,7 +2304,6 @@ pub enum BorderPaintingMode<'a> {
|
|||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum StackingContextCreationMode {
|
||||
Normal,
|
||||
ScrollWrapper,
|
||||
PseudoPositioned,
|
||||
PseudoFloat,
|
||||
}
|
||||
|
|
|
@ -2595,8 +2595,6 @@ impl Fragment {
|
|||
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,
|
||||
self.style().get_position().z_index,
|
||||
self.style().get_box().overflow_x,
|
||||
|
@ -2615,11 +2613,7 @@ impl Fragment {
|
|||
overflow_x::T::visible) => false,
|
||||
(position::T::absolute, _, _, _) |
|
||||
(position::T::fixed, _, _, _) |
|
||||
(position::T::relative, _, _, _) |
|
||||
(_, _, overflow_x::T::auto, _) |
|
||||
(_, _, overflow_x::T::scroll, _) |
|
||||
(_, _, _, overflow_x::T::auto) |
|
||||
(_, _, _, overflow_x::T::scroll) => true,
|
||||
(position::T::relative, _, _, _) => true,
|
||||
(position::T::static_, _, _, _) => false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,34 +271,34 @@ pub struct BuildDisplayList<'a> {
|
|||
impl<'a> BuildDisplayList<'a> {
|
||||
#[inline]
|
||||
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() {
|
||||
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::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) {
|
||||
self.traverse(kid);
|
||||
}
|
||||
|
||||
if new_stacking_context {
|
||||
self.state.pop_stacking_context_id();
|
||||
}
|
||||
|
||||
if new_scroll_root {
|
||||
self.state.pop_scroll_root_id();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// completely converting layout to directly generate WebRender display lists, for example.
|
||||
|
||||
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::{DisplayItem, DisplayList, DisplayListTraversal};
|
||||
use gfx::display_list::{StackingContext, StackingContextType};
|
||||
|
@ -24,7 +24,8 @@ trait WebRenderStackingContextConverter {
|
|||
api: &mut webrender_traits::RenderApi,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
epoch: webrender_traits::Epoch,
|
||||
frame_builder: &mut WebRenderFrameBuilder)
|
||||
frame_builder: &mut WebRenderFrameBuilder,
|
||||
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
|
||||
-> webrender_traits::StackingContextId;
|
||||
|
||||
fn convert_children_to_webrender<'a>(&self,
|
||||
|
@ -235,17 +236,39 @@ impl WebRenderStackingContextConverter for StackingContext {
|
|||
&DisplayItem::PushStackingContext(ref stacking_context_item) => {
|
||||
let stacking_context = &stacking_context_item.stacking_context;
|
||||
debug_assert!(stacking_context.context_type == StackingContextType::Real);
|
||||
|
||||
let stacking_context_id =
|
||||
builder.push_stacking_context(
|
||||
stacking_context.convert_to_webrender(traversal,
|
||||
api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
frame_builder);
|
||||
builder.push_stacking_context(stacking_context_id);
|
||||
|
||||
frame_builder,
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -256,21 +279,14 @@ impl WebRenderStackingContextConverter for StackingContext {
|
|||
api: &mut webrender_traits::RenderApi,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
epoch: webrender_traits::Epoch,
|
||||
frame_builder: &mut WebRenderFrameBuilder)
|
||||
frame_builder: &mut WebRenderFrameBuilder,
|
||||
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
|
||||
-> webrender_traits::StackingContextId {
|
||||
let webrender_scroll_policy = match self.scroll_policy {
|
||||
ScrollPolicy::Scrollable => webrender_traits::ScrollPolicy::Scrollable,
|
||||
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 =
|
||||
webrender_traits::StackingContext::new(scroll_layer_id,
|
||||
webrender_scroll_policy,
|
||||
|
@ -310,11 +326,14 @@ impl WebRenderDisplayListConverter for DisplayList {
|
|||
match item {
|
||||
Some(&DisplayItem::PushStackingContext(ref stacking_context_item)) => {
|
||||
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,
|
||||
api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
frame_builder)
|
||||
frame_builder,
|
||||
scroll_layer_id)
|
||||
}
|
||||
_ => unreachable!("DisplayList did not start with StackingContext."),
|
||||
|
||||
|
@ -453,7 +472,11 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
item.base.clip.to_clip_region(frame_builder),
|
||||
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::size::Size2D;
|
||||
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_cache_thread::FontCacheThread;
|
||||
use gfx::font_context;
|
||||
|
@ -905,8 +906,8 @@ impl LayoutThread {
|
|||
match (data.goal, display_list_needed) {
|
||||
(ReflowGoal::ForDisplay, _) | (ReflowGoal::ForScriptQuery, true) => {
|
||||
let mut build_state =
|
||||
sequential::build_display_list_for_subtree(layout_root,
|
||||
shared_layout_context);
|
||||
sequential::build_display_list_for_subtree(layout_root,
|
||||
shared_layout_context);
|
||||
|
||||
debug!("Done building display list.");
|
||||
|
||||
|
|
4
components/servo/Cargo.lock
generated
4
components/servo/Cargo.lock
generated
|
@ -2832,7 +2832,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webrender"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/servo/webrender#8b53081a3de714f8c1296e20658fabe4e75a6244"
|
||||
source = "git+https://github.com/servo/webrender#c5eb15a9b8030bbad15809aba7dd1b5906d96397"
|
||||
dependencies = [
|
||||
"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)",
|
||||
|
@ -2857,7 +2857,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webrender_traits"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/servo/webrender#8b53081a3de714f8c1296e20658fabe4e75a6244"
|
||||
source = "git+https://github.com/servo/webrender#c5eb15a9b8030bbad15809aba7dd1b5906d96397"
|
||||
dependencies = [
|
||||
"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)",
|
||||
|
|
4
ports/cef/Cargo.lock
generated
4
ports/cef/Cargo.lock
generated
|
@ -2690,7 +2690,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webrender"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/servo/webrender#8b53081a3de714f8c1296e20658fabe4e75a6244"
|
||||
source = "git+https://github.com/servo/webrender#c5eb15a9b8030bbad15809aba7dd1b5906d96397"
|
||||
dependencies = [
|
||||
"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)",
|
||||
|
@ -2715,7 +2715,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webrender_traits"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/servo/webrender#8b53081a3de714f8c1296e20658fabe4e75a6244"
|
||||
source = "git+https://github.com/servo/webrender#c5eb15a9b8030bbad15809aba7dd1b5906d96397"
|
||||
dependencies = [
|
||||
"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)",
|
||||
|
|
|
@ -9,7 +9,7 @@ flat varying vec4 vClipMaskUvRect;
|
|||
flat varying vec4 vClipMaskLocalRect;
|
||||
|
||||
#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);
|
||||
vClipRadius = vec4(clip.top_left.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);
|
||||
//TODO: interpolate the final mask UV
|
||||
vec2 texture_size = textureSize(sMask, 0);
|
||||
vClipMaskUvRect = clip.mask_info.uv_rect / texture_size.xyxy;
|
||||
vClipMaskLocalRect = clip.mask_info.local_rect; //TODO: transform
|
||||
vClipMaskUvRect = clip.mask_data.uv_rect / texture_size.xyxy;
|
||||
vClipMaskLocalRect = clip.mask_data.local_rect; //TODO: transform
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -347,13 +347,13 @@ ClipRect fetch_clip_rect(int index) {
|
|||
return rect;
|
||||
}
|
||||
|
||||
struct ImageMaskInfo {
|
||||
struct ImageMaskData {
|
||||
vec4 uv_rect;
|
||||
vec4 local_rect;
|
||||
};
|
||||
|
||||
ImageMaskInfo fetch_mask_info(int index) {
|
||||
ImageMaskInfo info;
|
||||
ImageMaskData fetch_mask_data(int index) {
|
||||
ImageMaskData info;
|
||||
|
||||
ivec2 uv = get_fetch_uv_2(index);
|
||||
|
||||
|
@ -379,24 +379,24 @@ ClipCorner fetch_clip_corner(int index) {
|
|||
return corner;
|
||||
}
|
||||
|
||||
struct ClipInfo {
|
||||
struct ClipData {
|
||||
ClipRect rect;
|
||||
ClipCorner top_left;
|
||||
ClipCorner top_right;
|
||||
ClipCorner bottom_left;
|
||||
ClipCorner bottom_right;
|
||||
ImageMaskInfo mask_info;
|
||||
ImageMaskData mask_data;
|
||||
};
|
||||
|
||||
ClipInfo fetch_clip(int index) {
|
||||
ClipInfo clip;
|
||||
ClipData fetch_clip(int index) {
|
||||
ClipData clip;
|
||||
|
||||
clip.rect = fetch_clip_rect(index + 0);
|
||||
clip.top_left = fetch_clip_corner(index + 1);
|
||||
clip.top_right = fetch_clip_corner(index + 2);
|
||||
clip.bottom_left = fetch_clip_corner(index + 3);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,6 @@ void main(void) {
|
|||
break;
|
||||
}
|
||||
|
||||
ClipInfo clip = fetch_clip(prim.clip_index);
|
||||
ClipData clip = fetch_clip(prim.clip_index);
|
||||
write_clip(clip);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ void main(void) {
|
|||
vLocalPos = vi.local_clamped_pos;
|
||||
#endif
|
||||
|
||||
ClipInfo clip = fetch_clip(prim.clip_index);
|
||||
ClipData clip = fetch_clip(prim.clip_index);
|
||||
write_clip(clip);
|
||||
|
||||
// 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;
|
||||
#endif
|
||||
|
||||
ClipInfo clip = fetch_clip(prim.clip_index);
|
||||
ClipData clip = fetch_clip(prim.clip_index);
|
||||
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"
|
||||
}
|
||||
],
|
||||
"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": [
|
||||
{
|
||||
"path": "css/style_is_in_doc.html",
|
||||
|
@ -19848,6 +19872,30 @@
|
|||
"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": [
|
||||
{
|
||||
"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