mirror of
https://github.com/servo/servo.git
synced 2025-06-08 00:23:30 +00:00
Fix fixed position items with parents with CSS clips
In order to properly handle CSS clipping, we need to keep track of what the different kinds of clips that we have. On one hand, clipping due to overflow rules should respect the containing block hierarchy, while CSS clipping should respect the flow tree hierarchy. In order to represent the complexity of items that are scrolled via one clip/scroll frame and clipped by another we keep track of that status with a ClipAndScrollInfo.
This commit is contained in:
parent
46f6e68bad
commit
daf638bc3f
11 changed files with 214 additions and 106 deletions
|
@ -33,8 +33,8 @@ use style::values::computed::Filter;
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
use text::TextRun;
|
use text::TextRun;
|
||||||
use text::glyph::ByteIndex;
|
use text::glyph::ByteIndex;
|
||||||
use webrender_api::{self, ClipId, ColorF, GradientStop, LocalClip, MixBlendMode, ScrollPolicy};
|
use webrender_api::{self, ClipAndScrollInfo, ClipId, ColorF, GradientStop, LocalClip};
|
||||||
use webrender_api::{ScrollSensitivity, TransformStyle, WebGLContextId};
|
use webrender_api::{MixBlendMode, ScrollPolicy, ScrollSensitivity, TransformStyle, WebGLContextId};
|
||||||
|
|
||||||
pub use style::dom::OpaqueNode;
|
pub use style::dom::OpaqueNode;
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ impl DisplayList {
|
||||||
match item {
|
match item {
|
||||||
&DisplayItem::PushStackingContext(ref context_item) => {
|
&DisplayItem::PushStackingContext(ref context_item) => {
|
||||||
self.text_index_stacking_context(&context_item.stacking_context,
|
self.text_index_stacking_context(&context_item.stacking_context,
|
||||||
item.base().scroll_root_id,
|
item.scroll_node_id(),
|
||||||
node,
|
node,
|
||||||
traversal,
|
traversal,
|
||||||
point,
|
point,
|
||||||
|
@ -229,7 +229,7 @@ impl DisplayList {
|
||||||
match item {
|
match item {
|
||||||
&DisplayItem::PushStackingContext(ref context_item) => {
|
&DisplayItem::PushStackingContext(ref context_item) => {
|
||||||
self.hit_test_stacking_context(&context_item.stacking_context,
|
self.hit_test_stacking_context(&context_item.stacking_context,
|
||||||
item.base().scroll_root_id,
|
item.scroll_node_id(),
|
||||||
traversal,
|
traversal,
|
||||||
point,
|
point,
|
||||||
offset_lookup,
|
offset_lookup,
|
||||||
|
@ -286,10 +286,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: {:?} ScrollRoot: {:?}",
|
print_tree.add_item(format!("{:?} StackingContext: {:?} {:?}",
|
||||||
item,
|
item,
|
||||||
item.base().stacking_context_id,
|
item.base().stacking_context_id,
|
||||||
item.scroll_root_id()));
|
item.clip_and_scroll_info()));
|
||||||
}
|
}
|
||||||
print_tree.end_level();
|
print_tree.end_level();
|
||||||
}
|
}
|
||||||
|
@ -438,8 +438,8 @@ pub struct StackingContext {
|
||||||
/// The scroll policy of this layer.
|
/// The scroll policy of this layer.
|
||||||
pub scroll_policy: ScrollPolicy,
|
pub scroll_policy: ScrollPolicy,
|
||||||
|
|
||||||
/// The id of the parent scrolling area that contains this StackingContext.
|
/// The clip and scroll info for this StackingContext.
|
||||||
pub parent_scroll_id: ClipId,
|
pub parent_clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackingContext {
|
impl StackingContext {
|
||||||
|
@ -456,7 +456,7 @@ impl StackingContext {
|
||||||
transform_style: TransformStyle,
|
transform_style: TransformStyle,
|
||||||
perspective: Option<Transform3D<f32>>,
|
perspective: Option<Transform3D<f32>>,
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
parent_scroll_id: ClipId)
|
parent_clip_and_scroll_info: ClipAndScrollInfo)
|
||||||
-> StackingContext {
|
-> StackingContext {
|
||||||
StackingContext {
|
StackingContext {
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -470,7 +470,7 @@ impl StackingContext {
|
||||||
transform_style: transform_style,
|
transform_style: transform_style,
|
||||||
perspective: perspective,
|
perspective: perspective,
|
||||||
scroll_policy: scroll_policy,
|
scroll_policy: scroll_policy,
|
||||||
parent_scroll_id: parent_scroll_id,
|
parent_clip_and_scroll_info: parent_clip_and_scroll_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,13 +487,13 @@ impl StackingContext {
|
||||||
TransformStyle::Flat,
|
TransformStyle::Flat,
|
||||||
None,
|
None,
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
pipeline_id.root_scroll_node())
|
pipeline_id.root_clip_and_scroll_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_display_list_items(self, pipeline_id: PipelineId) -> (DisplayItem, DisplayItem) {
|
pub fn to_display_list_items(self, pipeline_id: PipelineId) -> (DisplayItem, DisplayItem) {
|
||||||
let mut base_item = BaseDisplayItem::empty(pipeline_id);
|
let mut base_item = BaseDisplayItem::empty(pipeline_id);
|
||||||
base_item.stacking_context_id = self.id;
|
base_item.stacking_context_id = self.id;
|
||||||
base_item.scroll_root_id = self.parent_scroll_id;
|
base_item.clip_and_scroll_info = self.parent_clip_and_scroll_info;
|
||||||
|
|
||||||
let pop_item = DisplayItem::PopStackingContext(Box::new(
|
let pop_item = DisplayItem::PopStackingContext(Box::new(
|
||||||
PopStackingContextItem {
|
PopStackingContextItem {
|
||||||
|
@ -631,8 +631,8 @@ 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.
|
/// The clip and scroll info for this item.
|
||||||
pub scroll_root_id: ClipId,
|
pub clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseDisplayItem {
|
impl BaseDisplayItem {
|
||||||
|
@ -642,7 +642,7 @@ impl BaseDisplayItem {
|
||||||
local_clip: LocalClip,
|
local_clip: LocalClip,
|
||||||
section: DisplayListSection,
|
section: DisplayListSection,
|
||||||
stacking_context_id: StackingContextId,
|
stacking_context_id: StackingContextId,
|
||||||
scroll_root_id: ClipId)
|
clip_and_scroll_info: ClipAndScrollInfo)
|
||||||
-> BaseDisplayItem {
|
-> BaseDisplayItem {
|
||||||
BaseDisplayItem {
|
BaseDisplayItem {
|
||||||
bounds: *bounds,
|
bounds: *bounds,
|
||||||
|
@ -650,7 +650,7 @@ impl BaseDisplayItem {
|
||||||
local_clip: local_clip,
|
local_clip: local_clip,
|
||||||
section: section,
|
section: section,
|
||||||
stacking_context_id: stacking_context_id,
|
stacking_context_id: stacking_context_id,
|
||||||
scroll_root_id: scroll_root_id,
|
clip_and_scroll_info: clip_and_scroll_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,7 +665,7 @@ impl BaseDisplayItem {
|
||||||
local_clip: LocalClip::from(max_rect().to_rectf()),
|
local_clip: LocalClip::from(max_rect().to_rectf()),
|
||||||
section: DisplayListSection::Content,
|
section: DisplayListSection::Content,
|
||||||
stacking_context_id: StackingContextId::root(),
|
stacking_context_id: StackingContextId::root(),
|
||||||
scroll_root_id: pipeline_id.root_scroll_node(),
|
clip_and_scroll_info: pipeline_id.root_clip_and_scroll_info(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1265,8 +1265,12 @@ impl DisplayItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scroll_root_id(&self) -> ClipId {
|
pub fn scroll_node_id(&self) -> ClipId {
|
||||||
self.base().scroll_root_id
|
self.base().clip_and_scroll_info.scroll_node_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clip_and_scroll_info(&self) -> ClipAndScrollInfo {
|
||||||
|
self.base().clip_and_scroll_info
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stacking_context_id(&self) -> StackingContextId {
|
pub fn stacking_context_id(&self) -> StackingContextId {
|
||||||
|
@ -1297,7 +1301,7 @@ impl DisplayItem {
|
||||||
// test elements with `border-radius`, for example.
|
// test elements with `border-radius`, for example.
|
||||||
let base_item = self.base();
|
let base_item = self.base();
|
||||||
|
|
||||||
let scroll_offset = offset_lookup.full_offset_for_scroll_root(&base_item.scroll_root_id);
|
let scroll_offset = offset_lookup.full_offset_for_scroll_root(&self.scroll_node_id());
|
||||||
let point = Point2D::new(point.x - Au::from_f32_px(scroll_offset.x),
|
let point = Point2D::new(point.x - Au::from_f32_px(scroll_offset.x),
|
||||||
point.y - Au::from_f32_px(scroll_offset.y));
|
point.y - Au::from_f32_px(scroll_offset.y));
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl Epoch {
|
||||||
pub struct StackingContextId(
|
pub struct StackingContextId(
|
||||||
/// The identifier for this StackingContext, derived from the Flow's memory address
|
/// The identifier for this StackingContext, derived from the Flow's memory address
|
||||||
/// and fragment type. As a space optimization, these are combined into a single word.
|
/// and fragment type. As a space optimization, these are combined into a single word.
|
||||||
u64
|
pub u64
|
||||||
);
|
);
|
||||||
|
|
||||||
impl StackingContextId {
|
impl StackingContextId {
|
||||||
|
|
|
@ -71,8 +71,8 @@ use style_traits::CSSPixel;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
use table_cell::CollapsedBordersForCell;
|
use table_cell::CollapsedBordersForCell;
|
||||||
use webrender_api::{ClipId, ColorF, ComplexClipRegion, GradientStop, LocalClip, RepeatMode};
|
use webrender_api::{ClipAndScrollInfo, ClipId, ColorF, ComplexClipRegion, GradientStop, LineStyle};
|
||||||
use webrender_api::{LineStyle, ScrollPolicy, ScrollSensitivity, TransformStyle};
|
use webrender_api::{LocalClip, RepeatMode, ScrollPolicy, ScrollSensitivity, TransformStyle};
|
||||||
use webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle};
|
use webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle};
|
||||||
|
|
||||||
trait ResolvePercentage {
|
trait ResolvePercentage {
|
||||||
|
@ -169,14 +169,14 @@ pub struct DisplayListBuildState<'a> {
|
||||||
/// recursively building and processing the display list.
|
/// recursively building and processing the display list.
|
||||||
pub current_stacking_context_id: StackingContextId,
|
pub current_stacking_context_id: StackingContextId,
|
||||||
|
|
||||||
/// The current scroll root id, used to keep track of state when
|
/// The current clip and scroll info, used to keep track of state when
|
||||||
/// recursively building and processing the display list.
|
/// recursively building and processing the display list.
|
||||||
pub current_scroll_root_id: ClipId,
|
pub current_clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
|
|
||||||
/// The scroll root id of the first ancestor which defines a containing block.
|
/// The clip and scroll info of the first ancestor which defines a containing block.
|
||||||
/// This is necessary because absolutely positioned items should be clipped
|
/// This is necessary because absolutely positioned items should be clipped
|
||||||
/// by their containing block's scroll root.
|
/// by their containing block's scroll root.
|
||||||
pub containing_block_scroll_root_id: ClipId,
|
pub containing_block_clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
|
|
||||||
/// Vector containing iframe sizes, used to inform the constellation about
|
/// Vector containing iframe sizes, used to inform the constellation about
|
||||||
/// new iframe sizes
|
/// new iframe sizes
|
||||||
|
@ -196,6 +196,7 @@ pub struct DisplayListBuildState<'a> {
|
||||||
|
|
||||||
impl<'a> DisplayListBuildState<'a> {
|
impl<'a> DisplayListBuildState<'a> {
|
||||||
pub fn new(layout_context: &'a LayoutContext) -> DisplayListBuildState<'a> {
|
pub fn new(layout_context: &'a LayoutContext) -> DisplayListBuildState<'a> {
|
||||||
|
let root_clip_info = ClipAndScrollInfo::simple(layout_context.id.root_scroll_node());
|
||||||
DisplayListBuildState {
|
DisplayListBuildState {
|
||||||
layout_context: layout_context,
|
layout_context: layout_context,
|
||||||
root_stacking_context: StackingContext::root(layout_context.id),
|
root_stacking_context: StackingContext::root(layout_context.id),
|
||||||
|
@ -204,8 +205,8 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
scroll_root_parents: HashMap::new(),
|
scroll_root_parents: HashMap::new(),
|
||||||
processing_scroll_root_element: false,
|
processing_scroll_root_element: false,
|
||||||
current_stacking_context_id: StackingContextId::root(),
|
current_stacking_context_id: StackingContextId::root(),
|
||||||
current_scroll_root_id: layout_context.id.root_scroll_node(),
|
current_clip_and_scroll_info: root_clip_info,
|
||||||
containing_block_scroll_root_id: layout_context.id.root_scroll_node(),
|
containing_block_clip_and_scroll_info: root_clip_info,
|
||||||
iframe_sizes: Vec::new(),
|
iframe_sizes: Vec::new(),
|
||||||
clip_stack: Vec::new(),
|
clip_stack: Vec::new(),
|
||||||
containing_block_clip_stack: Vec::new(),
|
containing_block_clip_stack: Vec::new(),
|
||||||
|
@ -249,6 +250,12 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
*self.scroll_root_parents.get(&scroll_root_id).unwrap()
|
*self.scroll_root_parents.get(&scroll_root_id).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_background_or_border_of_scroll_root(&self, section: DisplayListSection) -> bool {
|
||||||
|
(section == DisplayListSection::BackgroundAndBorders ||
|
||||||
|
section == DisplayListSection::BlockBackgroundsAndBorders) &&
|
||||||
|
self.processing_scroll_root_element
|
||||||
|
}
|
||||||
|
|
||||||
fn create_base_display_item(&self,
|
fn create_base_display_item(&self,
|
||||||
bounds: &Rect<Au>,
|
bounds: &Rect<Au>,
|
||||||
clip: LocalClip,
|
clip: LocalClip,
|
||||||
|
@ -256,12 +263,10 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
cursor: Option<Cursor>,
|
cursor: Option<Cursor>,
|
||||||
section: DisplayListSection)
|
section: DisplayListSection)
|
||||||
-> BaseDisplayItem {
|
-> BaseDisplayItem {
|
||||||
let scroll_root_id = if (section == DisplayListSection::BackgroundAndBorders ||
|
let clip_and_scroll_info = if self.is_background_or_border_of_scroll_root(section) {
|
||||||
section == DisplayListSection::BlockBackgroundsAndBorders) &&
|
ClipAndScrollInfo::simple(self.parent_scroll_root_id(self.current_clip_and_scroll_info.scroll_node_id))
|
||||||
self.processing_scroll_root_element {
|
|
||||||
self.parent_scroll_root_id(self.current_scroll_root_id)
|
|
||||||
} else {
|
} else {
|
||||||
self.current_scroll_root_id
|
self.current_clip_and_scroll_info
|
||||||
};
|
};
|
||||||
|
|
||||||
BaseDisplayItem::new(&bounds,
|
BaseDisplayItem::new(&bounds,
|
||||||
|
@ -272,7 +277,7 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
clip,
|
clip,
|
||||||
section,
|
section,
|
||||||
self.current_stacking_context_id,
|
self.current_stacking_context_id,
|
||||||
scroll_root_id)
|
clip_and_scroll_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_display_list(mut self) -> DisplayList {
|
pub fn to_display_list(mut self) -> DisplayList {
|
||||||
|
@ -548,7 +553,7 @@ pub trait FragmentDisplayListBuilding {
|
||||||
base_flow: &BaseFlow,
|
base_flow: &BaseFlow,
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
mode: StackingContextCreationMode,
|
mode: StackingContextCreationMode,
|
||||||
parent_scroll_id: ClipId)
|
parent_clip_and_scroll_info: ClipAndScrollInfo)
|
||||||
-> StackingContext;
|
-> StackingContext;
|
||||||
|
|
||||||
|
|
||||||
|
@ -2029,7 +2034,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
base_flow: &BaseFlow,
|
base_flow: &BaseFlow,
|
||||||
scroll_policy: ScrollPolicy,
|
scroll_policy: ScrollPolicy,
|
||||||
mode: StackingContextCreationMode,
|
mode: StackingContextCreationMode,
|
||||||
parent_scroll_id: ClipId)
|
parent_clip_and_scroll_info: ClipAndScrollInfo)
|
||||||
-> StackingContext {
|
-> StackingContext {
|
||||||
let border_box =
|
let border_box =
|
||||||
self.stacking_relative_border_box(&base_flow.stacking_relative_position,
|
self.stacking_relative_border_box(&base_flow.stacking_relative_position,
|
||||||
|
@ -2069,7 +2074,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
self.style().get_used_transform_style().to_transform_style(),
|
self.style().get_used_transform_style().to_transform_style(),
|
||||||
self.perspective_matrix(&border_box),
|
self.perspective_matrix(&border_box),
|
||||||
scroll_policy,
|
scroll_policy,
|
||||||
parent_scroll_id)
|
parent_clip_and_scroll_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list_for_text_fragment(&self,
|
fn build_display_list_for_text_fragment(&self,
|
||||||
|
@ -2255,7 +2260,7 @@ pub trait BlockFlowDisplayListBuilding {
|
||||||
state: &mut DisplayListBuildState,
|
state: &mut DisplayListBuildState,
|
||||||
preserved_state: &mut PreservedDisplayListState,
|
preserved_state: &mut PreservedDisplayListState,
|
||||||
stacking_context_type: BlockStackingContextType)
|
stacking_context_type: BlockStackingContextType)
|
||||||
-> ClipId;
|
-> ClipAndScrollInfo;
|
||||||
fn setup_scroll_root_for_overflow(&mut self,
|
fn setup_scroll_root_for_overflow(&mut self,
|
||||||
state: &mut DisplayListBuildState,
|
state: &mut DisplayListBuildState,
|
||||||
border_box: &Rect<Au>);
|
border_box: &Rect<Au>);
|
||||||
|
@ -2265,11 +2270,11 @@ pub trait BlockFlowDisplayListBuilding {
|
||||||
stacking_relative_border_box: &Rect<Au>);
|
stacking_relative_border_box: &Rect<Au>);
|
||||||
fn create_pseudo_stacking_context_for_block(&mut self,
|
fn create_pseudo_stacking_context_for_block(&mut self,
|
||||||
parent_stacking_context_id: StackingContextId,
|
parent_stacking_context_id: StackingContextId,
|
||||||
parent_scroll_root_id: ClipId,
|
parent_clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
state: &mut DisplayListBuildState);
|
state: &mut DisplayListBuildState);
|
||||||
fn create_real_stacking_context_for_block(&mut self,
|
fn create_real_stacking_context_for_block(&mut self,
|
||||||
parent_stacking_context_id: StackingContextId,
|
parent_stacking_context_id: StackingContextId,
|
||||||
parent_scroll_root_id: ClipId,
|
parent_clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
state: &mut DisplayListBuildState);
|
state: &mut DisplayListBuildState);
|
||||||
fn build_display_list_for_block(&mut self,
|
fn build_display_list_for_block(&mut self,
|
||||||
state: &mut DisplayListBuildState,
|
state: &mut DisplayListBuildState,
|
||||||
|
@ -2283,8 +2288,8 @@ pub trait BlockFlowDisplayListBuilding {
|
||||||
/// TODO(mrobinson): It would be nice to use RAII here to avoid having to call restore.
|
/// TODO(mrobinson): It would be nice to use RAII here to avoid having to call restore.
|
||||||
pub struct PreservedDisplayListState {
|
pub struct PreservedDisplayListState {
|
||||||
stacking_context_id: StackingContextId,
|
stacking_context_id: StackingContextId,
|
||||||
scroll_root_id: ClipId,
|
clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
containing_block_scroll_root_id: ClipId,
|
containing_block_clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
clips_pushed: usize,
|
clips_pushed: usize,
|
||||||
containing_block_clips_pushed: usize,
|
containing_block_clips_pushed: usize,
|
||||||
transform_style: TransformStyle,
|
transform_style: TransformStyle,
|
||||||
|
@ -2294,8 +2299,8 @@ impl PreservedDisplayListState {
|
||||||
fn new(state: &mut DisplayListBuildState) -> PreservedDisplayListState {
|
fn new(state: &mut DisplayListBuildState) -> PreservedDisplayListState {
|
||||||
PreservedDisplayListState {
|
PreservedDisplayListState {
|
||||||
stacking_context_id: state.current_stacking_context_id,
|
stacking_context_id: state.current_stacking_context_id,
|
||||||
scroll_root_id: state.current_scroll_root_id,
|
clip_and_scroll_info: state.current_clip_and_scroll_info,
|
||||||
containing_block_scroll_root_id: state.containing_block_scroll_root_id,
|
containing_block_clip_and_scroll_info: state.containing_block_clip_and_scroll_info,
|
||||||
clips_pushed: 0,
|
clips_pushed: 0,
|
||||||
containing_block_clips_pushed: 0,
|
containing_block_clips_pushed: 0,
|
||||||
transform_style: state.current_transform_style,
|
transform_style: state.current_transform_style,
|
||||||
|
@ -2310,8 +2315,8 @@ impl PreservedDisplayListState {
|
||||||
|
|
||||||
fn restore(self, state: &mut DisplayListBuildState) {
|
fn restore(self, state: &mut DisplayListBuildState) {
|
||||||
state.current_stacking_context_id = self.stacking_context_id;
|
state.current_stacking_context_id = self.stacking_context_id;
|
||||||
state.current_scroll_root_id = self.scroll_root_id;
|
state.current_clip_and_scroll_info = self.clip_and_scroll_info;
|
||||||
state.containing_block_scroll_root_id = self.containing_block_scroll_root_id;
|
state.containing_block_clip_and_scroll_info = self.containing_block_clip_and_scroll_info;
|
||||||
|
|
||||||
let truncate_length = state.clip_stack.len() - self.clips_pushed;
|
let truncate_length = state.clip_stack.len() - self.clips_pushed;
|
||||||
state.clip_stack.truncate(truncate_length);
|
state.clip_stack.truncate(truncate_length);
|
||||||
|
@ -2417,14 +2422,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
|
|
||||||
// We are getting the id of the scroll root that contains us here, not the id of
|
// We are getting the id of the scroll root that contains us here, not the id of
|
||||||
// any scroll root that we create. If we create a scroll root, its id will be
|
// any scroll root that we create. If we create a scroll root, its id will be
|
||||||
// stored in state.current_scroll_root_id. If we should create a stacking context,
|
// stored in state.current_clip_and_scroll_info. If we create a stacking context,
|
||||||
// we don't want it to be clipped by its own scroll root.
|
// we don't want it to be contained by its own scroll root.
|
||||||
let containing_scroll_root_id = self.setup_clipping_for_block(state,
|
let containing_clip_and_scroll_info =
|
||||||
&mut preserved_state,
|
self.setup_clipping_for_block(state, &mut preserved_state, block_stacking_context_type);
|
||||||
block_stacking_context_type);
|
|
||||||
|
|
||||||
if establishes_containing_block_for_absolute(self.positioning()) {
|
if establishes_containing_block_for_absolute(self.positioning()) {
|
||||||
state.containing_block_scroll_root_id = state.current_scroll_root_id;
|
state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
match block_stacking_context_type {
|
match block_stacking_context_type {
|
||||||
|
@ -2433,12 +2436,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
}
|
}
|
||||||
BlockStackingContextType::PseudoStackingContext => {
|
BlockStackingContextType::PseudoStackingContext => {
|
||||||
self.create_pseudo_stacking_context_for_block(preserved_state.stacking_context_id,
|
self.create_pseudo_stacking_context_for_block(preserved_state.stacking_context_id,
|
||||||
containing_scroll_root_id,
|
containing_clip_and_scroll_info,
|
||||||
state);
|
state);
|
||||||
}
|
}
|
||||||
BlockStackingContextType::StackingContext => {
|
BlockStackingContextType::StackingContext => {
|
||||||
self.create_real_stacking_context_for_block(preserved_state.stacking_context_id,
|
self.create_real_stacking_context_for_block(preserved_state.stacking_context_id,
|
||||||
containing_scroll_root_id,
|
containing_clip_and_scroll_info,
|
||||||
state);
|
state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2450,22 +2453,22 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
state: &mut DisplayListBuildState,
|
state: &mut DisplayListBuildState,
|
||||||
preserved_state: &mut PreservedDisplayListState,
|
preserved_state: &mut PreservedDisplayListState,
|
||||||
stacking_context_type: BlockStackingContextType)
|
stacking_context_type: BlockStackingContextType)
|
||||||
-> ClipId {
|
-> ClipAndScrollInfo {
|
||||||
// If this block is absolutely positioned, we should be clipped and positioned by
|
// If this block is absolutely positioned, we should be clipped and positioned by
|
||||||
// the scroll root of our nearest ancestor that establishes a containing block.
|
// the scroll root of our nearest ancestor that establishes a containing block.
|
||||||
let containing_scroll_root_id = match self.positioning() {
|
let containing_clip_and_scroll_info = match self.positioning() {
|
||||||
position::T::absolute => {
|
position::T::absolute => {
|
||||||
preserved_state.switch_to_containing_block_clip(state);
|
preserved_state.switch_to_containing_block_clip(state);
|
||||||
state.current_scroll_root_id = state.containing_block_scroll_root_id;
|
state.current_clip_and_scroll_info = state.containing_block_clip_and_scroll_info;
|
||||||
state.containing_block_scroll_root_id
|
state.containing_block_clip_and_scroll_info
|
||||||
}
|
}
|
||||||
position::T::fixed => {
|
position::T::fixed => {
|
||||||
preserved_state.push_clip(state, &max_rect(), position::T::fixed);
|
preserved_state.push_clip(state, &max_rect(), position::T::fixed);
|
||||||
state.current_scroll_root_id
|
state.current_clip_and_scroll_info
|
||||||
}
|
}
|
||||||
_ => state.current_scroll_root_id,
|
_ => state.current_clip_and_scroll_info,
|
||||||
};
|
};
|
||||||
self.base.scroll_root_id = Some(containing_scroll_root_id);
|
self.base.clip_and_scroll_info = Some(containing_clip_and_scroll_info);
|
||||||
|
|
||||||
let coordinate_system = if self.fragment.establishes_stacking_context() {
|
let coordinate_system = if self.fragment.establishes_stacking_context() {
|
||||||
CoordinateSystem::Own
|
CoordinateSystem::Own
|
||||||
|
@ -2489,11 +2492,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
|
|
||||||
match self.positioning() {
|
match self.positioning() {
|
||||||
position::T::absolute | position::T::relative | position::T::fixed =>
|
position::T::absolute | position::T::relative | position::T::fixed =>
|
||||||
state.containing_block_scroll_root_id = state.current_scroll_root_id,
|
state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
containing_scroll_root_id
|
containing_clip_and_scroll_info
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_scroll_root_for_overflow(&mut self,
|
fn setup_scroll_root_for_overflow(&mut self,
|
||||||
|
@ -2542,7 +2545,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
let content_size = self.base.overflow.scroll.origin + self.base.overflow.scroll.size;
|
let content_size = self.base.overflow.scroll.origin + self.base.overflow.scroll.size;
|
||||||
let content_size = Size2D::new(content_size.x, content_size.y);
|
let content_size = Size2D::new(content_size.x, content_size.y);
|
||||||
|
|
||||||
let parent_id = self.scroll_root_id(state.layout_context.id);
|
let parent_id = self.clip_and_scroll_info(state.layout_context.id).scroll_node_id;
|
||||||
state.add_scroll_root(
|
state.add_scroll_root(
|
||||||
ScrollRoot {
|
ScrollRoot {
|
||||||
id: new_scroll_root_id,
|
id: new_scroll_root_id,
|
||||||
|
@ -2554,8 +2557,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
self.base.stacking_context_id
|
self.base.stacking_context_id
|
||||||
);
|
);
|
||||||
|
|
||||||
self.base.scroll_root_id = Some(new_scroll_root_id);
|
let new_clip_and_scroll_info = ClipAndScrollInfo::simple(new_scroll_root_id);
|
||||||
state.current_scroll_root_id = new_scroll_root_id;
|
self.base.clip_and_scroll_info = Some(new_clip_and_scroll_info);
|
||||||
|
state.current_clip_and_scroll_info = new_clip_and_scroll_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a scroll root for a block to take the `clip` property into account
|
/// Adds a scroll root for a block to take the `clip` property into account
|
||||||
|
@ -2570,6 +2574,13 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// CSS `clip` should only apply to position:absolute or positione:fixed elements.
|
||||||
|
// CSS Masking Appendix A: "Applies to: Absolutely positioned elements."
|
||||||
|
match self.positioning() {
|
||||||
|
position::T::absolute | position::T::fixed => {}
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
|
||||||
let clip_origin = Point2D::new(stacking_relative_border_box.origin.x +
|
let clip_origin = Point2D::new(stacking_relative_border_box.origin.x +
|
||||||
style_clip_rect.left.unwrap_or(Au(0)),
|
style_clip_rect.left.unwrap_or(Au(0)),
|
||||||
stacking_relative_border_box.origin.y +
|
stacking_relative_border_box.origin.y +
|
||||||
|
@ -2595,7 +2606,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
let clip_rect = Rect::new(clip_origin, clip_size);
|
let clip_rect = Rect::new(clip_origin, clip_size);
|
||||||
preserved_state.push_clip(state, &clip_rect, self.positioning());
|
preserved_state.push_clip(state, &clip_rect, self.positioning());
|
||||||
|
|
||||||
let parent_id = self.scroll_root_id(state.layout_context.id);
|
let parent_id = self.clip_and_scroll_info(state.layout_context.id).scroll_node_id;
|
||||||
state.add_scroll_root(
|
state.add_scroll_root(
|
||||||
ScrollRoot {
|
ScrollRoot {
|
||||||
id: new_scroll_root_id,
|
id: new_scroll_root_id,
|
||||||
|
@ -2607,13 +2618,14 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
self.base.stacking_context_id
|
self.base.stacking_context_id
|
||||||
);
|
);
|
||||||
|
|
||||||
self.base.scroll_root_id = Some(new_scroll_root_id);
|
let new_clip_and_scroll_info = ClipAndScrollInfo::new(new_scroll_root_id, new_scroll_root_id);
|
||||||
state.current_scroll_root_id = new_scroll_root_id;
|
self.base.clip_and_scroll_info = Some(new_clip_and_scroll_info);
|
||||||
|
state.current_clip_and_scroll_info = new_clip_and_scroll_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_pseudo_stacking_context_for_block(&mut self,
|
fn create_pseudo_stacking_context_for_block(&mut self,
|
||||||
parent_stacking_context_id: StackingContextId,
|
parent_stacking_context_id: StackingContextId,
|
||||||
parent_scroll_root_id: ClipId,
|
parent_clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
state: &mut DisplayListBuildState) {
|
state: &mut DisplayListBuildState) {
|
||||||
let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
|
let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
|
||||||
self.fragment.style.get_box().position != position::T::static_ {
|
self.fragment.style.get_box().position != position::T::static_ {
|
||||||
|
@ -2627,7 +2639,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
&self.base,
|
&self.base,
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
creation_mode,
|
creation_mode,
|
||||||
parent_scroll_root_id);
|
parent_clip_and_scroll_info);
|
||||||
state.add_stacking_context(parent_stacking_context_id, new_context);
|
state.add_stacking_context(parent_stacking_context_id, new_context);
|
||||||
|
|
||||||
self.base.collect_stacking_contexts_for_children(state);
|
self.base.collect_stacking_contexts_for_children(state);
|
||||||
|
@ -2647,7 +2659,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
|
|
||||||
fn create_real_stacking_context_for_block(&mut self,
|
fn create_real_stacking_context_for_block(&mut self,
|
||||||
parent_stacking_context_id: StackingContextId,
|
parent_stacking_context_id: StackingContextId,
|
||||||
parent_scroll_root_id: ClipId,
|
parent_clip_and_scroll_info: ClipAndScrollInfo,
|
||||||
state: &mut DisplayListBuildState) {
|
state: &mut DisplayListBuildState) {
|
||||||
let scroll_policy = if self.is_fixed() {
|
let scroll_policy = if self.is_fixed() {
|
||||||
ScrollPolicy::Fixed
|
ScrollPolicy::Fixed
|
||||||
|
@ -2660,7 +2672,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
&self.base,
|
&self.base,
|
||||||
scroll_policy,
|
scroll_policy,
|
||||||
StackingContextCreationMode::Normal,
|
StackingContextCreationMode::Normal,
|
||||||
parent_scroll_root_id);
|
parent_clip_and_scroll_info);
|
||||||
|
|
||||||
state.add_stacking_context(parent_stacking_context_id, stacking_context);
|
state.add_stacking_context(parent_stacking_context_id, stacking_context);
|
||||||
self.base.collect_stacking_contexts_for_children(state);
|
self.base.collect_stacking_contexts_for_children(state);
|
||||||
|
@ -2715,13 +2727,13 @@ pub trait InlineFlowDisplayListBuilding {
|
||||||
impl InlineFlowDisplayListBuilding for InlineFlow {
|
impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
fn collect_stacking_contexts_for_inline(&mut self, state: &mut DisplayListBuildState) {
|
fn collect_stacking_contexts_for_inline(&mut self, state: &mut DisplayListBuildState) {
|
||||||
self.base.stacking_context_id = state.current_stacking_context_id;
|
self.base.stacking_context_id = state.current_stacking_context_id;
|
||||||
self.base.scroll_root_id = Some(state.current_scroll_root_id);
|
self.base.clip_and_scroll_info = Some(state.current_clip_and_scroll_info);
|
||||||
self.base.clip = state.clip_stack.last().cloned().unwrap_or_else(max_rect);
|
self.base.clip = state.clip_stack.last().cloned().unwrap_or_else(max_rect);
|
||||||
|
|
||||||
for mut fragment in self.fragments.fragments.iter_mut() {
|
for mut fragment in self.fragments.fragments.iter_mut() {
|
||||||
let previous_containing_block_scroll_root_id = state.containing_block_scroll_root_id;
|
let previous_cb_clip_scroll_info = state.containing_block_clip_and_scroll_info;
|
||||||
if establishes_containing_block_for_absolute(fragment.style.get_box().position) {
|
if establishes_containing_block_for_absolute(fragment.style.get_box().position) {
|
||||||
state.containing_block_scroll_root_id = state.current_scroll_root_id;
|
state.containing_block_clip_and_scroll_info = state.current_clip_and_scroll_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
match fragment.specific {
|
match fragment.specific {
|
||||||
|
@ -2745,14 +2757,14 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
&self.base,
|
&self.base,
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
StackingContextCreationMode::Normal,
|
StackingContextCreationMode::Normal,
|
||||||
state.current_scroll_root_id);
|
state.current_clip_and_scroll_info);
|
||||||
|
|
||||||
state.add_stacking_context(current_stacking_context_id,
|
state.add_stacking_context(current_stacking_context_id,
|
||||||
stacking_context);
|
stacking_context);
|
||||||
}
|
}
|
||||||
_ => fragment.stacking_context_id = state.current_stacking_context_id,
|
_ => fragment.stacking_context_id = state.current_stacking_context_id,
|
||||||
}
|
}
|
||||||
state.containing_block_scroll_root_id = previous_containing_block_scroll_root_id;
|
state.containing_block_clip_and_scroll_info = previous_cb_clip_scroll_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ use table_colgroup::TableColGroupFlow;
|
||||||
use table_row::TableRowFlow;
|
use table_row::TableRowFlow;
|
||||||
use table_rowgroup::TableRowGroupFlow;
|
use table_rowgroup::TableRowGroupFlow;
|
||||||
use table_wrapper::TableWrapperFlow;
|
use table_wrapper::TableWrapperFlow;
|
||||||
use webrender_api::ClipId;
|
use webrender_api::ClipAndScrollInfo;
|
||||||
|
|
||||||
/// Virtual methods that make up a float context.
|
/// Virtual methods that make up a float context.
|
||||||
///
|
///
|
||||||
|
@ -431,12 +431,12 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
|
||||||
/// children of this flow.
|
/// children of this flow.
|
||||||
fn print_extra_flow_children(&self, _: &mut PrintTree) { }
|
fn print_extra_flow_children(&self, _: &mut PrintTree) { }
|
||||||
|
|
||||||
fn scroll_root_id(&self, pipeline_id: PipelineId) -> ClipId {
|
fn clip_and_scroll_info(&self, pipeline_id: PipelineId) -> ClipAndScrollInfo {
|
||||||
match base(self).scroll_root_id {
|
match base(self).clip_and_scroll_info {
|
||||||
Some(id) => id,
|
Some(info) => info,
|
||||||
None => {
|
None => {
|
||||||
warn!("Tried to access scroll root id on Flow before assignment");
|
debug_assert!(false, "Tried to access scroll root id on Flow before assignment");
|
||||||
pipeline_id.root_scroll_node()
|
pipeline_id.root_clip_and_scroll_info()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -969,7 +969,7 @@ pub struct BaseFlow {
|
||||||
/// list construction.
|
/// list construction.
|
||||||
pub stacking_context_id: StackingContextId,
|
pub stacking_context_id: StackingContextId,
|
||||||
|
|
||||||
pub scroll_root_id: Option<ClipId>,
|
pub clip_and_scroll_info: Option<ClipAndScrollInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for BaseFlow {
|
impl fmt::Debug for BaseFlow {
|
||||||
|
@ -1111,7 +1111,7 @@ impl BaseFlow {
|
||||||
writing_mode: writing_mode,
|
writing_mode: writing_mode,
|
||||||
thread_id: 0,
|
thread_id: 0,
|
||||||
stacking_context_id: StackingContextId::root(),
|
stacking_context_id: StackingContextId::root(),
|
||||||
scroll_root_id: None,
|
clip_and_scroll_info: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,10 +94,9 @@ impl Flow for TableColGroupFlow {
|
||||||
|
|
||||||
fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) {
|
fn collect_stacking_contexts(&mut self, state: &mut DisplayListBuildState) {
|
||||||
self.base.stacking_context_id = state.current_stacking_context_id;
|
self.base.stacking_context_id = state.current_stacking_context_id;
|
||||||
self.base.scroll_root_id = Some(state.current_scroll_root_id);
|
self.base.clip_and_scroll_info = Some(state.current_clip_and_scroll_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn repair_style(&mut self, _: &::ServoArc<ComputedValues>) {}
|
fn repair_style(&mut self, _: &::ServoArc<ComputedValues>) {}
|
||||||
|
|
||||||
fn compute_overflow(&self) -> Overflow {
|
fn compute_overflow(&self) -> Overflow {
|
||||||
|
|
|
@ -222,8 +222,9 @@ impl<'a> BuildDisplayList<'a> {
|
||||||
let parent_stacking_context_id = self.state.current_stacking_context_id;
|
let parent_stacking_context_id = self.state.current_stacking_context_id;
|
||||||
self.state.current_stacking_context_id = flow::base(flow).stacking_context_id;
|
self.state.current_stacking_context_id = flow::base(flow).stacking_context_id;
|
||||||
|
|
||||||
let parent_scroll_root_id = self.state.current_scroll_root_id;
|
let parent_clip_and_scroll_info = self.state.current_clip_and_scroll_info;
|
||||||
self.state.current_scroll_root_id = flow.scroll_root_id(self.state.layout_context.id);
|
self.state.current_clip_and_scroll_info =
|
||||||
|
flow.clip_and_scroll_info(self.state.layout_context.id);
|
||||||
|
|
||||||
if self.should_process() {
|
if self.should_process() {
|
||||||
flow.build_display_list(&mut self.state);
|
flow.build_display_list(&mut self.state);
|
||||||
|
@ -235,7 +236,7 @@ impl<'a> BuildDisplayList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state.current_stacking_context_id = parent_stacking_context_id;
|
self.state.current_stacking_context_id = parent_stacking_context_id;
|
||||||
self.state.current_scroll_root_id = parent_scroll_root_id;
|
self.state.current_clip_and_scroll_info = parent_clip_and_scroll_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -16,8 +16,8 @@ use msg::constellation_msg::PipelineId;
|
||||||
use style::computed_values::{image_rendering, mix_blend_mode, transform_style};
|
use style::computed_values::{image_rendering, mix_blend_mode, transform_style};
|
||||||
use style::values::computed::{BorderStyle, Filter};
|
use style::values::computed::{BorderStyle, Filter};
|
||||||
use style::values::generics::effects::Filter as GenericFilter;
|
use style::values::generics::effects::Filter as GenericFilter;
|
||||||
use webrender_api::{self, ClipId, ComplexClipRegion, DisplayListBuilder, ExtendMode};
|
use webrender_api::{self, ClipAndScrollInfo, ComplexClipRegion, DisplayListBuilder};
|
||||||
use webrender_api::LayoutTransform;
|
use webrender_api::{ExtendMode, LayoutTransform};
|
||||||
|
|
||||||
pub trait WebRenderDisplayListConverter {
|
pub trait WebRenderDisplayListConverter {
|
||||||
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder;
|
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder;
|
||||||
|
@ -26,7 +26,7 @@ pub trait WebRenderDisplayListConverter {
|
||||||
trait WebRenderDisplayItemConverter {
|
trait WebRenderDisplayItemConverter {
|
||||||
fn convert_to_webrender(&self,
|
fn convert_to_webrender(&self,
|
||||||
builder: &mut DisplayListBuilder,
|
builder: &mut DisplayListBuilder,
|
||||||
current_scroll_root_id: &mut ClipId);
|
current_clip_and_scroll_info: &mut ClipAndScrollInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ToBorderStyle {
|
trait ToBorderStyle {
|
||||||
|
@ -222,16 +222,15 @@ impl ToTransformStyle for transform_style::T {
|
||||||
impl WebRenderDisplayListConverter for DisplayList {
|
impl WebRenderDisplayListConverter for DisplayList {
|
||||||
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder {
|
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder {
|
||||||
let traversal = DisplayListTraversal::new(self);
|
let traversal = DisplayListTraversal::new(self);
|
||||||
let webrender_pipeline_id = pipeline_id.to_webrender();
|
let mut builder = DisplayListBuilder::with_capacity(pipeline_id.to_webrender(),
|
||||||
let mut builder = DisplayListBuilder::with_capacity(webrender_pipeline_id,
|
|
||||||
self.bounds().size.to_sizef(),
|
self.bounds().size.to_sizef(),
|
||||||
1024 * 1024); // 1 MB of space
|
1024 * 1024); // 1 MB of space
|
||||||
|
|
||||||
let mut current_scroll_root_id = ClipId::root_scroll_node(webrender_pipeline_id);
|
let mut current_clip_and_scroll_info = pipeline_id.root_clip_and_scroll_info();
|
||||||
builder.push_clip_id(current_scroll_root_id);
|
builder.push_clip_and_scroll_info(current_clip_and_scroll_info);
|
||||||
|
|
||||||
for item in traversal {
|
for item in traversal {
|
||||||
item.convert_to_webrender(&mut builder, &mut current_scroll_root_id);
|
item.convert_to_webrender(&mut builder, &mut current_clip_and_scroll_info);
|
||||||
}
|
}
|
||||||
builder
|
builder
|
||||||
}
|
}
|
||||||
|
@ -240,12 +239,12 @@ impl WebRenderDisplayListConverter for DisplayList {
|
||||||
impl WebRenderDisplayItemConverter for DisplayItem {
|
impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
fn convert_to_webrender(&self,
|
fn convert_to_webrender(&self,
|
||||||
builder: &mut DisplayListBuilder,
|
builder: &mut DisplayListBuilder,
|
||||||
current_scroll_root_id: &mut ClipId) {
|
current_clip_and_scroll_info: &mut ClipAndScrollInfo) {
|
||||||
let scroll_root_id = self.base().scroll_root_id;
|
let clip_and_scroll_info = self.base().clip_and_scroll_info;
|
||||||
if scroll_root_id != *current_scroll_root_id {
|
if clip_and_scroll_info != *current_clip_and_scroll_info {
|
||||||
builder.pop_clip_id();
|
builder.pop_clip_id();
|
||||||
builder.push_clip_id(scroll_root_id);
|
builder.push_clip_and_scroll_info(clip_and_scroll_info);
|
||||||
*current_scroll_root_id = scroll_root_id;
|
*current_clip_and_scroll_info = clip_and_scroll_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -248,6 +248,10 @@ impl PipelineId {
|
||||||
pub fn root_scroll_node(&self) -> webrender_api::ClipId {
|
pub fn root_scroll_node(&self) -> webrender_api::ClipId {
|
||||||
webrender_api::ClipId::root_scroll_node(self.to_webrender())
|
webrender_api::ClipId::root_scroll_node(self.to_webrender())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn root_clip_and_scroll_info(&self) -> webrender_api::ClipAndScrollInfo {
|
||||||
|
webrender_api::ClipAndScrollInfo::simple(self.root_scroll_node())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PipelineId {
|
impl fmt::Display for PipelineId {
|
||||||
|
|
|
@ -1583,6 +1583,18 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"css/fixed_position_css_clip.html": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/fixed_position_css_clip.html",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"/_mozilla/css/fixed_position_css_clip_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"css/fixed_width_overrides_child_intrinsic_width_a.html": [
|
"css/fixed_width_overrides_child_intrinsic_width_a.html": [
|
||||||
[
|
[
|
||||||
"/_mozilla/css/fixed_width_overrides_child_intrinsic_width_a.html",
|
"/_mozilla/css/fixed_width_overrides_child_intrinsic_width_a.html",
|
||||||
|
@ -8179,6 +8191,11 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"css/fixed_position_css_clip_ref.html": [
|
||||||
|
[
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"css/fixed_width_overrides_child_intrinsic_width_ref.html": [
|
"css/fixed_width_overrides_child_intrinsic_width_ref.html": [
|
||||||
[
|
[
|
||||||
{}
|
{}
|
||||||
|
@ -23064,6 +23081,14 @@
|
||||||
"fe23d2dc9a4507b3b632518a53f21900d0e4d1d7",
|
"fe23d2dc9a4507b3b632518a53f21900d0e4d1d7",
|
||||||
"support"
|
"support"
|
||||||
],
|
],
|
||||||
|
"css/fixed_position_css_clip.html": [
|
||||||
|
"2bf1fb572a72fbb4a7a35b8c8b08960b48ccf408",
|
||||||
|
"reftest"
|
||||||
|
],
|
||||||
|
"css/fixed_position_css_clip_ref.html": [
|
||||||
|
"ad0341fc9f843177ccf53a1667b5016c234b7651",
|
||||||
|
"support"
|
||||||
|
],
|
||||||
"css/fixed_width_overrides_child_intrinsic_width_a.html": [
|
"css/fixed_width_overrides_child_intrinsic_width_a.html": [
|
||||||
"88cf78524712525ad4252c8a420c9b9f545b2621",
|
"88cf78524712525ad4252c8a420c9b9f545b2621",
|
||||||
"reftest"
|
"reftest"
|
||||||
|
|
40
tests/wpt/mozilla/tests/css/fixed_position_css_clip.html
Normal file
40
tests/wpt/mozilla/tests/css/fixed_position_css_clip.html
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Fixed position elements should be clipped by parent CSS clips</title>
|
||||||
|
<link rel="match" href="fixed_position_css_clip_ref.html">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#base {
|
||||||
|
position: absolute;
|
||||||
|
left; 0px;
|
||||||
|
top: 0px;
|
||||||
|
background: red;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
clip: rect(0, auto, auto, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#fixed {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="base">
|
||||||
|
<!-- Even though this fixed position child is positioned and clipped by the
|
||||||
|
containing block, it should also be clipped by the CSS clip of its
|
||||||
|
non-containing block parent. -->
|
||||||
|
<div id="fixed"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
24
tests/wpt/mozilla/tests/css/fixed_position_css_clip_ref.html
Normal file
24
tests/wpt/mozilla/tests/css/fixed_position_css_clip_ref.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Fixed position elements should be clipped by parent CSS clips</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#box {
|
||||||
|
left; 0px;
|
||||||
|
top: 0px;
|
||||||
|
background: green;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
clip: rect(0, auto, auto, 0);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="box">
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue