Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / RenderTreeBuilder.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@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/FullscreenElementStack.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 (FullscreenElementStack::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 }