Changeset 154738 in webkit
- Timestamp:
- Aug 28, 2013, 6:12:52 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r154734 r154738 1 2013-08-28 Antti Koivisto <antti@apple.com> 2 3 Don't use NodeRenderingContext when attaching text renderers 4 https://bugs.webkit.org/show_bug.cgi?id=120402 5 6 Reviewed by Andreas Kling. 7 8 This patch moves various functions for creating text renderers from NodeRenderingContext and Text to StyleResolveTree. 9 It also tightens the logic and combines some functions. 10 11 * dom/CharacterData.cpp: 12 (WebCore::CharacterData::parserAppendData): 13 (WebCore::CharacterData::setDataAndUpdate): 14 * dom/ContainerNode.cpp: 15 (WebCore::attachChild): 16 (WebCore::detachChild): 17 * dom/NodeRenderingContext.cpp: 18 * dom/NodeRenderingContext.h: 19 * dom/Text.cpp: 20 (WebCore::Text::~Text): 21 * dom/Text.h: 22 * html/HTMLViewSourceDocument.cpp: 23 (WebCore::HTMLViewSourceDocument::addText): 24 * html/parser/HTMLConstructionSite.cpp: 25 (WebCore::executeTask): 26 * html/shadow/InsertionPoint.cpp: 27 (WebCore::InsertionPoint::willAttachRenderers): 28 (WebCore::InsertionPoint::willDetachRenderers): 29 * style/StyleResolveTree.cpp: 30 (WebCore::Style::isRendererReparented): 31 (WebCore::Style::previousSiblingRenderer): 32 (WebCore::Style::nextSiblingRenderer): 33 34 From NodeRenderingContext::next/previousRenderer 35 36 (WebCore::Style::createTextRenderersForSiblingsAfterAttachIfNeeded): 37 38 From Text::createTextRenderersForSiblingsAfterAttachIfNeeded() 39 40 (WebCore::Style::textRendererIsNeeded): 41 42 From Text::textRendererIsNeeded 43 44 (WebCore::Style::createTextRendererIfNeeded): 45 46 Combines code from Text::createTextRendererIfNeeded, NodeRenderingContext::createRendererForTextIfNeeded, 47 NodeRenderingContext constructor and text node relevant code NodeRenderingContext::shouldCreateRenderer. 48 49 (WebCore::Style::attachTextRenderer): 50 (WebCore::Style::detachTextRenderer): 51 52 New functions of attaching text renderers. From Text::attach/detachText() 53 54 (WebCore::Style::updateTextRendererAfterContentChange): 55 56 From Text::updateTextRenderer. 57 58 (WebCore::Style::attachShadowRoot): 59 (WebCore::Style::attachChildren): 60 (WebCore::Style::attachRenderTree): 61 (WebCore::Style::detachShadowRoot): 62 (WebCore::Style::detachChildren): 63 (WebCore::Style::updateTextStyle): 64 * style/StyleResolveTree.h: 65 * xml/parser/XMLDocumentParser.cpp: 66 (WebCore::XMLDocumentParser::exitText): 67 * xml/parser/XMLDocumentParserLibxml2.cpp: 68 (WebCore::XMLDocumentParser::cdataBlock): 69 1 70 2013-08-28 Antti Koivisto <antti@apple.com> 2 71 -
trunk/Source/WebCore/dom/CharacterData.cpp
r154371 r154738 92 92 ASSERT(!renderer() || isTextNode()); 93 93 if (isTextNode()) 94 toText(this)->updateTextRenderer(oldLength, 0);94 Style::updateTextRendererAfterContentChange(*toText(this), oldLength, 0); 95 95 96 96 document()->incDOMTreeVersion(); … … 192 192 ASSERT(!renderer() || isTextNode()); 193 193 if (isTextNode()) 194 toText(this)->updateTextRenderer(offsetOfReplacedData, oldLength);194 Style::updateTextRendererAfterContentChange(*toText(this), offsetOfReplacedData, oldLength); 195 195 196 196 if (document()->frame()) -
trunk/Source/WebCore/dom/ContainerNode.cpp
r154525 r154738 111 111 Style::attachRenderTree(toElement(child)); 112 112 else if (child->isTextNode()) 113 toText(child)->attachText();113 Style::attachTextRenderer(*toText(child)); 114 114 } 115 115 … … 119 119 Style::detachRenderTree(toElement(child)); 120 120 else if (child->isTextNode()) 121 toText(child)->detachText();121 Style::detachTextRenderer(*toText(child)); 122 122 } 123 123 -
trunk/Source/WebCore/dom/NodeRenderingContext.cpp
r154686 r154738 286 286 } 287 287 288 void NodeRenderingContext::createRendererForTextIfNeeded()289 {290 ASSERT(!m_node->renderer());291 292 Text* textNode = toText(m_node);293 294 if (!shouldCreateRenderer())295 return;296 297 RenderObject* parentRenderer = this->parentRenderer();298 ASSERT(parentRenderer);299 Document* document = textNode->document();300 301 if (resetStyleInheritance())302 m_style = document->ensureStyleResolver().defaultStyleForElement();303 else304 m_style = parentRenderer->style();305 306 if (!textNode->textRendererIsNeeded(*this))307 return;308 RenderText* newRenderer = textNode->createTextRenderer(document->renderArena(), m_style.get());309 if (!newRenderer)310 return;311 if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {312 newRenderer->destroy();313 return;314 }315 316 // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style317 // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.318 newRenderer->setFlowThreadState(parentRenderer->flowThreadState());319 320 RenderObject* nextRenderer = this->nextRenderer();321 textNode->setRenderer(newRenderer);322 // Parent takes care of the animations, no need to call setAnimatableStyle.323 newRenderer->setStyle(m_style.release());324 parentRenderer->addChild(newRenderer, nextRenderer);325 }326 327 288 bool NodeRenderingContext::resetStyleInheritance() const 328 289 { -
trunk/Source/WebCore/dom/NodeRenderingContext.h
r154371 r154738 51 51 ~NodeRenderingContext(); 52 52 53 void createRendererForTextIfNeeded();54 53 void createRendererForElementIfNeeded(); 55 54 -
trunk/Source/WebCore/dom/Text.cpp
r154241 r154738 59 59 Text::~Text() 60 60 { 61 if (renderer()) 62 detachText(); 61 ASSERT(!renderer()); 63 62 } 64 63 … … 179 178 } 180 179 181 bool Text::textRendererIsNeeded(const NodeRenderingContext& context)182 {183 if (isEditingText())184 return true;185 186 if (!length())187 return false;188 189 if (context.style()->display() == NONE)190 return false;191 192 bool onlyWS = containsOnlyWhitespace();193 if (!onlyWS)194 return true;195 196 RenderObject* parent = context.parentRenderer();197 if (parent->isTable() || parent->isTableRow() || parent->isTableSection() || parent->isRenderTableCol() || parent->isFrameSet())198 return false;199 200 if (context.style()->preserveNewline()) // pre/pre-wrap/pre-line always make renderers.201 return true;202 203 RenderObject* prev = context.previousRenderer();204 if (prev && prev->isBR()) // <span><br/> <br/></span>205 return false;206 207 if (parent->isRenderInline()) {208 // <span><div/> <div/></span>209 if (prev && !prev->isInline())210 return false;211 } else {212 if (parent->isRenderBlock() && !parent->childrenInline() && (!prev || !prev->isInline()))213 return false;214 215 RenderObject* first = parent->firstChild();216 while (first && first->isFloatingOrOutOfFlowPositioned())217 first = first->nextSibling();218 if (!first || context.nextRenderer() == first) {219 // Whitespace at the start of a block just goes away. Don't even220 // make a render object for this text.221 return false;222 }223 }224 225 return true;226 }227 180 228 181 #if ENABLE(SVG) … … 239 192 } 240 193 #endif 241 242 void Text::createTextRendererIfNeeded()243 {244 NodeRenderingContext(this).createRendererForTextIfNeeded();245 }246 194 247 195 RenderText* Text::createTextRenderer(RenderArena* arena, RenderStyle* style) … … 255 203 256 204 return new (arena) RenderText(this, dataImpl()); 257 }258 259 void Text::createTextRenderersForSiblingsAfterAttachIfNeeded(Node* sibling)260 {261 ASSERT(sibling->previousSibling());262 ASSERT(sibling->previousSibling()->renderer());263 ASSERT(!sibling->renderer());264 ASSERT(sibling->attached());265 // If this node got a renderer it may be the previousRenderer() of sibling text nodes and thus affect the266 // result of Text::textRendererIsNeeded() for those nodes.267 for (; sibling; sibling = sibling->nextSibling()) {268 if (sibling->renderer())269 break;270 if (!sibling->attached())271 break; // Assume this means none of the following siblings are attached.272 if (!sibling->isTextNode())273 continue;274 ASSERT(!sibling->renderer());275 toText(sibling)->createTextRendererIfNeeded();276 // If we again decided not to create a renderer for next, we can bail out the loop,277 // because it won't affect the result of Text::textRendererIsNeeded() for the rest278 // of sibling nodes.279 if (!sibling->renderer())280 break;281 }282 }283 284 void Text::attachText()285 {286 createTextRendererIfNeeded();287 288 Node* sibling = nextSibling();289 if (renderer() && sibling && !sibling->renderer() && sibling->attached())290 createTextRenderersForSiblingsAfterAttachIfNeeded(sibling);291 292 setAttached(true);293 clearNeedsStyleRecalc();294 }295 296 void Text::detachText()297 {298 if (renderer())299 renderer()->destroyAndCleanupAnonymousWrappers();300 setRenderer(0);301 setAttached(false);302 }303 304 void Text::updateTextRenderer(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData)305 {306 if (!attached())307 return;308 RenderText* textRenderer = toRenderText(renderer());309 if (!textRenderer) {310 attachText();311 return;312 }313 NodeRenderingContext renderingContext(this, textRenderer->style());314 if (!textRendererIsNeeded(renderingContext)) {315 if (attached())316 detachText();317 attachText();318 return;319 }320 textRenderer->setTextWithOffset(dataImpl(), offsetOfReplacedData, lengthOfReplacedData);321 205 } 322 206 -
trunk/Source/WebCore/dom/Text.h
r154371 r154738 49 49 PassRefPtr<Text> replaceWholeText(const String&, ExceptionCode&); 50 50 51 void createTextRendererIfNeeded();52 bool textRendererIsNeeded(const NodeRenderingContext&);53 51 RenderText* createTextRenderer(RenderArena*, RenderStyle*); 54 void updateTextRenderer(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData);55 56 void attachText();57 void detachText();58 59 static void createTextRenderersForSiblingsAfterAttachIfNeeded(Node*);60 52 61 53 virtual bool canContainRangeEndPoint() const OVERRIDE FINAL { return true; } -
trunk/Source/WebCore/html/HTMLViewSourceDocument.cpp
r154257 r154738 254 254 RefPtr<Text> text = Text::create(this, substring); 255 255 m_current->parserAppendChild(text); 256 text->attachText();256 Style::attachTextRenderer(*text); 257 257 if (i < size - 1) 258 258 finishLine(); -
trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp
r154449 r154738 104 104 Style::attachRenderTree(toElement(task.child.get())); 105 105 else if (task.child->isTextNode()) 106 toText(task.child.get())->attachText();106 Style::attachTextRenderer(*toText(task.child.get())); 107 107 } 108 108 -
trunk/Source/WebCore/html/shadow/InsertionPoint.cpp
r154371 r154738 61 61 continue; 62 62 if (current->isTextNode()) { 63 toText(current)->attachText();63 Style::attachTextRenderer(*toText(current)); 64 64 continue; 65 65 } … … 76 76 for (Node* current = firstDistributed(); current; current = nextDistributedTo(current)) { 77 77 if (current->isTextNode()) { 78 toText(current)->detachText();78 Style::detachTextRenderer(*toText(current)); 79 79 continue; 80 80 } -
trunk/Source/WebCore/style/StyleResolveTree.cpp
r154541 r154738 110 110 } 111 111 112 static bool isRendererReparented(const RenderObject* renderer) 113 { 114 if (!renderer->node()->isElementNode()) 115 return false; 116 if (renderer->style() && !renderer->style()->flowThread().isEmpty()) 117 return true; 118 return false; 119 } 120 121 static RenderObject* previousSiblingRenderer(const Text& textNode) 122 { 123 if (textNode.renderer()) 124 return textNode.renderer()->previousSibling(); 125 for (Node* sibling = NodeRenderingTraversal::previousSibling(&textNode); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) { 126 RenderObject* renderer = sibling->renderer(); 127 if (renderer && !isRendererReparented(renderer)) 128 return renderer; 129 } 130 return 0; 131 } 132 133 static RenderObject* nextSiblingRenderer(const Text& textNode) 134 { 135 if (textNode.renderer()) 136 return textNode.renderer()->nextSibling(); 137 for (Node* sibling = NodeRenderingTraversal::nextSibling(&textNode); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) { 138 RenderObject* renderer = sibling->renderer(); 139 if (renderer && !isRendererReparented(renderer)) 140 return renderer; 141 } 142 return 0; 143 } 144 145 static void createTextRenderersForSiblingsAfterAttachIfNeeded(Node* sibling) 146 { 147 ASSERT(sibling->previousSibling()); 148 ASSERT(sibling->previousSibling()->renderer()); 149 ASSERT(!sibling->renderer()); 150 ASSERT(sibling->attached()); 151 // If this node got a renderer it may be the previousRenderer() of sibling text nodes and thus affect the 152 // result of Text::textRendererIsNeeded() for those nodes. 153 for (; sibling; sibling = sibling->nextSibling()) { 154 if (sibling->renderer()) 155 break; 156 if (!sibling->attached()) 157 break; // Assume this means none of the following siblings are attached. 158 if (!sibling->isTextNode()) 159 continue; 160 ASSERT(!sibling->renderer()); 161 attachTextRenderer(*toText(sibling)); 162 // If we again decided not to create a renderer for next, we can bail out the loop, 163 // because it won't affect the result of Text::textRendererIsNeeded() for the rest 164 // of sibling nodes. 165 if (!sibling->renderer()) 166 break; 167 } 168 } 169 170 static bool textRendererIsNeeded(const Text& textNode, const RenderObject& parentRenderer, const RenderStyle& style) 171 { 172 if (textNode.isEditingText()) 173 return true; 174 if (!textNode.length()) 175 return false; 176 if (style.display() == NONE) 177 return false; 178 if (!textNode.containsOnlyWhitespace()) 179 return true; 180 // This text node has nothing but white space. We may still need a renderer in some cases. 181 if (parentRenderer.isTable() || parentRenderer.isTableRow() || parentRenderer.isTableSection() || parentRenderer.isRenderTableCol() || parentRenderer.isFrameSet()) 182 return false; 183 if (style.preserveNewline()) // pre/pre-wrap/pre-line always make renderers. 184 return true; 185 186 RenderObject* previousRenderer = previousSiblingRenderer(textNode); 187 if (previousRenderer && previousRenderer->isBR()) // <span><br/> <br/></span> 188 return false; 189 190 if (parentRenderer.isRenderInline()) { 191 // <span><div/> <div/></span> 192 if (previousRenderer && !previousRenderer->isInline()) 193 return false; 194 } else { 195 if (parentRenderer.isRenderBlock() && !parentRenderer.childrenInline() && (!previousRenderer || !previousRenderer->isInline())) 196 return false; 197 198 RenderObject* first = parentRenderer.firstChild(); 199 while (first && first->isFloatingOrOutOfFlowPositioned()) 200 first = first->nextSibling(); 201 RenderObject* nextRenderer = nextSiblingRenderer(textNode); 202 if (!first || nextRenderer == first) { 203 // Whitespace at the start of a block just goes away. Don't even make a render object for this text. 204 return false; 205 } 206 } 207 return true; 208 } 209 210 static void createTextRendererIfNeeded(Text& textNode) 211 { 212 ASSERT(!textNode.renderer()); 213 214 ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode); 215 if (!renderingParentNode) 216 return; 217 RenderObject* parentRenderer = renderingParentNode->renderer(); 218 if (!parentRenderer || !parentRenderer->canHaveChildren()) 219 return; 220 if (!renderingParentNode->childShouldCreateRenderer(&textNode)) 221 return; 222 223 Document* document = textNode.document(); 224 RefPtr<RenderStyle> style; 225 bool resetStyleInheritance = renderingParentNode->isShadowRoot() && toShadowRoot(renderingParentNode)->resetStyleInheritance(); 226 if (resetStyleInheritance) 227 style = document->ensureStyleResolver().defaultStyleForElement(); 228 else 229 style = parentRenderer->style(); 230 231 if (!textRendererIsNeeded(textNode, *parentRenderer, *style)) 232 return; 233 RenderText* newRenderer = textNode.createTextRenderer(document->renderArena(), style.get()); 234 if (!newRenderer) 235 return; 236 if (!parentRenderer->isChildAllowed(newRenderer, style.get())) { 237 newRenderer->destroy(); 238 return; 239 } 240 241 // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style 242 // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail. 243 newRenderer->setFlowThreadState(parentRenderer->flowThreadState()); 244 245 RenderObject* nextRenderer = nextSiblingRenderer(textNode); 246 textNode.setRenderer(newRenderer); 247 // Parent takes care of the animations, no need to call setAnimatableStyle. 248 newRenderer->setStyle(style.release()); 249 parentRenderer->addChild(newRenderer, nextRenderer); 250 251 Node* sibling = textNode.nextSibling(); 252 if (sibling && !sibling->renderer() && sibling->attached()) 253 createTextRenderersForSiblingsAfterAttachIfNeeded(sibling); 254 } 255 256 void attachTextRenderer(Text& textNode) 257 { 258 createTextRendererIfNeeded(textNode); 259 260 textNode.setAttached(true); 261 textNode.clearNeedsStyleRecalc(); 262 } 263 264 void detachTextRenderer(Text& textNode) 265 { 266 if (textNode.renderer()) 267 textNode.renderer()->destroyAndCleanupAnonymousWrappers(); 268 textNode.setRenderer(0); 269 textNode.setAttached(false); 270 } 271 272 void updateTextRendererAfterContentChange(Text& textNode, unsigned offsetOfReplacedData, unsigned lengthOfReplacedData) 273 { 274 if (!textNode.attached()) 275 return; 276 RenderText* textRenderer = toRenderText(textNode.renderer()); 277 if (!textRenderer) { 278 attachTextRenderer(textNode); 279 return; 280 } 281 RenderObject* parentRenderer = NodeRenderingTraversal::parent(&textNode)->renderer(); 282 if (!textRendererIsNeeded(textNode, *parentRenderer, *textRenderer->style())) { 283 detachTextRenderer(textNode); 284 attachTextRenderer(textNode); 285 return; 286 } 287 textRenderer->setTextWithOffset(textNode.dataImpl(), offsetOfReplacedData, lengthOfReplacedData); 288 } 289 290 112 291 static void attachShadowRoot(ShadowRoot* shadowRoot, const AttachContext& context) 113 292 { … … 121 300 for (Node* child = shadowRoot->firstChild(); child; child = child->nextSibling()) { 122 301 if (child->isTextNode()) { 123 toText(child)->attachText();302 attachTextRenderer(*toText(child)); 124 303 continue; 125 304 } … … 156 335 continue; 157 336 if (child->isTextNode()) { 158 toText(child)->attachText();337 attachTextRenderer(*toText(child)); 159 338 continue; 160 339 } … … 192 371 Node* sibling = current->nextSibling(); 193 372 if (current->renderer() && sibling && !sibling->renderer() && sibling->attached()) 194 Text::createTextRenderersForSiblingsAfterAttachIfNeeded(sibling);373 createTextRenderersForSiblingsAfterAttachIfNeeded(sibling); 195 374 196 375 current->setAttached(true); … … 218 397 for (Node* child = shadowRoot->firstChild(); child; child = child->nextSibling()) { 219 398 if (child->isTextNode()) { 220 toText(child)->detachText();399 Style::detachTextRenderer(*toText(child)); 221 400 continue; 222 401 } … … 235 414 for (Node* child = current->firstChild(); child; child = child->nextSibling()) { 236 415 if (child->isTextNode()) { 237 toText(child)->detachText();416 Style::detachTextRenderer(*toText(child)); 238 417 continue; 239 418 } … … 374 553 renderer->setText(text->dataImpl()); 375 554 else 376 text->attachText();555 attachTextRenderer(*text); 377 556 text->clearNeedsStyleRecalc(); 378 557 } -
trunk/Source/WebCore/style/StyleResolveTree.h
r154257 r154738 33 33 class RenderStyle; 34 34 class Settings; 35 class Text; 35 36 36 37 namespace Style { … … 51 52 void reattachRenderTree(Element*, const AttachContext& = AttachContext()); 52 53 54 void attachTextRenderer(Text&); 55 void detachTextRenderer(Text&); 56 void updateTextRendererAfterContentChange(Text&, unsigned offsetOfReplacedData, unsigned lengthOfReplacedData); 57 53 58 Change determineChange(const RenderStyle*, const RenderStyle*, Settings*); 54 59 -
trunk/Source/WebCore/xml/parser/XMLDocumentParser.cpp
r154047 r154738 173 173 #endif 174 174 175 if (m_view && m_leafTextNode->parentNode() && m_leafTextNode->parentNode()->attached() 176 && !m_leafTextNode->attached()) 177 m_leafTextNode->attachText(); 175 if (m_view && m_leafTextNode->parentNode() && m_leafTextNode->parentNode()->attached() && !m_leafTextNode->attached()) 176 Style::attachTextRenderer(*m_leafTextNode); 178 177 179 178 m_leafTextNode = 0; -
trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp
r154558 r154738 1038 1038 m_currentNode->parserAppendChild(newNode.get()); 1039 1039 if (m_view && !newNode->attached()) 1040 newNode->attachText();1040 Style::attachTextRenderer(*newNode); 1041 1041 } 1042 1042
Note:
See TracChangeset
for help on using the changeset viewer.