Changeset 270474 in webkit


Ignore:
Timestamp:
Dec 5, 2020, 10:53:41 AM (5 years ago)
Author:
Simon Fraser
Message:

[LFC Display] Store the display tree as a tree of stacking items
https://bugs.webkit.org/show_bug.cgi?id=219315

Reviewed by Zalan Bujtas.

Currently the display tree is a full tree, crossing stacking context boundaries, and the
z-order lists are built at paint time.

Change to a tree of StackingItems, where a StackingItem exists for each box that
participates in the z-order sorting algorithm (i.e. boxes that are positioned, or have
styles that create stacking context). Each StackingItem owns the subtree of Display::Boxes
that it paints, and those subtrees are not otherwise connected.

The Display::Tree owns the root StackingItem, and each StackingItem owns its child
StackingItems. The StackingItem tree is built at display tree building time by storing state
in the BuildingState stack. StackingItems are added to the z-order lists of their parent
item at creation time; when done processing boxes for a StackingItem, we then sort its
z-order lists.

Add Box::participatesInZOrderSorting() and a LineBreakBox flag, and call that function
instead of the version on Display::Style to work around webkit.org/b/219335 for now.

  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • display/DisplayLayerController.cpp:
  • display/DisplayTree.cpp:

(WebCore::Display::Tree::Tree):
(WebCore::Display::Tree::rootBox const):

  • display/DisplayTree.h:

(WebCore::Display::Tree::rootStackingItem const):
(WebCore::Display::Tree::rootBox const): Deleted.

  • display/DisplayTreeBuilder.cpp:

(WebCore::Display::TreeBuilder::build):
(WebCore::Display::TreeBuilder::pushStateForBoxDescendants):
(WebCore::Display::TreeBuilder::popState):
(WebCore::Display::TreeBuilder::insertIntoTree):
(WebCore::Display::TreeBuilder::buildInlineDisplayTree):
(WebCore::Display::TreeBuilder::recursiveBuildDisplayTree):
(WebCore::Display::outputDisplayBox):
(WebCore::Display::outputDisplayTree):
(WebCore::Display::displayTreeAsText):
(WebCore::Display::outputStackingTree):
(WebCore::Display::showDisplayTree):

  • display/DisplayTreeBuilder.h:
  • display/css/DisplayBox.cpp:

(WebCore::Display::Box::participatesInZOrderSorting const):

  • display/css/DisplayBox.h:

(WebCore::Display::Box::isLineBreakBox const):

  • display/css/DisplayBoxFactory.cpp:

(WebCore::Display::BoxFactory::displayBoxForRootBox const):
(WebCore::Display::BoxFactory::displayBoxForLayoutBox const):
(WebCore::Display::BoxFactory::setupBoxModelBox const):

  • display/css/DisplayBoxFactory.h:
  • display/css/DisplayCSSPainter.cpp:

(WebCore::Display::CSSPainter::recursivePaintDescendantsForPhase):
(WebCore::Display::CSSPainter::paintAtomicallyPaintedBox):
(WebCore::Display::CSSPainter::paintStackingContext):
(WebCore::Display::CSSPainter::paintTree):
(WebCore::Display::CSSPainter::isStackingContextPaintingBoundary): Deleted.
(WebCore::Display::CSSPainter::participatesInZOrderSorting): Deleted.
(WebCore::Display::CSSPainter::collectStackingContextDescendants): Deleted.
(WebCore::Display::CSSPainter::recursiveCollectLayers): Deleted.

  • display/css/DisplayCSSPainter.h:
