Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mix stacking contexts into the positioned content list #8174

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Mix stacking contexts into the positioned content list

Sometimes positioned content needs to be layered on top of stacking
contexts. The layer synthesis code can do this, but the current design
prevents it because stacking contexts are stored in a separate struct
member. In order to preserve tree order, mix stacking contexts into the
positioned content list, by adding a new StackingContextClass
DisplayItem. Such items do not have a base DisplayItem.

In some ways this simplifies the code, because we no longer have to
have a separate code path in the StackingContextLayerCreator.
  • Loading branch information
mrobinson committed Oct 24, 2015
commit f8f9a47304717a455f572f8f8bee300d28649b18

Large diffs are not rendered by default.

@@ -40,7 +40,6 @@ impl DisplayListOptimizer {
display_list.positioned_content.iter());
self.add_in_bounds_display_items(&mut result.outlines,
display_list.outlines.iter());
self.add_in_bounds_stacking_contexts(&mut result.children, display_list.children.iter());
result
}

@@ -50,39 +49,49 @@ impl DisplayListOptimizer {
display_items: I)
where I: Iterator<Item=&'a DisplayItem> {
for display_item in display_items {
if self.visible_rect.intersects(&display_item.base().bounds) &&
display_item.base().clip.might_intersect_rect(&self.visible_rect) {
result_list.push_back((*display_item).clone())
if !self.should_include_display_item(display_item) {
continue;
}
result_list.push_back((*display_item).clone())
}
}

