diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-10-18 21:34:23 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-18 21:34:23 -0500 |
commit | 865b9aea357d4b51696d4a0343521a0f2a20bcf1 (patch) | |
tree | 8717e02dcc3102ca31fefa0faf06cc83b869c7ec | |
parent | 4c538b642e4bdfbf42c522c5a59c258a6d14546e (diff) | |
parent | 36fa7e4c448cbc110ada5d5e45482aa228e505e3 (diff) | |
download | servo-865b9aea357d4b51696d4a0343521a0f2a20bcf1.tar.gz servo-865b9aea357d4b51696d4a0343521a0f2a20bcf1.zip |
Auto merge of #18921 - mrobinson:incremental-stacking-context-ids, r=emilio
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.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes do not require tests because they are covered by existing tests.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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/18921)
<!-- Reviewable:end -->
9 files changed, 72 insertions, 42 deletions
diff --git a/components/gfx_traits/lib.rs b/components/gfx_traits/lib.rs index 9688d90bbef..6f5b380dd43 100644 --- a/components/gfx_traits/lib.rs +++ b/components/gfx_traits/lib.rs @@ -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) } } diff --git a/components/layout/block.rs b/components/layout/block.rs index bffcbef0e67..aaad1d51937 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -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) { diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index d478bdd3694..170b662662c 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -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 = diff --git a/components/layout/table.rs b/components/layout/table.rs index 7009e4ec60b..37fb246935f 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -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>) { diff --git a/components/style/stylist.rs b/components/style/stylist.rs index e40c1a7c842..72445369d7c 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -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, diff --git a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-table-002.htm.ini b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-table-002.htm.ini new file mode 100644 index 00000000000..7a0e1e2fac8 --- /dev/null +++ b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-table-002.htm.ini @@ -0,0 +1,4 @@ +[transform-table-002.htm] + type: reftest + expected: FAIL + bug: https://github.com/servo/servo/issues/8003 diff --git a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-table-005.htm.ini b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-table-005.htm.ini new file mode 100644 index 00000000000..1e3a14cf667 --- /dev/null +++ b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-table-005.htm.ini @@ -0,0 +1,4 @@ +[transform-table-005.htm] + type: reftest + expected: FAIL + bug: https://github.com/servo/servo/issues/8003 diff --git a/tests/wpt/metadata-css/css21_dev/html4/abspos-containing-block-initial-005b.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/abspos-containing-block-initial-005b.htm.ini deleted file mode 100644 index 02c3f7ec9dd..00000000000 --- a/tests/wpt/metadata-css/css21_dev/html4/abspos-containing-block-initial-005b.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[abspos-containing-block-initial-005b.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata-css/css21_dev/html4/abspos-containing-block-initial-005d.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/abspos-containing-block-initial-005d.htm.ini deleted file mode 100644 index 087e871ddf4..00000000000 --- a/tests/wpt/metadata-css/css21_dev/html4/abspos-containing-block-initial-005d.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[abspos-containing-block-initial-005d.htm] - type: reftest - expected: FAIL |