Changeset 269813 in webkit


Ignore:
Timestamp:
Nov 14, 2020 1:01:04 AM (3 years ago)
Author:
graouts@webkit.org
Message:

Support animations on more pseudo-elements
https://bugs.webkit.org/show_bug.cgi?id=218792
<rdar://problem/71274485>

Reviewed by Antti Koivisto.

LayoutTests/imported/w3c:

Add PASS results for WPT tests running animations on ::marker pseudo-elements.

  • web-platform-tests/css/css-animations/Document-getAnimations.tentative-expected.txt:
  • web-platform-tests/css/css-animations/animationevent-marker-pseudoelement-expected.txt:
  • web-platform-tests/css/css-animations/event-order.tentative-expected.txt:
  • web-platform-tests/css/css-pseudo/marker-animate-expected.txt:
  • web-platform-tests/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt:
  • web-platform-tests/css/css-transitions/Document-getAnimations.tentative-expected.txt:

Source/WebCore:

We used to only support animations for pseudo-elements that were represented by PseudoElement (::before and ::after).
With this patch, we can now animate any public pseudo-element, such as ::marker.

  • animation/KeyframeEffect.cpp:

(WebCore::elementOrPseudoElementForStyleable): For pseudo-elements other than ::before or ::after, return the Styleable's
element since a PseudoElement is only accessible for the aforementioned pseudo-elements.
(WebCore::KeyframeEffect::targetElementOrPseudoElement const): For pseudo-elements other than ::before or ::after, return
the animation target as the target element.

  • dom/PseudoElement.cpp:

(WebCore::PseudoElement::rendererIsNeeded): Refactor what was originally isTargetedByKeyframeEffectRequiringPseudoElement()
into this method since isTargetedByKeyframeEffectRequiringPseudoElement() was removed.
(WebCore::PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement): Remove this method from PseudoElement since
pseudo-elements that are not represented by a PseudoElement need similar logic, which is now available through the static
function elementIsTargetedByKeyframeEffectRequiringPseudoElement() in RenderTreeUpdaterGeneratedContent.cpp.

  • dom/PseudoElement.h:
  • rendering/updating/RenderTreeUpdater.cpp:

(WebCore::RenderTreeUpdater::updateRenderTree): Pass the entire set of ElementUpdates instead of just the ElementUpdate to
updateElementRenderer() such that it may process the new pseudoElementUpdates member.
(WebCore::RenderTreeUpdater::updateBeforeDescendants): Pass the entire set of ElementUpdates and a PseudoId to
updatePseudoElement() such that it may use the new pseudoElementUpdates member in combination with the PseudoId
to determine what ElementUpdate to use.
(WebCore::RenderTreeUpdater::updateAfterDescendants): Pass the entire set of ElementUpdates and a PseudoId to
updatePseudoElement() such that it may use the new pseudoElementUpdates member in combination with the PseudoId
to determine what ElementUpdate to use.
(WebCore::RenderTreeUpdater::updateElementRenderer): Use the new pseudoElementUpdates member in ElementUpdates to set the
pseudo-element styles.

  • rendering/updating/RenderTreeUpdater.h:
  • rendering/updating/RenderTreeUpdaterGeneratedContent.cpp:

(WebCore::elementIsTargetedByKeyframeEffectRequiringPseudoElement): New static method meant to replace the removed
PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement() such that we may use this method regardless of whether
the pseudo-element is represented by PseudoElement.
(WebCore::createContentRenderers): Use elementIsTargetedByKeyframeEffectRequiringPseudoElement() instead of the removed
PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement().
(WebCore::RenderTreeUpdater::GeneratedContent::updatePseudoElement): Look up all ElementUpdate for the provided PseudoId
in the new pseudoElementUpdates member in ElementUpdates in order to determine what ElementUpdate to process. Also, use
elementIsTargetedByKeyframeEffectRequiringPseudoElement() instead of the removed
PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement().
(WebCore::RenderTreeUpdater::GeneratedContent::needsPseudoElement):

  • rendering/updating/RenderTreeUpdaterGeneratedContent.h:
  • style/StyleTreeResolver.cpp:

