Changeset 208470 in webkit


Ignore:
Timestamp:
Nov 9, 2016 12:38:28 PM (7 years ago)
Author:
Alan Bujtas
Message:

Move RenderNamedFlowThread nextRendererForElement logic to RenderTreeUpdater.
https://bugs.webkit.org/show_bug.cgi?id=164503

Reviewed by Antti Koivisto.

When we insert a renderer into the render tree, we need to know both its parent
and its next sibling. Normally the parent and the sibling are based on the DOM, but
when this renderer is part of a flow thread, its insertion sibling is not necessarily the DOM sibling.
To find the correct sibling, we call RenderNamedFlowThread's nextRendererForElement().
RenderNamedFlowThread keeps track of its children so that it can compute the next sibling
for the insertion point.

This patch eliminates the need for keeping track of the child renderers of each
flow by moving the 'next sibling' logic to RenderTreePosition.

No change in functionality.

  • rendering/RenderElement.cpp:

(WebCore::RenderElement::insertedIntoTree):
(WebCore::RenderElement::willBeDestroyed):
(WebCore::RenderElement::removeFromRenderFlowThread):
(WebCore::RenderElement::renderNamedFlowThreadWrapper): Deleted.

  • rendering/RenderElement.h:
  • rendering/RenderNamedFlowThread.cpp:

(WebCore::RenderNamedFlowThread::nextRendererForElement): Deleted.
(WebCore::RenderNamedFlowThread::addFlowChild): Deleted.
(WebCore::RenderNamedFlowThread::removeFlowChild): Deleted.

  • rendering/RenderNamedFlowThread.h:
  • style/RenderTreePosition.cpp:

(WebCore::RenderTreePosition::previousSiblingRenderer):
(WebCore::RenderTreePosition::flowThreadInsertionContext):

  • style/RenderTreePosition.h:

(WebCore::RenderTreePosition::RenderTreePosition):
(WebCore::RenderTreePosition::parent):

  • style/RenderTreeUpdater.cpp:

(WebCore::registerElementForFlowThreadIfNeeded): We need to registed the element even when it does not create renderer (display: none).
(WebCore::RenderTreeUpdater::createRenderer):
(WebCore::moveToFlowThreadIfNeeded): Deleted.

Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r208469 r208470  
     12016-11-09  Zalan Bujtas  <zalan@apple.com>
     2
     3        Move RenderNamedFlowThread nextRendererForElement logic to RenderTreeUpdater.
     4        https://bugs.webkit.org/show_bug.cgi?id=164503
     5
     6        Reviewed by Antti Koivisto.
     7
     8        When we insert a renderer into the render tree, we need to know both its parent
     9        and its next sibling. Normally the parent and the sibling are based on the DOM, but
     10        when this renderer is part of a flow thread, its insertion sibling is not necessarily the DOM sibling.
     11        To find the correct sibling, we call RenderNamedFlowThread's nextRendererForElement().
     12        RenderNamedFlowThread keeps track of its children so that it can compute the next sibling
     13        for the insertion point.
     14
     15        This patch eliminates the need for keeping track of the child renderers of each
     16        flow by moving the 'next sibling' logic to RenderTreePosition.
     17
     18        No change in functionality.
     19
     20        * rendering/RenderElement.cpp:
     21        (WebCore::RenderElement::insertedIntoTree):
     22        (WebCore::RenderElement::willBeDestroyed):
     23        (WebCore::RenderElement::removeFromRenderFlowThread):
     24        (WebCore::RenderElement::renderNamedFlowThreadWrapper): Deleted.
     25        * rendering/RenderElement.h:
     26        * rendering/RenderNamedFlowThread.cpp:
     27        (WebCore::RenderNamedFlowThread::nextRendererForElement): Deleted.
     28        (WebCore::RenderNamedFlowThread::addFlowChild): Deleted.
     29        (WebCore::RenderNamedFlowThread::removeFlowChild): Deleted.
     30        * rendering/RenderNamedFlowThread.h:
     31        * style/RenderTreePosition.cpp:
     32        (WebCore::RenderTreePosition::previousSiblingRenderer):
     33        (WebCore::RenderTreePosition::flowThreadInsertionContext):
     34        * style/RenderTreePosition.h:
     35        (WebCore::RenderTreePosition::RenderTreePosition):
     36        (WebCore::RenderTreePosition::parent):
     37        * style/RenderTreeUpdater.cpp:
     38        (WebCore::registerElementForFlowThreadIfNeeded): We need to registed the element even when it does not create renderer (display: none).
     39        (WebCore::RenderTreeUpdater::createRenderer):
     40        (WebCore::moveToFlowThreadIfNeeded): Deleted.
     41
    1422016-11-09  Per Arne Vollan  <pvollan@apple.com>
    243
  • trunk/Source/WebCore/rendering/RenderElement.cpp

    r208460 r208470  
    10451045void RenderElement::insertedIntoTree()
    10461046{
    1047     if (auto* containerFlowThread = parent()->renderNamedFlowThreadWrapper())
    1048         containerFlowThread->addFlowChild(*this);
    1049 
    10501047    // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
    10511048    // and don't have a layer attached to ourselves.
     
    11251122        // After remove, the object and the associated information should not be in any flow thread.
    11261123        for (auto& flowThread : *view().flowThreadController().renderNamedFlowThreadList()) {
    1127             ASSERT(!flowThread->hasChild(*this));
    11281124            ASSERT(!flowThread->hasChildInfo(this));
    11291125        }
     
    15241520
    15251521    return true;
    1526 }
    1527 
    1528 RenderNamedFlowThread* RenderElement::renderNamedFlowThreadWrapper()
    1529 {
    1530     auto* renderer = this;
    1531     while (renderer && renderer->isAnonymousBlock() && !is<RenderNamedFlowThread>(*renderer))
    1532         renderer = renderer->parent();
    1533     return is<RenderNamedFlowThread>(renderer) ? downcast<RenderNamedFlowThread>(renderer) : nullptr;
    15341522}
    15351523
     
    22082196{
    22092197    ASSERT(flowThreadState() != NotInsideFlowThread);
    2210     if (auto* containerFlowThread = parent()->renderNamedFlowThreadWrapper())
    2211         containerFlowThread->removeFlowChild(*this);
    22122198    // Sometimes we remove the element from the flow, but it's not destroyed at that time.
    22132199    // It's only until later when we actually destroy it and remove all the children from it.
  • trunk/Source/WebCore/rendering/RenderElement.h

    r207499 r208470  
    200200    void setHasPausedImageAnimations(bool b) { m_hasPausedImageAnimations = b; }
    201201
    202     RenderNamedFlowThread* renderNamedFlowThreadWrapper();
    203 
    204202    void setRenderBoxNeedsLazyRepaint(bool b) { m_renderBoxNeedsLazyRepaint = b; }
    205203    bool renderBoxNeedsLazyRepaint() const { return m_renderBoxNeedsLazyRepaint; }
  • trunk/Source/WebCore/rendering/RenderNamedFlowThread.cpp

    r206049 r208470  
    9696    newStyle.setWritingMode(firstFragment->style().writingMode());
    9797    setStyle(WTFMove(newStyle));
    98 }
    99 
    100 RenderElement* RenderNamedFlowThread::nextRendererForElement(Element& element) const
    101 {
    102     for (auto& child : m_flowThreadChildList) {
    103         ASSERT(!child->isAnonymous());
    104         ASSERT_WITH_MESSAGE(child->element(), "Can only be null for anonymous renderers");
    105 
    106         unsigned short position = element.compareDocumentPosition(*child->element());
    107         if (position & Node::DOCUMENT_POSITION_FOLLOWING)
    108             return child;
    109     }
    110 
    111     return nullptr;
    112 }
    113 
    114 void RenderNamedFlowThread::addFlowChild(RenderElement& newChild)
    115 {
    116     // The child list is used to sort the flow thread's children render objects
    117     // based on their corresponding nodes DOM order. The list is needed to avoid searching the whole DOM.
    118 
    119     if (newChild.isAnonymous())
    120         return;
    121 
    122     auto* beforeChild = nextRendererForElement(*newChild.element());
    123     if (beforeChild)
    124         m_flowThreadChildList.insertBefore(beforeChild, &newChild);
    125     else
    126         m_flowThreadChildList.add(&newChild);
    127 }
    128 
    129 void RenderNamedFlowThread::removeFlowChild(RenderElement& child)
    130 {
    131     m_flowThreadChildList.remove(&child);
    13298}
    13399
  • trunk/Source/WebCore/rendering/RenderNamedFlowThread.h

    r206049 r208470  
    5353
    5454    const RenderRegionList& invalidRenderRegionList() const { return m_invalidRegionList; }
    55 
    56     RenderElement* nextRendererForElement(Element&) const;
    57 
    58     void addFlowChild(RenderElement&);
    59     void removeFlowChild(RenderElement&);
    60     bool hasChildren() const { return !m_flowThreadChildList.isEmpty(); }
    61 #ifndef NDEBUG
    62     bool hasChild(RenderElement& child) const { return m_flowThreadChildList.contains(&child); }
    63 #endif
    6455
    6556    static RenderBlock* fragmentFromRenderBoxAsRenderBlock(RenderBox*, const IntPoint& absolutePoint, const RenderBox& flowedBox);
     
    142133    RenderNamedFlowThreadCountedSet m_layoutBeforeThreadsSet;
    143134
    144     // Holds the sorted children of a named flow. This is the only way we can get the ordering right.
    145     ListHashSet<RenderElement*> m_flowThreadChildList;
    146 
    147135    NamedFlowContentElements m_contentElements;
    148136
  • trunk/Source/WebCore/style/RenderTreePosition.cpp

    r208112 r208470  
    2828
    2929#include "ComposedTreeIterator.h"
     30#include "FlowThreadController.h"
    3031#include "PseudoElement.h"
    3132#include "RenderObject.h"
     
    6768    for (auto it = composedChildren.at(textNode), end = composedChildren.end(); it != end; --it) {
    6869        RenderObject* renderer = it->renderer();
    69         if (renderer && !RenderTreePosition::isRendererReparented(*renderer))
     70        if (renderer && !isRendererReparented(*renderer))
    7071            return renderer;
    7172    }
     
    105106}
    106107
     108#if ENABLE(CSS_REGIONS)
     109RenderTreePosition RenderTreePosition::insertionPositionForFlowThread(Element* insertionParent, Element& element, const RenderStyle& style)
     110{
     111    ASSERT(element.shouldMoveToFlowThread(style));
     112    auto& parentFlowThread = element.document().renderView()->flowThreadController().ensureRenderFlowThreadWithName(style.flowThread());
     113
     114    if (!insertionParent)
     115        return { parentFlowThread, nullptr };
     116
     117    auto composedDescendants = composedTreeDescendants(*insertionParent);
     118    auto it = element.isBeforePseudoElement() ? composedDescendants.begin() : composedDescendants.at(element);
     119    auto end = composedDescendants.end();
     120    while (it != end) {
     121        auto& currentNode = *it;
     122        bool hasDisplayContents = is<Element>(currentNode) && downcast<Element>(currentNode).hasDisplayContents();
     123        if (hasDisplayContents) {
     124            it.traverseNext();
     125            continue;
     126        }
     127
     128        auto* renderer = currentNode.renderer();
     129        if (!renderer) {
     130            it.traverseNextSkippingChildren();
     131            continue;
     132        }
     133
     134        if (!is<RenderElement>(*renderer)) {
     135            it.traverseNext();
     136            continue;
     137        }
     138
     139        // We are the last child in this flow.
     140        if (!isRendererReparented(*renderer))
     141            return { parentFlowThread, nullptr };
     142
     143        if (renderer->style().hasFlowInto() && style.flowThread() == renderer->style().flowThread())
     144            return { parentFlowThread, downcast<RenderElement>(renderer) };
     145        // Nested flows, skip.
     146        it.traverseNextSkippingChildren();
     147    }
     148    return { parentFlowThread, nullptr };
     149}
     150#endif
     151   
    107152bool RenderTreePosition::isRendererReparented(const RenderObject& renderer)
    108153{
  • trunk/Source/WebCore/style/RenderTreePosition.h

    r201393 r208470  
    2828
    2929#include "RenderElement.h"
     30#include "RenderNamedFlowThread.h"
    3031#include "RenderText.h"
    3132#include "RenderView.h"
     
    4647    }
    4748   
    48     RenderTreePosition(RenderElement& parent, RenderObject* nextSibling)
    49         : m_parent(parent)
    50         , m_nextSibling(nextSibling)
    51         , m_hasValidNextSibling(true)
    52     {
    53     }
     49#if ENABLE(CSS_REGIONS)
     50    static RenderTreePosition insertionPositionForFlowThread(Element* insertionParent, Element& child, const RenderStyle&);
     51#endif
    5452
    5553    RenderElement& parent() const { return m_parent; }
    56 
    5754    void insert(RenderObject&);
    5855    bool canInsert(RenderElement&) const;
     
    6865
    6966private:
     67#if ENABLE(CSS_REGIONS)
     68    RenderTreePosition(RenderFlowThread& parent, RenderObject* nextSibling)
     69        : m_parent(parent)
     70        , m_nextSibling(nextSibling)
     71        , m_hasValidNextSibling(true)
     72    {
     73    }
     74#endif
     75
    7076    RenderElement& m_parent;
    7177    RenderObject* m_nextSibling { nullptr };
  • trunk/Source/WebCore/style/RenderTreeUpdater.cpp

    r207458 r208470  
    307307
    308308#if ENABLE(CSS_REGIONS)
    309 static RenderNamedFlowThread* moveToFlowThreadIfNeeded(Element& element, const RenderStyle& style)
     309static void registerElementForFlowThreadIfNeeded(Element& element, const RenderStyle& style)
    310310{
    311311    if (!element.shouldMoveToFlowThread(style))
    312         return nullptr;
    313 
     312        return;
    314313    FlowThreadController& flowThreadController = element.document().renderView()->flowThreadController();
    315     RenderNamedFlowThread& parentFlowRenderer = flowThreadController.ensureRenderFlowThreadWithName(style.flowThread());
    316     flowThreadController.registerNamedFlowContentElement(element, parentFlowRenderer);
    317     return &parentFlowRenderer;
     314    flowThreadController.registerNamedFlowContentElement(element, flowThreadController.ensureRenderFlowThreadWithName(style.flowThread()));
    318315}
    319316#endif
     
    321318void RenderTreeUpdater::createRenderer(Element& element, RenderStyle&& style)
    322319{
     320    auto computeInsertionPosition = [this, &element, &style] () {
     321#if ENABLE(CSS_REGIONS)
     322        if (element.shouldMoveToFlowThread(style))
     323            return RenderTreePosition::insertionPositionForFlowThread(renderTreePosition().parent().element(), element, style);
     324#endif
     325        renderTreePosition().computeNextSibling(element);
     326        return renderTreePosition();
     327    };
     328   
    323329    if (!shouldCreateRenderer(element, renderTreePosition().parent()))
    324330        return;
    325331
    326     RenderNamedFlowThread* parentFlowRenderer = nullptr;
    327332#if ENABLE(CSS_REGIONS)
    328     parentFlowRenderer = moveToFlowThreadIfNeeded(element, style);
     333    // Even display: none elements need to be registered in FlowThreadController.
     334    registerElementForFlowThreadIfNeeded(element, style);
    329335#endif
    330336
     
    332338        return;
    333339
    334     renderTreePosition().computeNextSibling(element);
    335 
    336     RenderTreePosition insertionPosition = parentFlowRenderer
    337         ? RenderTreePosition(*parentFlowRenderer, parentFlowRenderer->nextRendererForElement(element))
    338         : renderTreePosition();
    339 
     340    RenderTreePosition insertionPosition = computeInsertionPosition();
    340341    RenderElement* newRenderer = element.createElementRenderer(WTFMove(style), insertionPosition).leakPtr();
    341342    if (!newRenderer)
Note: See TracChangeset for help on using the changeset viewer.