Location:
trunk/Source/WebCore
Files:
14 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r270473 r270474  
     12020-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
    1672020-12-05  Zalan Bujtas  <zalan@apple.com>
    268
  • trunk/Source/WebCore/Sources.txt

    r270435 r270474  
    849849display/css/DisplayImageBox.cpp
    850850display/css/DisplayReplacedBox.cpp
     851display/css/DisplayStackingItem.cpp
    851852display/css/DisplayStyle.cpp
    852853display/css/DisplayTextBox.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r270462 r270474  
    60846084                0F7DF1471E2BF1A60095951B /* WebCoreJSClientData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebCoreJSClientData.cpp; sourceTree = "<group>"; };
    60856085                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>"; };
    60866088                0F87166D1C869D83004FF0DE /* LengthPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LengthPoint.cpp; sourceTree = "<group>"; };
    60876089                0F87166E1C869D83004FF0DE /* LengthPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LengthPoint.h; sourceTree = "<group>"; };
     
    1787017872                                0FFF1B7C251BC6570098795A /* DisplayReplacedBox.cpp */,
    1787117873                                0FFF1B79251BC6570098795A /* DisplayReplacedBox.h */,
     17874                                0F8682FC25707F4700C08BB5 /* DisplayStackingItem.cpp */,
     17875                                0F8682FA25707F4700C08BB5 /* DisplayStackingItem.h */,
    1787217876                                0FFF1B76251BC6570098795A /* DisplayStyle.cpp */,
    1787317877                                0FFF1B73251BC6570098795A /* DisplayStyle.h */,
  • trunk/Source/WebCore/display/DisplayLayerController.cpp

    r269239 r270474  
    3232#include "ChromeClient.h"
    3333#include "DisplayCSSPainter.h"
     34#include "DisplayContainerBox.h"
    3435#include "DisplayPaintingContext.h"
    3536#include "DisplayTree.h"
  • trunk/Source/WebCore/display/DisplayTree.cpp

    r267509 r270474  
    2929#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
    3030
     31#include "DisplayContainerBox.h"
     32#include "DisplayStackingItem.h"
    3133#include <wtf/IsoMallocInlines.h>
    3234
     
    3436namespace Display {
    3537
    36 Tree::Tree(std::unique_ptr<ContainerBox>&& rootBox)
    37     : m_rootBox(WTFMove(rootBox))
     38Tree::Tree(std::unique_ptr<StackingItem>&& rootStackingItem)
     39    : m_rootStackingItem(WTFMove(rootStackingItem))
    3840{
    39     ASSERT(m_rootBox);
     41    ASSERT(m_rootStackingItem);
     42}
     43
     44Tree::~Tree() = default;
     45
     46const ContainerBox& Tree::rootBox() const
     47{
     48    return downcast<ContainerBox>(m_rootStackingItem->box());
    4049}
    4150
  • trunk/Source/WebCore/display/DisplayTree.h

    r267509 r270474  
    2828#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
    2929
    30 #include "DisplayContainerBox.h"
    3130#include <wtf/IsoMalloc.h>
    3231
     
    3433namespace Display {
    3534
     35class ContainerBox;
     36class StackingItem;
     37
    3638class Tree {
    3739    WTF_MAKE_FAST_ALLOCATED(Tree);
    3840public:
    39     Tree(std::unique_ptr<ContainerBox>&&);
     41    explicit Tree(std::unique_ptr<StackingItem>&&);
     42    ~Tree();
    4043
    41     const ContainerBox& rootBox() const { return *m_rootBox; }
     44    const StackingItem& rootStackingItem() const { return *m_rootStackingItem; }
     45    const ContainerBox& rootBox() const;
    4246
    4347private:
    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;
    4649};
    4750
  • trunk/Source/WebCore/display/DisplayTreeBuilder.cpp

    r270251 r270474  
    3131#include "DisplayBoxFactory.h"
    3232#include "DisplayContainerBox.h"
     33#include "DisplayStackingItem.h"
    3334#include "DisplayStyle.h"
    3435#include "DisplayTree.h"
     
    99100struct BuildingState {
    100101    PositioningContext positioningContext;
     102    StackingItem& currentStackingContextItem;
    101103};
    102104
     
    124126    auto geometry = layoutState.geometryForBox(rootLayoutBox);
    125127    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    }
    136137
    137138#if ENABLE(TREE_DEBUGGING)
    138     LOG_WITH_STREAM(FormattingContextLayout, stream << "Display tree:\n" << displayTreeAsText(*rootDisplayContainerBox));
     139    LOG_WITH_STREAM(FormattingContextLayout, stream << "Display tree:\n" << displayTreeAsText(*rootStackingItem));
    139140#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
     144void TreeBuilder::pushStateForBoxDescendants(const Layout::ContainerBox& layoutContainerBox, const Layout::BoxGeometry& layoutGeometry, const ContainerBox& displayBox, StackingItem* boxStackingItem)
    145145{
    146146    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
     152void TreeBuilder::popState(const ContainerBox& currentBox)
     153{
     154    auto& currentState = m_stateStack->last();
     155    if (&currentState.currentStackingContextItem.box() == &currentBox)
     156        currentState.currentStackingContextItem.sortLists();
     157
    152158    m_stateStack->removeLast();
    153159}
     
    176182}
    177183
     184StackingItem* 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
    178199void TreeBuilder::buildInlineDisplayTree(const Layout::LayoutState& layoutState, const Layout::ContainerBox& inlineFormattingRoot, InsertionPosition& insertionPosition)
    179200{
     
    193214        }
    194215
     216        // FIXME: Workaround for webkit.orgb/b/219335.
     217        if (run.layoutBox().isLineBreakBox() && run.layoutBox().isOutOfFlowPositioned())
     218            continue;
     219
    195220        auto geometry = layoutState.geometryForBox(run.layoutBox());
    196221        auto displayBox = m_boxFactory.displayBoxForLayoutBox(run.layoutBox(), geometry, positioningContext().inFlowContainingBlockContext());
    197         insert(WTFMove(displayBox), insertionPosition);
     222        insertIntoTree(WTFMove(displayBox), insertionPosition);
    198223    }
    199224}
     
    209234    else
    210235        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);
    214240    if (!is<Layout::ContainerBox>(layoutBox))
    215241        return;
     
    219245        return;
    220246
    221     ContainerBox& currentBox = 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 };
    225251
    226252    enum class DescendantBoxInclusion { AllBoxes, OutOfFlowOnly };
     
    245271    }
    246272
    247     popState();
     273    popState(currentContainerBox);
    248274}
    249275
    250276#if ENABLE(TREE_DEBUGGING)
    251277
    252 static void outputDisplayBox(TextStream& stream, const Box& displayBox, unsigned)
    253 {
    254     stream.writeIndent();
     278static void outputDisplayBox(TextStream& stream, const Box& displayBox, bool writeIndent = true)
     279{
     280    if (writeIndent)
     281        stream.writeIndent();
    255282
    256283    stream << displayBox.debugDescription();
     
    258285}
    259286
    260 static void outputDisplayTree(TextStream& stream, const Box& displayBox, unsigned depth)
    261 {
    262     outputDisplayBox(stream, displayBox, depth);
     287static void outputDisplayTree(TextStream& stream, const Box& displayBox, bool writeFirstItemIndent = true)
     288{
     289    outputDisplayBox(stream, displayBox, writeFirstItemIndent);
    263290
    264291    if (is<ContainerBox>(displayBox)) {
    265292        TextStream::IndentScope indent(stream);
    266293        for (auto child = downcast<ContainerBox>(displayBox).firstChild(); child; child = child->nextSibling())
    267             outputDisplayTree(stream, *child, depth + 1);
     294            outputDisplayTree(stream, *child);
    268295    }
    269296}
     
    272299{
    273300    TextStream stream(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect);
    274     outputDisplayTree(stream, box, 1);
     301    outputDisplayTree(stream, box);
    275302    return stream.release();
    276303}
     
    282309}
    283310
     311static 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
     329String displayTreeAsText(const StackingItem& stackingItem)
     330{
     331    TextStream stream(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect);
     332    outputStackingTree(stream, "", stackingItem);
     333    return stream.release();
     334}
     335
     336void showDisplayTree(const StackingItem& stackingItem)
     337{
     338    auto treeAsText = displayTreeAsText(stackingItem);
     339    WTFLogAlways("%s", treeAsText.utf8().data());
     340}
     341
    284342#endif
    285343
  • trunk/Source/WebCore/display/DisplayTreeBuilder.h

    r270251 r270474  
    5151class ContainerBox;
    5252class PositioningContext;
     53class StackingItem;
    5354class Tree;
    5455struct BuildingState;
     
    7071    void buildInlineDisplayTree(const Layout::LayoutState&, const Layout::ContainerBox&, InsertionPosition&);
    7172
     73    StackingItem* insertIntoTree(std::unique_ptr<Box>&&, InsertionPosition&);
    7274    void insert(std::unique_ptr<Box>&&, InsertionPosition&) const;
    7375
    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);
    7678   
    7779    const BuildingState& currentState() const;
     
    8082    BoxFactory m_boxFactory;
    8183    RootBackgroundPropagation m_rootBackgroundPropgation { RootBackgroundPropagation::None };
    82    
     84
    8385    std::unique_ptr<Vector<BuildingState>> m_stateStack;
    8486};
     
    8789String displayTreeAsText(const Box&);
    8890void showDisplayTree(const Box&);
     91
     92String displayTreeAsText(const StackingItem&);
     93void showDisplayTree(const StackingItem&);
    8994#endif
    9095
  • trunk/Source/WebCore/display/css/DisplayBox.cpp

    r270206 r270474  
    5151}
    5252
     53bool Box::participatesInZOrderSorting() const
     54{
     55    return !isLineBreakBox() && style().participatesInZOrderSorting();
     56}
     57
    5358String Box::debugDescription() const
    5459{
  • trunk/Source/WebCore/display/css/DisplayBox.h

    r268955 r270474  
    4747        ImageBox        = 1 << 2,
    4848        TextBox         = 1 << 3,
     49        LineBreakBox    = 1 << 4, // FIXME: Workaround for webkit.org/b/219335
    4950    };
    5051
     
    6162    bool isReplacedBox() const { return m_flags.contains(Flags::ImageBox); /* and other types later. */ }
    6263    bool isTextBox() const { return m_flags.contains(Flags::TextBox); }
     64    bool isLineBreakBox() const { return m_flags.contains(Flags::LineBreakBox); }
     65
     66    bool participatesInZOrderSorting() const;
    6367
    6468    const Box* nextSibling() const { return m_nextSibling.get(); }
  • trunk/Source/WebCore/display/css/DisplayBoxFactory.cpp

    r270225 r270474  
    6868}
    6969
    70 std::unique_ptr<Box> BoxFactory::displayBoxForRootBox(const Layout::ContainerBox& rootLayoutBox, const Layout::BoxGeometry& geometry, RootBackgroundPropagation rootBackgroundPropagation) const
     70std::unique_ptr<ContainerBox> BoxFactory::displayBoxForRootBox(const Layout::ContainerBox& rootLayoutBox, const Layout::BoxGeometry& geometry, RootBackgroundPropagation rootBackgroundPropagation) const
    7171{
    7272    ASSERT(is<Layout::InitialContainingBlock>(rootLayoutBox));
     
    136136    }
    137137
    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);
    139144}
    140145
     
    265270    box.setBoxDecorationData(WTFMove(boxDecorationData));
    266271
    267     if (box.style().participatesInZOrderSorting()) {
     272    if (box.participatesInZOrderSorting()) {
    268273        RefPtr<BoxClip> clip = containingBlockContext.box.clipForDescendants();
    269274        box.setAncestorClip(WTFMove(clip));
  • trunk/Source/WebCore/display/css/DisplayBoxFactory.h

    r270222 r270474  
    7070    static RootBackgroundPropagation determineRootBackgroundPropagation(const Layout::ContainerBox& rootLayoutBox);
    7171
    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;
    7373    std::unique_ptr<Box> displayBoxForBodyBox(const Layout::Box&, const Layout::BoxGeometry&, const ContainingBlockContext&, RootBackgroundPropagation) const;
    7474    std::unique_ptr<Box> displayBoxForLayoutBox(const Layout::Box&, const Layout::BoxGeometry&, const ContainingBlockContext&) const;
  • trunk/Source/WebCore/display/css/DisplayCSSPainter.cpp

    r270225 r270474  
    3434#include "DisplayContainerBox.h"
    3535#include "DisplayPaintingContext.h"
     36#include "DisplayStackingItem.h"
    3637#include "DisplayStyle.h"
    3738#include "DisplayTree.h"
     
    8384    for (const auto* child = containerBox.firstChild(); child; child = child->nextSibling()) {
    8485        auto& box = *child;
    85         if (participatesInZOrderSorting(box))
    86             continue;
     86        ASSERT(!box.participatesInZOrderSorting());
    8787
    8888        switch (paintPhase) {
     
    125125}
    126126
    127 void CSSPainter::paintAtomicallyPaintedBox(const Box& box, PaintingContext& paintingContext, const IntRect& dirtyRect, IncludeStackingContextDescendants includeStackingContextDescendants)
     127void CSSPainter::paintAtomicallyPaintedBox(const StackingItem& stackingItem, PaintingContext& paintingContext, const IntRect& dirtyRect, IncludeStackingContextDescendants includeStackingContextDescendants)
    128128{
    129129    UNUSED_PARAM(dirtyRect);
     130
     131    auto& box = stackingItem.box();
    130132
    131133    auto needToSaveState = [](const Box& box) {
     
    162164        return;
    163165
     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
    164172    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 
    176173    recursivePaintDescendants(containerBox, paintingContext);
    177174
     
    181178        // should be considered part of the parent stacking context, not this new one. For those with 'z-index: 0', treat the stacking context
    182179        // 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);
    186183            else
    187                 paintAtomicallyPaintedBox(*box, paintingContext, dirtyRect);
     184                paintAtomicallyPaintedBox(*stackingItem, paintingContext, dirtyRect);
    188185        }
    189186    }
    190187}
    191188
    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     }
     189void CSSPainter::paintStackingContext(const StackingItem& stackingItem, PaintingContext& paintingContext, const IntRect& dirtyRect)
     190{
     191    paintAtomicallyPaintedBox(stackingItem, paintingContext, dirtyRect, IncludeStackingContextDescendants::Yes);
    238192}
    239193
    240194void CSSPainter::paintTree(const Tree& displayTree, PaintingContext& paintingContext, const IntRect& dirtyRect)
    241195{
    242     paintStackingContext(displayTree.rootBox(), paintingContext, dirtyRect);
     196    paintStackingContext(displayTree.rootStackingItem(), paintingContext, dirtyRect);
    243197}
    244198
  • trunk/Source/WebCore/display/css/DisplayCSSPainter.h

    r270200 r270474  
    4343class BoxModelBox;
    4444class ContainerBox;
     45class StackingItem;
    4546class Tree;
    4647
     
    6162
    6263    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);
    6465
    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);
    7267};
    7368
  • trunk/Source/WebCore/display/css/DisplayStackingItem.cpp

    r270473 r270474  
    2525
    2626#include "config.h"
    27 #include "DisplayBox.h"
     27#include "DisplayStackingItem.h"
    2828
    2929#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
    3030
    31 #include "FillLayer.h"
    32 #include "ShadowData.h"
    3331#include <wtf/IsoMallocInlines.h>
    3432#include <wtf/text/TextStream.h>
     
    3735namespace Display {
    3836
    39 Box::Box(AbsoluteFloatRect absoluteRect, Style&& displayStyle, OptionSet<Flags> flags)
    40     : m_absoluteBoxRect(absoluteRect)
    41     , m_style(WTFMove(displayStyle))
    42     , m_flags(flags)
     37StackingItem::StackingItem(std::unique_ptr<BoxModelBox>&& box)
     38    : m_box(WTFMove(box))
    4339{
     40    ASSERT(m_box);
    4441}
    4542
    46 Box::~Box() = default;
    47 
    48 void Box::setNextSibling(std::unique_ptr<Box>&& box)
     43bool StackingItem::isStackingContext() const
    4944{
    50     m_nextSibling = WTFMove(box);
     45    return m_box->style().isStackingContext();
    5146}
    5247
    53 String Box::debugDescription() const
     48void StackingItem::addChildStackingItem(std::unique_ptr<StackingItem>&& item)
    5449{
    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));
    5855}
     56
     57void 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
    5967
    6068} // namespace Display
  • trunk/Source/WebCore/display/css/DisplayStackingItem.h

    r270473 r270474  
    2828#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
    2929
    30 #include "DisplayContainerBox.h"
    3130#include <wtf/IsoMalloc.h>
     31#include <wtf/OptionSet.h>
     32#include <wtf/Vector.h>
    3233
    3334namespace WebCore {
    3435namespace Display {
    3536
    36 class Tree {
    37     WTF_MAKE_FAST_ALLOCATED(Tree);
     37class 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
     43class StackingItem {
     44    WTF_MAKE_FAST_ALLOCATED;
     45    friend class TreeBuilder;
    3846public:
    39     Tree(std::unique_ptr<ContainerBox>&&);
     47    using StackingItemList = Vector<std::unique_ptr<StackingItem>>;
    4048
    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; }
    4258
    4359private:
    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;
    4665};
    4766
     
    4968} // namespace WebCore
    5069
     70
    5171#endif // ENABLE(LAYOUT_FORMATTING_CONTEXT)
Note: See TracChangeset for help on using the changeset viewer.