(WebCore::Style::TreeResolver::resolveElement): Resolve any public pseudo-element instead of just ::before and ::after
and save those in the new ElementUpdates pseudoElementUpdates member.
(WebCore::Style::TreeResolver::resolvePseudoStyle): Resolve any pseudo-element set on an element that either has animations
set on it, either set by Web Animations, as seen on the KeyframeEffectStack, or yet to be applied through a CSS Animation or
CSS Transition, as seen on the RenderStyle.

  • style/StyleTreeResolver.h:
  • style/StyleUpdate.h: Add a new pseudoElementUpdates member on ElementUpdates.
Location:
trunk
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r269812 r269813  
     12020-11-13  Antoine Quint  <graouts@webkit.org>
     2
     3        Support animations on more pseudo-elements
     4        https://bugs.webkit.org/show_bug.cgi?id=218792
     5        <rdar://problem/71274485>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Add PASS results for WPT tests running animations on ::marker pseudo-elements.
     10
     11        * web-platform-tests/css/css-animations/Document-getAnimations.tentative-expected.txt:
     12        * web-platform-tests/css/css-animations/animationevent-marker-pseudoelement-expected.txt:
     13        * web-platform-tests/css/css-animations/event-order.tentative-expected.txt:
     14        * web-platform-tests/css/css-pseudo/marker-animate-expected.txt:
     15        * web-platform-tests/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt:
     16        * web-platform-tests/css/css-transitions/Document-getAnimations.tentative-expected.txt:
     17
    1182020-11-13  Antoine Quint  <graouts@webkit.org>
    219
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/Document-getAnimations.tentative-expected.txt

    r267650 r269813  
    1717PASS pseudo element with replaced target does not affect animation ordering
    1818PASS CSS Animations targetting (pseudo-)elements should have correct order after sorting
    19 FAIL CSS Animations targetting (pseudo-)elements should have correct order after sorting (::marker) assert_equals: CSS animations on both pseudo-elements and elements are returned expected 5 but got 4
     19PASS CSS Animations targetting (pseudo-)elements should have correct order after sorting (::marker)
    2020
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/animationevent-marker-pseudoelement-expected.txt

    r251591 r269813  
    11
    2 Harness Error (TIMEOUT), message = null
     2PASS AnimationEvent should have the correct pseudoElement memeber
    33
    4 TIMEOUT AnimationEvent should have the correct pseudoElement memeber Test timed out
    5 
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/event-order.tentative-expected.txt

    r267650 r269813  
    22PASS Same events are ordered by elements
    33PASS Same events on pseudo-elements follow the prescribed order
    4 FAIL Same events on pseudo-elements follow the prescribed order (::marker) assert_equals: Number of events received (4) should match expected number (5) (expected: animationstart, animationstart, animationstart, animationstart, animationstart, actual: animationstart, animationstart, animationstart, animationstart) expected 5 but got 4
     4PASS Same events on pseudo-elements follow the prescribed order (::marker)
    55FAIL Start and iteration events are ordered by time assert_equals: Event #1 types should match (expected: animationiteration, animationstart, actual: animationstart, animationiteration) expected "animationiteration" but got "animationstart"
    66FAIL Iteration and end events are ordered by time assert_equals: Event #1 types should match (expected: animationiteration, animationend, actual: animationend, animationiteration) expected "animationiteration" but got "animationend"
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/marker-animate-expected.txt

    r267650 r269813  
    11
    2 FAIL 'color' animation assert_equals: color expected "rgb(100, 50, 150)" but got "rgb(0, 0, 0)"
    3 PASS 'opacity' animation
    4 FAIL 'color' + 'opacity' animation assert_equals: color expected "rgb(100, 50, 150)" but got "rgb(0, 0, 0)"
     2PASS 'color' animation
     3FAIL 'opacity' animation assert_equals: opacity expected "1" but got "0.5"
     4FAIL 'color' + 'opacity' animation assert_equals: opacity expected "1" but got "0.5"
    55list item
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt

    r267650 r269813  
    11
    2 FAIL Animation of font in ::marker assert_in_array: value "normal normal normal normal 16px/normal -webkit-standard" not in array ["italic small-caps 500 expanded 15px Ahem", "italic small-caps 500 expanded 15px/normal Ahem"]
     2FAIL Animation of font in ::marker assert_in_array: value "italic normal 500 expanded 15px/35px -webkit-standard" not in array ["italic small-caps 500 expanded 15px Ahem", "italic small-caps 500 expanded 15px/normal Ahem"]
    33FAIL Animation of font-family in ::marker assert_equals: expected "Ahem" but got "-webkit-standard"
    44FAIL Animation of font-feature-settings in ::marker assert_equals: expected "\"smcp\"" but got "normal"
    55FAIL Animation of font-kerning in ::marker assert_equals: expected "none" but got "auto"
    6 FAIL Animation of font-size in ::marker assert_equals: expected "15px" but got "16px"
     6PASS Animation of font-size in ::marker
    77FAIL Animation of font-size-adjust in ::marker assert_true: font-size-adjust doesn't seem to be supported in the computed style expected true got false
    8 FAIL Animation of font-stretch in ::marker assert_in_array: value "normal" not in array ["expanded", "125%"]
    9 FAIL Animation of font-style in ::marker assert_equals: expected "italic" but got "normal"
     8PASS Animation of font-stretch in ::marker
     9PASS Animation of font-style in ::marker
    1010FAIL Animation of font-synthesis in ::marker assert_equals: expected "none" but got "style weight small-caps"
    1111FAIL Animation of font-variant in ::marker assert_equals: expected "small-caps" but got "tabular-nums"
     
    1515FAIL Animation of font-variant-numeric in ::marker assert_equals: expected "slashed-zero" but got "tabular-nums"
    1616FAIL Animation of font-variant-position in ::marker assert_equals: expected "sub" but got "normal"
    17 FAIL Animation of font-weight in ::marker assert_equals: expected "500" but got "normal"
     17PASS Animation of font-weight in ::marker
    1818FAIL Animation of white-space in ::marker assert_equals: expected "nowrap" but got "normal"
    1919FAIL Animation of color in ::marker assert_equals: expected "rgb(50, 150, 100)" but got "rgb(0, 0, 0)"
     
    2929PASS Animation of list-style-position in ::marker
    3030PASS Animation of list-style-type in ::marker
    31 PASS Animation of line-height in ::marker
    32 FAIL Transition of font in ::marker assert_in_array: value "italic small-caps 900 ultra-expanded 25px/normal Ahem" not in array ["italic small-caps 500 expanded 15px Ahem", "italic small-caps 500 expanded 15px/normal Ahem"]
     31FAIL Animation of line-height in ::marker assert_equals: expected "normal" but got "35px"
     32FAIL Transition of font in ::marker assert_in_array: value "italic small-caps 500 expanded 15px/35px Ahem" not in array ["italic small-caps 500 expanded 15px Ahem", "italic small-caps 500 expanded 15px/normal Ahem"]
    3333PASS Transition of font-family in ::marker
    3434PASS Transition of font-feature-settings in ::marker
    3535FAIL Transition of font-kerning in ::marker assert_equals: expected "none" but got "auto"
    36 FAIL Transition of font-size in ::marker assert_equals: expected "15px" but got "25px"
     36PASS Transition of font-size in ::marker
    3737FAIL Transition of font-size-adjust in ::marker assert_true: font-size-adjust doesn't seem to be supported in the computed style expected true got false
    38 FAIL Transition of font-stretch in ::marker assert_in_array: value "ultra-expanded" not in array ["expanded", "125%"]
     38PASS Transition of font-stretch in ::marker
    3939PASS Transition of font-style in ::marker
    4040PASS Transition of font-synthesis in ::marker
     
    4545PASS Transition of font-variant-numeric in ::marker
    4646PASS Transition of font-variant-position in ::marker
    47 FAIL Transition of font-weight in ::marker assert_equals: expected "500" but got "900"
     47PASS Transition of font-weight in ::marker
    4848FAIL Transition of white-space in ::marker assert_equals: expected "nowrap" but got "normal"
    49 FAIL Transition of color in ::marker assert_equals: expected "rgb(50, 150, 100)" but got "rgb(100, 200, 0)"
     49PASS Transition of color in ::marker
    5050FAIL Transition of text-combine-upright in ::marker assert_true: text-combine-upright doesn't seem to be supported in the computed style expected true got false
    5151FAIL Transition of unicode-bidi in ::marker assert_equals: expected "plaintext" but got "normal"
     
    5959PASS Transition of list-style-position in ::marker
    6060PASS Transition of list-style-type in ::marker
    61 PASS Transition of line-height in ::marker
     61FAIL Transition of line-height in ::marker assert_equals: expected "normal" but got "35px"
    6262target
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-transitions/Document-getAnimations.tentative-expected.txt

    r267650 r269813  
    55PASS getAnimations for CSS Transitions sort by transition generation
    66PASS CSS Transitions targetting (pseudo-)elements should have correct order after sorting
    7 FAIL CSS Transitions targetting (pseudo-)elements should have correct order after sorting (::marker) assert_equals: CSS transition on both pseudo-elements and elements are returned expected 5 but got 4
     7PASS CSS Transitions targetting (pseudo-)elements should have correct order after sorting (::marker)
    88PASS Transitions are not returned after they have finished
    99
  • trunk/Source/WebCore/ChangeLog

    r269812 r269813  
     12020-11-13  Antoine Quint  <graouts@webkit.org>
     2
     3        Support animations on more pseudo-elements
     4        https://bugs.webkit.org/show_bug.cgi?id=218792
     5        <rdar://problem/71274485>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        We used to only support animations for pseudo-elements that were represented by PseudoElement (::before and ::after).
     10        With this patch, we can now animate any public pseudo-element, such as ::marker.
     11
     12        * animation/KeyframeEffect.cpp:
     13        (WebCore::elementOrPseudoElementForStyleable): For pseudo-elements other than ::before or ::after, return the Styleable's
     14        element since a PseudoElement is only accessible for the aforementioned pseudo-elements.
     15        (WebCore::KeyframeEffect::targetElementOrPseudoElement const): For pseudo-elements other than ::before or ::after, return
     16        the animation target as the target element.
     17        * dom/PseudoElement.cpp:
     18        (WebCore::PseudoElement::rendererIsNeeded): Refactor what was originally isTargetedByKeyframeEffectRequiringPseudoElement()
     19        into this method since isTargetedByKeyframeEffectRequiringPseudoElement() was removed.
     20        (WebCore::PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement): Remove this method from PseudoElement since
     21        pseudo-elements that are not represented by a PseudoElement need similar logic, which is now available through the static
     22        function elementIsTargetedByKeyframeEffectRequiringPseudoElement() in RenderTreeUpdaterGeneratedContent.cpp.
     23        * dom/PseudoElement.h:
     24        * rendering/updating/RenderTreeUpdater.cpp:
     25        (WebCore::RenderTreeUpdater::updateRenderTree): Pass the entire set of ElementUpdates instead of just the ElementUpdate to
     26        updateElementRenderer() such that it may process the new pseudoElementUpdates member.
     27        (WebCore::RenderTreeUpdater::updateBeforeDescendants): Pass the entire set of ElementUpdates and a PseudoId to
     28        updatePseudoElement() such that it may use the new pseudoElementUpdates member in combination with the PseudoId
     29        to determine what ElementUpdate to use.
     30        (WebCore::RenderTreeUpdater::updateAfterDescendants): Pass the entire set of ElementUpdates and a PseudoId to
     31        updatePseudoElement() such that it may use the new pseudoElementUpdates member in combination with the PseudoId
     32        to determine what ElementUpdate to use.
     33        (WebCore::RenderTreeUpdater::updateElementRenderer): Use the new pseudoElementUpdates member in ElementUpdates to set the
     34        pseudo-element styles.
     35        * rendering/updating/RenderTreeUpdater.h:
     36        * rendering/updating/RenderTreeUpdaterGeneratedContent.cpp:
     37        (WebCore::elementIsTargetedByKeyframeEffectRequiringPseudoElement): New static method meant to replace the removed
     38        PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement() such that we may use this method regardless of whether
     39        the pseudo-element is represented by PseudoElement.
     40        (WebCore::createContentRenderers): Use elementIsTargetedByKeyframeEffectRequiringPseudoElement() instead of the removed
     41        PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement().
     42        (WebCore::RenderTreeUpdater::GeneratedContent::updatePseudoElement): Look up all ElementUpdate for the provided PseudoId
     43        in the new pseudoElementUpdates member in ElementUpdates in order to determine what ElementUpdate to process. Also, use
     44        elementIsTargetedByKeyframeEffectRequiringPseudoElement() instead of the removed
     45        PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement().
     46        (WebCore::RenderTreeUpdater::GeneratedContent::needsPseudoElement):
     47        * rendering/updating/RenderTreeUpdaterGeneratedContent.h:
     48        * style/StyleTreeResolver.cpp:
     49        (WebCore::Style::TreeResolver::resolveElement): Resolve any public pseudo-element instead of just ::before and ::after
     50        and save those in the new ElementUpdates pseudoElementUpdates member.
     51        (WebCore::Style::TreeResolver::resolvePseudoStyle): Resolve any pseudo-element set on an element that either has animations
     52        set on it, either set by Web Animations, as seen on the KeyframeEffectStack, or yet to be applied through a CSS Animation or
     53        CSS Transition, as seen on the RenderStyle.
     54        * style/StyleTreeResolver.h:
     55        * style/StyleUpdate.h: Add a new pseudoElementUpdates member on ElementUpdates.
     56
    1572020-11-13  Antoine Quint  <graouts@webkit.org>
    258
  • trunk/Source/WebCore/animation/KeyframeEffect.cpp

    r269623 r269813  
    7373
    7474    switch (styleable->pseudoId) {
    75     case PseudoId::None:
    76         return &styleable->element;
    7775    case PseudoId::Before:
    7876        return styleable->element.beforePseudoElement();
     
    8078        return styleable->element.afterPseudoElement();
    8179    default:
    82         return nullptr;
     80        return &styleable->element;
    8381    }
    8482}
     
    11481146Element* KeyframeEffect::targetElementOrPseudoElement() const
    11491147{
    1150     if (!targetsPseudoElement())
    1151         return m_target.get();
    1152 
    1153     if (m_pseudoId == PseudoId::Before)
    1154         return m_target->beforePseudoElement();
    1155 
    1156     if (m_pseudoId == PseudoId::After)
    1157         return m_target->afterPseudoElement();
    1158 
    1159     // We only support targeting ::before and ::after pseudo-elements at the moment.
    1160     return nullptr;
     1148    if (m_target) {
     1149        if (m_pseudoId == PseudoId::Before)
     1150            return m_target->beforePseudoElement();
     1151
     1152        if (m_pseudoId == PseudoId::After)
     1153            return m_target->afterPseudoElement();
     1154    }
     1155
     1156    return m_target.get();
    11611157}
    11621158
  • trunk/Source/WebCore/dom/PseudoElement.cpp

    r269623 r269813  
    8484bool PseudoElement::rendererIsNeeded(const RenderStyle& style)
    8585{
    86     return pseudoElementRendererIsNeeded(&style) || isTargetedByKeyframeEffectRequiringPseudoElement();
    87 }
     86    if (pseudoElementRendererIsNeeded(&style))
     87        return true;
    8888
    89 bool PseudoElement::isTargetedByKeyframeEffectRequiringPseudoElement()
    90 {
    9189    if (m_hostElement) {
    9290        if (auto* stack = m_hostElement->keyframeEffectStack(pseudoId()))
  • trunk/Source/WebCore/dom/PseudoElement.h

    r269623 r269813  
    4242
    4343    bool rendererIsNeeded(const RenderStyle&) override;
    44     bool isTargetedByKeyframeEffectRequiringPseudoElement();
    4544
    4645    bool canStartSelection() const override { return false; }
  • trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp

    r267571 r269813  
    192192
    193193        if (elementUpdates)
    194             updateElementRenderer(element, elementUpdates->update);
     194            updateElementRenderer(element, *elementUpdates);
    195195
    196196        storePreviousRenderer(element);
     
    252252{
    253253    if (updates)
    254         generatedContent().updatePseudoElement(element, updates->beforePseudoElementUpdate, PseudoId::Before);
     254        generatedContent().updatePseudoElement(element, *updates, PseudoId::Before);
    255255}
    256256
     
    258258{
    259259    if (updates)
    260         generatedContent().updatePseudoElement(element, updates->afterPseudoElementUpdate, PseudoId::After);
     260        generatedContent().updatePseudoElement(element, *updates, PseudoId::After);
    261261
    262262    auto* renderer = element.renderer();
     
    298298}
    299299
    300 void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::ElementUpdate& update)
     300void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::ElementUpdates& updates)
    301301{
    302302#if PLATFORM(IOS_FAMILY)
     
    304304#endif
    305305
    306     bool shouldTearDownRenderers = update.change == Style::Change::Renderer && (element.renderer() || element.hasDisplayContents());
     306    auto& elementUpdate = updates.update;
     307    auto elementUpdateStyle = RenderStyle::clonePtr(*elementUpdate.style);
     308
     309    for (auto& it : updates.pseudoElementUpdates) {
     310        auto pseudoId = it.key;
     311        if (pseudoId == PseudoId::Before || pseudoId == PseudoId::After)
     312            continue;
     313        elementUpdateStyle->addCachedPseudoStyle(RenderStyle::clonePtr(*it.value.style));
     314    }
     315
     316    bool shouldTearDownRenderers = elementUpdate.change == Style::Change::Renderer && (element.renderer() || element.hasDisplayContents());
    307317    if (shouldTearDownRenderers) {
    308318        if (!element.renderer()) {
     
    312322
    313323        // display:none cancels animations.
    314         auto teardownType = update.style->display() == DisplayType::None ? TeardownType::RendererUpdateCancelingAnimations : TeardownType::RendererUpdate;
     324        auto teardownType = elementUpdate.style->display() == DisplayType::None ? TeardownType::RendererUpdateCancelingAnimations : TeardownType::RendererUpdate;
    315325        tearDownRenderers(element, teardownType, m_builder);
    316326
     
    318328    }
    319329
    320     bool hasDisplayContents = update.style->display() == DisplayType::Contents;
     330    bool hasDisplayContents = elementUpdate.style->display() == DisplayType::Contents;
    321331    if (hasDisplayContents)
    322         element.storeDisplayContentsStyle(RenderStyle::clonePtr(*update.style));
     332        element.storeDisplayContentsStyle(WTFMove(elementUpdateStyle));
    323333    else
    324334        element.resetComputedStyle();
     
    328338        if (element.hasCustomStyleResolveCallbacks())
    329339            element.willAttachRenderers();
    330         createRenderer(element, RenderStyle::clone(*update.style));
     340        createRenderer(element, WTFMove(*elementUpdateStyle));
    331341
    332342        renderingParent().didCreateOrDestroyChildRenderer = true;
     
    338348    auto& renderer = *element.renderer();
    339349
    340     if (update.recompositeLayer) {
    341         updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::RecompositeLayer);
    342         return;
    343     }
    344 
    345     if (update.change == Style::Change::None) {
    346         if (pseudoStyleCacheIsInvalid(&renderer, update.style.get())) {
    347             updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::Equal);
     350    if (elementUpdate.recompositeLayer) {
     351        updateRendererStyle(renderer, WTFMove(*elementUpdateStyle), StyleDifference::RecompositeLayer);
     352        return;
     353    }
     354
     355    if (elementUpdate.change == Style::Change::None) {
     356        if (pseudoStyleCacheIsInvalid(&renderer, elementUpdateStyle.get())) {
     357            updateRendererStyle(renderer, WTFMove(*elementUpdateStyle), StyleDifference::Equal);
    348358            return;
    349359        }
     
    351361    }
    352362
    353     updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::Equal);
     363    updateRendererStyle(renderer, WTFMove(*elementUpdateStyle), StyleDifference::Equal);
    354364}
    355365
  • trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.h

    r262095 r269813  
    5959    void updateTextRenderer(Text&, const Style::TextUpdate*);
    6060    void createTextRenderer(Text&, const Style::TextUpdate*);
    61     void updateElementRenderer(Element&, const Style::ElementUpdate&);
     61    void updateElementRenderer(Element&, const Style::ElementUpdates&);
    6262    void updateRendererStyle(RenderElement&, RenderStyle&&, StyleDifference);
    6363    void createRenderer(Element&, RenderStyle&&);
  • trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.cpp

    r267191 r269813  
    7070}
    7171
    72 static void createContentRenderers(RenderTreeBuilder& builder, RenderElement& pseudoRenderer, const RenderStyle& style)
     72static bool elementIsTargetedByKeyframeEffectRequiringPseudoElement(const Element* element, PseudoId pseudoId)
     73{
     74    if (is<PseudoElement>(element))
     75        return elementIsTargetedByKeyframeEffectRequiringPseudoElement(downcast<PseudoElement>(*element).hostElement(), pseudoId);
     76
     77    if (element) {
     78        if (auto* stack = element->keyframeEffectStack(pseudoId))
     79            return stack->requiresPseudoElement();
     80    }
     81
     82    return false;
     83}
     84
     85static void createContentRenderers(RenderTreeBuilder& builder, RenderElement& pseudoRenderer, const RenderStyle& style, PseudoId pseudoId)
    7386{
    7487    if (auto* contentData = style.contentData()) {
     
    8194        // The only valid scenario where this method is called without the "content" property being set
    8295        // is the case where a pseudo-element has animations set on it via the Web Animations API.
    83         ASSERT(is<PseudoElement>(pseudoRenderer.element()) && downcast<PseudoElement>(*pseudoRenderer.element()).isTargetedByKeyframeEffectRequiringPseudoElement());
     96        ASSERT_UNUSED(pseudoId, elementIsTargetedByKeyframeEffectRequiringPseudoElement(pseudoRenderer.element(), pseudoId));
    8497    }
    8598}
     
    95108}
    96109
    97 void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, const Optional<Style::ElementUpdate>& update, PseudoId pseudoId)
     110void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, const Style::ElementUpdates& updates, PseudoId pseudoId)
    98111{
    99112    PseudoElement* pseudoElement = pseudoId == PseudoId::Before ? current.beforePseudoElement() : current.afterPseudoElement();
     
    102115        m_updater.renderTreePosition().invalidateNextSibling(*renderer);
    103116
    104     if (!needsPseudoElement(update) && (!pseudoElement || !pseudoElement->isTargetedByKeyframeEffectRequiringPseudoElement())) {
     117    auto* update = [&]() -> const Style::ElementUpdate* {
     118        auto iterator = updates.pseudoElementUpdates.find(pseudoId);
     119        if (iterator != updates.pseudoElementUpdates.end())
     120            return &iterator->value;
     121        return nullptr;
     122    }();
     123
     124    if (!needsPseudoElement(update) && (!pseudoElement || !elementIsTargetedByKeyframeEffectRequiringPseudoElement(pseudoElement, pseudoId))) {
    105125        if (pseudoElement) {
    106126            if (pseudoId == PseudoId::Before)
     
    112132    }
    113133
    114     if (update->change == Style::Change::None)
     134    if (!update || update->change == Style::Change::None)
    115135        return;
    116136
     
    126146
    127147        Style::ElementUpdate contentsUpdate { WTFMove(contentsStyle), update->change, update->recompositeLayer };
    128         m_updater.updateElementRenderer(*pseudoElement, contentsUpdate);
     148        Style::ElementUpdates contentsUpdates { WTFMove(contentsUpdate), Style::DescendantsToResolve::None, { } };
     149        m_updater.updateElementRenderer(*pseudoElement, WTFMove(contentsUpdates));
    129150        pseudoElement->storeDisplayContentsStyle(RenderStyle::clonePtr(*update->style));
    130151    } else {
    131         m_updater.updateElementRenderer(*pseudoElement, *update);
     152        auto pseudoElementUpdateStyle = RenderStyle::clonePtr(*update->style);
     153        Style::ElementUpdate pseudoElementUpdate { WTFMove(pseudoElementUpdateStyle), update->change, update->recompositeLayer };
     154        Style::ElementUpdates pseudoElementUpdates { WTFMove(pseudoElementUpdate), Style::DescendantsToResolve::None, { } };
     155        m_updater.updateElementRenderer(*pseudoElement, WTFMove(pseudoElementUpdates));
    132156        ASSERT(!pseudoElement->hasDisplayContents());
    133157    }
     
    138162
    139163    if (update->change == Style::Change::Renderer)
    140         createContentRenderers(m_updater.m_builder, *pseudoElementRenderer, *update->style);
     164        createContentRenderers(m_updater.m_builder, *pseudoElementRenderer, *update->style, pseudoId);
    141165    else
    142166        updateStyleForContentRenderers(*pseudoElementRenderer, *update->style);
     
    149173}
    150174
    151 bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(const Optional<Style::ElementUpdate>& update)
     175bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(const Style::ElementUpdate* update)
    152176{
    153177    if (!update)
  • trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterGeneratedContent.h

    r239427 r269813  
    3939    GeneratedContent(RenderTreeUpdater&);
    4040
    41     void updatePseudoElement(Element&, const Optional<Style::ElementUpdate>&, PseudoId);
     41    void updatePseudoElement(Element&, const Style::ElementUpdates&, PseudoId);
    4242    void updateRemainingQuotes();
    4343
     
    4848    void updateQuotesUpTo(RenderQuote*);
    4949   
    50     bool needsPseudoElement(const Optional<Style::ElementUpdate>&);
     50    bool needsPseudoElement(const Style::ElementUpdate*);
    5151
    5252    RenderTreeUpdater& m_updater;
  • trunk/Source/WebCore/style/StyleTreeResolver.cpp

    r269384 r269813  
    5555#include "Text.h"
    5656#include "WebAnimationTypes.h"
     57#include "WebAnimationUtilities.h"
    5758
    5859namespace WebCore {
     
    245246    }
    246247
    247     auto beforeUpdate = resolvePseudoStyle(element, update, PseudoId::Before);
    248     auto afterUpdate = resolvePseudoStyle(element, update, PseudoId::After);
     248    PseudoIdToElementUpdateMap pseudoUpdates;
     249    for (PseudoId pseudoId = PseudoId::FirstPublicPseudoId; pseudoId < PseudoId::FirstInternalPseudoId; pseudoId = static_cast<PseudoId>(static_cast<unsigned>(pseudoId) + 1)) {
     250        if (auto elementUpdate = resolvePseudoStyle(element, update, pseudoId))
     251            pseudoUpdates.set(pseudoId, WTFMove(*elementUpdate));
     252    }
    249253
    250254#if ENABLE(TOUCH_ACTION_REGIONS)
     
    258262#endif
    259263
    260     return { WTFMove(update), descendantsToResolve, WTFMove(beforeUpdate), WTFMove(afterUpdate) };
    261 }
    262 
    263 ElementUpdate TreeResolver::resolvePseudoStyle(Element& element, const ElementUpdate& elementUpdate, PseudoId pseudoId)
    264 {
     264    return { WTFMove(update), descendantsToResolve, WTFMove(pseudoUpdates) };
     265}
     266
     267Optional<ElementUpdate> TreeResolver::resolvePseudoStyle(Element& element, const ElementUpdate& elementUpdate, PseudoId pseudoId)
     268{
     269    if (pseudoId == PseudoId::Marker && elementUpdate.style->display() != DisplayType::ListItem)
     270        return { };
    265271    if (elementUpdate.style->display() == DisplayType::None)
    266272        return { };
     
    272278        return { };
    273279
    274     auto* pseudoElement = pseudoId == PseudoId::Before ? element.beforePseudoElement() : element.afterPseudoElement();
    275     bool hasAnimations = pseudoElement && pseudoElement->isTargetedByKeyframeEffectRequiringPseudoElement();
     280    bool hasAnimations = pseudoStyle->hasAnimationsOrTransitions() || element.hasKeyframeEffects(pseudoId);
    276281    if (!pseudoElementRendererIsNeeded(pseudoStyle.get()) && !hasAnimations)
    277282        return { };
  • trunk/Source/WebCore/style/StyleTreeResolver.h

    r267571 r269813  
    6363
    6464    ElementUpdate createAnimatedElementUpdate(std::unique_ptr<RenderStyle>, const Styleable&, Change);
    65     ElementUpdate resolvePseudoStyle(Element&, const ElementUpdate&, PseudoId);
     65    Optional<ElementUpdate> resolvePseudoStyle(Element&, const ElementUpdate&, PseudoId);
    6666
    6767    struct Scope : RefCounted<Scope> {
  • trunk/Source/WebCore/style/StyleUpdate.h

    r267191 r269813  
    5151enum class DescendantsToResolve { None, ChildrenWithExplicitInherit, Children, All };
    5252
     53using PseudoIdToElementUpdateMap = HashMap<PseudoId, ElementUpdate, WTF::IntHash<PseudoId>, WTF::StrongEnumHashTraits<PseudoId>>;
     54
    5355struct ElementUpdates {
    5456    ElementUpdate update;
    5557    DescendantsToResolve descendantsToResolve { DescendantsToResolve::None };
    56     Optional<ElementUpdate> beforePseudoElementUpdate;
    57     Optional<ElementUpdate> afterPseudoElementUpdate;
     58    PseudoIdToElementUpdateMap pseudoElementUpdates;
    5859};
    5960
Note: See TracChangeset for help on using the changeset viewer.