Changeset 137336 in webkit
- Timestamp:
- Dec 11, 2012 10:53:19 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 31 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r137333 r137336 1 2012-12-11 Elliott Sprehn <esprehn@chromium.org> 2 3 Switch to new PseudoElement based :before and :after 4 https://bugs.webkit.org/show_bug.cgi?id=104462 5 6 Reviewed by Antti Koivisto. 7 8 Add test for block generated content inside inlines which is now supported 9 properly, and also for using box-orient and reordering. 10 11 before-content-continuation.html's expectations change because we now 12 support block content properly. 13 14 I skipped fast/css-generated-content/table-row-group-to-inline.html 15 which needs a rebaseline after this this lands. Unfortunately the test 16 output is still wrong because we leave an anonymous RenderTable in the 17 tree, but that bug has always been there. 18 19 I also skipped fast/css/empty-generated-content.html which needs rebaselines 20 as we no longer create extra anonymous blocks, though the reason is not clear 21 to me. 22 23 * fast/css-generated-content/before-content-continuation-chain-expected.txt: 24 * fast/css-generated-content/block-inside-inline-expected.html: Added. 25 * fast/css-generated-content/block-inside-inline.html: Added. 26 * fast/css-generated-content/box-orient-expected.html: Added. 27 * fast/css-generated-content/box-orient.html: Added. 28 * platform/chromium/TestExpectations: 29 * platform/mac/TestExpectations: 30 1 31 2012-12-11 Nate Chapin <japhet@chromium.org> 2 32 -
trunk/LayoutTests/fast/css-generated-content/before-content-continuation-chain-expected.txt
r131050 r137336 4 4 RenderBlock {HTML} at (0,0) size 800x416 5 5 RenderBody {BODY} at (8,8) size 784x400 6 RenderBlock (anonymous) at (0,0) size 784x0 7 RenderInline {SPAN} at (0,0) size 0x0 [color=#008000] 6 8 RenderBlock (anonymous) at (0,0) size 784x200 7 RenderInline {SPAN} at (0,0) size 200x200 [color=#008000] 8 RenderInline (generated) at (0,0) size 200x200 [color=#0000FF] 9 RenderText at (0,0) size 200x200 10 text run at (0,0) width 200: "A" 11 RenderBlock (anonymous) at (0,200) size 784x0 12 RenderBlock {DIV} at (0,0) size 784x0 [color=#008000] 9 RenderBlock (generated) at (0,0) size 784x200 [color=#0000FF] 10 RenderText at (0,0) size 200x200 11 text run at (0,0) width 200: "A" 12 RenderBlock {DIV} at (0,200) size 784x0 [color=#008000] 13 13 RenderBlock (anonymous) at (0,200) size 784x200 14 14 RenderInline {SPAN} at (0,0) size 200x200 [color=#008000] -
trunk/LayoutTests/platform/chromium/TestExpectations
r137323 r137336 3902 3902 webkit.org/b/101177 svg/repaint/inner-svg-change-viewBox.svg [ ImageOnlyFailure Pass ] 3903 3903 3904 # Needs rebaseline after bug https://bugs.webkit.org/show_bug.cgi?id=104462 3905 webkit.org/b/98687 fast/css-generated-content/table-row-group-to-inline.html [ Failure ] 3906 webkit.org/b/104595 fast/css/empty-generated-content.html [ Failure ] 3907 3904 3908 # These are real failues due to 95121. 3905 3909 # This is spilling caused by LANCZOS3 scaling algorithm that samples outside the source rect. -
trunk/LayoutTests/platform/mac/TestExpectations
r137214 r137336 1154 1154 webkit.org/b/101177 svg/repaint/inner-svg-change-viewBox.svg [ ImageOnlyFailure Pass ] 1155 1155 1156 # Needs rebaseline after bug https://bugs.webkit.org/show_bug.cgi?id=104462 1157 webkit.org/b/98687 fast/css-generated-content/table-row-group-to-inline.html [ Failure ] 1158 webkit.org/b/104595 fast/css/empty-generated-content.html [ Failure ] 1159 1156 1160 webkit.org/b/93247 [ Debug ] fast/lists/list-marker-remove-crash.html [ Crash ] 1157 1161 -
trunk/Source/WebCore/ChangeLog
r137334 r137336 1 2012-12-11 Elliott Sprehn <esprehn@chromium.org> 2 3 Switch to new PseudoElement based :before and :after 4 https://bugs.webkit.org/show_bug.cgi?id=104462 5 6 Reviewed by Antti Koivisto. 7 8 Switch to the new PseudoElement based generated content implementation 9 that moves :before and :after into the DOM. This also switches to using 10 the ComposedShadowTreeWalker for determining the siblings of PseudoElement's 11 making the new generated content implementation support adding :before 12 and :after into <input> elements. 13 14 Tests: fast/css-generated-content/block-inside-inline.html 15 fast/css-generated-content/box-orient.html 16 17 * dom/ComposedShadowTreeWalker.cpp: 18 (WebCore::ComposedShadowTreeWalker::pseudoAwareNextSibling): 19 (WebCore): 20 (WebCore::ComposedShadowTreeWalker::pseudoAwarePreviousSibling): 21 (WebCore::ComposedShadowTreeWalker::traverseParent): 22 * dom/ComposedShadowTreeWalker.h: 23 (ComposedShadowTreeWalker): 24 * dom/Element.cpp: 25 (WebCore::Element::attach): 26 (WebCore::Element::recalcStyle): 27 * dom/Node.cpp: 28 * dom/Node.h: 29 (Node): 30 * dom/NodeRenderingContext.cpp: 31 (WebCore::NodeRenderingContext::nextRenderer): 32 (WebCore::NodeRenderingContext::previousRenderer): 33 (WebCore::NodeRenderingContext::createRendererForElementIfNeeded): 34 * dom/Position.cpp: 35 (WebCore::Position::Position): 36 (WebCore::Position::hasRenderedNonAnonymousDescendantsWithHeight): 37 * editing/visible_units.cpp: 38 (WebCore::logicallyPreviousBox): 39 (WebCore::logicallyNextBox): 40 (WebCore::startPositionForLine): 41 (WebCore::endPositionForLine): 42 * html/HTMLTextFormControlElement.cpp: 43 (WebCore::HTMLTextFormControlElement::childShouldCreateRenderer): 44 * page/DragController.cpp: 45 (WebCore::DragController::draggableNode): 46 * rendering/RenderBlock.cpp: 47 (WebCore::RenderBlock::styleDidChange): 48 (WebCore::RenderBlock::splitBlocks): 49 (WebCore::RenderBlock::addChildIgnoringAnonymousColumnBlocks): 50 (WebCore::RenderBlock::createReplacementRunIn): 51 (WebCore::RenderBlock::isSelectionRoot): 52 * rendering/RenderBlock.h: 53 (RenderBlock): 54 * rendering/RenderButton.cpp: 55 * rendering/RenderButton.h: 56 (RenderButton): 57 * rendering/RenderInline.cpp: 58 (WebCore::RenderInline::styleDidChange): 59 (WebCore::RenderInline::addChildIgnoringContinuation): 60 (WebCore::RenderInline::splitInlines): 61 * rendering/RenderListItem.cpp: 62 (WebCore::RenderListItem::updateMarkerLocation): 63 * rendering/RenderObject.cpp: 64 (WebCore::RenderObject::createVisiblePosition): 65 * rendering/RenderObject.h: 66 (WebCore::RenderObject::nonPseudoNode): 67 (RenderObject): 68 (WebCore::RenderObject::clearNode): 69 (WebCore::RenderObject::generatingNode): 70 * rendering/RenderObjectChildList.cpp: 71 * rendering/RenderObjectChildList.h: 72 (RenderObjectChildList): 73 * rendering/RenderRubyText.cpp: 74 * rendering/RenderRubyText.h: 75 (RenderRubyText): 76 * rendering/RenderTableRow.cpp: 77 (WebCore::RenderTableRow::styleDidChange): 78 * rendering/RenderTableRow.h: 79 * rendering/RenderTableSection.cpp: 80 (WebCore::RenderTableSection::addChild): 81 * rendering/RenderWidget.cpp: 82 (WebCore::RenderWidget::destroy): 83 1 84 2012-12-11 Jacky Jiang <zhajiang@rim.com> 2 85 -
trunk/Source/WebCore/dom/ComposedShadowTreeWalker.cpp
r135251 r137336 34 34 #include "HTMLShadowElement.h" 35 35 #include "InsertionPoint.h" 36 #include "PseudoElement.h" 36 37 37 38 namespace WebCore { … … 178 179 assertPrecondition(); 179 180 m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionBackward); 181 assertPostcondition(); 182 } 183 184 void ComposedShadowTreeWalker::pseudoAwareNextSibling() 185 { 186 assertPrecondition(); 187 188 const Node* node = m_node; 189 190 if (node->isBeforePseudoElement()) 191 m_node = traverseFirstChild(traverseParent(node)); 192 else 193 m_node = traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionForward); 194 195 if (!m_node && !node->isAfterPseudoElement()) { 196 Node* parent = traverseParent(node); 197 if (parent && parent->isElementNode()) 198 m_node = toElement(parent)->afterPseudoElement(); 199 } 200 201 assertPostcondition(); 202 } 203 204 void ComposedShadowTreeWalker::pseudoAwarePreviousSibling() 205 { 206 assertPrecondition(); 207 208 const Node* node = m_node; 209 210 if (node->isAfterPseudoElement()) 211 m_node = traverseLastChild(traverseParent(node)); 212 else 213 m_node = traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionBackward); 214 215 if (!m_node && !node->isBeforePseudoElement()) { 216 Node* parent = traverseParent(node); 217 if (parent && parent->isElementNode()) 218 m_node = toElement(parent)->beforePseudoElement(); 219 } 220 180 221 assertPostcondition(); 181 222 } … … 259 300 Node* ComposedShadowTreeWalker::traverseParent(const Node* node, ParentTraversalDetails* details) const 260 301 { 302 if (node->isPseudoElement()) 303 return node->parentOrHostNode(); 304 261 305 if (!canCrossUpperBoundary() && node->isShadowRoot()) { 262 306 ASSERT(toShadowRoot(node)->isYoungest()); -
trunk/Source/WebCore/dom/ComposedShadowTreeWalker.h
r131070 r137336 91 91 void previousSibling(); 92 92 93 void pseudoAwareNextSibling(); 94 void pseudoAwarePreviousSibling(); 95 93 96 void parent(); 94 97 -
trunk/Source/WebCore/dom/Element.cpp
r137284 r137336 1169 1169 setIsInCanvasSubtree(true); 1170 1170 1171 updatePseudoElement(BEFORE); 1172 1171 1173 // When a shadow root exists, it does the work of attaching the children. 1172 1174 if (ElementShadow* shadow = this->shadow()) { … … 1177 1179 1178 1180 ContainerNode::attach(); 1181 1182 updatePseudoElement(AFTER); 1179 1183 1180 1184 if (hasRareData()) { … … 1330 1334 } 1331 1335 1336 updatePseudoElement(BEFORE, change); 1337 1332 1338 // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar. 1333 1339 // For now we will just worry about the common case, since it's a lot trickier to get the second case right … … 1354 1360 } 1355 1361 1362 updatePseudoElement(AFTER, change); 1363 1356 1364 clearNeedsStyleRecalc(); 1357 1365 clearChildNeedsStyleRecalc(); -
trunk/Source/WebCore/dom/Node.cpp
r137277 r137336 41 41 #include "ChildNodeList.h" 42 42 #include "ClassNodeList.h" 43 #include "ComposedShadowTreeWalker.h" 43 44 #include "ContainerNodeAlgorithms.h" 44 45 #include "ContextMenuController.h" … … 450 451 } 451 452 452 Node* Node::pseudoAwarePreviousSibling() const453 {454 if (isElementNode() && !previousSibling()) {455 Element* parent = parentOrHostElement();456 if (!parent)457 return 0;458 if (isAfterPseudoElement() && parent->lastChild())459 return parent->lastChild();460 if (!isBeforePseudoElement())461 return parent->beforePseudoElement();462 }463 return previousSibling();464 }465 466 Node* Node::pseudoAwareNextSibling() const467 {468 if (isElementNode() && !nextSibling()) {469 Element* parent = parentOrHostElement();470 if (!parent)471 return 0;472 if (isBeforePseudoElement() && parent->firstChild())473 return parent->firstChild();474 if (!isAfterPseudoElement())475 return parent->afterPseudoElement();476 }477 return nextSibling();478 }479 480 453 NodeRareData* Node::rareData() const 481 454 { -
trunk/Source/WebCore/dom/Node.h
r137277 r137336 191 191 NamedNodeMap* attributes() const; 192 192 193 Node* pseudoAwarePreviousSibling() const;194 Node* pseudoAwareNextSibling() const;195 196 193 virtual KURL baseURI() const; 197 194 -
trunk/Source/WebCore/dom/NodeRenderingContext.cpp
r136744 r137336 33 33 #include "FlowThreadController.h" 34 34 #include "HTMLContentElement.h" 35 #include "HTMLInputElement.h" 35 36 #include "HTMLNames.h" 36 37 #include "HTMLShadowElement.h" 37 38 #include "Node.h" 39 #include "PseudoElement.h" 38 40 #include "RenderFullScreen.h" 39 41 #include "RenderNamedFlowThread.h" … … 84 86 return 0; 85 87 86 // FIXME: This is wrong when the next sibling was actually moved around by shadow insertion points.87 if (m_node->isPseudoElement()) {88 for (Node* sibling = m_node->pseudoAwareNextSibling(); sibling; sibling = sibling->pseudoAwareNextSibling()) {89 if (RenderObject* renderer = sibling->renderer())90 return renderer;91 }92 return 0;93 }94 95 88 ComposedShadowTreeWalker walker(m_node); 96 for (walker. nextSibling(); walker.get(); walker.nextSibling()) {89 for (walker.pseudoAwareNextSibling(); walker.get(); walker.pseudoAwareNextSibling()) { 97 90 if (RenderObject* renderer = walker.get()->renderer()) { 98 91 // Renderers for elements attached to a flow thread should be skipped because they are parented differently. … … 111 104 return renderer->previousSibling(); 112 105 113 // FIXME: This method doesn't support pseudo elements since nothing needs114 // previousRenderer() support for them yet.115 ASSERT(!m_node->isPseudoElement());116 117 106 if (m_parentFlowRenderer) 118 107 return m_parentFlowRenderer->previousRendererForNode(m_node); … … 122 111 123 112 ComposedShadowTreeWalker walker(m_node); 124 for (walker.p reviousSibling(); walker.get(); walker.previousSibling()) {113 for (walker.pseudoAwarePreviousSibling(); walker.get(); walker.pseudoAwarePreviousSibling()) { 125 114 if (RenderObject* renderer = walker.get()->renderer()) { 126 115 // Renderers for elements attached to a flow thread should be skipped because they are parented differently. … … 236 225 RenderObject* parentRenderer = this->parentRenderer(); 237 226 RenderObject* nextRenderer = this->nextRenderer(); 238 227 239 228 #if ENABLE(DIALOG_ELEMENT) 240 229 if (element->isInTopLayer()) -
trunk/Source/WebCore/dom/Position.cpp
r136744 r137336 88 88 ASSERT(!m_anchorNode || !m_anchorNode->isShadowRoot()); 89 89 #endif 90 ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement()); 90 91 } 91 92 … … 103 104 #endif 104 105 106 ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement()); 107 105 108 ASSERT(anchorType != PositionIsOffsetInAnchor); 106 109 ASSERT(!((anchorType == PositionIsBeforeChildren || anchorType == PositionIsAfterChildren) … … 120 123 ASSERT(!m_anchorNode || !editingIgnoresContent(m_anchorNode.get()) || !m_anchorNode->isShadowRoot()); 121 124 #endif 125 126 ASSERT(!m_anchorNode || !m_anchorNode->isPseudoElement()); 122 127 123 128 ASSERT(anchorType == PositionIsOffsetInAnchor); … … 841 846 RenderObject* stop = renderer->nextInPreOrderAfterChildren(); 842 847 for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextInPreOrder()) 843 if (o->no de() && !o->node()->isPseudoElement()) {848 if (o->nonPseudoNode()) { 844 849 if ((o->isText() && toRenderText(o)->linesBoundingBox().height()) || 845 850 (o->isBox() && toRenderBox(o)->borderBoundingBox().height())) -
trunk/Source/WebCore/editing/visible_units.cpp
r137221 r137336 216 216 217 217 while (1) { 218 Node* startNode = startBox->renderer() ? startBox->renderer()->no de() : 0;219 if (!startNode || startNode->isPseudoElement())218 Node* startNode = startBox->renderer() ? startBox->renderer()->nonPseudoNode() : 0; 219 if (!startNode) 220 220 break; 221 221 … … 257 257 258 258 while (1) { 259 Node* startNode = startBox->renderer() ? startBox->renderer()->no de() : 0;260 if (!startNode || startNode->isPseudoElement())259 Node* startNode = startBox->renderer() ? startBox->renderer()->nonPseudoNode() : 0; 260 if (!startNode) 261 261 break; 262 262 … … 745 745 return VisiblePosition(); 746 746 747 startNode = startRenderer->no de();748 if (startNode && !startNode->isPseudoElement())747 startNode = startRenderer->nonPseudoNode(); 748 if (startNode) 749 749 break; 750 750 … … 817 817 return VisiblePosition(); 818 818 819 endNode = endRenderer->no de();820 if (endNode && !endNode->isPseudoElement())819 endNode = endRenderer->nonPseudoNode(); 820 if (endNode) 821 821 break; 822 822 -
trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp
r137221 r137336 67 67 bool HTMLTextFormControlElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const 68 68 { 69 // FIXME: We shouldn't force the pseudo elements down into the shadow, but 70 // this perserves the current behavior of WebKit. 71 if (childContext.node()->isPseudoElement()) 72 return HTMLFormControlElementWithState::childShouldCreateRenderer(childContext); 69 73 return childContext.isOnEncapsulationBoundary() && HTMLFormControlElementWithState::childShouldCreateRenderer(childContext); 70 74 } -
trunk/Source/WebCore/page/DragController.cpp
r135952 r137336 626 626 627 627 for (const RenderObject* renderer = startNode->renderer(); renderer; renderer = renderer->parent()) { 628 Node* node = renderer->no de();628 Node* node = renderer->nonPseudoNode(); 629 629 if (!node) 630 630 // Anonymous render blocks don't correspond to actual DOM nodes, so we skip over them -
trunk/Source/WebCore/rendering/RenderBlock.cpp
r137200 r137336 345 345 m_lineHeight = -1; 346 346 347 // Update pseudos for :before and :after now.348 if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules() && canHaveGeneratedChildren()) {349 updateBeforeAfterContent(BEFORE);350 updateBeforeAfterContent(AFTER);351 }352 353 347 // After our style changed, if we lose our ability to propagate floats into next sibling 354 348 // blocks, then we need to find the top most parent containing that overhanging float and … … 380 374 parentBlock->markSiblingsWithFloatsForLayout(); 381 375 } 382 }383 384 void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId)385 {386 // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.387 if (parent() && parent()->createsAnonymousWrapper())388 return;389 children()->updateBeforeAfterContent(this, pseudoId);390 376 } 391 377 … … 604 590 RenderBoxModelObject* currChild = this; 605 591 RenderObject* currChildNextSibling = currChild->nextSibling(); 606 bool documentUsesBeforeAfterRules = document()->styleSheetCollection()->usesBeforeAfterRules(); 607 608 // Note: |this| can be destroyed inside this loop if it is an empty anonymous 609 // block and we try to call updateBeforeAfterContent inside which removes the 610 // generated content and additionally cleans up |this| empty anonymous block. 611 // See RenderBlock::removeChild(). DO NOT reference any local variables to |this| 612 // after this point. 592 613 593 while (curr && curr != fromBlock) { 614 594 ASSERT(curr->isRenderBlock()); … … 632 612 cloneBlock->setContinuation(oldCont); 633 613 } 634 635 // Someone may have indirectly caused a <q> to split. When this happens, the :after content636 // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after637 // content gets properly destroyed.638 bool isLastChild = (currChildNextSibling == blockCurr->lastChild());639 if (documentUsesBeforeAfterRules)640 blockCurr->children()->updateBeforeAfterContent(blockCurr, AFTER);641 if (isLastChild && currChildNextSibling != blockCurr->lastChild())642 currChildNextSibling = 0; // We destroyed the last child, so now we need to update643 // the value of currChildNextSibling.644 614 645 615 // Now we need to take all of the children starting from the first child … … 874 844 if (!isAnonymousBlock()) 875 845 setContinuation(newBox); 876 877 // Someone may have put a <p> inside a <q>, causing a split. When this happens, the :after content878 // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that our :after879 // content gets properly destroyed.880 bool isFirstChild = (beforeChild == firstChild());881 bool isLastChild = (beforeChild == lastChild());882 if (document()->styleSheetCollection()->usesBeforeAfterRules())883 children()->updateBeforeAfterContent(this, AFTER);884 if (isLastChild && beforeChild != lastChild()) {885 // We destroyed the last child, so now we need to update our insertion886 // point to be 0. It's just a straight append now.887 beforeChild = 0;888 } else if (isFirstChild && beforeChild != firstChild()) {889 // If beforeChild was the last anonymous block that collapsed,890 // then we need to update its value.891 beforeChild = firstChild();892 }893 846 894 847 splitFlow(beforeChild, newBox, newChild, oldContinuation); … … 1879 1832 ASSERT(runIn->isRunIn()); 1880 1833 1881 // First we destroy any :before/:after content. It will be regenerated by the new run-in.1882 // Exception is if the run-in itself is generated.1883 if (runIn->style()->styleType() != BEFORE && runIn->style()->styleType() != AFTER) {1884 RenderObject* generatedContent;1885 if (runIn->getCachedPseudoStyle(BEFORE) && (generatedContent = runIn->beforePseudoElementRenderer()))1886 generatedContent->destroy();1887 if (runIn->getCachedPseudoStyle(AFTER) && (generatedContent = runIn->afterPseudoElementRenderer()))1888 generatedContent->destroy();1889 }1890 1891 1834 bool newRunInShouldBeBlock = !runIn->isRenderBlock(); 1892 1835 Node* runInNode = runIn->node(); … … 3237 3180 bool RenderBlock::isSelectionRoot() const 3238 3181 { 3239 if (!no de() || isPseudoElement())3182 if (!nonPseudoNode()) 3240 3183 return false; 3241 3184 -
trunk/Source/WebCore/rendering/RenderBlock.h
r137200 r137336 573 573 virtual void borderFitAdjust(LayoutRect&) const; // Shrink the box in which the border paints if border-fit is set. 574 574 575 virtual void updateBeforeAfterContent(PseudoId);576 577 575 virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG and Ruby. 578 576 -
trunk/Source/WebCore/rendering/RenderButton.cpp
r133717 r137336 154 154 } 155 155 156 void RenderButton::updateBeforeAfterContent(PseudoId type)157 {158 if (m_inner)159 m_inner->children()->updateBeforeAfterContent(m_inner, type, this);160 else161 children()->updateBeforeAfterContent(this, type);162 }163 164 156 LayoutRect RenderButton::controlClipRect(const LayoutPoint& additionalOffset) const 165 157 { -
trunk/Source/WebCore/rendering/RenderButton.h
r131050 r137336 51 51 virtual void updateFromElement(); 52 52 53 virtual void updateBeforeAfterContent(PseudoId);54 55 53 virtual bool canHaveGeneratedChildren() const OVERRIDE; 56 54 virtual bool hasControlClip() const { return true; } -
trunk/Source/WebCore/rendering/RenderInline.cpp
r137108 r137336 42 42 #include "WebCoreMemoryInstrumentation.h" 43 43 44 #include <wtf/TemporaryChange.h>45 46 44 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION) 47 45 #include "Frame.h" … … 171 169 RenderStyle* newStyle = style(); 172 170 RenderInline* continuation = inlineElementContinuation(); 173 { 174 TemporaryChange<bool> enableAfter(RenderObjectChildList::s_enableUpdateBeforeAfterContent, false); 175 RenderInline* nextInlineElementCont = 0; 176 for (RenderInline* currCont = continuation; currCont; currCont = nextInlineElementCont) { 177 nextInlineElementCont = currCont->inlineElementContinuation(); 178 // We need to update :after content for the last continuation in the chain. 179 RenderObjectChildList::s_enableUpdateBeforeAfterContent = !nextInlineElementCont; 180 RenderBoxModelObject* nextCont = currCont->continuation(); 181 currCont->setContinuation(0); 182 currCont->setStyle(newStyle); 183 currCont->setContinuation(nextCont); 184 } 171 for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) { 172 RenderBoxModelObject* nextCont = currCont->continuation(); 173 currCont->setContinuation(0); 174 currCont->setStyle(newStyle); 175 currCont->setContinuation(nextCont); 185 176 } 186 177 … … 202 193 } 203 194 m_alwaysCreateLineBoxes = alwaysCreateLineBoxes; 204 }205 206 // Update pseudos for :before and :after now.207 if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules()) {208 children()->updateBeforeAfterContent(this, BEFORE);209 children()->updateBeforeAfterContent(this, AFTER);210 195 } 211 196 } … … 330 315 RenderBoxModelObject* oldContinuation = continuation(); 331 316 setContinuation(newBox); 332 333 // Someone may have put a <p> inside a <q>, causing a split. When this happens, the :after content334 // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that our :after335 // content gets properly destroyed.336 bool isLastChild = (beforeChild == lastChild());337 if (document()->styleSheetCollection()->usesBeforeAfterRules())338 children()->updateBeforeAfterContent(this, AFTER);339 if (isLastChild && beforeChild != lastChild())340 beforeChild = 0; // We destroyed the last child, so now we need to update our insertion341 // point to be 0. It's just a straight append now.342 317 343 318 splitFlow(beforeChild, newBox, newChild, oldContinuation); … … 406 381 inlineCurr->setContinuation(cloneInline); 407 382 cloneInline->setContinuation(oldCont); 408 409 // Someone may have indirectly caused a <q> to split. When this happens, the :after content410 // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after411 // content gets properly destroyed.412 if (document()->styleSheetCollection()->usesBeforeAfterRules())413 inlineCurr->children()->updateBeforeAfterContent(inlineCurr, AFTER);414 383 415 384 // Now we need to take all of the children starting from the first child -
trunk/Source/WebCore/rendering/RenderListItem.cpp
r131938 r137336 269 269 m_marker->computePreferredLogicalWidths(); 270 270 // If markerPar is an anonymous block that has lost all its children, destroy it. 271 // Extraneous anonymous blocks can cause problems for RenderBlock::updateBeforeAfterContent.272 271 if (markerPar && markerPar->isAnonymousBlock() && !markerPar->firstChild() && !toRenderBlock(markerPar)->continuation()) 273 272 markerPar->destroy(); -
trunk/Source/WebCore/rendering/RenderObject.cpp
r137108 r137336 2996 2996 { 2997 2997 // If this is a non-anonymous renderer in an editable area, then it's simple. 2998 if (node() && !isPseudoElement()) { 2999 Node* node = this->node(); 2998 if (Node* node = nonPseudoNode()) { 3000 2999 if (!node->rendererIsEditable()) { 3001 3000 // If it can be found, we prefer a visually equivalent position that is editable. … … 3023 3022 RenderObject* renderer = child; 3024 3023 while ((renderer = renderer->nextInPreOrder(parent))) { 3025 if ( renderer->node() && !renderer->isPseudoElement())3026 return VisiblePosition(firstPositionInOrBeforeNode( renderer->node()), DOWNSTREAM);3024 if (Node* node = renderer->nonPseudoNode()) 3025 return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM); 3027 3026 } 3028 3027 … … 3032 3031 if (renderer == parent) 3033 3032 break; 3034 if ( renderer->node() && !renderer->isPseudoElement())3035 return VisiblePosition(lastPositionInOrAfterNode( renderer->node()), DOWNSTREAM);3033 if (Node* node = renderer->nonPseudoNode()) 3034 return VisiblePosition(lastPositionInOrAfterNode(node), DOWNSTREAM); 3036 3035 } 3037 3036 3038 3037 // Use the parent itself unless it too is anonymous. 3039 if ( parent->node() && !isPseudoElement())3040 return VisiblePosition(firstPositionInOrBeforeNode( parent->node()), DOWNSTREAM);3038 if (Node* node = parent->nonPseudoNode()) 3039 return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM); 3041 3040 3042 3041 // Repeat at the next level up. -
trunk/Source/WebCore/rendering/RenderObject.h
r137108 r137336 624 624 625 625 Node* node() const { return isAnonymous() ? 0 : m_node; } 626 Node* nonPseudoNode() const { return isPseudoElement() ? 0 : node(); } 627 628 // FIXME: Why does RenderWidget need this? 629 void clearNode() { m_node = 0; } 626 630 627 631 // Returns the styled node that caused the generation of this renderer. 628 632 // This is the same as node() except for renderers of :before and :after 629 633 // pseudo elements for which their parent node is returned. 630 Node* generatingNode() const 631 { 632 if (isPseudoElement()) 633 return node()->parentOrHostNode(); 634 return m_node == document() ? 0 : m_node; 635 } 636 void setNode(Node* node) { m_node = node; } 634 Node* generatingNode() const { return isPseudoElement() ? node()->parentOrHostNode() : node(); } 637 635 638 636 Document* document() const { return m_node->document(); } -
trunk/Source/WebCore/rendering/RenderObjectChildList.cpp
r132753 r137336 41 41 namespace WebCore { 42 42 43 bool RenderObjectChildList::s_enableUpdateBeforeAfterContent = true;44 45 43 void RenderObjectChildList::destroyLeftoverChildren() 46 44 { … … 186 184 if (AXObjectCache::accessibilityEnabled()) 187 185 owner->document()->axObjectCache()->childrenChanged(owner); 188 }189 190 static RenderObject* findBeforeAfterParent(RenderObject* object)191 {192 // Only table parts and flex-boxes need to search for the :before or :after parent193 // FIXME: We could likely get away without this check and always look for the right parent.194 if (!(object->isTable() || object->isTableSection() || object->isTableRow() || object->isFlexibleBoxIncludingDeprecated()))195 return object;196 197 // If there is a :first-letter style applied on the :before or :after content,198 // then we want the parent of the first-letter block199 RenderObject* beforeAfterParent = object;200 while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage())201 && (beforeAfterParent->style()->styleType() != FIRST_LETTER))202 beforeAfterParent = beforeAfterParent->firstChild();203 204 return beforeAfterParent ? beforeAfterParent->parent() : 0;205 186 } 206 187 … … 251 232 } 252 233 253 void RenderObjectChildList::updateBeforeAfterStyle(RenderObject* child, PseudoId type, RenderStyle* pseudoElementStyle)254 {255 if (!child || child->style()->styleType() != type)256 return;257 258 // We have generated content present still. We want to walk this content and update our259 // style information with the new pseudo-element style.260 child->setStyle(pseudoElementStyle);261 262 RenderObject* beforeAfterParent = findBeforeAfterParent(child);263 if (!beforeAfterParent)264 return;265 266 // When beforeAfterParent is not equal to child (e.g. in tables),267 // we need to create new styles inheriting from pseudoElementStyle268 // on all the intermediate parents (leaving their display same).269 if (beforeAfterParent != child) {270 RenderObject* curr = beforeAfterParent;271 while (curr && curr != child) {272 ASSERT(curr->isAnonymous());273 RefPtr<RenderStyle> newStyle = RenderStyle::create();274 newStyle->inheritFrom(pseudoElementStyle);275 newStyle->setDisplay(curr->style()->display());276 newStyle->setStyleType(curr->style()->styleType());277 curr->setStyle(newStyle);278 curr = curr->parent();279 }280 }281 282 // Note that if we ever support additional types of generated content (which should be way off283 // in the future), this code will need to be patched.284 for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {285 if (genChild->isText())286 // Generated text content is a child whose style also needs to be set to the pseudo-element style.287 genChild->setStyle(pseudoElementStyle);288 else if (genChild->isImage()) {289 // Images get an empty style that inherits from the pseudo.290 RefPtr<RenderStyle> style = RenderStyle::create();291 style->inheritFrom(pseudoElementStyle);292 genChild->setStyle(style.release());293 } else {294 // RenderListItem may insert a list marker here. We do not need to care about this case.295 // Otherwise, genChild must be a first-letter container. updateFirstLetter() will take care of it.296 ASSERT(genChild->isListMarker() || genChild->style()->styleType() == FIRST_LETTER);297 }298 }299 }300 301 static RenderObject* ensureBeforeAfterContainer(RenderObject* owner, PseudoId type, RenderStyle* pseudoElementStyle, Node* generatingNode, RenderObject* insertBefore)302 {303 // Make a generated box that might be any display type now that we are able to drill down into children304 // to find the original content properly.305 RenderObject* generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);306 ASSERT(generatingNode); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements.307 generatedContentContainer->setNode(generatingNode); // This allows access to the generatingNode.308 generatedContentContainer->setStyle(pseudoElementStyle);309 if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) {310 // The generated content container is not allowed here -> abort.311 generatedContentContainer->destroy();312 return 0;313 }314 315 // When we don't have a first child and are part of a continuation chain,316 // insertBefore is incorrectly set to zero above, which causes the :before317 // child to end up at the end of continuation chain.318 // See https://bugs.webkit.org/show_bug.cgi?id=78380.319 if (!insertBefore && type == BEFORE && owner->virtualContinuation())320 owner->addChildIgnoringContinuation(generatedContentContainer, 0);321 else322 owner->addChild(generatedContentContainer, insertBefore);323 324 return generatedContentContainer;325 }326 327 void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject)328 {329 // Double check that the document did in fact use generated content rules. Otherwise we should not have been called.330 ASSERT(owner->document()->styleSheetCollection()->usesBeforeAfterRules());331 332 // In CSS2, before/after pseudo-content cannot nest. Check this first.333 if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER)334 return;335 if (!s_enableUpdateBeforeAfterContent)336 return;337 338 if (!styledObject)339 styledObject = owner;340 341 RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);342 RenderObject* child;343 switch (type) {344 case BEFORE:345 child = beforePseudoElementRenderer(owner);346 break;347 case AFTER:348 child = afterPseudoElementRenderer(owner);349 break;350 default:351 ASSERT_NOT_REACHED();352 return;353 }354 355 // Whether or not we currently have generated content attached.356 bool oldContentPresent = child;357 358 // Whether or not we now want generated content.359 bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;360 361 // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate362 // :after content and not :before content.363 if (newContentWanted && type == BEFORE && owner->isElementContinuation())364 newContentWanted = false;365 366 // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,367 // then we don't generate the :after content.368 if (newContentWanted && type == AFTER && owner->virtualContinuation())369 newContentWanted = false;370 371 // If we don't want generated content any longer, or if we have generated content, but it's no longer372 // identical to the new content data we want to build render objects for, then we nuke all373 // of the old generated content.374 if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle, owner->document()) == Node::Detach)) {375 // Nuke the child.376 if (child->style()->styleType() == type) {377 oldContentPresent = false;378 child->destroy();379 child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild();380 }381 }382 383 // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we384 // have no generated content and can now return.385 if (!newContentWanted)386 return;387 388 if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && !pseudoElementStyle->isFloating() &&389 !pseudoElementStyle->hasOutOfFlowPosition())390 // According to the CSS2 spec (the end of section 12.1), the only allowed391 // display values for the pseudo style are NONE and INLINE for inline flows.392 // FIXME: CSS2.1 lifted this restriction, but block display types will crash.393 // For now we at least relax the restriction to allow all inline types like inline-block394 // and inline-table.395 pseudoElementStyle->setDisplay(INLINE);396 397 if (oldContentPresent) {398 updateBeforeAfterStyle(child, type, pseudoElementStyle);399 return; // We've updated the generated content. That's all we needed to do.400 }401 402 RenderObject* insertBefore = (type == BEFORE) ? owner->virtualChildren()->firstChild() : 0;403 if (insertBefore && insertBefore->isAnonymousBlock() && insertBefore->childrenInline() && !insertBefore->isEmpty()) {404 // We are going to add the "before" element. We have to check whether the "insertBefore" element405 // is an anonymous block with inline children. If it is, then we should insert the "before" element406 // before the first inline child of the anonymous block, otherwise we will end up with the "before"407 // element in a different block. We do this only when the anonymous block has children, otherwise408 // we end up with the before element in a wrong block.409 insertBefore = insertBefore->firstChild();410 }411 412 // Nothing goes before the intruded run-in, not even generated content.413 if (insertBefore && insertBefore->isRunIn() && owner->isRenderBlock()414 && toRenderBlock(owner)->runInIsPlacedIntoSiblingBlock(insertBefore))415 insertBefore = insertBefore->nextSibling();416 417 // Generated content consists of a single container that houses multiple children (specified418 // by the content property). This generated content container gets the pseudo-element style set on it.419 // For pseudo-elements that are regions, the container is the RenderRegion.420 RenderObject* generatedContentContainer = 0;421 422 if (!pseudoElementStyle->regionThread().isEmpty())423 generatedContentContainer = ensureBeforeAfterContainer(owner, type, pseudoElementStyle, styledObject->node(), insertBefore);424 else {425 // Walk our list of generated content and create render objects for each.426 for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {427 RenderObject* renderer = content->createRenderer(owner->document(), pseudoElementStyle);428 429 if (!generatedContentContainer) {430 generatedContentContainer = ensureBeforeAfterContainer(owner, type, pseudoElementStyle, styledObject->node(), insertBefore);431 if (!generatedContentContainer) {432 renderer->destroy();433 return;434 }435 }436 if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle))437 generatedContentContainer->addChild(renderer);438 else439 renderer->destroy();440 }441 }442 443 if (!generatedContentContainer)444 return;445 446 // Handle placement of run-ins. We do the run-in placement at the end since generatedContentContainer can get destroyed.447 RenderObject* generatedContentContainerImmediateParent = generatedContentContainer->parent();448 if (generatedContentContainerImmediateParent->isRenderBlock())449 toRenderBlock(generatedContentContainerImmediateParent)->placeRunInIfNeeded(generatedContentContainer, PlaceGeneratedRunIn);450 }451 452 234 } // namespace WebCore -
trunk/Source/WebCore/rendering/RenderObjectChildList.h
r131050 r137336 27 27 #define RenderObjectChildList_h 28 28 29 #include "RenderStyleConstants.h"30 29 #include <wtf/Forward.h> 31 30 … … 57 56 void insertChildNode(RenderObject* owner, RenderObject* child, RenderObject* before, bool notifyRenderer = true); 58 57 59 void updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject = 0);60 58 RenderObject* beforePseudoElementRenderer(const RenderObject* owner) const; 61 59 RenderObject* afterPseudoElementRenderer(const RenderObject* owner) const; 62 60 63 public:64 static bool s_enableUpdateBeforeAfterContent;65 66 61 private: 67 void updateBeforeAfterStyle(RenderObject* child, PseudoId type, RenderStyle* pseudoElementStyle);68 69 62 RenderObject* m_firstChild; 70 63 RenderObject* m_lastChild; -
trunk/Source/WebCore/rendering/RenderRubyText.cpp
r131050 r137336 89 89 } 90 90 91 void RenderRubyText::updateBeforeAfterContent(PseudoId pseudoId)92 {93 // RenderRubyText manages its own :before and :after content94 // and is not handled by its anonymous wrappers RenderRubyRun95 // and RenderRuby. This contrasts with other ruby children, which96 // are enclosed in RenderRubyBase and hence they are able to97 // update their :before, :after content (since RenderRubyBase98 // is not a anonymous wrapper).99 return children()->updateBeforeAfterContent(this, pseudoId);100 }101 102 91 } // namespace WebCore -
trunk/Source/WebCore/rendering/RenderRubyText.h
r131050 r137336 47 47 virtual bool isChildAllowed(RenderObject*, RenderStyle*) const; 48 48 49 virtual void updateBeforeAfterContent(PseudoId);50 51 49 private: 52 50 virtual bool avoidsFloats() const; -
trunk/Source/WebCore/rendering/RenderTableRow.cpp
r137169 r137336 55 55 } 56 56 57 void RenderTableRow::updateBeforeAndAfterContent()58 {59 if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules()) {60 children()->updateBeforeAfterContent(this, BEFORE);61 children()->updateBeforeAfterContent(this, AFTER);62 }63 }64 65 57 void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) 66 58 { … … 69 61 RenderBox::styleDidChange(diff, oldStyle); 70 62 propagateStyleToAnonymousChildren(); 71 72 if (parent())73 updateBeforeAndAfterContent();74 63 75 64 if (section() && oldStyle && style()->logicalHeight() != oldStyle->logicalHeight()) -
trunk/Source/WebCore/rendering/RenderTableRow.h
r137169 r137336 46 46 RenderTable* table() const { return toRenderTable(parent()->parent()); } 47 47 48 void updateBeforeAndAfterContent();49 48 void paintOutlineForRowIfNeeded(PaintInfo&, const LayoutPoint&); 50 49 -
trunk/Source/WebCore/rendering/RenderTableSection.cpp
r137169 r137336 191 191 ASSERT(!beforeChild || beforeChild->isTableRow()); 192 192 RenderBox::addChild(child, beforeChild); 193 toRenderTableRow(child)->updateBeforeAndAfterContent();194 193 } 195 194 -
trunk/Source/WebCore/rendering/RenderWidget.cpp
r131938 r137336 120 120 // Clear the node before deref-ing, as this may be deleted when deref is called. 121 121 RenderArena* arena = renderArena(); 122 setNode(0);122 clearNode(); 123 123 deref(arena); 124 124 }
Note: See TracChangeset
for help on using the changeset viewer.