/// Adds child stacking contexts whose boundaries intersect the visible rect to `result_list`.
fn add_in_bounds_stacking_contexts<'a, I>(&self,
result_list: &mut LinkedList<Arc<StackingContext>>,
stacking_contexts: I)
where I: Iterator<Item=&'a Arc<StackingContext>> {
for stacking_context in stacking_contexts {
// Transform this stacking context to get it into the same space as
// the parent stacking context.
let origin_x = stacking_context.bounds.origin.x.to_f32_px();
let origin_y = stacking_context.bounds.origin.y.to_f32_px();

let transform = Matrix4::identity().translate(origin_x,
origin_y,
0.0)
.mul(&stacking_context.transform);
let transform_2d = Matrix2D::new(transform.m11, transform.m12,
transform.m21, transform.m22,
transform.m41, transform.m42);
fn should_include_display_item(&self, item: &DisplayItem) -> bool {
if let &DisplayItem::StackingContextClass(ref stacking_context) = item {
return self.should_include_stacking_context(stacking_context);
}

let overflow = geometry::au_rect_to_f32_rect(stacking_context.overflow);
let overflow = transform_2d.transform_rect(&overflow);
let overflow = geometry::f32_rect_to_au_rect(overflow);
if !self.visible_rect.intersects(&item.bounds()) {
return false;
}

if self.visible_rect.intersects(&overflow) {
result_list.push_back((*stacking_context).clone())
if let Some(base_item) = item.base() {
if !base_item.clip.might_intersect_rect(&self.visible_rect) {
return false;
}
}

true
}

fn should_include_stacking_context(&self, stacking_context: &Arc<StackingContext>) -> bool {
// Transform this stacking context to get it into the same space as
// the parent stacking context.
let origin_x = stacking_context.bounds.origin.x.to_f32_px();
let origin_y = stacking_context.bounds.origin.y.to_f32_px();

let transform = Matrix4::identity().translate(origin_x,
origin_y,
0.0)
.mul(&stacking_context.transform);
let transform_2d = Matrix2D::new(transform.m11, transform.m12,
transform.m21, transform.m22,
transform.m41, transform.m42);

let overflow = geometry::au_rect_to_f32_rect(stacking_context.overflow);
let overflow = transform_2d.transform_rect(&overflow);
let overflow = geometry::f32_rect_to_au_rect(overflow);

self.visible_rect.intersects(&overflow)
}
}
@@ -8,7 +8,7 @@ use app_units::Au;
use azure::AzFloat;
use azure::azure_hl::{BackendType, Color, DrawTarget, SurfaceFormat};
use canvas_traits::CanvasMsg;
use display_list::{DisplayList, LayerInfo, StackingContext};
use display_list::{DisplayItem, DisplayList, LayerInfo, StackingContext};
use euclid::Matrix4;
use euclid::point::Point2D;
use euclid::rect::Rect;
@@ -499,13 +499,16 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
transform: &Matrix4,
perspective: &Matrix4,
parent_id: Option<LayerId>) {
for kid in stacking_context.display_list.children.iter() {
build_from_stacking_context(properties,
&kid,
&parent_origin,
&transform,
&perspective,
parent_id)
for kid in stacking_context.display_list.positioned_content.iter() {
if let &DisplayItem::StackingContextClass(ref stacking_context) = kid {
build_from_stacking_context(properties,
&stacking_context,
&parent_origin,
&transform,
&perspective,
parent_id)

}
}

for kid in stacking_context.display_list.layered_children.iter() {
@@ -81,7 +81,8 @@ impl DisplayListBuildingResult {
match *self {
DisplayListBuildingResult::None => return,
DisplayListBuildingResult::StackingContext(ref mut stacking_context) => {
display_list.children.push_back((*stacking_context).clone())
display_list.positioned_content.push_back(
DisplayItem::StackingContextClass((*stacking_context).clone()))
}
DisplayListBuildingResult::Normal(ref mut source_display_list) => {
display_list.append_from(&mut **source_display_list)
@@ -1684,11 +1685,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow {

let stacking_context = match outer_display_list_for_overflow_scroll {
Some(mut outer_display_list) => {
outer_display_list.children.push_back(self.fragment.create_stacking_context(
&self.base,
display_list,
scroll_policy,
StackingContextCreationMode::InnerScrollWrapper));
outer_display_list.positioned_content.push_back(
DisplayItem::StackingContextClass(self.fragment.create_stacking_context(
&self.base,
display_list,
scroll_policy,
StackingContextCreationMode::InnerScrollWrapper)));
self.fragment.create_stacking_context(
&self.base,
outer_display_list,
@@ -1114,13 +1114,15 @@ impl BaseFlow {
};

for item in &all_items {
let paint_bounds = item.base().clip.clone().intersect_rect(&item.base().bounds);
if !paint_bounds.might_be_nonempty() {
continue;
}
if let Some(base_item) = item.base() {
let paint_bounds = base_item.clip.clone().intersect_rect(&base_item.bounds);
if !paint_bounds.might_be_nonempty() {
continue;
}

if bounds.union(&paint_bounds.bounding_rect()) != bounds {
error!("DisplayList item {:?} outside of Flow overflow ({:?})", item, paint_bounds);
if bounds.union(&paint_bounds.bounding_rect()) != bounds {
error!("DisplayList item {:?} outside of Flow overflow ({:?})", item, paint_bounds);
}
}
}
}
@@ -22,6 +22,13 @@
<div class="gray box" style="margin-left: 20px; margin-top: 10px; position: absolute; top: 20px; z-index: 5;"> </div>
</div>

<!-- These divs should be stacked in tree order, even though the second one
initiates a stacking context and the third one does not. -->
<div class="test grayest box">
<div class="grayer box" style="transform: translateX(10px) translateY(10px);"> </div>
<div class="gray box" style="top: -30px; left: 20px; position: relative; "></div>
</div>

<!-- The z-index of the second box should be ignored since it is not a positioned element.
so these boxes stack in tree order. -->
<div class="test grayest box">
@@ -20,6 +20,11 @@
<div class="gray box" style="margin-left: 20px; margin-top: 10px; position: absolute; top: 20px; z-index: 5;"></div>
</div>

<div class="test grayest box">
<div class="grayer box" style="margin-left: 10px; margin-top: 10px;"></div>
<div class="gray box" style="margin-left: 20px; margin-top: -40px;"></div>
</div>

<div class="test grayest box">
<div class="grayer box" style="margin-left: 10px; margin-top: 10px; position: absolute; opacity: 0.999;"></div>
<div class="gray box" style="margin-left: 20px; margin-top: 20px; position: relative; opacity: 0.999;"></div>
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.