Changeset 270474 in webkit
- Timestamp:
- Dec 5, 2020, 10:53:41 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 14 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r270473 r270474 1 2020-12-05 Simon Fraser <simon.fraser@apple.com> 2 3 [LFC Display] Store the display tree as a tree of stacking items 4 https://bugs.webkit.org/show_bug.cgi?id=219315 5 6 Reviewed by Zalan Bujtas. 7 8 Currently the display tree is a full tree, crossing stacking context boundaries, and the 9 z-order lists are built at paint time. 10 11 Change to a tree of StackingItems, where a StackingItem exists for each box that 12 participates in the z-order sorting algorithm (i.e. boxes that are positioned, or have 13 styles that create stacking context). Each StackingItem owns the subtree of Display::Boxes 14 that it paints, and those subtrees are not otherwise connected. 15 16 The Display::Tree owns the root StackingItem, and each StackingItem owns its child 17 StackingItems. The StackingItem tree is built at display tree building time by storing state 18 in the BuildingState stack. StackingItems are added to the z-order lists of their parent 19 item at creation time; when done processing boxes for a StackingItem, we then sort its 20 z-order lists. 21 22 Add Box::participatesInZOrderSorting() and a LineBreakBox flag, and call that function 23 instead of the version on Display::Style to work around webkit.org/b/219335 for now. 24 25 * Sources.txt: 26 * WebCore.xcodeproj/project.pbxproj: 27 * display/DisplayLayerController.cpp: 28 * display/DisplayTree.cpp: 29 (WebCore::Display::Tree::Tree): 30 (WebCore::Display::Tree::rootBox const): 31 * display/DisplayTree.h: 32 (WebCore::Display::Tree::rootStackingItem const): 33 (WebCore::Display::Tree::rootBox const): Deleted. 34 * display/DisplayTreeBuilder.cpp: 35 (WebCore::Display::TreeBuilder::build): 36 (WebCore::Display::TreeBuilder::pushStateForBoxDescendants): 37 (WebCore::Display::TreeBuilder::popState): 38 (WebCore::Display::TreeBuilder::insertIntoTree): 39 (WebCore::Display::TreeBuilder::buildInlineDisplayTree): 40 (WebCore::Display::TreeBuilder::recursiveBuildDisplayTree): 41 (WebCore::Display::outputDisplayBox): 42 (WebCore::Display::outputDisplayTree): 43 (WebCore::Display::displayTreeAsText): 44 (WebCore::Display::outputStackingTree): 45 (WebCore::Display::showDisplayTree): 46 * display/DisplayTreeBuilder.h: 47 * display/css/DisplayBox.cpp: 48 (WebCore::Display::Box::participatesInZOrderSorting const): 49 * display/css/DisplayBox.h: 50 (WebCore::Display::Box::isLineBreakBox const): 51 * display/css/DisplayBoxFactory.cpp: 52 (WebCore::Display::BoxFactory::displayBoxForRootBox const): 53 (WebCore::Display::BoxFactory::displayBoxForLayoutBox const): 54 (WebCore::Display::BoxFactory::setupBoxModelBox const): 55 * display/css/DisplayBoxFactory.h: 56 * display/css/DisplayCSSPainter.cpp: 57 (WebCore::Display::CSSPainter::recursivePaintDescendantsForPhase): 58 (WebCore::Display::CSSPainter::paintAtomicallyPaintedBox): 59 (WebCore::Display::CSSPainter::paintStackingContext): 60 (WebCore::Display::CSSPainter::paintTree): 61 (WebCore::Display::CSSPainter::isStackingContextPaintingBoundary): Deleted. 62 (WebCore::Display::CSSPainter::participatesInZOrderSorting): Deleted. 63 (WebCore::Display::CSSPainter::collectStackingContextDescendants): Deleted. 64 (WebCore::Display::CSSPainter::recursiveCollectLayers): Deleted. 65 * display/css/DisplayCSSPainter.h: 66 1 67 2020-12-05 Zalan Bujtas <zalan@apple.com> 2 68 -
trunk/Source/WebCore/Sources.txt
r270435 r270474 849 849 display/css/DisplayImageBox.cpp 850 850 display/css/DisplayReplacedBox.cpp 851 display/css/DisplayStackingItem.cpp 851 852 display/css/DisplayStyle.cpp 852 853 display/css/DisplayTextBox.cpp -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r270462 r270474 6084 6084 0F7DF1471E2BF1A60095951B /* WebCoreJSClientData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebCoreJSClientData.cpp; sourceTree = "<group>"; }; 6085 6085 0F850FE21ED7C18300FB77A7 /* PerformanceLoggingClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PerformanceLoggingClient.h; sourceTree = "<group>"; }; 6086 0F8682FA25707F4700C08BB5 /* DisplayStackingItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayStackingItem.h; sourceTree = "<group>"; }; 6087 0F8682FC25707F4700C08BB5 /* DisplayStackingItem.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayStackingItem.cpp; sourceTree = "<group>"; }; 6086 6088 0F87166D1C869D83004FF0DE /* LengthPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LengthPoint.cpp; sourceTree = "<group>"; }; 6087 6089 0F87166E1C869D83004FF0DE /* LengthPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LengthPoint.h; sourceTree = "<group>"; }; … … 17870 17872 0FFF1B7C251BC6570098795A /* DisplayReplacedBox.cpp */, 17871 17873 0FFF1B79251BC6570098795A /* DisplayReplacedBox.h */, 17874 0F8682FC25707F4700C08BB5 /* DisplayStackingItem.cpp */, 17875 0F8682FA25707F4700C08BB5 /* DisplayStackingItem.h */, 17872 17876 0FFF1B76251BC6570098795A /* DisplayStyle.cpp */, 17873 17877 0FFF1B73251BC6570098795A /* DisplayStyle.h */, -
trunk/Source/WebCore/display/DisplayLayerController.cpp
r269239 r270474 32 32 #include "ChromeClient.h" 33 33 #include "DisplayCSSPainter.h" 34 #include "DisplayContainerBox.h" 34 35 #include "DisplayPaintingContext.h" 35 36 #include "DisplayTree.h" -
trunk/Source/WebCore/display/DisplayTree.cpp
r267509 r270474 29 29 #if ENABLE(LAYOUT_FORMATTING_CONTEXT) 30 30 31 #include "DisplayContainerBox.h" 32 #include "DisplayStackingItem.h" 31 33 #include <wtf/IsoMallocInlines.h> 32 34 … … 34 36 namespace Display { 35 37 36 Tree::Tree(std::unique_ptr< ContainerBox>&& rootBox)37 : m_root Box(WTFMove(rootBox))38 Tree::Tree(std::unique_ptr<StackingItem>&& rootStackingItem) 39 : m_rootStackingItem(WTFMove(rootStackingItem)) 38 40 { 39 ASSERT(m_rootBox); 41 ASSERT(m_rootStackingItem); 42 } 43 44 Tree::~Tree() = default; 45 46 const ContainerBox& Tree::rootBox() const 47 { 48 return downcast<ContainerBox>(m_rootStackingItem->box()); 40 49 } 41 50 -
trunk/Source/WebCore/display/DisplayTree.h
r267509 r270474 28 28 #if ENABLE(LAYOUT_FORMATTING_CONTEXT) 29 29 30 #include "DisplayContainerBox.h"31 30 #include <wtf/IsoMalloc.h> 32 31 … … 34 33 namespace Display { 35 34 35 class ContainerBox; 36 class StackingItem; 37 36 38 class Tree { 37 39 WTF_MAKE_FAST_ALLOCATED(Tree); 38 40 public: 39 Tree(std::unique_ptr<ContainerBox>&&); 41 explicit Tree(std::unique_ptr<StackingItem>&&); 42 ~Tree(); 40 43 41 const ContainerBox& rootBox() const { return *m_rootBox; } 44 const StackingItem& rootStackingItem() const { return *m_rootStackingItem; } 45 const ContainerBox& rootBox() const; 42 46 43 47 private: 44 // Ideally this root box would be agnostic to display type (CSS vs SVG). 45 std::unique_ptr<ContainerBox> m_rootBox; 48 std::unique_ptr<StackingItem> m_rootStackingItem; 46 49 }; 47 50 -
trunk/Source/WebCore/display/DisplayTreeBuilder.cpp
r270251 r270474 31 31 #include "DisplayBoxFactory.h" 32 32 #include "DisplayContainerBox.h" 33 #include "DisplayStackingItem.h" 33 34 #include "DisplayStyle.h" 34 35 #include "DisplayTree.h" … … 99 100 struct BuildingState { 100 101 PositioningContext positioningContext; 102 StackingItem& currentStackingContextItem; 101 103 }; 102 104 … … 124 126 auto geometry = layoutState.geometryForBox(rootLayoutBox); 125 127 auto rootDisplayBox = m_boxFactory.displayBoxForRootBox(rootLayoutBox, geometry, m_rootBackgroundPropgation); 126 auto rootDisplayContainerBox = std::unique_ptr<ContainerBox> { downcast<ContainerBox>(rootDisplayBox.release()) }; 127 128 if (!rootLayoutBox.firstChild()) 129 return makeUnique<Tree>(WTFMove(rootDisplayContainerBox)); 130 131 auto insertionPosition = InsertionPosition { *rootDisplayContainerBox }; 132 133 m_stateStack->append({ *rootDisplayContainerBox }); 134 135 recursiveBuildDisplayTree(layoutState, *rootLayoutBox.firstChild(), insertionPosition); 128 129 auto insertionPosition = InsertionPosition { *rootDisplayBox }; 130 auto rootStackingItem = makeUnique<StackingItem>(WTFMove(rootDisplayBox)); 131 132 if (rootLayoutBox.firstChild()) { 133 auto& rootContainerBox = downcast<ContainerBox>(rootStackingItem->box()); 134 m_stateStack->append({ rootContainerBox, *rootStackingItem }); 135 recursiveBuildDisplayTree(layoutState, *rootLayoutBox.firstChild(), insertionPosition); 136 } 136 137 137 138 #if ENABLE(TREE_DEBUGGING) 138 LOG_WITH_STREAM(FormattingContextLayout, stream << "Display tree:\n" << displayTreeAsText(*root DisplayContainerBox));139 LOG_WITH_STREAM(FormattingContextLayout, stream << "Display tree:\n" << displayTreeAsText(*rootStackingItem)); 139 140 #endif 140 141 return makeUnique<Tree>(WTFMove(rootDisplayContainerBox)); 142 } 143 144 void TreeBuilder::pushStateForBoxDescendants(const Layout::ContainerBox& layoutContainerBox, const Layout::BoxGeometry& layoutGeometry, const ContainerBox& displayBox) 141 return makeUnique<Tree>(WTFMove(rootStackingItem)); 142 } 143 144 void TreeBuilder::pushStateForBoxDescendants(const Layout::ContainerBox& layoutContainerBox, const Layout::BoxGeometry& layoutGeometry, const ContainerBox& displayBox, StackingItem* boxStackingItem) 145 145 { 146 146 auto& positioningContext = m_stateStack->last().positioningContext; 147 m_stateStack->append({ positioningContext.contextForDescendants(layoutContainerBox, layoutGeometry, displayBox) }); 148 } 149 150 void TreeBuilder::popState() 151 { 147 auto& currentStackingContextItem = (boxStackingItem && boxStackingItem->isStackingContext()) ? *boxStackingItem : m_stateStack->last().currentStackingContextItem; 148 149 m_stateStack->append({ positioningContext.contextForDescendants(layoutContainerBox, layoutGeometry, displayBox), currentStackingContextItem }); 150 } 151 152 void TreeBuilder::popState(const ContainerBox& currentBox) 153 { 154 auto& currentState = m_stateStack->last(); 155 if (¤tState.currentStackingContextItem.box() == ¤tBox) 156 currentState.currentStackingContextItem.sortLists(); 157 152 158 m_stateStack->removeLast(); 153 159 } … … 176 182 } 177 183 184 StackingItem* TreeBuilder::insertIntoTree(std::unique_ptr<Box>&& box, InsertionPosition& insertionPosition) 185 { 186 if (box->participatesInZOrderSorting() && is<BoxModelBox>(*box)) { 187 auto boxModelBox = std::unique_ptr<BoxModelBox> { downcast<BoxModelBox>(box.release()) }; 188 auto stackingItem = makeUnique<StackingItem>(WTFMove(boxModelBox)); 189 190 auto* stackingItemPtr = stackingItem.get(); 191 currentState().currentStackingContextItem.addChildStackingItem(WTFMove(stackingItem)); 192 return stackingItemPtr; 193 } 194 195 insert(WTFMove(box), insertionPosition); 196 return nullptr; 197 } 198 178 199 void TreeBuilder::buildInlineDisplayTree(const Layout::LayoutState& layoutState, const Layout::ContainerBox& inlineFormattingRoot, InsertionPosition& insertionPosition) 179 200 { … … 193 214 } 194 215 216 // FIXME: Workaround for webkit.orgb/b/219335. 217 if (run.layoutBox().isLineBreakBox() && run.layoutBox().isOutOfFlowPositioned()) 218 continue; 219 195 220 auto geometry = layoutState.geometryForBox(run.layoutBox()); 196 221 auto displayBox = m_boxFactory.displayBoxForLayoutBox(run.layoutBox(), geometry, positioningContext().inFlowContainingBlockContext()); 197 insert (WTFMove(displayBox), insertionPosition);222 insertIntoTree(WTFMove(displayBox), insertionPosition); 198 223 } 199 224 } … … 209 234 else 210 235 displayBox = m_boxFactory.displayBoxForLayoutBox(layoutBox, geometry, containingBlockContext); 211 212 insert(WTFMove(displayBox), insertionPosition); 213 236 237 Box& currentBox = *displayBox; 238 239 auto* stackingItem = insertIntoTree(WTFMove(displayBox), insertionPosition); 214 240 if (!is<Layout::ContainerBox>(layoutBox)) 215 241 return; … … 219 245 return; 220 246 221 ContainerBox& current Box = downcast<ContainerBox>(*insertionPosition.currentChild);222 auto insertionPositionForChildren = InsertionPosition { currentBox };223 224 pushStateForBoxDescendants(layoutContainerBox, geometry, currentBox);247 ContainerBox& currentContainerBox = downcast<ContainerBox>(currentBox); 248 pushStateForBoxDescendants(layoutContainerBox, geometry, currentContainerBox, stackingItem); 249 250 auto insertionPositionForChildren = InsertionPosition { currentContainerBox }; 225 251 226 252 enum class DescendantBoxInclusion { AllBoxes, OutOfFlowOnly }; … … 245 271 } 246 272 247 popState( );273 popState(currentContainerBox); 248 274 } 249 275 250 276 #if ENABLE(TREE_DEBUGGING) 251 277 252 static void outputDisplayBox(TextStream& stream, const Box& displayBox, unsigned) 253 { 254 stream.writeIndent(); 278 static void outputDisplayBox(TextStream& stream, const Box& displayBox, bool writeIndent = true) 279 { 280 if (writeIndent) 281 stream.writeIndent(); 255 282 256 283 stream << displayBox.debugDescription(); … … 258 285 } 259 286 260 static void outputDisplayTree(TextStream& stream, const Box& displayBox, unsigned depth)261 { 262 outputDisplayBox(stream, displayBox, depth);287 static void outputDisplayTree(TextStream& stream, const Box& displayBox, bool writeFirstItemIndent = true) 288 { 289 outputDisplayBox(stream, displayBox, writeFirstItemIndent); 263 290 264 291 if (is<ContainerBox>(displayBox)) { 265 292 TextStream::IndentScope indent(stream); 266 293 for (auto child = downcast<ContainerBox>(displayBox).firstChild(); child; child = child->nextSibling()) 267 outputDisplayTree(stream, *child , depth + 1);294 outputDisplayTree(stream, *child); 268 295 } 269 296 } … … 272 299 { 273 300 TextStream stream(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect); 274 outputDisplayTree(stream, box , 1);301 outputDisplayTree(stream, box); 275 302 return stream.release(); 276 303 } … … 282 309 } 283 310 311 static void outputStackingTree(TextStream& stream, const char* prefix, const StackingItem& stackingItem) 312 { 313 stream.writeIndent(); 314 stream << prefix; 315 316 TextStream::IndentScope indent(stream); 317 outputDisplayTree(stream, stackingItem.box(), false); 318 319 { 320 TextStream::IndentScope indent(stream); 321 for (auto& childStackingItem : stackingItem.negativeZOrderList()) 322 outputStackingTree(stream, "- ", *childStackingItem); 323 324 for (auto& childStackingItem : stackingItem.positiveZOrderList()) 325 outputStackingTree(stream, childStackingItem->isStackingContext() ? "+ " : "p ", *childStackingItem); 326 } 327 } 328 329 String displayTreeAsText(const StackingItem& stackingItem) 330 { 331 TextStream stream(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect); 332 outputStackingTree(stream, "", stackingItem); 333 return stream.release(); 334 } 335 336 void showDisplayTree(const StackingItem& stackingItem) 337 { 338 auto treeAsText = displayTreeAsText(stackingItem); 339 WTFLogAlways("%s", treeAsText.utf8().data()); 340 } 341 284 342 #endif 285 343 -
trunk/Source/WebCore/display/DisplayTreeBuilder.h
r270251 r270474 51 51 class ContainerBox; 52 52 class PositioningContext; 53 class StackingItem; 53 54 class Tree; 54 55 struct BuildingState; … … 70 71 void buildInlineDisplayTree(const Layout::LayoutState&, const Layout::ContainerBox&, InsertionPosition&); 71 72 73 StackingItem* insertIntoTree(std::unique_ptr<Box>&&, InsertionPosition&); 72 74 void insert(std::unique_ptr<Box>&&, InsertionPosition&) const; 73 75 74 void pushStateForBoxDescendants(const Layout::ContainerBox&, const Layout::BoxGeometry&, const ContainerBox& );75 void popState( );76 void pushStateForBoxDescendants(const Layout::ContainerBox&, const Layout::BoxGeometry&, const ContainerBox&, StackingItem*); 77 void popState(const ContainerBox& currentBox); 76 78 77 79 const BuildingState& currentState() const; … … 80 82 BoxFactory m_boxFactory; 81 83 RootBackgroundPropagation m_rootBackgroundPropgation { RootBackgroundPropagation::None }; 82 84 83 85 std::unique_ptr<Vector<BuildingState>> m_stateStack; 84 86 }; … … 87 89 String displayTreeAsText(const Box&); 88 90 void showDisplayTree(const Box&); 91 92 String displayTreeAsText(const StackingItem&); 93 void showDisplayTree(const StackingItem&); 89 94 #endif 90 95 -
trunk/Source/WebCore/display/css/DisplayBox.cpp
r270206 r270474 51 51 } 52 52 53 bool Box::participatesInZOrderSorting() const 54 { 55 return !isLineBreakBox() && style().participatesInZOrderSorting(); 56 } 57 53 58 String Box::debugDescription() const 54 59 { -
trunk/Source/WebCore/display/css/DisplayBox.h
r268955 r270474 47 47 ImageBox = 1 << 2, 48 48 TextBox = 1 << 3, 49 LineBreakBox = 1 << 4, // FIXME: Workaround for webkit.org/b/219335 49 50 }; 50 51 … … 61 62 bool isReplacedBox() const { return m_flags.contains(Flags::ImageBox); /* and other types later. */ } 62 63 bool isTextBox() const { return m_flags.contains(Flags::TextBox); } 64 bool isLineBreakBox() const { return m_flags.contains(Flags::LineBreakBox); } 65 66 bool participatesInZOrderSorting() const; 63 67 64 68 const Box* nextSibling() const { return m_nextSibling.get(); } -
trunk/Source/WebCore/display/css/DisplayBoxFactory.cpp
r270225 r270474 68 68 } 69 69 70 std::unique_ptr< Box> BoxFactory::displayBoxForRootBox(const Layout::ContainerBox& rootLayoutBox, const Layout::BoxGeometry& geometry, RootBackgroundPropagation rootBackgroundPropagation) const70 std::unique_ptr<ContainerBox> BoxFactory::displayBoxForRootBox(const Layout::ContainerBox& rootLayoutBox, const Layout::BoxGeometry& geometry, RootBackgroundPropagation rootBackgroundPropagation) const 71 71 { 72 72 ASSERT(is<Layout::InitialContainingBlock>(rootLayoutBox)); … … 136 136 } 137 137 138 return makeUnique<Box>(snapRectToDevicePixels(borderBoxRect, m_pixelSnappingFactor), WTFMove(style)); 138 OptionSet<Box::Flags> flags; 139 // FIXME: Workaround for webkit.org/b/219335. 140 if (layoutBox.isLineBreakBox()) 141 flags.add(Box::Flags::LineBreakBox); 142 143 return makeUnique<Box>(snapRectToDevicePixels(borderBoxRect, m_pixelSnappingFactor), WTFMove(style), flags); 139 144 } 140 145 … … 265 270 box.setBoxDecorationData(WTFMove(boxDecorationData)); 266 271 267 if (box. style().participatesInZOrderSorting()) {272 if (box.participatesInZOrderSorting()) { 268 273 RefPtr<BoxClip> clip = containingBlockContext.box.clipForDescendants(); 269 274 box.setAncestorClip(WTFMove(clip)); -
trunk/Source/WebCore/display/css/DisplayBoxFactory.h
r270222 r270474 70 70 static RootBackgroundPropagation determineRootBackgroundPropagation(const Layout::ContainerBox& rootLayoutBox); 71 71 72 std::unique_ptr< Box> displayBoxForRootBox(const Layout::ContainerBox&, const Layout::BoxGeometry&, RootBackgroundPropagation) const;72 std::unique_ptr<ContainerBox> displayBoxForRootBox(const Layout::ContainerBox&, const Layout::BoxGeometry&, RootBackgroundPropagation) const; 73 73 std::unique_ptr<Box> displayBoxForBodyBox(const Layout::Box&, const Layout::BoxGeometry&, const ContainingBlockContext&, RootBackgroundPropagation) const; 74 74 std::unique_ptr<Box> displayBoxForLayoutBox(const Layout::Box&, const Layout::BoxGeometry&, const ContainingBlockContext&) const; -
trunk/Source/WebCore/display/css/DisplayCSSPainter.cpp
r270225 r270474 34 34 #include "DisplayContainerBox.h" 35 35 #include "DisplayPaintingContext.h" 36 #include "DisplayStackingItem.h" 36 37 #include "DisplayStyle.h" 37 38 #include "DisplayTree.h" … … 83 84 for (const auto* child = containerBox.firstChild(); child; child = child->nextSibling()) { 84 85 auto& box = *child; 85 if (participatesInZOrderSorting(box)) 86 continue; 86 ASSERT(!box.participatesInZOrderSorting()); 87 87 88 88 switch (paintPhase) { … … 125 125 } 126 126 127 void CSSPainter::paintAtomicallyPaintedBox(const Box& box, PaintingContext& paintingContext, const IntRect& dirtyRect, IncludeStackingContextDescendants includeStackingContextDescendants)127 void CSSPainter::paintAtomicallyPaintedBox(const StackingItem& stackingItem, PaintingContext& paintingContext, const IntRect& dirtyRect, IncludeStackingContextDescendants includeStackingContextDescendants) 128 128 { 129 129 UNUSED_PARAM(dirtyRect); 130 131 auto& box = stackingItem.box(); 130 132 131 133 auto needToSaveState = [](const Box& box) { … … 162 164 return; 163 165 166 if (includeStackingContextDescendants == IncludeStackingContextDescendants::Yes) { 167 // Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order. 168 for (auto& stackingItem : stackingItem.negativeZOrderList()) 169 paintStackingContext(*stackingItem, paintingContext, dirtyRect); 170 } 171 164 172 auto& containerBox = downcast<ContainerBox>(box); 165 166 Vector<const BoxModelBox*> negativeZOrderList;167 Vector<const BoxModelBox*> positiveZOrderList;168 if (includeStackingContextDescendants == IncludeStackingContextDescendants::Yes) {169 collectStackingContextDescendants(containerBox, negativeZOrderList, positiveZOrderList);170 171 // Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.172 for (auto* box : negativeZOrderList)173 paintStackingContext(*box, paintingContext, dirtyRect);174 }175 176 173 recursivePaintDescendants(containerBox, paintingContext); 177 174 … … 181 178 // should be considered part of the parent stacking context, not this new one. For those with 'z-index: 0', treat the stacking context 182 179 // generated atomically. 183 for (auto * box : positiveZOrderList) {184 if ( box->style().isStackingContext())185 paintStackingContext(* box, paintingContext, dirtyRect);180 for (auto& stackingItem : stackingItem.positiveZOrderList()) { 181 if (stackingItem->isStackingContext()) 182 paintStackingContext(*stackingItem, paintingContext, dirtyRect); 186 183 else 187 paintAtomicallyPaintedBox(* box, paintingContext, dirtyRect);184 paintAtomicallyPaintedBox(*stackingItem, paintingContext, dirtyRect); 188 185 } 189 186 } 190 187 } 191 188 192 void CSSPainter::paintStackingContext(const BoxModelBox& contextRoot, PaintingContext& paintingContext, const IntRect& dirtyRect) 193 { 194 paintAtomicallyPaintedBox(contextRoot, paintingContext, dirtyRect, IncludeStackingContextDescendants::Yes); 195 } 196 197 bool CSSPainter::isStackingContextPaintingBoundary(const Box& box) 198 { 199 return box.style().isStackingContext(); 200 } 201 202 bool CSSPainter::participatesInZOrderSorting(const Box& box) 203 { 204 return box.style().participatesInZOrderSorting(); 205 } 206 207 void CSSPainter::collectStackingContextDescendants(const ContainerBox& containerBox, Vector<const BoxModelBox*>& negativeZOrderList, Vector<const BoxModelBox*>& positiveZOrderList) 208 { 209 recursiveCollectLayers(containerBox, negativeZOrderList, positiveZOrderList); 210 211 auto compareZIndex = [] (const BoxModelBox* a, const BoxModelBox* b) { 212 return a->style().zIndex().valueOr(0) < b->style().zIndex().valueOr(0); 213 }; 214 215 std::stable_sort(positiveZOrderList.begin(), positiveZOrderList.end(), compareZIndex); 216 std::stable_sort(negativeZOrderList.begin(), negativeZOrderList.end(), compareZIndex); 217 } 218 219 void CSSPainter::recursiveCollectLayers(const ContainerBox& containerBox, Vector<const BoxModelBox*>& negativeZOrderList, Vector<const BoxModelBox*>& positiveZOrderList) 220 { 221 for (const auto* child = containerBox.firstChild(); child; child = child->nextSibling()) { 222 if (child->style().participatesInZOrderSorting() && is<BoxModelBox>(*child)) { 223 auto& childBox = downcast<BoxModelBox>(*child); 224 225 auto zIndex = childBox.style().zIndex().valueOr(0); 226 if (zIndex < 0) 227 negativeZOrderList.append(&childBox); 228 else 229 positiveZOrderList.append(&childBox); 230 } 231 232 if (isStackingContextPaintingBoundary(*child)) 233 continue; 234 235 if (is<ContainerBox>(*child)) 236 recursiveCollectLayers(downcast<ContainerBox>(*child), negativeZOrderList, positiveZOrderList); 237 } 189 void CSSPainter::paintStackingContext(const StackingItem& stackingItem, PaintingContext& paintingContext, const IntRect& dirtyRect) 190 { 191 paintAtomicallyPaintedBox(stackingItem, paintingContext, dirtyRect, IncludeStackingContextDescendants::Yes); 238 192 } 239 193 240 194 void CSSPainter::paintTree(const Tree& displayTree, PaintingContext& paintingContext, const IntRect& dirtyRect) 241 195 { 242 paintStackingContext(displayTree.root Box(), paintingContext, dirtyRect);196 paintStackingContext(displayTree.rootStackingItem(), paintingContext, dirtyRect); 243 197 } 244 198 -
trunk/Source/WebCore/display/css/DisplayCSSPainter.h
r270200 r270474 43 43 class BoxModelBox; 44 44 class ContainerBox; 45 class StackingItem; 45 46 class Tree; 46 47 … … 61 62 62 63 enum class IncludeStackingContextDescendants { Yes, No }; 63 static void paintAtomicallyPaintedBox(const Box&, PaintingContext&, const IntRect& dirtyRect, IncludeStackingContextDescendants = IncludeStackingContextDescendants::No);64 static void paintAtomicallyPaintedBox(const StackingItem&, PaintingContext&, const IntRect& dirtyRect, IncludeStackingContextDescendants = IncludeStackingContextDescendants::No); 64 65 65 static void paintStackingContext(const BoxModelBox&, PaintingContext&, const IntRect& dirtyRect); 66 67 static bool isStackingContextPaintingBoundary(const Box&); 68 static bool participatesInZOrderSorting(const Box&); 69 70 static void collectStackingContextDescendants(const ContainerBox&, Vector<const BoxModelBox*>& negativeZOrderList, Vector<const BoxModelBox*>& positiveZOrderList); 71 static void recursiveCollectLayers(const ContainerBox&, Vector<const BoxModelBox*>& negativeZOrderList, Vector<const BoxModelBox*>& positiveZOrderList); 66 static void paintStackingContext(const StackingItem&, PaintingContext&, const IntRect& dirtyRect); 72 67 }; 73 68 -
trunk/Source/WebCore/display/css/DisplayStackingItem.cpp
r270473 r270474 25 25 26 26 #include "config.h" 27 #include "Display Box.h"27 #include "DisplayStackingItem.h" 28 28 29 29 #if ENABLE(LAYOUT_FORMATTING_CONTEXT) 30 30 31 #include "FillLayer.h"32 #include "ShadowData.h"33 31 #include <wtf/IsoMallocInlines.h> 34 32 #include <wtf/text/TextStream.h> … … 37 35 namespace Display { 38 36 39 Box::Box(AbsoluteFloatRect absoluteRect, Style&& displayStyle, OptionSet<Flags> flags) 40 : m_absoluteBoxRect(absoluteRect) 41 , m_style(WTFMove(displayStyle)) 42 , m_flags(flags) 37 StackingItem::StackingItem(std::unique_ptr<BoxModelBox>&& box) 38 : m_box(WTFMove(box)) 43 39 { 40 ASSERT(m_box); 44 41 } 45 42 46 Box::~Box() = default; 47 48 void Box::setNextSibling(std::unique_ptr<Box>&& box) 43 bool StackingItem::isStackingContext() const 49 44 { 50 m_nextSibling = WTFMove(box);45 return m_box->style().isStackingContext(); 51 46 } 52 47 53 String Box::debugDescription() const 48 void StackingItem::addChildStackingItem(std::unique_ptr<StackingItem>&& item) 54 49 { 55 TextStream stream; 56 stream << "display box " << absoluteBoxRect() << " (" << this << ")"; 57 return stream.release(); 50 auto zIndex = item->box().style().zIndex().valueOr(0); 51 if (zIndex < 0) 52 m_negativeZOrderList.append(WTFMove(item)); 53 else 54 m_positiveZOrderList.append(WTFMove(item)); 58 55 } 56 57 void StackingItem::sortLists() 58 { 59 auto compareZIndex = [](const std::unique_ptr<StackingItem>& a, const std::unique_ptr<StackingItem>& b) { 60 return a->box().style().zIndex().valueOr(0) < b->box().style().zIndex().valueOr(0); 61 }; 62 63 std::stable_sort(m_positiveZOrderList.begin(), m_positiveZOrderList.end(), compareZIndex); 64 std::stable_sort(m_negativeZOrderList.begin(), m_negativeZOrderList.end(), compareZIndex); 65 } 66 59 67 60 68 } // namespace Display -
trunk/Source/WebCore/display/css/DisplayStackingItem.h
r270473 r270474 28 28 #if ENABLE(LAYOUT_FORMATTING_CONTEXT) 29 29 30 #include "DisplayContainerBox.h"31 30 #include <wtf/IsoMalloc.h> 31 #include <wtf/OptionSet.h> 32 #include <wtf/Vector.h> 32 33 33 34 namespace WebCore { 34 35 namespace Display { 35 36 36 class Tree { 37 WTF_MAKE_FAST_ALLOCATED(Tree); 37 class BoxModelBox; 38 39 // Container for a display box and its descendants, for boxes that participate in the CSS stacking 40 // algorithm <https://www.w3.org/TR/CSS22/zindex.html>, i.e. positioned boxes, and those that create 41 // CSS stacking context. 42 43 class StackingItem { 44 WTF_MAKE_FAST_ALLOCATED; 45 friend class TreeBuilder; 38 46 public: 39 Tree(std::unique_ptr<ContainerBox>&&);47 using StackingItemList = Vector<std::unique_ptr<StackingItem>>; 40 48 41 const ContainerBox& rootBox() const { return *m_rootBox; } 49 explicit StackingItem(std::unique_ptr<BoxModelBox>&&); 50 51 void addChildStackingItem(std::unique_ptr<StackingItem>&&); 52 const BoxModelBox& box() const { return *m_box; } 53 54 bool isStackingContext() const; 55 56 const StackingItemList& negativeZOrderList() const { return m_negativeZOrderList; } 57 const StackingItemList& positiveZOrderList() const { return m_positiveZOrderList; } 42 58 43 59 private: 44 // Ideally this root box would be agnostic to display type (CSS vs SVG). 45 std::unique_ptr<ContainerBox> m_rootBox; 60 void sortLists(); 61 62 std::unique_ptr<BoxModelBox> m_box; 63 StackingItemList m_negativeZOrderList; 64 StackingItemList m_positiveZOrderList; 46 65 }; 47 66 … … 49 68 } // namespace WebCore 50 69 70 51 71 #endif // ENABLE(LAYOUT_FORMATTING_CONTEXT)
Note:
See TracChangeset
for help on using the changeset viewer.