Changeset 154806 in webkit


Ignore:
Timestamp:
Aug 29, 2013 5:25:23 AM (11 years ago)
Author:
Antti Koivisto
Message:

Move element renderer creation out of NodeRenderingContext
https://bugs.webkit.org/show_bug.cgi?id=120461

Reviewed by Andreas Kling.

Move NodeRenderingContext::createRendererIfNeeded() and the related utility functions to StyleResolveTree.

Tighten typing and constness. Refactor sligthly to be more understandable.

  • dom/Element.cpp:

(WebCore::Element::shouldMoveToFlowThread):

  • dom/Element.h:
  • dom/NodeRenderingContext.cpp:

(WebCore::NodeRenderingContext::NodeRenderingContext):
(WebCore::NodeRenderingContext::nextRenderer):
(WebCore::NodeRenderingContext::previousRenderer):
(WebCore::NodeRenderingContext::parentRenderer):

  • dom/NodeRenderingContext.h:
  • dom/PseudoElement.h:
  • style/StyleResolveTree.cpp:

(WebCore::Style::nextSiblingRenderer):
(WebCore::Style::shouldCreateRenderer):
(WebCore::Style::elementInsideRegionNeedsRenderer):
(WebCore::Style::moveToFlowThreadIfNeeded):
(WebCore::Style::createRendererIfNeeded):
(WebCore::Style::attachRenderTree):

  • svg/SVGElement.cpp:

(WebCore::SVGElement::shouldMoveToFlowThread):

  • svg/SVGElement.h:
Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r154802 r154806  
     12013-08-29  Antti Koivisto  <antti@apple.com>
     2
     3        Move element renderer creation out of NodeRenderingContext
     4        https://bugs.webkit.org/show_bug.cgi?id=120461
     5
     6        Reviewed by Andreas Kling.
     7
     8        Move NodeRenderingContext::createRendererIfNeeded() and the related utility functions to StyleResolveTree.
     9       
     10        Tighten typing and constness. Refactor sligthly to be more understandable.
     11
     12        * dom/Element.cpp:
     13        (WebCore::Element::shouldMoveToFlowThread):
     14        * dom/Element.h:
     15        * dom/NodeRenderingContext.cpp:
     16        (WebCore::NodeRenderingContext::NodeRenderingContext):
     17        (WebCore::NodeRenderingContext::nextRenderer):
     18        (WebCore::NodeRenderingContext::previousRenderer):
     19        (WebCore::NodeRenderingContext::parentRenderer):
     20        * dom/NodeRenderingContext.h:
     21        * dom/PseudoElement.h:
     22        * style/StyleResolveTree.cpp:
     23        (WebCore::Style::nextSiblingRenderer):
     24        (WebCore::Style::shouldCreateRenderer):
     25        (WebCore::Style::elementInsideRegionNeedsRenderer):
     26        (WebCore::Style::moveToFlowThreadIfNeeded):
     27        (WebCore::Style::createRendererIfNeeded):
     28        (WebCore::Style::attachRenderTree):
     29        * svg/SVGElement.cpp:
     30        (WebCore::SVGElement::shouldMoveToFlowThread):
     31        * svg/SVGElement.h:
     32
    1332013-08-28  Chris Fleizach  <cfleizach@apple.com>
    234
  • trunk/Source/WebCore/dom/Element.cpp

    r154686 r154806  
    26782678#if ENABLE(CSS_REGIONS)
    26792679
    2680 bool Element::shouldMoveToFlowThread(RenderStyle* styleToUse) const
    2681 {
    2682     ASSERT(styleToUse);
    2683 
     2680bool Element::shouldMoveToFlowThread(const RenderStyle& styleToUse) const
     2681{
    26842682#if ENABLE(FULLSCREEN_API)
    26852683    if (document()->webkitIsFullScreen() && document()->webkitCurrentFullScreenElement() == this)
     
    26902688        return false;
    26912689
    2692     if (styleToUse->flowThread().isEmpty())
     2690    if (styleToUse.flowThread().isEmpty())
    26932691        return false;
    26942692
  • trunk/Source/WebCore/dom/Element.h

    r154778 r154806  
    526526
    527527#if ENABLE(CSS_REGIONS)
    528     virtual bool shouldMoveToFlowThread(RenderStyle*) const;
     528    virtual bool shouldMoveToFlowThread(const RenderStyle&) const;
    529529   
    530530    const AtomicString& webkitRegionOverset() const;
  • trunk/Source/WebCore/dom/NodeRenderingContext.cpp

    r154738 r154806  
    5555NodeRenderingContext::NodeRenderingContext(Node* node)
    5656    : m_node(node)
    57     , m_parentFlowRenderer(0)
    58 {
    59     m_renderingParent = NodeRenderingTraversal::parent(node);
    60 }
    61 
    62 NodeRenderingContext::NodeRenderingContext(Node* node, RenderStyle* style)
    63     : m_node(node)
    64     , m_renderingParent(0)
    65     , m_style(style)
    66     , m_parentFlowRenderer(0)
    67 {
    68 }
    69 
    70 NodeRenderingContext::NodeRenderingContext(Node* node, const Style::AttachContext& context)
    71     : m_node(node)
    72     , m_style(context.resolvedStyle)
    73     , m_parentFlowRenderer(0)
    7457{
    7558    m_renderingParent = NodeRenderingTraversal::parent(node);
     
    11295#endif
    11396
    114     if (m_parentFlowRenderer)
    115         return m_parentFlowRenderer->nextRendererForNode(m_node);
    116 
    11797    // Avoid an O(N^2) problem with this function by not checking for
    11898    // nextRenderer() when the parent element hasn't attached yet.
     
    140120    ASSERT(!m_node->isElementNode() || !toElement(m_node)->isInTopLayer());
    141121#endif
    142 
    143     if (m_parentFlowRenderer)
    144         return m_parentFlowRenderer->previousRendererForNode(m_node);
    145122
    146123    // FIXME: We should have the same O(N^2) avoidance as nextRenderer does
     
    174151#endif
    175152
    176     if (m_parentFlowRenderer)
    177         return m_parentFlowRenderer;
    178 
    179153    return m_renderingParent ? m_renderingParent->renderer() : 0;
    180 }
    181 
    182 bool NodeRenderingContext::shouldCreateRenderer() const
    183 {
    184     if (!m_node->document()->shouldCreateRenderers())
    185         return false;
    186     if (!m_renderingParent)
    187         return false;
    188     RenderObject* parentRenderer = this->parentRenderer();
    189     if (!parentRenderer)
    190         return false;
    191     if (!parentRenderer->canHaveChildren() && !(m_node->isPseudoElement() && parentRenderer->canHaveGeneratedChildren()))
    192         return false;
    193     if (!m_renderingParent->childShouldCreateRenderer(m_node))
    194         return false;
    195     return true;
    196 }
    197 
    198 // Check the specific case of elements that are children of regions but are flowed into a flow thread themselves.
    199 bool NodeRenderingContext::elementInsideRegionNeedsRenderer()
    200 {
    201     bool elementInsideRegionNeedsRenderer = false;
    202 
    203 #if ENABLE(CSS_REGIONS)
    204     Element* element = toElement(m_node);
    205     RenderObject* parentRenderer = this->parentRenderer();
    206     if ((parentRenderer && !parentRenderer->canHaveChildren() && parentRenderer->isRenderRegion())
    207         || (!parentRenderer && element->parentElement() && element->parentElement()->isInsideRegion())) {
    208 
    209         if (!m_style)
    210             m_style = element->styleForRenderer();
    211 
    212         elementInsideRegionNeedsRenderer = element->shouldMoveToFlowThread(m_style.get());
    213 
    214         // Children of this element will only be allowed to be flowed into other flow-threads if display is NOT none.
    215         if (element->rendererIsNeeded(*m_style))
    216             element->setIsInsideRegion(true);
    217     }
    218 #endif
    219 
    220     return elementInsideRegionNeedsRenderer;
    221 }
    222 
    223 void NodeRenderingContext::moveToFlowThreadIfNeeded()
    224 {
    225 #if ENABLE(CSS_REGIONS)
    226     Element* element = toElement(m_node);
    227 
    228     if (!element->shouldMoveToFlowThread(m_style.get()))
    229         return;
    230 
    231     ASSERT(m_node->document()->renderView());
    232     FlowThreadController& flowThreadController = m_node->document()->renderView()->flowThreadController();
    233     m_parentFlowRenderer = &flowThreadController.ensureRenderFlowThreadWithName(m_style->flowThread());
    234     flowThreadController.registerNamedFlowContentNode(m_node, m_parentFlowRenderer);
    235 #endif
    236 }
    237 
    238 void NodeRenderingContext::createRendererForElementIfNeeded()
    239 {
    240     ASSERT(!m_node->renderer());
    241 
    242     Element* element = toElement(m_node);
    243 
    244     element->setIsInsideRegion(false);
    245 
    246     if (!shouldCreateRenderer() && !elementInsideRegionNeedsRenderer())
    247         return;
    248 
    249     if (!m_style)
    250         m_style = element->styleForRenderer();
    251     ASSERT(m_style);
    252 
    253     moveToFlowThreadIfNeeded();
    254 
    255     if (!element->rendererIsNeeded(*m_style))
    256         return;
    257 
    258     RenderObject* parentRenderer = this->parentRenderer();
    259     RenderObject* nextRenderer = this->nextRenderer();
    260 
    261     Document* document = element->document();
    262     RenderObject* newRenderer = element->createRenderer(document->renderArena(), m_style.get());
    263     if (!newRenderer)
    264         return;
    265     if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
    266         newRenderer->destroy();
    267         return;
    268     }
    269 
    270     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
    271     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
    272     newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
    273 
    274     element->setRenderer(newRenderer);
    275     newRenderer->setAnimatableStyle(m_style.release()); // setAnimatableStyle() can depend on renderer() already being set.
    276 
    277 #if ENABLE(FULLSCREEN_API)
    278     if (document->webkitIsFullScreen() && document->webkitCurrentFullScreenElement() == element) {
    279         newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, document);
    280         if (!newRenderer)
    281             return;
    282     }
    283 #endif
    284     // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    285     parentRenderer->addChild(newRenderer, nextRenderer);
    286154}
    287155
  • trunk/Source/WebCore/dom/NodeRenderingContext.h

    r154738 r154806  
    2828
    2929#include "NodeRenderingTraversal.h"
    30 #include "StyleResolveTree.h"
    3130
    3231#include <wtf/Noncopyable.h>
     
    3736
    3837class ContainerNode;
    39 class Document;
    40 class InsertionPoint;
    4138class Node;
    42 class RenderNamedFlowThread;
    4339class RenderObject;
    44 class RenderStyle;
    4540
    4641class NodeRenderingContext {
    4742public:
    4843    explicit NodeRenderingContext(Node*);
    49     NodeRenderingContext(Node*, RenderStyle*);
    50     NodeRenderingContext(Node*, const Style::AttachContext&);
    5144    ~NodeRenderingContext();
    52 
    53     void createRendererForElementIfNeeded();
    5445
    5546    Node* node() const;
     
    6051    RenderObject* previousRenderer() const;
    6152
    62     const RenderStyle* style() const;
    63 
    6453private:
    65     bool shouldCreateRenderer() const;
    66     void moveToFlowThreadIfNeeded();
    67     bool elementInsideRegionNeedsRenderer();
    68 
    6954    Node* m_node;
    7055    ContainerNode* m_renderingParent;
    71     RefPtr<RenderStyle> m_style;
    72     RenderNamedFlowThread* m_parentFlowRenderer;
    7356};
    7457
     
    8366}
    8467
    85 inline const RenderStyle* NodeRenderingContext::style() const
    86 {
    87     return m_style.get();
    88 }
    89 
    9068} // namespace WebCore
    9169
  • trunk/Source/WebCore/dom/PseudoElement.h

    r154358 r154806  
    5353    // cannot be directly collected into a named flow.
    5454#if ENABLE(CSS_REGIONS)
    55     virtual bool shouldMoveToFlowThread(RenderStyle*) const OVERRIDE { return false; }
     55    virtual bool shouldMoveToFlowThread(const RenderStyle&) const OVERRIDE { return false; }
    5656#endif
    5757
  • trunk/Source/WebCore/style/StyleResolveTree.cpp

    r154746 r154806  
    3131#include "ElementRareData.h"
    3232#include "ElementTraversal.h"
     33#include "FlowThreadController.h"
    3334#include "NodeRenderStyle.h"
    3435#include "NodeRenderingContext.h"
    3536#include "NodeTraversal.h"
     37#include "RenderFullScreen.h"
     38#include "RenderNamedFlowThread.h"
    3639#include "RenderObject.h"
    3740#include "RenderText.h"
     
    105108}
    106109
    107 static void createRendererIfNeeded(Element* element, const AttachContext& context)
    108 {
    109     NodeRenderingContext(element, context).createRendererForElementIfNeeded();
    110 }
    111 
    112110static bool isRendererReparented(const RenderObject* renderer)
    113111{
     
    117115        return true;
    118116    return false;
     117}
     118
     119static RenderObject* nextSiblingRenderer(const Element& element, const ContainerNode* renderingParentNode)
     120{
     121    // Avoid an O(N^2) problem with this function by not checking for
     122    // nextRenderer() when the parent element hasn't attached yet.
     123    // FIXME: Why would we get here anyway if parent is not attached?
     124    if (renderingParentNode && !renderingParentNode->attached())
     125        return 0;
     126    for (Node* sibling = NodeRenderingTraversal::nextSibling(&element); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
     127        RenderObject* renderer = sibling->renderer();
     128        if (renderer && !isRendererReparented(renderer))
     129            return renderer;
     130    }
     131    return 0;
     132}
     133
     134static bool shouldCreateRenderer(const Element& element, const ContainerNode* renderingParent)
     135{
     136    if (!element.document()->shouldCreateRenderers())
     137        return false;
     138    if (!renderingParent)
     139        return false;
     140    RenderObject* parentRenderer = renderingParent->renderer();
     141    if (!parentRenderer)
     142        return false;
     143    if (!parentRenderer->canHaveChildren() && !(element.isPseudoElement() && parentRenderer->canHaveGeneratedChildren()))
     144        return false;
     145    if (!renderingParent->childShouldCreateRenderer(&element))
     146        return false;
     147    return true;
     148}
     149
     150// Check the specific case of elements that are children of regions but are flowed into a flow thread themselves.
     151static bool elementInsideRegionNeedsRenderer(Element& element, const ContainerNode* renderingParentNode, RefPtr<RenderStyle>& style)
     152{
     153#if ENABLE(CSS_REGIONS)
     154    const RenderObject* parentRenderer = renderingParentNode ? renderingParentNode->renderer() : 0;
     155
     156    bool parentIsRegion = parentRenderer && !parentRenderer->canHaveChildren() && parentRenderer->isRenderRegion();
     157    bool parentIsNonRenderedInsideRegion = !parentRenderer && element.parentElement() && element.parentElement()->isInsideRegion();
     158    if (!parentIsRegion && !parentIsNonRenderedInsideRegion)
     159        return false;
     160
     161    if (!style)
     162        style = element.styleForRenderer();
     163
     164    // Children of this element will only be allowed to be flowed into other flow-threads if display is NOT none.
     165    if (element.rendererIsNeeded(*style))
     166        element.setIsInsideRegion(true);
     167
     168    if (element.shouldMoveToFlowThread(*style))
     169        return true;
     170#endif
     171    return false;
     172}
     173
     174static RenderNamedFlowThread* moveToFlowThreadIfNeeded(Element& element, const RenderStyle& style)
     175{
     176    if (!element.shouldMoveToFlowThread(style))
     177        return 0;
     178    FlowThreadController& flowThreadController = element.document()->renderView()->flowThreadController();
     179    RenderNamedFlowThread& parentFlowRenderer = flowThreadController.ensureRenderFlowThreadWithName(style.flowThread());
     180    flowThreadController.registerNamedFlowContentNode(&element, &parentFlowRenderer);
     181    return &parentFlowRenderer;
     182}
     183
     184static void createRendererIfNeeded(Element& element, const AttachContext& context)
     185{
     186    ASSERT(!element.renderer());
     187
     188    Document& document = *element.document();
     189    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&element);
     190
     191    RefPtr<RenderStyle> style = context.resolvedStyle;
     192
     193    element.setIsInsideRegion(false);
     194
     195    if (!shouldCreateRenderer(element, renderingParentNode) && !elementInsideRegionNeedsRenderer(element, renderingParentNode, style))
     196        return;
     197
     198    if (!style)
     199        style = element.styleForRenderer();
     200
     201    RenderNamedFlowThread* parentFlowRenderer = 0;
     202#if ENABLE(CSS_REGIONS)
     203    parentFlowRenderer = moveToFlowThreadIfNeeded(element, *style);
     204#endif
     205
     206    if (!element.rendererIsNeeded(*style))
     207        return;
     208
     209    RenderObject* parentRenderer;
     210    RenderObject* nextRenderer;
     211    if (parentFlowRenderer) {
     212        parentRenderer = parentFlowRenderer;
     213        nextRenderer = parentFlowRenderer->nextRendererForNode(&element);
     214    } else {
     215        parentRenderer = renderingParentNode->renderer();
     216        nextRenderer = nextSiblingRenderer(element, renderingParentNode);
     217    }
     218
     219    RenderObject* newRenderer = element.createRenderer(document.renderArena(), style.get());
     220    if (!newRenderer)
     221        return;
     222    if (!parentRenderer->isChildAllowed(newRenderer, style.get())) {
     223        newRenderer->destroy();
     224        return;
     225    }
     226
     227    // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
     228    // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
     229    newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
     230
     231    element.setRenderer(newRenderer);
     232    newRenderer->setAnimatableStyle(style.release()); // setAnimatableStyle() can depend on renderer() already being set.
     233
     234#if ENABLE(FULLSCREEN_API)
     235    if (document.webkitIsFullScreen() && document.webkitCurrentFullScreenElement() == &element) {
     236        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, &document);
     237        if (!newRenderer)
     238            return;
     239    }
     240#endif
     241    // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
     242    parentRenderer->addChild(newRenderer, nextRenderer);
    119243}
    120244
     
    342466        current->willAttachRenderers();
    343467
    344     createRendererIfNeeded(current, context);
     468    createRendererIfNeeded(*current, context);
    345469
    346470    if (current->parentElement() && current->parentElement()->isInCanvasSubtree())
  • trunk/Source/WebCore/svg/SVGElement.cpp

    r154769 r154806  
    570570
    571571#if ENABLE(CSS_REGIONS)
    572 bool SVGElement::shouldMoveToFlowThread(RenderStyle* styleToUse) const
     572bool SVGElement::shouldMoveToFlowThread(const RenderStyle& styleToUse) const
    573573{
    574574    // Allow only svg root elements to be directly collected by a render flow thread.
  • trunk/Source/WebCore/svg/SVGElement.h

    r154481 r154806  
    136136
    137137#if ENABLE(CSS_REGIONS)
    138     virtual bool shouldMoveToFlowThread(RenderStyle*) const OVERRIDE;
     138    virtual bool shouldMoveToFlowThread(const RenderStyle&) const OVERRIDE;
    139139#endif
    140140
Note: See TracChangeset for help on using the changeset viewer.