Changeset 223514 in webkit
- Timestamp:
- Oct 17, 2017 3:18:19 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r223505 r223514 1 2017-10-17 Antti Koivisto <antti@apple.com> 2 3 Text nodes with display:contents parent should render as if they were wrapped in an unstyled <span> 4 https://bugs.webkit.org/show_bug.cgi?id=178332 5 6 Reviewed by Ryosuke Niwa. 7 8 * TestExpectations: 10 more display:contents tests pass. 9 1 10 2017-10-17 Alicia Boya García <aboya@igalia.com> 2 11 -
trunk/LayoutTests/TestExpectations
r223440 r223514 1265 1265 ### START OF display: contents failures 1266 1266 1267 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-list-001.html [ ImageOnlyFailure ]1268 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-table-002-inline.html [ ImageOnlyFailure ]1269 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-inline-flex-001.html [ ImageOnlyFailure ]1270 1267 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-before-after-first-letter-001.html [ ImageOnlyFailure ] 1271 1268 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-before-after-001.html [ ImageOnlyFailure ] 1272 1269 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-table-002-none.html [ ImageOnlyFailure ] 1273 1270 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-flex-003.html [ ImageOnlyFailure ] 1274 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-table-001.html [ ImageOnlyFailure ]1275 1271 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-before-after-002.html [ ImageOnlyFailure ] 1276 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-table-002.html [ ImageOnlyFailure ]1277 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-inline-flex-001-none.html [ ImageOnlyFailure ]1278 1272 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-table-001-inline.html [ ImageOnlyFailure ] 1279 1273 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-flex-002-none.html [ ImageOnlyFailure ] … … 1281 1275 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-before-after-001.html [ ImageOnlyFailure ] 1282 1276 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-flow-root-001.html [ ImageOnlyFailure ] 1283 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-inline-flex-001-inline.html [ ImageOnlyFailure ]1284 1277 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-flex-003-none.html [ ImageOnlyFailure ] 1285 1278 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-table-001-none.html [ ImageOnlyFailure ] 1286 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-state-change-001.html [ ImageOnlyFailure ]1287 1279 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-flex-002-inline.html [ ImageOnlyFailure ] 1288 1280 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-flex-003-inline.html [ ImageOnlyFailure ] 1289 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-list-001-inline.html [ ImageOnlyFailure ]1290 webkit.org/b/157477 imported/w3c/web-platform-tests/css/css-display-3/display-contents-dynamic-list-001-none.html [ ImageOnlyFailure ]1291 1281 1292 1282 ### END OF display: contents failures -
trunk/Source/WebCore/ChangeLog
r223505 r223514 1 2017-10-17 Antti Koivisto <antti@apple.com> 2 3 Text nodes with display:contents parent should render as if they were wrapped in an unstyled <span> 4 https://bugs.webkit.org/show_bug.cgi?id=178332 5 6 Reviewed by Ryosuke Niwa. 7 8 According to https://github.com/w3c/csswg-drafts/issues/1118 9 10 <div style="display:contents;color:green">text</div> 11 12 must result in green text even though div doesn't generate a box. 13 14 This patch implements the behavior by wrapping text renderers with display:contents parent element 15 in an anonymous inline box that receives its style by inheriting from the parent element. 16 17 * dom/Document.cpp: 18 (WebCore::Document::updateTextRenderer): 19 * rendering/RenderElement.cpp: 20 (WebCore::RenderElement::computeFirstLineStyle const): 21 22 Synthesize the first line style in display:contents parent case. 23 24 * rendering/RenderObject.cpp: 25 (WebCore::findDestroyRootIncludingAnonymous): 26 27 Factor into a function. 28 29 (WebCore::RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers): 30 31 Get rid of the anonymous wrapper if it exists. 32 33 * rendering/RenderText.cpp: 34 (WebCore::inlineWrapperForDisplayContentsMap): 35 (WebCore::RenderText::RenderText): 36 (WebCore::RenderText::willBeDestroyed): 37 (WebCore::RenderText::inlineWrapperForDisplayContents): 38 (WebCore::RenderText::setInlineWrapperForDisplayContents): 39 40 Add a weak member (implemented as a rare data map) for holding the wrapper pointer. 41 42 (WebCore::RenderText::findByDisplayContentsInlineWrapperCandidate): 43 44 Helper to get the text renderer for a wrapper. 45 46 * rendering/RenderText.h: 47 * style/RenderTreeUpdater.cpp: 48 (WebCore::createTextRenderer): 49 (WebCore::RenderTreeUpdater::updateTextRenderer): 50 51 Create the wrapper if needed. 52 53 * style/StyleTreeResolver.cpp: 54 (WebCore::Style::TreeResolver::resolveComposedTree): 55 56 Compute the wrapper style by inheriting from the display:contents parent. 57 58 * style/StyleUpdate.h: 59 (WebCore::Style::TextUpdate::TextUpdate): 60 1 61 2017-10-17 Alicia Boya García <aboya@igalia.com> 2 62 -
trunk/Source/WebCore/dom/Document.cpp
r223476 r223514 1872 1872 1873 1873 auto textUpdate = std::make_unique<Style::Update>(*this); 1874 textUpdate->addText(text, { offsetOfReplacedText, lengthOfReplacedText });1874 textUpdate->addText(text, { offsetOfReplacedText, lengthOfReplacedText, std::nullopt }); 1875 1875 1876 1876 RenderTreeUpdater renderTreeUpdater(*this); -
trunk/Source/WebCore/rendering/RenderElement.cpp
r223194 r223514 218 218 } 219 219 220 if ( rendererForFirstLineStyle.isAnonymous() ||!rendererForFirstLineStyle.isRenderInline())220 if (!rendererForFirstLineStyle.isRenderInline()) 221 221 return nullptr; 222 222 … … 224 224 if (&parentStyle == &rendererForFirstLineStyle.parent()->style()) 225 225 return nullptr; 226 227 if (rendererForFirstLineStyle.isAnonymous()) { 228 auto* textRendererWithDisplayContentsParent = RenderText::findByDisplayContentsInlineWrapperCandidate(rendererForFirstLineStyle); 229 if (!textRendererWithDisplayContentsParent) 230 return nullptr; 231 auto* composedTreeParentElement = textRendererWithDisplayContentsParent->textNode()->parentElementInComposedTree(); 232 if (!composedTreeParentElement) 233 return nullptr; 234 235 auto style = composedTreeParentElement->styleResolver().styleForElement(*composedTreeParentElement, &parentStyle).renderStyle; 236 ASSERT(style->display() == CONTENTS); 237 238 // We act as if there was an unstyled <span> around the text node. Only styling happens via inheritance. 239 auto firstLineStyle = RenderStyle::createPtr(); 240 firstLineStyle->inheritFrom(*style); 241 return firstLineStyle; 242 } 243 226 244 return rendererForFirstLineStyle.element()->styleResolver().styleForElement(*element(), &parentStyle).renderStyle; 227 245 } -
trunk/Source/WebCore/rendering/RenderObject.cpp
r223139 r223514 1456 1456 } 1457 1457 1458 void RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers() 1459 { 1460 // If the tree is destroyed, there is no need for a clean-up phase. 1461 if (renderTreeBeingDestroyed()) { 1462 removeFromParentAndDestroy(); 1463 return; 1464 } 1465 1466 auto* destroyRoot = this; 1458 static RenderObject& findDestroyRootIncludingAnonymous(RenderObject& renderer) 1459 { 1460 auto* inlineWrapperForDisplayContents = is<RenderText>(renderer) ? downcast<RenderText>(renderer).inlineWrapperForDisplayContents() : nullptr; 1461 1462 auto* destroyRoot = inlineWrapperForDisplayContents ? inlineWrapperForDisplayContents : &renderer; 1467 1463 auto* destroyRootParent = destroyRoot->parent(); 1468 1464 while (destroyRootParent && destroyRootParent->isAnonymous()) { … … 1476 1472 destroyRootParent = destroyRootParent->parent(); 1477 1473 } 1478 1479 if (is<RenderTableRow>(*destroyRoot)) 1480 downcast<RenderTableRow>(*destroyRoot).collapseAndDestroyAnonymousSiblingRows(); 1481 1482 destroyRoot->removeFromParentAndDestroy(); 1474 return *destroyRoot; 1475 } 1476 1477 void RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers() 1478 { 1479 // If the tree is destroyed, there is no need for a clean-up phase. 1480 if (renderTreeBeingDestroyed()) { 1481 removeFromParentAndDestroy(); 1482 return; 1483 } 1484 1485 auto& destroyRoot = findDestroyRootIncludingAnonymous(*this); 1486 1487 if (is<RenderTableRow>(destroyRoot)) 1488 downcast<RenderTableRow>(destroyRoot).collapseAndDestroyAnonymousSiblingRows(); 1489 1490 destroyRoot.removeFromParentAndDestroy(); 1483 1491 // WARNING: |this| is deleted here. 1484 1492 } -
trunk/Source/WebCore/rendering/RenderText.cpp
r223476 r223514 133 133 } 134 134 135 static HashMap<const RenderText*, WeakPtr<RenderInline>>& inlineWrapperForDisplayContentsMap() 136 { 137 static NeverDestroyed<HashMap<const RenderText*, WeakPtr<RenderInline>>> map; 138 return map; 139 } 140 135 141 void makeCapitalized(String* string, UChar previous) 136 142 { … … 184 190 , m_useBackslashAsYenSymbol(false) 185 191 , m_originalTextDiffersFromRendered(false) 192 , m_hasInlineWrapperForDisplayContents(false) 186 193 #if ENABLE(TEXT_AUTOSIZING) 187 194 , m_candidateComputedTextSize(0) … … 292 299 if (m_originalTextDiffersFromRendered) 293 300 originalTextMap().remove(this); 301 302 setInlineWrapperForDisplayContents(nullptr); 294 303 295 304 RenderObject::willBeDestroyed(); … … 1738 1747 } 1739 1748 1749 RenderInline* RenderText::inlineWrapperForDisplayContents() 1750 { 1751 ASSERT(m_hasInlineWrapperForDisplayContents == inlineWrapperForDisplayContentsMap().contains(this)); 1752 1753 if (!m_hasInlineWrapperForDisplayContents) 1754 return nullptr; 1755 return inlineWrapperForDisplayContentsMap().get(this).get(); 1756 } 1757 1758 void RenderText::setInlineWrapperForDisplayContents(RenderInline* wrapper) 1759 { 1760 ASSERT(m_hasInlineWrapperForDisplayContents == inlineWrapperForDisplayContentsMap().contains(this)); 1761 1762 if (!wrapper) { 1763 if (!m_hasInlineWrapperForDisplayContents) 1764 return; 1765 inlineWrapperForDisplayContentsMap().remove(this); 1766 m_hasInlineWrapperForDisplayContents = false; 1767 return; 1768 } 1769 inlineWrapperForDisplayContentsMap().add(this, makeWeakPtr(wrapper)); 1770 m_hasInlineWrapperForDisplayContents = true; 1771 } 1772 1773 RenderText* RenderText::findByDisplayContentsInlineWrapperCandidate(RenderElement& renderer) 1774 { 1775 auto* firstChild = renderer.firstChild(); 1776 if (!is<RenderText>(firstChild)) 1777 return nullptr; 1778 auto& textRenderer = downcast<RenderText>(*firstChild); 1779 if (textRenderer.inlineWrapperForDisplayContents() != &renderer) 1780 return nullptr; 1781 ASSERT(textRenderer.textNode()); 1782 ASSERT(renderer.firstChild() == renderer.lastChild()); 1783 return &textRenderer; 1784 1785 } 1786 1740 1787 } // namespace WebCore -
trunk/Source/WebCore/rendering/RenderText.h
r222556 r223514 180 180 Vector<std::pair<unsigned, unsigned>> draggedContentRangesBetweenOffsets(unsigned startOffset, unsigned endOffset) const; 181 181 182 RenderInline* inlineWrapperForDisplayContents(); 183 void setInlineWrapperForDisplayContents(RenderInline*); 184 185 static RenderText* findByDisplayContentsInlineWrapperCandidate(RenderElement&); 186 182 187 protected: 183 188 virtual void computePreferredLogicalWidths(float leadWidth); … … 234 239 unsigned m_useBackslashAsYenSymbol : 1; 235 240 unsigned m_originalTextDiffersFromRendered : 1; 241 unsigned m_hasInlineWrapperForDisplayContents : 1; 236 242 unsigned m_canUseSimplifiedTextMeasuring : 1; 237 243 -
trunk/Source/WebCore/style/RenderTreeUpdater.cpp
r223500 r223514 39 39 #include "RenderDescendantIterator.h" 40 40 #include "RenderFullScreen.h" 41 #include "RenderInline.h" 41 42 #include "RenderListItem.h" 42 43 #include "RenderTreeUpdaterFirstLetter.h" … … 429 430 } 430 431 431 static void createTextRenderer(Text& textNode, RenderTreePosition& renderTreePosition )432 static void createTextRenderer(Text& textNode, RenderTreePosition& renderTreePosition, const Style::TextUpdate* textUpdate) 432 433 { 433 434 ASSERT(!textNode.renderer()); 434 435 435 auto newRenderer = textNode.createTextRenderer(renderTreePosition.parent().style()); 436 ASSERT(newRenderer); 436 auto textRenderer = textNode.createTextRenderer(renderTreePosition.parent().style()); 437 437 438 438 renderTreePosition.computeNextSibling(textNode); 439 439 440 if (!renderTreePosition.canInsert(*newRenderer)) 441 return; 442 443 textNode.setRenderer(newRenderer.get()); 444 renderTreePosition.insert(WTFMove(newRenderer)); 440 if (!renderTreePosition.canInsert(*textRenderer)) 441 return; 442 443 textNode.setRenderer(textRenderer.get()); 444 445 if (textUpdate && textUpdate->inheritedDisplayContentsStyle && *textUpdate->inheritedDisplayContentsStyle) { 446 // Wrap text renderer into anonymous inline so we can give it a style. 447 // This is to support "<div style='display:contents;color:green'>text</div>" type cases 448 auto newDisplayContentsAnonymousWrapper = createRenderer<RenderInline>(textNode.document(), RenderStyle::clone(**textUpdate->inheritedDisplayContentsStyle)); 449 newDisplayContentsAnonymousWrapper->initializeStyle(); 450 auto& displayContentsAnonymousWrapper = *newDisplayContentsAnonymousWrapper; 451 renderTreePosition.insert(WTFMove(newDisplayContentsAnonymousWrapper)); 452 453 textRenderer->setInlineWrapperForDisplayContents(&displayContentsAnonymousWrapper); 454 displayContentsAnonymousWrapper.addChild(WTFMove(textRenderer)); 455 return; 456 } 457 458 renderTreePosition.insert(WTFMove(textRenderer)); 445 459 } 446 460 … … 449 463 auto* existingRenderer = text.renderer(); 450 464 bool needsRenderer = textRendererIsNeeded(text, renderTreePosition()); 465 466 if (existingRenderer && textUpdate && textUpdate->inheritedDisplayContentsStyle) { 467 if (existingRenderer->inlineWrapperForDisplayContents() || *textUpdate->inheritedDisplayContentsStyle) { 468 // FIXME: We could update without teardown. 469 tearDownRenderer(text); 470 existingRenderer = nullptr; 471 } 472 } 473 451 474 if (existingRenderer) { 452 475 if (needsRenderer) { … … 461 484 if (!needsRenderer) 462 485 return; 463 createTextRenderer(text, renderTreePosition() );486 createTextRenderer(text, renderTreePosition(), textUpdate); 464 487 invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text); 465 488 } -
trunk/Source/WebCore/style/StyleTreeResolver.cpp
r223500 r223514 373 373 } 374 374 375 static std::unique_ptr<RenderStyle> createInheritedDisplayContentsStyleIfNeeded(const RenderStyle& parentElementStyle, const RenderStyle* parentBoxStyle) 376 { 377 if (parentElementStyle.display() != CONTENTS) 378 return nullptr; 379 if (parentBoxStyle && !parentBoxStyle->inheritedNotEqual(&parentElementStyle)) 380 return nullptr; 381 // Compute style for imaginary unstyled <span> around the text node. 382 auto style = RenderStyle::createPtr(); 383 style->inheritFrom(parentElementStyle); 384 return style; 385 } 386 375 387 void TreeResolver::resolveComposedTree() 376 388 { … … 397 409 if (is<Text>(node)) { 398 410 auto& text = downcast<Text>(node); 399 if (text.styleValidity() >= Validity::SubtreeAndRenderersInvalid && parent.change != Detach) 400 m_update->addText(text, parent.element, { }); 411 412 if ((text.styleValidity() >= Validity::SubtreeAndRenderersInvalid && parent.change != Detach) || parent.style.display() == CONTENTS) { 413 TextUpdate textUpdate; 414 textUpdate.inheritedDisplayContentsStyle = createInheritedDisplayContentsStyleIfNeeded(parent.style, parentBoxStyle()); 415 416 m_update->addText(text, parent.element, WTFMove(textUpdate)); 417 } 401 418 402 419 text.setHasValidStyle(); -
trunk/Source/WebCore/style/StyleUpdate.h
r223500 r223514 76 76 #if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES) 77 77 TextUpdate() = default; 78 TextUpdate(unsigned offset, unsigned length )78 TextUpdate(unsigned offset, unsigned length, std::optional<std::unique_ptr<RenderStyle>> inheritedDisplayContentsStyle) 79 79 : offset { offset } 80 80 , length { length } 81 , inheritedDisplayContentsStyle { WTFMove(inheritedDisplayContentsStyle) } 81 82 { 82 83 } … … 85 86 unsigned offset { 0 }; 86 87 unsigned length { std::numeric_limits<unsigned>::max() }; 88 std::optional<std::unique_ptr<RenderStyle>> inheritedDisplayContentsStyle; 87 89 }; 88 90
Note: See TracChangeset
for help on using the changeset viewer.