Changeset 294291 in webkit
- Timestamp:
- May 16, 2022, 10:59:55 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 11 deleted
- 14 edited
- 1 copied
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/css-generated-content/first-letter-in-nested-before-expected.html (added)
-
LayoutTests/fast/css-generated-content/first-letter-in-nested-before-expected.png (deleted)
-
LayoutTests/fast/css-generated-content/first-letter-in-nested-before-expected.txt (deleted)
-
LayoutTests/fast/css-generated-content/first-letter-in-nested-before-table-expected.html (copied) (copied from trunk/LayoutTests/fast/css-generated-content/first-letter-in-nested-before-table.html ) (2 diffs)
-
LayoutTests/fast/css-generated-content/first-letter-in-nested-before-table-expected.png (deleted)
-
LayoutTests/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt (deleted)
-
LayoutTests/fast/css-generated-content/first-letter-in-nested-before-table.html (modified) (1 diff)
-
LayoutTests/fast/css-generated-content/first-letter-in-nested-before.html (modified) (1 diff)
-
LayoutTests/platform/glib/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt (deleted)
-
LayoutTests/platform/gtk/fast/css-generated-content/first-letter-in-nested-before-expected.png (deleted)
-
LayoutTests/platform/gtk/fast/css-generated-content/first-letter-in-nested-before-table-expected.png (deleted)
-
LayoutTests/platform/ios/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt (deleted)
-
LayoutTests/platform/mac/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt (deleted)
-
LayoutTests/platform/win/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt (deleted)
-
LayoutTests/platform/wincairo/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt (deleted)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/rendering/RenderTextFragment.cpp (modified) (1 diff)
-
Source/WebCore/rendering/RenderTextFragment.h (modified) (1 diff)
-
Source/WebCore/rendering/TextAutoSizing.cpp (modified) (2 diffs)
-
Source/WebCore/rendering/style/RenderStyle.cpp (modified) (3 diffs)
-
Source/WebCore/rendering/style/RenderStyle.h (modified) (2 diffs)
-
Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.cpp (modified) (7 diffs)
-
Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.h (modified) (1 diff)
-
Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.cpp (modified) (1 diff)
-
Source/WebCore/style/StyleTreeResolver.cpp (modified) (13 diffs)
-
Source/WebCore/style/StyleTreeResolver.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r294283 r294291 1 2022-05-16 Antti Koivisto <antti@apple.com> 2 3 Resolve ::first-letter eagerly 4 https://bugs.webkit.org/show_bug.cgi?id=239844 5 6 Reviewed by Alan Bujtas. 7 8 * fast/css-generated-content/first-letter-in-nested-before-expected.html: Added. 9 * fast/css-generated-content/first-letter-in-nested-before-expected.png: Removed. 10 * fast/css-generated-content/first-letter-in-nested-before-expected.txt: Removed. 11 * fast/css-generated-content/first-letter-in-nested-before-table-expected.html: Copied from LayoutTests/fast/css-generated-content/first-letter-in-nested-before-table.html. 12 * fast/css-generated-content/first-letter-in-nested-before-table-expected.png: Removed. 13 * fast/css-generated-content/first-letter-in-nested-before-table-expected.txt: Removed. 14 * fast/css-generated-content/first-letter-in-nested-before-table.html: 15 * fast/css-generated-content/first-letter-in-nested-before.html: 16 17 Make reftest and update the behavior. ::first-letter won't affect ::before/after with display:table, 18 matching Firefox behavior (and spec logic). 19 20 * platform/glib/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt: Removed. 21 * platform/gtk/fast/css-generated-content/first-letter-in-nested-before-expected.png: Removed. 22 * platform/gtk/fast/css-generated-content/first-letter-in-nested-before-table-expected.png: Removed. 23 * platform/ios/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt: Removed. 24 * platform/mac/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt: Removed. 25 * platform/win/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt: Removed. 26 * platform/wincairo/fast/css-generated-content/first-letter-in-nested-before-table-expected.txt: Removed. 27 1 28 2022-05-16 Karl Rackler <rackler@apple.com> 2 29 -
trunk/LayoutTests/fast/css-generated-content/first-letter-in-nested-before-table-expected.html
r294290 r294291 1 1 <!DOCTYPE html> 2 <!-- No text in black, B and F should be blue. -->3 2 <html> 4 3 <body style="font-family: ahem; font-size: 50px; -webkit-font-smoothing: none;"> … … 12 11 content: "EF"; 13 12 } 14 .test1:first-letter { color: green; }15 .test2:first-letter { color: green; }16 13 </style> 17 14 <div class="test1">C</div> 18 <div class="test2"> D</div>15 <div class="test2"><span style="color:green">D</span></div> 19 16 <div class="test2"></div> 20 17 <script> -
trunk/LayoutTests/fast/css-generated-content/first-letter-in-nested-before-table.html
r97124 r294291 1 1 <!DOCTYPE html> 2 <!-- No text in black, B and F should be blue. -->3 2 <html> 4 3 <body style="font-family: ahem; font-size: 50px; -webkit-font-smoothing: none;"> -
trunk/LayoutTests/fast/css-generated-content/first-letter-in-nested-before.html
r96427 r294291 1 1 <style> 2 2 #target { color: green; margin-top: -100px; } 3 #target:before { display: table; content: "A"; }3 #target:before { display: block; content: "A"; } 4 4 #target:first-letter { font-size: 200%; } 5 5 </style> -
trunk/Source/WebCore/ChangeLog
r294290 r294291 1 2022-05-16 Antti Koivisto <antti@apple.com> 2 3 Resolve ::first-letter eagerly 4 https://bugs.webkit.org/show_bug.cgi?id=239844 5 6 Reviewed by Alan Bujtas. 7 8 ::first-letter pseudo-element should be resolved eagerly during style resolution, similar to ::first-line. 9 This will clean up the architecture. It also makes ::first-letter animatable. 10 11 * rendering/RenderTextFragment.cpp: 12 (WebCore::RenderTextFragment::styleDidChange): Deleted. 13 * rendering/RenderTextFragment.h: 14 * rendering/style/RenderStyle.cpp: 15 (WebCore::RenderStyle::removeCachedPseudoStyle): Deleted. 16 17 We always create a new style. There is no need to removed pseudo element styles. 18 19 * rendering/style/RenderStyle.h: 20 * rendering/updating/RenderTreeBuilderFirstLetter.cpp: 21 (WebCore::styleForFirstLetter): 22 23 Pull first-letter style from the parent style instead of resolving it in the middle of render tree building. 24 25 (WebCore::RenderTreeBuilder::FirstLetter::updateAfterDescendants): 26 (WebCore::RenderTreeBuilder::FirstLetter::updateStyle): 27 28 Delete the renderer if we no longer have a style. 29 30 (WebCore::RenderTreeBuilder::FirstLetter::createRenderers): 31 * rendering/updating/RenderTreeBuilderFirstLetter.h: 32 * style/StyleTreeResolver.cpp: 33 (WebCore::Style::TreeResolver::resolveElement): 34 35 Resove first-letter. 36 37 (WebCore::Style::TreeResolver::resolvePseudoElement): 38 (WebCore::Style::TreeResolver::resolveInheritedPseudoElement): 39 40 Factor into a function. 41 42 (WebCore::Style::isChildInBlockFormattingContext): 43 (WebCore::Style::TreeResolver::resolveAncestorFirstLinePseudoElement): 44 (WebCore::Style::TreeResolver::resolveAncestorFirstLetterPseudoElement): 45 46 Resolving first-letter is similar to first-line except it is always a leaf and so won't be inherited from. 47 48 (WebCore::Style::TreeResolver::makeResolutionContextForPseudoElement): 49 (WebCore::Style::TreeResolver::makeResolutionContextForInheritedFirstLine): 50 * style/StyleTreeResolver.h: 51 1 52 2022-05-16 Zan Dobersek <zdobersek@igalia.com> 2 53 -
trunk/Source/WebCore/rendering/RenderTextFragment.cpp
r232178 r294291 70 70 } 71 71 72 void RenderTextFragment::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)73 {74 RenderText::styleDidChange(diff, oldStyle);75 76 if (RenderBlock* block = blockForAccompanyingFirstLetter())77 block->mutableStyle().removeCachedPseudoStyle(PseudoId::FirstLetter);78 }79 80 72 void RenderTextFragment::setText(const String& newText, bool force) 81 73 { -
trunk/Source/WebCore/rendering/RenderTextFragment.h
r284093 r294291 61 61 private: 62 62 bool isTextFragment() const override { return true; } 63 void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;64 63 65 64 UChar previousCharacter() const override; -
trunk/Source/WebCore/rendering/TextAutoSizing.cpp
r272805 r294291 46 46 { 47 47 auto newStyle = RenderStyle::clone(currentStyle); 48 49 // FIXME: This should probably handle at least ::first-line too. 50 if (auto* firstLetterStyle = currentStyle.getCachedPseudoStyle(PseudoId::FirstLetter)) 51 newStyle.addCachedPseudoStyle(makeUnique<RenderStyle>(RenderStyle::clone(*firstLetterStyle))); 52 48 53 if (currentStyle.lastChildState()) 49 54 newStyle.setLastChildState(); … … 171 176 if (!block) 172 177 continue; 178 179 RenderObject* firstLetterRenderer; 180 RenderElement* dummy; 181 block->getFirstLetter(firstLetterRenderer, dummy); 182 if (firstLetterRenderer && firstLetterRenderer->parent() && firstLetterRenderer->parent()->parent()) { 183 auto& parentStyle = firstLetterRenderer->parent()->parent()->style(); 184 auto* firstLetterStyle = parentStyle.getCachedPseudoStyle(PseudoId::FirstLetter); 185 if (!firstLetterStyle) 186 continue; 187 auto fontDescription = firstLetterStyle->fontDescription(); 188 fontDescription.setComputedSize(averageSize * fontDescription.specifiedSize() / parentStyle.fontDescription().specifiedSize()); 189 firstLetterStyle->setFontDescription(FontCascadeDescription { fontDescription }); 190 firstLetterStyle->fontCascade().update(&node->document().fontSelector()); 191 } 192 173 193 builder.updateAfterDescendants(*block); 174 194 } -
trunk/Source/WebCore/rendering/style/RenderStyle.cpp
r294195 r294291 116 116 { 117 117 auto newStyle = RenderStyle(style, Clone); 118 119 if (!style.m_cachedPseudoStyles) 120 return newStyle; 121 122 for (auto& pseudoElementStyle : *style.m_cachedPseudoStyles) { 123 auto clone = makeUnique<RenderStyle>(cloneIncludingPseudoElements(*pseudoElementStyle)); 124 newStyle.addCachedPseudoStyle(WTFMove(clone)); 125 } 118 newStyle.copyPseudoElementsFrom(style); 126 119 return newStyle; 127 120 } … … 393 386 } 394 387 388 void RenderStyle::copyPseudoElementsFrom(const RenderStyle& other) 389 { 390 if (!other.m_cachedPseudoStyles) 391 return; 392 393 for (auto& pseudoElementStyle : *other.m_cachedPseudoStyles) 394 addCachedPseudoStyle(makeUnique<RenderStyle>(cloneIncludingPseudoElements(*pseudoElementStyle))); 395 } 396 395 397 bool RenderStyle::operator==(const RenderStyle& other) const 396 398 { … … 449 451 450 452 return result; 451 }452 453 void RenderStyle::removeCachedPseudoStyle(PseudoId pid)454 {455 if (!m_cachedPseudoStyles)456 return;457 for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {458 RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();459 if (pseudoStyle->styleType() == pid) {460 m_cachedPseudoStyles->remove(i);461 return;462 }463 }464 453 } 465 454 -
trunk/Source/WebCore/rendering/style/RenderStyle.h
r294195 r294291 170 170 void copyNonInheritedFrom(const RenderStyle&); 171 171 void copyContentFrom(const RenderStyle&); 172 void copyPseudoElementsFrom(const RenderStyle&); 172 173 173 174 ContentPosition resolvedJustifyContentPosition(const StyleContentAlignmentData& normalValueBehavior) const; … … 187 188 RenderStyle* getCachedPseudoStyle(PseudoId) const; 188 189 RenderStyle* addCachedPseudoStyle(std::unique_ptr<RenderStyle>); 189 void removeCachedPseudoStyle(PseudoId);190 190 191 191 const PseudoStyleCache* cachedPseudoStyles() const { return m_cachedPseudoStyles.get(); } -
trunk/Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.cpp
r290205 r294291 39 39 namespace WebCore { 40 40 41 static RenderStyle styleForFirstLetter(const RenderBlock& firstLetterBlock, const RenderObject& firstLetterContainer) 42 { 43 auto* containerFirstLetterStyle = firstLetterBlock.getCachedPseudoStyle(PseudoId::FirstLetter, &firstLetterContainer.firstLineStyle()); 44 // FIXME: first-letter style needs to be computed eagerly. 45 auto firstLetterStyle = RenderStyle::clone(containerFirstLetterStyle ? *containerFirstLetterStyle : firstLetterContainer.firstLineStyle()); 41 static std::optional<RenderStyle> styleForFirstLetter(const RenderElement& firstLetterContainer) 42 { 43 auto& styleContainer = firstLetterContainer.isAnonymous() && firstLetterContainer.parent() ? *firstLetterContainer.parent() : firstLetterContainer; 44 auto style = styleContainer.style().getCachedPseudoStyle(PseudoId::FirstLetter); 45 if (!style) 46 return { }; 47 48 auto firstLetterStyle = RenderStyle::clone(*style); 46 49 47 50 // If we have an initial letter drop that is >= 1, then we need to force floating to be on. … … 151 154 return; 152 155 153 createRenderers( block,downcast<RenderText>(*firstLetterRenderer));156 createRenderers(downcast<RenderText>(*firstLetterRenderer)); 154 157 } 155 158 … … 165 168 RenderElement* firstLetter = currentChild.parent(); 166 169 ASSERT(firstLetter->isFirstLetter()); 167 168 RenderElement* firstLetterContainer = firstLetter->parent(); 169 auto pseudoStyle = styleForFirstLetter(firstLetterBlock, *firstLetterContainer); 170 if (!firstLetter || !firstLetter->parent()) 171 return; 172 173 auto& firstLetterContainer = *firstLetter->parent(); 174 175 auto pseudoStyle = styleForFirstLetter(firstLetterContainer); 176 if (!pseudoStyle) { 177 m_builder.destroy(*firstLetter, CanCollapseAnonymousBlock::No); 178 return; 179 } 180 170 181 ASSERT(firstLetter->isFloating() || firstLetter->isInline()); 171 182 172 if (Style::determineChange(firstLetter->style(), pseudoStyle) == Style::Change::Renderer) {183 if (Style::determineChange(firstLetter->style(), *pseudoStyle) == Style::Change::Renderer) { 173 184 // The first-letter renderer needs to be replaced. Create a new renderer of the right type. 174 185 RenderPtr<RenderBoxModelObject> newFirstLetter; 175 if (pseudoStyle .display() == DisplayType::Inline)176 newFirstLetter = createRenderer<RenderInline>(firstLetterBlock.document(), WTFMove( pseudoStyle));186 if (pseudoStyle->display() == DisplayType::Inline) 187 newFirstLetter = createRenderer<RenderInline>(firstLetterBlock.document(), WTFMove(*pseudoStyle)); 177 188 else 178 newFirstLetter = createRenderer<RenderBlockFlow>(firstLetterBlock.document(), WTFMove( pseudoStyle));189 newFirstLetter = createRenderer<RenderBlockFlow>(firstLetterBlock.document(), WTFMove(*pseudoStyle)); 179 190 newFirstLetter->initializeStyle(); 180 191 newFirstLetter->setIsFirstLetter(); … … 196 207 WeakPtr nextSibling = firstLetter->nextSibling(); 197 208 m_builder.destroy(*firstLetter); 198 m_builder.attach( *firstLetterContainer, WTFMove(newFirstLetter), nextSibling.get());199 return; 200 } 201 202 firstLetter->setStyle(WTFMove( pseudoStyle));203 } 204 205 void RenderTreeBuilder::FirstLetter::createRenderers(Render Block& firstLetterBlock, RenderText& currentTextChild)209 m_builder.attach(firstLetterContainer, WTFMove(newFirstLetter), nextSibling.get()); 210 return; 211 } 212 213 firstLetter->setStyle(WTFMove(*pseudoStyle)); 214 } 215 216 void RenderTreeBuilder::FirstLetter::createRenderers(RenderText& currentTextChild) 206 217 { 207 218 RenderElement* textContentParent = currentTextChild.parent(); … … 211 222 else 212 223 firstLetterContainer = textContentParent; 213 auto pseudoStyle = styleForFirstLetter(firstLetterBlock, *firstLetterContainer); 224 if (!firstLetterContainer) 225 return; 226 227 auto pseudoStyle = styleForFirstLetter(*firstLetterContainer); 228 if (!pseudoStyle) 229 return; 230 214 231 RenderPtr<RenderBoxModelObject> newFirstLetter; 215 if (pseudoStyle .display() == DisplayType::Inline)216 newFirstLetter = createRenderer<RenderInline>( firstLetterBlock.document(), WTFMove(pseudoStyle));232 if (pseudoStyle->display() == DisplayType::Inline) 233 newFirstLetter = createRenderer<RenderInline>(currentTextChild.document(), WTFMove(*pseudoStyle)); 217 234 else 218 newFirstLetter = createRenderer<RenderBlockFlow>( firstLetterBlock.document(), WTFMove(pseudoStyle));235 newFirstLetter = createRenderer<RenderBlockFlow>(currentTextChild.document(), WTFMove(*pseudoStyle)); 219 236 newFirstLetter->initializeStyle(); 220 237 newFirstLetter->setIsFirstLetter(); … … 264 281 textNode->setRenderer(newRemainingText.get()); 265 282 } else 266 newRemainingText = createRenderer<RenderTextFragment>( firstLetterBlock.document(), oldText, length, oldText.length() - length);283 newRemainingText = createRenderer<RenderTextFragment>(m_builder.m_view.document(), oldText, length, oldText.length() - length); 267 284 268 285 RenderTextFragment& remainingText = *newRemainingText; … … 278 295 279 296 // Construct text fragment for the first letter. 280 auto letter = createRenderer<RenderTextFragment>( firstLetterBlock.document(), oldText, 0, length);297 auto letter = createRenderer<RenderTextFragment>(m_builder.m_view.document(), oldText, 0, length); 281 298 m_builder.attach(firstLetter, WTFMove(letter)); 282 299 } -
trunk/Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.h
r253290 r294291 43 43 private: 44 44 void updateStyle(RenderBlock& firstLetterBlock, RenderObject& currentChild); 45 void createRenderers(Render Block& firstLetterBlock, RenderText& currentTextChild);45 void createRenderers(RenderText& currentTextChild); 46 46 47 47 RenderTreeBuilder& m_builder; -
trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.cpp
r290867 r294291 145 145 contentsStyle->inheritFrom(*updateStyle); 146 146 contentsStyle->copyContentFrom(*updateStyle); 147 contentsStyle->copyPseudoElementsFrom(*updateStyle); 147 148 148 149 Style::ElementUpdate contentsUpdate { WTFMove(contentsStyle), styleChange, elementUpdate.recompositeLayer }; -
trunk/Source/WebCore/style/StyleTreeResolver.cpp
r293956 r294291 274 274 if (resolveAndAddPseudoElementStyle(PseudoId::FirstLine) != Change::None) 275 275 descendantsToResolve = DescendantsToResolve::All; 276 if (resolveAndAddPseudoElementStyle(PseudoId::FirstLetter) != Change::None) 277 descendantsToResolve = DescendantsToResolve::All; 276 278 277 279 resolveAndAddPseudoElementStyle(PseudoId::Marker); … … 293 295 } 294 296 295 inline bool supportsFirstLine PseudoElement(const RenderStyle& style)297 inline bool supportsFirstLineAndLetterPseudoElement(const RenderStyle& style) 296 298 { 297 299 auto display = style.display(); … … 312 314 if (pseudoId == PseudoId::FirstLine && !scope().resolver->usesFirstLineRules()) 313 315 return { }; 316 if (pseudoId == PseudoId::FirstLetter && !scope().resolver->usesFirstLetterRules()) 317 return { }; 314 318 if (elementUpdate.style->display() == DisplayType::None) 315 319 return { }; 316 320 317 if (!elementUpdate.style->hasPseudoStyle(pseudoId)) { 318 if (pseudoId == PseudoId::FirstLine) { 319 auto firstLineStyle = resolveInheritedFirstLinePseudoElement(element, elementUpdate); 320 if (!firstLineStyle) 321 return { }; 322 323 auto* oldStyle = element.renderOrDisplayContentsStyle(PseudoId::FirstLine); 324 auto change = oldStyle ? determineChange(*oldStyle, *firstLineStyle) : Change::Renderer; 325 return ElementUpdate { WTFMove(firstLineStyle), change }; 326 } 327 return { }; 328 } 329 330 if (pseudoId == PseudoId::FirstLine && !supportsFirstLinePseudoElement(*elementUpdate.style)) 331 return { }; 332 333 auto resolutionContext = makeResolutionContextForPseudoElement(elementUpdate); 321 if (!elementUpdate.style->hasPseudoStyle(pseudoId)) 322 return resolveAncestorPseudoElement(element, pseudoId, elementUpdate); 323 324 if ((pseudoId == PseudoId::FirstLine || pseudoId == PseudoId::FirstLetter) && !supportsFirstLineAndLetterPseudoElement(*elementUpdate.style)) 325 return { }; 326 327 auto resolutionContext = makeResolutionContextForPseudoElement(elementUpdate, pseudoId); 334 328 335 329 auto pseudoStyle = scope().resolver->pseudoStyleForElement(element, { pseudoId }, resolutionContext); … … 338 332 339 333 // FIXME: This test shouldn't be needed. 340 bool hasAnimations = pseudoStyle->hasAnimationsOrTransitions() || element.hasKeyframeEffects(pseudoId); 341 if (pseudoId != PseudoId::FirstLine && !pseudoElementRendererIsNeeded(pseudoStyle.get()) && !hasAnimations) 334 bool alwaysNeedsPseudoElement = pseudoStyle->hasAnimationsOrTransitions() 335 || element.hasKeyframeEffects(pseudoId) 336 || pseudoId == PseudoId::FirstLine 337 || pseudoId == PseudoId::FirstLetter; 338 if (!alwaysNeedsPseudoElement && !pseudoElementRendererIsNeeded(pseudoStyle.get())) 342 339 return { }; 343 340 … … 345 342 346 343 if (pseudoId == PseudoId::Before || pseudoId == PseudoId::After) { 347 // ::first-line can inherit to ::before/::after 348 auto firstLineContext = makeResolutionContextForInheritedFirstLine(elementUpdate, *elementUpdate.style); 349 if (firstLineContext) { 350 auto firstLineStyle = scope().resolver->pseudoStyleForElement(element, { pseudoId }, *firstLineContext); 351 firstLineStyle->setStyleType(PseudoId::FirstLine); 352 animatedUpdate.style->addCachedPseudoStyle(WTFMove(firstLineStyle)); 344 if (scope().resolver->usesFirstLineRules()) { 345 // ::first-line can inherit to ::before/::after 346 if (auto firstLineContext = makeResolutionContextForInheritedFirstLine(elementUpdate, *elementUpdate.style)) { 347 auto firstLineStyle = scope().resolver->pseudoStyleForElement(element, { pseudoId }, *firstLineContext); 348 firstLineStyle->setStyleType(PseudoId::FirstLine); 349 animatedUpdate.style->addCachedPseudoStyle(WTFMove(firstLineStyle)); 350 } 351 } 352 if (scope().resolver->usesFirstLetterRules()) { 353 auto beforeAfterContext = makeResolutionContextForPseudoElement(animatedUpdate, PseudoId::FirstLetter); 354 if (auto firstLetterStyle = resolveAncestorFirstLetterPseudoElement(element, elementUpdate, beforeAfterContext)) 355 animatedUpdate.style->addCachedPseudoStyle(WTFMove(firstLetterStyle)); 353 356 } 354 357 } … … 357 360 } 358 361 359 std::unique_ptr<RenderStyle> TreeResolver::resolveInheritedFirstLinePseudoElement(Element& element, const ElementUpdate& elementUpdate) 362 std::optional<ElementUpdate> TreeResolver::resolveAncestorPseudoElement(Element& element, PseudoId pseudoId, const ElementUpdate& elementUpdate) 363 { 364 ASSERT(!elementUpdate.style->hasPseudoStyle(pseudoId)); 365 366 auto pseudoElementStyle = [&]() -> std::unique_ptr<RenderStyle> { 367 // ::first-line and ::first-letter defined on an ancestor element may need to be resolved for the current element. 368 if (pseudoId == PseudoId::FirstLine) 369 return resolveAncestorFirstLinePseudoElement(element, elementUpdate); 370 if (pseudoId == PseudoId::FirstLetter) { 371 auto resolutionContext = makeResolutionContextForPseudoElement(elementUpdate, PseudoId::FirstLetter); 372 return resolveAncestorFirstLetterPseudoElement(element, elementUpdate, resolutionContext); 373 } 374 return nullptr; 375 }(); 376 377 if (!pseudoElementStyle) 378 return { }; 379 380 auto* oldStyle = element.renderOrDisplayContentsStyle(pseudoId); 381 auto change = oldStyle ? determineChange(*oldStyle, *pseudoElementStyle) : Change::Renderer; 382 auto resolutionContext = makeResolutionContextForPseudoElement(elementUpdate, pseudoId); 383 384 return createAnimatedElementUpdate(WTFMove(pseudoElementStyle), { element, pseudoId }, change, resolutionContext); 385 } 386 387 static bool isChildInBlockFormattingContext(const RenderStyle& style) 388 { 389 // FIXME: Incomplete. There should be shared code with layout for this. 390 if (style.display() != DisplayType::Block && style.display() != DisplayType::ListItem) 391 return false; 392 if (style.hasOutOfFlowPosition()) 393 return false; 394 if (style.floating() != Float::None) 395 return false; 396 if (style.overflowX() != Overflow::Visible || style.overflowY() != Overflow::Visible) 397 return false; 398 return true; 399 }; 400 401 std::unique_ptr<RenderStyle> TreeResolver::resolveAncestorFirstLinePseudoElement(Element& element, const ElementUpdate& elementUpdate) 360 402 { 361 403 if (elementUpdate.style->display() == DisplayType::Inline) { … … 375 417 } 376 418 377 auto isChildInBlockFormattingContext = [](const RenderStyle& style) { 378 // FIXME: Incomplete. There should be shared code with layout for this. 379 if (style.display() != DisplayType::Block) 380 return false; 381 if (style.hasOutOfFlowPosition()) 382 return false; 383 if (style.floating() != Float::None) 384 return false; 385 if (style.overflowX() != Overflow::Visible || style.overflowY() != Overflow::Visible) 386 return false; 387 return true; 388 }; 389 390 auto firstLineElementForBlock = [&]() -> Element* { 419 auto findFirstLineElementForBlock = [&]() -> Element* { 391 420 if (!isChildInBlockFormattingContext(*elementUpdate.style)) 392 421 return nullptr; 393 422 394 423 // ::first-line is only propagated to the first block. 395 if (parent().resolvedFirst BoxGeneratingChild)424 if (parent().resolvedFirstLineAndLetterChild) 396 425 return nullptr; 397 426 … … 399 428 if (parent.style.display() == DisplayType::Contents) 400 429 continue; 401 if (!supportsFirstLine PseudoElement(parent.style))430 if (!supportsFirstLineAndLetterPseudoElement(parent.style)) 402 431 return nullptr; 403 432 if (parent.style.hasPseudoStyle(PseudoId::FirstLine)) … … 409 438 }; 410 439 411 auto firstLineElement = fi rstLineElementForBlock();440 auto firstLineElement = findFirstLineElementForBlock(); 412 441 if (!firstLineElement) 413 442 return { }; 414 443 415 auto resolutionContext = makeResolutionContextForPseudoElement(elementUpdate );444 auto resolutionContext = makeResolutionContextForPseudoElement(elementUpdate, PseudoId::FirstLine); 416 445 // Can't use the cached state since the element being resolved is not the current one. 417 446 resolutionContext.selectorMatchingState = nullptr; 418 447 419 448 return scope().resolver->pseudoStyleForElement(*firstLineElement, { PseudoId::FirstLine }, resolutionContext); 449 } 450 451 std::unique_ptr<RenderStyle> TreeResolver::resolveAncestorFirstLetterPseudoElement(Element& element, const ElementUpdate& elementUpdate, ResolutionContext& resolutionContext) 452 { 453 auto findFirstLetterElement = [&]() -> Element* { 454 if (elementUpdate.style->hasPseudoStyle(PseudoId::FirstLetter) && supportsFirstLineAndLetterPseudoElement(*elementUpdate.style)) 455 return &element; 456 457 // ::first-letter is only propagated to the first box. 458 if (parent().resolvedFirstLineAndLetterChild) 459 return nullptr; 460 461 bool skipInlines = elementUpdate.style->display() == DisplayType::Inline; 462 if (!skipInlines && !isChildInBlockFormattingContext(*elementUpdate.style)) 463 return nullptr; 464 465 for (auto& parent : makeReversedRange(m_parentStack)) { 466 if (parent.style.display() == DisplayType::Contents) 467 continue; 468 if (skipInlines && parent.style.display() == DisplayType::Inline) 469 continue; 470 skipInlines = false; 471 472 if (!supportsFirstLineAndLetterPseudoElement(parent.style)) 473 return nullptr; 474 if (parent.style.hasPseudoStyle(PseudoId::FirstLetter)) 475 return parent.element; 476 if (!isChildInBlockFormattingContext(parent.style)) 477 return nullptr; 478 } 479 return nullptr; 480 }; 481 482 auto firstLetterElement = findFirstLetterElement(); 483 if (!firstLetterElement) 484 return { }; 485 486 // Can't use the cached state since the element being resolved is not the current one. 487 resolutionContext.selectorMatchingState = nullptr; 488 489 return scope().resolver->pseudoStyleForElement(*firstLetterElement, { PseudoId::FirstLetter }, resolutionContext); 420 490 } 421 491 … … 430 500 } 431 501 432 ResolutionContext TreeResolver::makeResolutionContextForPseudoElement(const ElementUpdate& elementUpdate) 433 { 502 ResolutionContext TreeResolver::makeResolutionContextForPseudoElement(const ElementUpdate& elementUpdate, PseudoId pseudoId) 503 { 504 auto parentStyle = [&] { 505 if (pseudoId == PseudoId::FirstLetter) { 506 if (auto* firstLineStyle = elementUpdate.style->getCachedPseudoStyle(PseudoId::FirstLine)) 507 return firstLineStyle; 508 } 509 return elementUpdate.style.get(); 510 }; 511 434 512 return { 435 elementUpdate.style.get(),513 parentStyle(), 436 514 parentBoxStyleForPseudoElement(elementUpdate), 437 515 m_documentElementStyle.get(), … … 442 520 std::optional<ResolutionContext> TreeResolver::makeResolutionContextForInheritedFirstLine(const ElementUpdate& elementUpdate, const RenderStyle& inheritStyle) 443 521 { 444 if (!scope().resolver->usesFirstLineRules())445 return { };446 447 522 auto parentFirstLineStyle = inheritStyle.getCachedPseudoStyle(PseudoId::FirstLine); 448 523 if (!parentFirstLineStyle) … … 706 781 707 782 if (!text.data().isAllSpecialCharacters<isHTMLSpace>()) 708 parent.resolvedFirst BoxGeneratingChild = true;783 parent.resolvedFirstLineAndLetterChild = true; 709 784 710 785 text.setHasValidStyle(); … … 763 838 m_didSeePendingStylesheet = hasLoadingStylesheet(m_document.styleScope(), element, !shouldIterateChildren); 764 839 765 if ( style && generatesBox(*style))766 parent.resolvedFirst BoxGeneratingChild = true;840 if (!parent.resolvedFirstLineAndLetterChild && style && generatesBox(*style) && supportsFirstLineAndLetterPseudoElement(*style)) 841 parent.resolvedFirstLineAndLetterChild = true; 767 842 768 843 if (!shouldIterateChildren) { -
trunk/Source/WebCore/style/StyleTreeResolver.h
r293956 r294291 72 72 static ElementUpdate createAnimatedElementUpdate(std::unique_ptr<RenderStyle>, const Styleable&, Change, const ResolutionContext&); 73 73 std::optional<ElementUpdate> resolvePseudoElement(Element&, PseudoId, const ElementUpdate&); 74 std::unique_ptr<RenderStyle> resolveInheritedFirstLinePseudoElement(Element&, const ElementUpdate&); 74 std::optional<ElementUpdate> resolveAncestorPseudoElement(Element&, PseudoId, const ElementUpdate&); 75 std::unique_ptr<RenderStyle> resolveAncestorFirstLinePseudoElement(Element&, const ElementUpdate&); 76 std::unique_ptr<RenderStyle> resolveAncestorFirstLetterPseudoElement(Element&, const ElementUpdate&, ResolutionContext&); 75 77 76 78 struct Scope : RefCounted<Scope> { … … 93 95 DescendantsToResolve descendantsToResolve { DescendantsToResolve::None }; 94 96 bool didPushScope { false }; 95 bool resolvedFirst BoxGeneratingChild { false };97 bool resolvedFirstLineAndLetterChild { false }; 96 98 97 99 Parent(Document&); … … 115 117 116 118 ResolutionContext makeResolutionContext(); 117 ResolutionContext makeResolutionContextForPseudoElement(const ElementUpdate& );119 ResolutionContext makeResolutionContextForPseudoElement(const ElementUpdate&, PseudoId); 118 120 std::optional<ResolutionContext> makeResolutionContextForInheritedFirstLine(const ElementUpdate&, const RenderStyle& inheritStyle); 119 121 const Parent* boxGeneratingParent() const;
Note:
See TracChangeset
for help on using the changeset viewer.