mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Fix duplicate stacking context creation for anonymous Flows
Anonymous nodes were previously creating duplicate stacking contexts, one for each node in the anonymous node chain. This change eliminates that for tables. Additionally the use of stacking context ids based on node addresses is no longer necessary since stacking contexts no longer control scrolling. This is the first step in eliminating the dependency between node addresses and ClipScrollNodes which causes issues like #16425.
This commit is contained in:
parent
c1e0889971
commit
36fa7e4c44
9 changed files with 72 additions and 42 deletions
|
@ -42,10 +42,9 @@ impl StackingContextId {
|
|||
StackingContextId(0)
|
||||
}
|
||||
|
||||
/// Returns a new sacking context id with the given numeric id.
|
||||
#[inline]
|
||||
pub fn new(id: u64) -> StackingContextId {
|
||||
StackingContextId(id)
|
||||
pub fn next(&self) -> StackingContextId {
|
||||
let StackingContextId(id) = *self;
|
||||
StackingContextId(id + 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1670,20 +1670,6 @@ impl BlockFlow {
|
|||
self.base.flags = flags
|
||||
}
|
||||
|
||||
pub fn block_stacking_context_type(&self) -> BlockStackingContextType {
|
||||
if self.fragment.establishes_stacking_context() {
|
||||
return BlockStackingContextType::StackingContext
|
||||
}
|
||||
|
||||
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
|
||||
self.fragment.style.get_box().position != position::T::static_ ||
|
||||
self.base.flags.is_float() {
|
||||
BlockStackingContextType::PseudoStackingContext
|
||||
} else {
|
||||
BlockStackingContextType::NonstackingContext
|
||||
}
|
||||
}
|
||||
|
||||
pub fn overflow_style_may_require_clip_scroll_node(&self) -> bool {
|
||||
match (self.fragment.style().get_box().overflow_x,
|
||||
self.fragment.style().get_box().overflow_y) {
|
||||
|
|
|
@ -181,6 +181,9 @@ pub struct StackingContextCollectionState {
|
|||
/// The current stacking real context id, which doesn't include pseudo-stacking contexts.
|
||||
pub current_real_stacking_context_id: StackingContextId,
|
||||
|
||||
/// The next stacking context id that we will assign to a stacking context.
|
||||
pub next_stacking_context_id: StackingContextId,
|
||||
|
||||
/// The current clip and scroll info, used to keep track of state when
|
||||
/// recursively building and processing the display list.
|
||||
pub current_clip_and_scroll_info: ClipAndScrollInfo,
|
||||
|
@ -212,6 +215,7 @@ impl StackingContextCollectionState {
|
|||
clip_scroll_node_parents: FnvHashMap::default(),
|
||||
current_stacking_context_id: StackingContextId::root(),
|
||||
current_real_stacking_context_id: StackingContextId::root(),
|
||||
next_stacking_context_id: StackingContextId::root().next(),
|
||||
current_clip_and_scroll_info: root_clip_info,
|
||||
containing_block_clip_and_scroll_info: root_clip_info,
|
||||
clip_stack: Vec::new(),
|
||||
|
@ -220,6 +224,11 @@ impl StackingContextCollectionState {
|
|||
}
|
||||
}
|
||||
|
||||
fn generate_stacking_context_id(&mut self) -> StackingContextId {
|
||||
let next_stacking_context_id = self.next_stacking_context_id.next();
|
||||
mem::replace(&mut self.next_stacking_context_id, next_stacking_context_id)
|
||||
}
|
||||
|
||||
fn add_stacking_context(&mut self,
|
||||
parent_id: StackingContextId,
|
||||
stacking_context: StackingContext) {
|
||||
|
@ -611,10 +620,6 @@ pub trait FragmentDisplayListBuilding {
|
|||
parent_clip_and_scroll_info: ClipAndScrollInfo)
|
||||
-> StackingContext;
|
||||
|
||||
|
||||
/// The id of stacking context this fragment would create.
|
||||
fn stacking_context_id(&self) -> StackingContextId;
|
||||
|
||||
fn unique_id(&self, id_type: IdType) -> u64;
|
||||
|
||||
fn fragment_type(&self) -> FragmentType;
|
||||
|
@ -2169,10 +2174,6 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
fn stacking_context_id(&self) -> StackingContextId {
|
||||
StackingContextId::new(self.unique_id(IdType::StackingContext))
|
||||
}
|
||||
|
||||
fn create_stacking_context(&self,
|
||||
id: StackingContextId,
|
||||
base_flow: &BaseFlow,
|
||||
|
@ -2394,9 +2395,11 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
bitflags! {
|
||||
pub flags StackingContextCollectionFlags: u8 {
|
||||
/// This flow never establishes a containing block.
|
||||
const NEVER_CREATES_CONTAINING_BLOCK = 0x01,
|
||||
const NEVER_CREATES_CONTAINING_BLOCK = 0b001,
|
||||
/// This flow never creates a ClipScrollNode.
|
||||
const NEVER_CREATES_CLIP_SCROLL_NODE = 0x02,
|
||||
const NEVER_CREATES_CLIP_SCROLL_NODE = 0b010,
|
||||
/// This flow never creates a stacking context.
|
||||
const NEVER_CREATES_STACKING_CONTEXT = 0b100,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2435,6 +2438,11 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
fn build_display_list_for_block(&mut self,
|
||||
state: &mut DisplayListBuildState,
|
||||
border_painting_mode: BorderPaintingMode);
|
||||
|
||||
fn block_stacking_context_type(
|
||||
&self,
|
||||
flags: StackingContextCollectionFlags,
|
||||
) -> BlockStackingContextType;
|
||||
}
|
||||
|
||||
/// This structure manages ensuring that modification to StackingContextCollectionState is
|
||||
|
@ -2572,11 +2580,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
flags: StackingContextCollectionFlags) {
|
||||
let mut preserved_state = SavedStackingContextCollectionState::new(state);
|
||||
|
||||
let block_stacking_context_type = self.block_stacking_context_type();
|
||||
let block_stacking_context_type = self.block_stacking_context_type(flags);
|
||||
self.base.stacking_context_id = match block_stacking_context_type {
|
||||
BlockStackingContextType::NonstackingContext => state.current_stacking_context_id,
|
||||
BlockStackingContextType::PseudoStackingContext |
|
||||
BlockStackingContextType::StackingContext => self.fragment.stacking_context_id(),
|
||||
BlockStackingContextType::StackingContext => state.generate_stacking_context_id(),
|
||||
};
|
||||
state.current_stacking_context_id = self.base.stacking_context_id;
|
||||
|
||||
|
@ -2963,6 +2971,33 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
state.processing_scrolling_overflow_element = false;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn block_stacking_context_type(
|
||||
&self,
|
||||
flags: StackingContextCollectionFlags,
|
||||
) -> BlockStackingContextType {
|
||||
if flags.contains(NEVER_CREATES_STACKING_CONTEXT) {
|
||||
return BlockStackingContextType::NonstackingContext;
|
||||
}
|
||||
|
||||
if self.fragment.establishes_stacking_context() {
|
||||
return BlockStackingContextType::StackingContext
|
||||
}
|
||||
|
||||
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
||||
return BlockStackingContextType::PseudoStackingContext
|
||||
}
|
||||
|
||||
if self.fragment.style.get_box().position != position::T::static_ {
|
||||
return BlockStackingContextType::PseudoStackingContext
|
||||
}
|
||||
|
||||
if self.base.flags.is_float() {
|
||||
return BlockStackingContextType::PseudoStackingContext
|
||||
}
|
||||
|
||||
BlockStackingContextType::NonstackingContext
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InlineFlowDisplayListBuilding {
|
||||
|
@ -2988,7 +3023,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
|||
|
||||
if !fragment.collect_stacking_contexts_for_blocklike_fragment(state) {
|
||||
if fragment.establishes_stacking_context() {
|
||||
fragment.stacking_context_id = fragment.stacking_context_id();
|
||||
fragment.stacking_context_id = state.generate_stacking_context_id();
|
||||
|
||||
let current_stacking_context_id = state.current_stacking_context_id;
|
||||
let stacking_context =
|
||||
|
|
|
@ -11,7 +11,7 @@ use block::{BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
|
|||
use block::{ISizeConstraintInput, ISizeConstraintSolution};
|
||||
use context::LayoutContext;
|
||||
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
|
||||
use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags};
|
||||
use display_list_builder::{DisplayListBuildState, NEVER_CREATES_STACKING_CONTEXT};
|
||||
use display_list_builder::StackingContextCollectionState;
|
||||
use euclid::Point2D;
|
||||
use flow;
|
||||
|
@ -504,8 +504,8 @@ impl Flow for TableFlow {
|
|||
}
|
||||
|
||||
fn collect_stacking_contexts(&mut self, state: &mut StackingContextCollectionState) {
|
||||
self.block_flow.collect_stacking_contexts_for_block(state,
|
||||
StackingContextCollectionFlags::empty());
|
||||
// Stacking contexts are collected by the table wrapper.
|
||||
self.block_flow.collect_stacking_contexts_for_block(state, NEVER_CREATES_STACKING_CONTEXT);
|
||||
}
|
||||
|
||||
fn repair_style(&mut self, new_style: &::ServoArc<ComputedValues>) {
|
||||
|
|
|
@ -763,13 +763,21 @@ impl Stylist {
|
|||
|
||||
// For most (but not all) pseudo-elements, we inherit all values from the parent.
|
||||
let inherit_all = match *pseudo {
|
||||
// Anonymous table flows shouldn't inherit their parents properties in order
|
||||
// to avoid doubling up styles such as transformations.
|
||||
PseudoElement::ServoAnonymousTableCell |
|
||||
PseudoElement::ServoAnonymousTableRow |
|
||||
PseudoElement::ServoText |
|
||||
PseudoElement::ServoInputText => false,
|
||||
PseudoElement::ServoAnonymousBlock |
|
||||
|
||||
// For tables, we do want style to inherit, because TableWrapper is responsible
|
||||
// for handling clipping and scrolling, while Table is responsible for creating
|
||||
// stacking contexts. StackingContextCollectionFlags makes sure this is processed
|
||||
// properly.
|
||||
PseudoElement::ServoAnonymousTable |
|
||||
PseudoElement::ServoAnonymousTableCell |
|
||||
PseudoElement::ServoAnonymousTableRow |
|
||||
PseudoElement::ServoAnonymousTableWrapper |
|
||||
|
||||
PseudoElement::ServoTableWrapper |
|
||||
PseudoElement::ServoInlineBlockWrapper |
|
||||
PseudoElement::ServoInlineAbsolute => true,
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[transform-table-002.htm]
|
||||
type: reftest
|
||||
expected: FAIL
|
||||
bug: https://github.com/servo/servo/issues/8003
|
|
@ -0,0 +1,4 @@
|
|||
[transform-table-005.htm]
|
||||
type: reftest
|
||||
expected: FAIL
|
||||
bug: https://github.com/servo/servo/issues/8003
|
|
@ -1,3 +0,0 @@
|
|||
[abspos-containing-block-initial-005b.htm]
|
||||
type: reftest
|
||||
expected: FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[abspos-containing-block-initial-005d.htm]
|
||||
type: reftest
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue