Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      6  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      7  * Copyright (C) 2011 Google Inc. All rights reserved.
      8  *
      9  * This library is free software; you can redistribute it and/or
     10  * modify it under the terms of the GNU Library General Public
     11  * License as published by the Free Software Foundation; either
     12  * version 2 of the License, or (at your option) any later version.
     13  *
     14  * This library is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17  * Library General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU Library General Public License
     20  * along with this library; see the file COPYING.LIB.  If not, write to
     21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  *
     24  */
     25 
     26 #include "config.h"
     27 #include "core/dom/RenderTreeBuilder.h"
     28 
     29 #include "core/HTMLNames.h"
     30 #include "core/SVGNames.h"
     31 #include "core/css/resolver/StyleResolver.h"
     32 #include "core/dom/Fullscreen.h"
     33 #include "core/dom/Node.h"
     34 #include "core/dom/Text.h"
     35 #include "core/rendering/RenderFullScreen.h"
     36 #include "core/rendering/RenderObject.h"
     37 #include "core/rendering/RenderText.h"
     38 #include "core/rendering/RenderView.h"
     39 #include "core/svg/SVGElement.h"
     40 #include "platform/RuntimeEnabledFeatures.h"
     41 
     42 namespace blink {
     43 
     44 RenderObject* RenderTreeBuilder::nextRenderer() const
     45 {
     46     ASSERT(m_renderingParent);
     47 
     48     Element* element = m_node->isElementNode() ? toElement(m_node) : 0;
     49 
     50     if (element && element->isInTopLayer())
     51         return NodeRenderingTraversal::nextInTopLayer(element);
     52 
     53     // Avoid an O(N^2) walk over the children when reattaching all children of a node.
     54     if (m_renderingParent->needsAttach())
     55         return 0;
     56 
     57     return NodeRenderingTraversal::nextSiblingRenderer(m_node);
     58 }
     59 
     60 RenderObject* RenderTreeBuilder::parentRenderer() const
     61 {
     62     ASSERT(m_renderingParent);
     63 
     64     Element* element = m_node->isElementNode() ? toElement(m_node) : 0;
     65 
     66     if (element && m_renderingParent->renderer()) {
     67         // FIXME: Guarding this by m_renderingParent->renderer() isn't quite right as the spec for
     68         // top layer only talks about display: none ancestors so putting a <dialog> inside an
     69         // <optgroup> seems like it should still work even though this check will prevent it.
     70         if (element->isInTopLayer())
     71             return m_node->document().renderView();
     72     }
     73 
     74     return m_renderingParent->renderer();
     75 }
     76 
     77 bool RenderTreeBuilder::shouldCreateRenderer() const
     78 {
     79     if (!m_renderingParent)
     80         return false;
     81     if (m_node->isSVGElement()) {
     82         // SVG elements only render when inside <svg>, or if the element is an <svg> itself.
     83         if (!isSVGSVGElement(*m_node) && !m_renderingParent->isSVGElement())
     84             return false;
     85         if (!toSVGElement(m_node)->isValid())
     86             return false;
     87     }
     88     RenderObject* parentRenderer = this->parentRenderer();
     89     if (!parentRenderer)
     90         return false;
     91     if (!parentRenderer->canHaveChildren())
     92         return false;
     93     return true;
     94 }
     95 
     96 RenderStyle& RenderTreeBuilder::style() const
     97 {
     98     if (!m_style)
     99         m_style = toElement(m_node)->styleForRenderer();
    100     return *m_style;
    101 }
    102 
    103 void RenderTreeBuilder::createRendererForElementIfNeeded()
    104 {
    105     ASSERT(!m_node->renderer());
    106 
    107     if (!shouldCreateRenderer())
    108         return;
    109 
    110     Element* element = toElement(m_node);
    111     RenderStyle& style = this->style();
    112 
    113     if (!element->rendererIsNeeded(style))
    114         return;
    115 
    116     RenderObject* newRenderer = element->createRenderer(&style);
    117     if (!newRenderer)
    118         return;
    119 
    120     RenderObject* parentRenderer = this->parentRenderer();
    121 
    122     if (!parentRenderer->isChildAllowed(newRenderer, &style)) {
    123         newRenderer->destroy();
    124         return;
    125     }
    126 
    127     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
    128     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
    129     newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
    130 
    131     RenderObject* nextRenderer = this->nextRenderer();
    132     element->setRenderer(newRenderer);
    133     newRenderer->setStyle(&style); // setStyle() can depend on renderer() already being set.
    134 
    135     if (Fullscreen::isActiveFullScreenElement(*element)) {
    136         newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, &element->document());
    137         if (!newRenderer)
    138             return;
    139     }
    140 
    141     // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    142     parentRenderer->addChild(newRenderer, nextRenderer);
    143 }
    144 
    145 void RenderTreeBuilder::createRendererForTextIfNeeded()
    146 {
    147     ASSERT(!m_node->renderer());
    148 
    149     if (!shouldCreateRenderer())
    150         return;
    151 
    152     Text* textNode = toText(m_node);
    153     RenderObject* parentRenderer = this->parentRenderer();
    154 
    155     m_style = parentRenderer->style();
    156 
    157     if (!textNode->textRendererIsNeeded(*m_style, *parentRenderer))
    158         return;
    159 
    160     RenderText* newRenderer = textNode->createTextRenderer(m_style.get());
    161     if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
    162         newRenderer->destroy();
    163         return;
    164     }
    165 
    166     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
    167     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
    168     newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
    169 
    170     RenderObject* nextRenderer = this->nextRenderer();
    171     textNode->setRenderer(newRenderer);
    172     // Parent takes care of the animations, no need to call setAnimatableStyle.
    173     newRenderer->setStyle(m_style.release());
    174     parentRenderer->addChild(newRenderer, nextRenderer);
    175 }
    176 
    177 }
    178