Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: Source/core/dom/RenderTreeBuilder.cpp

Issue 143323014: *** DO NOT LAND *** Attempt to understand Regions complexity Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/dom/RenderTreeBuilder.h ('k') | Source/core/dom/WebKitNamedFlow.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ights reserved. 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r ights reserved.
6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) 6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/)
7 * Copyright (C) 2011 Google Inc. All rights reserved. 7 * Copyright (C) 2011 Google Inc. All rights reserved.
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public 10 * modify it under the terms of the GNU Library General Public
(...skipping 15 matching lines...) Expand all
26 #include "config.h" 26 #include "config.h"
27 #include "core/dom/RenderTreeBuilder.h" 27 #include "core/dom/RenderTreeBuilder.h"
28 28
29 #include "HTMLNames.h" 29 #include "HTMLNames.h"
30 #include "RuntimeEnabledFeatures.h" 30 #include "RuntimeEnabledFeatures.h"
31 #include "SVGNames.h" 31 #include "SVGNames.h"
32 #include "core/css/resolver/StyleResolver.h" 32 #include "core/css/resolver/StyleResolver.h"
33 #include "core/dom/FullscreenElementStack.h" 33 #include "core/dom/FullscreenElementStack.h"
34 #include "core/dom/Node.h" 34 #include "core/dom/Node.h"
35 #include "core/dom/Text.h" 35 #include "core/dom/Text.h"
36 #include "core/rendering/FlowThreadController.h"
37 #include "core/rendering/RenderFullScreen.h" 36 #include "core/rendering/RenderFullScreen.h"
38 #include "core/rendering/RenderNamedFlowThread.h"
39 #include "core/rendering/RenderObject.h" 37 #include "core/rendering/RenderObject.h"
40 #include "core/rendering/RenderText.h" 38 #include "core/rendering/RenderText.h"
41 #include "core/rendering/RenderView.h" 39 #include "core/rendering/RenderView.h"
42 40
43 namespace WebCore { 41 namespace WebCore {
44 42
45 RenderObject* RenderTreeBuilder::nextRenderer() const 43 RenderObject* RenderTreeBuilder::nextRenderer() const
46 { 44 {
47 ASSERT(m_renderingParent); 45 ASSERT(m_renderingParent);
48 46
49 Element* element = m_node->isElementNode() ? toElement(m_node) : 0; 47 Element* element = m_node->isElementNode() ? toElement(m_node) : 0;
50 48
51 if (element) { 49 if (element) {
52 if (element->isInTopLayer()) 50 if (element->isInTopLayer())
53 return NodeRenderingTraversal::nextInTopLayer(element); 51 return NodeRenderingTraversal::nextInTopLayer(element);
54 // FIXME: Reparented dialogs not in the top layer need to be in DOM tree order. 52 // FIXME: Reparented dialogs not in the top layer need to be in DOM tree order.
55 // FIXME: The spec should not require magical behavior for <dialog>. 53 // FIXME: The spec should not require magical behavior for <dialog>.
56 if (element->hasTagName(HTMLNames::dialogTag) && m_style->position() == AbsolutePosition) 54 if (element->hasTagName(HTMLNames::dialogTag) && m_style->position() == AbsolutePosition)
57 return 0; 55 return 0;
58 } 56 }
59 57
60 if (m_parentFlowRenderer)
61 return m_parentFlowRenderer->nextRendererForNode(m_node);
62
63 // Avoid an O(N^2) walk over the children when reattaching all children of a node. 58 // Avoid an O(N^2) walk over the children when reattaching all children of a node.
64 if (m_renderingParent->needsAttach()) 59 if (m_renderingParent->needsAttach())
65 return 0; 60 return 0;
66 61
67 return NodeRenderingTraversal::nextSiblingRenderer(m_node); 62 return NodeRenderingTraversal::nextSiblingRenderer(m_node);
68 } 63 }
69 64
70 RenderObject* RenderTreeBuilder::parentRenderer() const 65 RenderObject* RenderTreeBuilder::parentRenderer() const
71 { 66 {
72 ASSERT(m_renderingParent); 67 ASSERT(m_renderingParent);
73 68
74 Element* element = m_node->isElementNode() ? toElement(m_node) : 0; 69 Element* element = m_node->isElementNode() ? toElement(m_node) : 0;
75 70
76 if (element && m_renderingParent->renderer()) { 71 if (element && m_renderingParent->renderer()) {
77 // FIXME: The spec should not require magical behavior for <dialog>. Not e that the first 72 // FIXME: The spec should not require magical behavior for <dialog>. Not e that the first
78 // time we enter here the m_style might be null because of a call in sho uldCreateRenderer() 73 // time we enter here the m_style might be null because of a call in sho uldCreateRenderer()
79 // which means we return the wrong wrong renderer for that check and the n return a totally 74 // which means we return the wrong wrong renderer for that check and the n return a totally
80 // different renderer (the RenderView) later when this method is called after setting m_style. 75 // different renderer (the RenderView) later when this method is called after setting m_style.
81 if (element->hasTagName(HTMLNames::dialogTag) && m_style && m_style->pos ition() == AbsolutePosition) 76 if (element->hasTagName(HTMLNames::dialogTag) && m_style && m_style->pos ition() == AbsolutePosition)
82 return m_node->document().renderView(); 77 return m_node->document().renderView();
83 78
84 // FIXME: Guarding this by m_renderingParent->renderer() isn't quite rig ht as the spec for 79 // FIXME: Guarding this by m_renderingParent->renderer() isn't quite rig ht as the spec for
85 // top layer only talks about display: none ancestors so putting a <dial og> inside an 80 // top layer only talks about display: none ancestors so putting a <dial og> inside an
86 // <optgroup> seems like it should still work even though this check wil l prevent it. 81 // <optgroup> seems like it should still work even though this check wil l prevent it.
87 if (element->isInTopLayer()) 82 if (element->isInTopLayer())
88 return m_node->document().renderView(); 83 return m_node->document().renderView();
89 } 84 }
90 85
91 // Even if the normal parent has no renderer we still can be flowed into a n amed flow.
92 // FIXME: This is bad, it breaks the assumption that if you have a renderer then
93 // NodeRenderingTraversal::parent(this) also has one which likely means lots of bugs
94 // with regions.
95 if (m_parentFlowRenderer)
96 return m_parentFlowRenderer;
97
98 return m_renderingParent->renderer(); 86 return m_renderingParent->renderer();
99 } 87 }
100 88
101 bool RenderTreeBuilder::shouldCreateRenderer() const 89 bool RenderTreeBuilder::shouldCreateRenderer() const
102 { 90 {
103 if (!m_renderingParent) 91 if (!m_renderingParent)
104 return false; 92 return false;
105 // SVG elements only render when inside <svg>, or if the element is an <svg> itself. 93 // SVG elements only render when inside <svg>, or if the element is an <svg> itself.
106 if (m_node->isSVGElement() && !m_node->hasTagName(SVGNames::svgTag) && !m_re nderingParent->isSVGElement()) 94 if (m_node->isSVGElement() && !m_node->hasTagName(SVGNames::svgTag) && !m_re nderingParent->isSVGElement())
107 return false; 95 return false;
108 RenderObject* parentRenderer = this->parentRenderer(); 96 RenderObject* parentRenderer = this->parentRenderer();
109 if (!parentRenderer) 97 if (!parentRenderer)
110 return false; 98 return false;
111 if (!parentRenderer->canHaveChildren()) 99 if (!parentRenderer->canHaveChildren())
112 return false; 100 return false;
113 if (!m_renderingParent->childShouldCreateRenderer(*m_node)) 101 if (!m_renderingParent->childShouldCreateRenderer(*m_node))
114 return false; 102 return false;
115 return true; 103 return true;
116 } 104 }
117 105
118 // Check the specific case of elements that are children of regions but are flow ed into a flow thread themselves.
119 bool RenderTreeBuilder::elementInsideRegionNeedsRenderer()
120 {
121 if (!RuntimeEnabledFeatures::cssRegionsEnabled())
122 return false;
123 Element& element = toElement(*m_node);
124 RenderObject* parentRenderer = this->parentRenderer();
125 if ((parentRenderer && !parentRenderer->canHaveChildren() && parentRenderer- >isRenderNamedFlowFragmentContainer())
126 || (!parentRenderer && element.parentElement() && element.parentElement( )->isInsideRegion())) {
127
128 // Children of this element will only be allowed to be flowed into other flow-threads if display is NOT none.
129 if (element.rendererIsNeeded(style()))
130 element.setIsInsideRegion(true);
131
132 return shouldMoveToFlowThread();
133 }
134
135 return false;
136 }
137
138 bool RenderTreeBuilder::shouldMoveToFlowThread() const
139 {
140 Element& element = toElement(*m_node);
141 RenderStyle& style = this->style();
142
143 if (style.flowThread().isEmpty())
144 return false;
145
146 if (FullscreenElementStack::isActiveFullScreenElement(&element))
147 return false;
148
149 if (element.isInShadowTree())
150 return false;
151
152 // As per http://dev.w3.org/csswg/css3-regions/#flow-into, pseudo-elements s uch as
153 // ::first-line, ::first-letter, ::before or ::after cannot be directly coll ected
154 // into a named flow.
155 if (element.isPseudoElement())
156 return false;
157
158 // Allow only svg root elements to be directly collected by a render flow th read.
159 if (element.isSVGElement()) {
160 if (!element.hasTagName(SVGNames::svgTag))
161 return false;
162 if (!element.parentNode())
163 return false;
164 if (element.parentNode()->isSVGElement())
165 return false;
166 }
167
168 return !element.isRegisteredWithNamedFlow();
169 }
170
171 void RenderTreeBuilder::moveToFlowThreadIfNeeded()
172 {
173 if (!RuntimeEnabledFeatures::cssRegionsEnabled())
174 return;
175
176 if (!shouldMoveToFlowThread())
177 return;
178
179 FlowThreadController* flowThreadController = m_node->document().renderView() ->flowThreadController();
180 m_parentFlowRenderer = flowThreadController->ensureRenderFlowThreadWithName( style().flowThread());
181 flowThreadController->registerNamedFlowContentNode(m_node, m_parentFlowRende rer);
182 }
183
184 RenderStyle& RenderTreeBuilder::style() const 106 RenderStyle& RenderTreeBuilder::style() const
185 { 107 {
186 if (!m_style) 108 if (!m_style)
187 m_style = toElement(m_node)->styleForRenderer(); 109 m_style = toElement(m_node)->styleForRenderer();
188 return *m_style; 110 return *m_style;
189 } 111 }
190 112
191 void RenderTreeBuilder::createRendererForElementIfNeeded() 113 void RenderTreeBuilder::createRendererForElementIfNeeded()
192 { 114 {
193 ASSERT(!m_node->renderer()); 115 ASSERT(!m_node->renderer());
194 116
195 // If we're out of composition then we can't render since there's no parent to inherit from. 117 // If we're out of composition then we can't render since there's no parent to inherit from.
196 if (!m_renderingParent) 118 if (!m_renderingParent)
197 return; 119 return;
198 120
199 Element* element = toElement(m_node); 121 Element* element = toElement(m_node);
200 122
201 if (!shouldCreateRenderer() && !elementInsideRegionNeedsRenderer()) 123 if (!shouldCreateRenderer())
202 return; 124 return;
203 125
204 moveToFlowThreadIfNeeded();
205
206 RenderStyle& style = this->style(); 126 RenderStyle& style = this->style();
207 127
208 if (!element->rendererIsNeeded(style)) 128 if (!element->rendererIsNeeded(style))
209 return; 129 return;
210 130
211 RenderObject* newRenderer = element->createRenderer(&style); 131 RenderObject* newRenderer = element->createRenderer(&style);
212 if (!newRenderer) 132 if (!newRenderer)
213 return; 133 return;
214 134
215 RenderObject* parentRenderer = this->parentRenderer(); 135 RenderObject* parentRenderer = this->parentRenderer();
216 136
217 if (!parentRenderer->isChildAllowed(newRenderer, &style)) { 137 if (!parentRenderer->isChildAllowed(newRenderer, &style)) {
218 newRenderer->destroy(); 138 newRenderer->destroy();
219 return; 139 return;
220 } 140 }
221 141
222 // Make sure the RenderObject already knows it is going to be added to a Ren derFlowThread before we set the style
223 // for the first time. Otherwise code using inRenderFlowThread() in the styl eWillChange and styleDidChange will fail.
224 newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
225
226 RenderObject* nextRenderer = this->nextRenderer(); 142 RenderObject* nextRenderer = this->nextRenderer();
227 element->setRenderer(newRenderer); 143 element->setRenderer(newRenderer);
228 newRenderer->setAnimatableStyle(&style); // setAnimatableStyle() can depend on renderer() already being set. 144 newRenderer->setAnimatableStyle(&style); // setAnimatableStyle() can depend on renderer() already being set.
229 145
230 if (FullscreenElementStack::isActiveFullScreenElement(element)) { 146 if (FullscreenElementStack::isActiveFullScreenElement(element)) {
231 newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer , &element->document()); 147 newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer , &element->document());
232 if (!newRenderer) 148 if (!newRenderer)
233 return; 149 return;
234 } 150 }
235 151
(...skipping 22 matching lines...) Expand all
258 174
259 if (!textNode->textRendererIsNeeded(*m_style, *parentRenderer)) 175 if (!textNode->textRendererIsNeeded(*m_style, *parentRenderer))
260 return; 176 return;
261 177
262 RenderText* newRenderer = textNode->createTextRenderer(m_style.get()); 178 RenderText* newRenderer = textNode->createTextRenderer(m_style.get());
263 if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) { 179 if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
264 newRenderer->destroy(); 180 newRenderer->destroy();
265 return; 181 return;
266 } 182 }
267 183
268 // Make sure the RenderObject already knows it is going to be added to a Ren derFlowThread before we set the style
269 // for the first time. Otherwise code using inRenderFlowThread() in the styl eWillChange and styleDidChange will fail.
270 newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
271
272 RenderObject* nextRenderer = this->nextRenderer(); 184 RenderObject* nextRenderer = this->nextRenderer();
273 textNode->setRenderer(newRenderer); 185 textNode->setRenderer(newRenderer);
274 // Parent takes care of the animations, no need to call setAnimatableStyle. 186 // Parent takes care of the animations, no need to call setAnimatableStyle.
275 newRenderer->setStyle(m_style.release()); 187 newRenderer->setStyle(m_style.release());
276 parentRenderer->addChild(newRenderer, nextRenderer); 188 parentRenderer->addChild(newRenderer, nextRenderer);
277 } 189 }
278 190
279 } 191 }
OLDNEW
« no previous file with comments | « Source/core/dom/RenderTreeBuilder.h ('k') | Source/core/dom/WebKitNamedFlow.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698