Ensure unique LayerIds for pseudo-elements

Currently pseudo-elements, like the fragments created for ::before and
::after, with layers will have the same LayerId as the body of their
owning fragments. Instead all LayerIds should be unique.

Fixes #2010.
This commit is contained in:
Martin Robinson 2015-09-08 18:59:30 -07:00
parent 1b6d4daf85
commit 1e6f797268
9 changed files with 128 additions and 41 deletions

View file

@ -48,10 +48,11 @@ use layout_debug;
use layout_task::DISPLAY_PORT_SIZE_FACTOR;
use model::{IntrinsicISizes, MarginCollapseInfo};
use model::{MaybeAuto, CollapsibleMargins, specified, specified_or_none};
use wrapper::PseudoElementType;
use euclid::{Point2D, Rect, Size2D};
use gfx::display_list::{ClippingRegion, DisplayList};
use msg::compositor_msg::LayerId;
use msg::compositor_msg::{LayerId, LayerType};
use rustc_serialize::{Encoder, Encodable};
use std::cmp::{max, min};
use std::fmt;
@ -1977,7 +1978,7 @@ impl Flow for BlockFlow {
let stacking_relative_position_of_display_port_for_children =
if is_stacking_context || self.is_root() {
let visible_rect =
match layout_context.shared.visible_rects.get(&self.layer_id(0)) {
match layout_context.shared.visible_rects.get(&self.layer_id()) {
Some(visible_rect) => *visible_rect,
None => Rect::new(Point2D::zero(), layout_context.shared.screen_size),
};
@ -2075,11 +2076,17 @@ impl Flow for BlockFlow {
(self.fragment.border_box - self.fragment.style().logical_border_width()).size
}
fn layer_id(&self, fragment_index: u32) -> LayerId {
// FIXME(#2010, pcwalton): This is a hack and is totally bogus in the presence of pseudo-
// elements. But until we have incremental reflow we can't do better--we recreate the flow
// for every DOM node so otherwise we nuke layers on every reflow.
LayerId(self.fragment.node.id() as usize, fragment_index, 0)
fn layer_id(&self) -> LayerId {
let layer_type = match self.fragment.pseudo {
PseudoElementType::Normal => LayerType::FragmentBody,
PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
PseudoElementType::After(_) => LayerType::AfterPseudoContent
};
LayerId::new_of_type(layer_type, self.fragment.node.id() as usize)
}
fn layer_id_for_overflow_scroll(&self) -> LayerId {
LayerId::new_of_type(LayerType::OverflowScroll, self.fragment.node.id() as usize)
}
fn is_absolute_containing_block(&self) -> bool {

View file

@ -66,11 +66,6 @@ use util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode
use util::opts;
use util::range::Range;
/// The fake fragment ID we use to indicate the inner display list for `overflow: scroll`.
///
/// FIXME(pcwalton): This is pretty ugly. Consider modifying `LayerId` somehow.
const FAKE_FRAGMENT_ID_FOR_OVERFLOW_SCROLL: u32 = 1000000;
/// The logical width of an insertion point: at the moment, a one-pixel-wide line.
const INSERTION_POINT_LOGICAL_WIDTH: Au = Au(1 * AU_PER_PX);
@ -1641,7 +1636,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base,
display_list,
layout_context,
StackingContextLayerNecessity::Always(self.layer_id(0), scroll_policy),
StackingContextLayerNecessity::Always(self.layer_id(), scroll_policy),
StackingContextCreationMode::Normal);
DisplayListBuildingResult::StackingContext(stacking_context)
} else if self.fragment.establishes_stacking_context() {
@ -1650,7 +1645,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base,
display_list,
layout_context,
StackingContextLayerNecessity::IfCanvas(self.layer_id(0)),
StackingContextLayerNecessity::IfCanvas(self.layer_id()),
StackingContextCreationMode::Normal))
} else {
match self.fragment.style.get_box().position {
@ -1727,7 +1722,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base,
display_list,
layout_context,
StackingContextLayerNecessity::IfCanvas(self.layer_id(0)),
StackingContextLayerNecessity::IfCanvas(self.layer_id()),
StackingContextCreationMode::Normal));
}
return
@ -1747,9 +1742,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
};
let layer_id = if outer_display_list_for_overflow_scroll.is_some() {
self.layer_id(FAKE_FRAGMENT_ID_FOR_OVERFLOW_SCROLL)
self.layer_id_for_overflow_scroll()
} else {
self.layer_id(0)
self.layer_id()
};
let stacking_context = self.fragment.create_stacking_context(
&self.base,
@ -1766,7 +1761,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base,
outer_display_list_for_overflow_scroll,
layout_context,
StackingContextLayerNecessity::Always(self.layer_id(0), scroll_policy),
StackingContextLayerNecessity::Always(self.layer_id(), scroll_policy),
StackingContextCreationMode::OuterScrollWrapper)
}
None => stacking_context,
@ -1792,7 +1787,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base,
display_list,
layout_context,
StackingContextLayerNecessity::IfCanvas(self.layer_id(0)),
StackingContextLayerNecessity::IfCanvas(self.layer_id()),
StackingContextCreationMode::Normal))
} else {
DisplayListBuildingResult::Normal(display_list)
@ -1892,7 +1887,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
&self.base,
display_list,
layout_context,
StackingContextLayerNecessity::IfCanvas(self.layer_id(0)),
StackingContextLayerNecessity::IfCanvas(self.layer_id()),
StackingContextCreationMode::Normal))
} else {
DisplayListBuildingResult::Normal(display_list)

View file

@ -48,7 +48,7 @@ use wrapper::{PseudoElementType, ThreadSafeLayoutNode};
use euclid::{Point2D, Rect, Size2D};
use gfx::display_list::ClippingRegion;
use msg::compositor_msg::LayerId;
use msg::compositor_msg::{LayerId, LayerType};
use msg::constellation_msg::ConstellationChan;
use rustc_serialize::{Encoder, Encodable};
use std::fmt;
@ -359,9 +359,16 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
/// Returns a layer ID for the given fragment.
#[allow(unsafe_code)]
fn layer_id(&self, fragment_id: u32) -> LayerId {
fn layer_id(&self) -> LayerId {
let obj = unsafe { mem::transmute::<&&Self, &raw::TraitObject>(&self) };
LayerId(obj.data as usize, fragment_id, 0)
LayerId::new_of_type(LayerType::FragmentBody, obj.data as usize)
}
/// Returns a layer ID for the given fragment.
#[allow(unsafe_code)]
fn layer_id_for_overflow_scroll(&self) -> LayerId {
let obj = unsafe { mem::transmute::<&&Self, &raw::TraitObject>(&self) };
LayerId::new_of_type(LayerType::OverflowScroll, obj.data as usize)
}
/// Attempts to perform incremental fixup of this flow by replacing its fragment's style with

View file

@ -1057,7 +1057,7 @@ impl LayoutTask {
.display_list_building_result
.add_to(&mut *display_list);
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
let layer_id = layout_root.layer_id(0);
let layer_id = layout_root.layer_id();
let stacking_context = Arc::new(StackingContext::new(display_list,
&origin,
&origin,