Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Unified Diff: third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp

Issue 2532953008: Apply custom property animations (Closed)
Patch Set: Make animatedElement usage consistent Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index 3e9c5d1e26b6a768db73e1eb8eb4afdb3bdfb0b3..14bff6828cacdeb78ae62952c1780ac1c059fe48 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -637,6 +637,37 @@ void StyleResolver::loadPendingResources(StyleResolverState& state) {
state.elementStyleResources().loadPendingResources(state.style());
}
+static const ComputedStyle* calculateBaseComputedStyle(
+ StyleResolverState& state,
+ const Element* animatingElement) {
+ if (!animatingElement)
+ return nullptr;
+
+ ElementAnimations* elementAnimations = animatingElement->elementAnimations();
+ if (!elementAnimations)
+ return nullptr;
+
+ if (CSSAnimations::isAnimatingCustomProperties(elementAnimations)) {
+ state.setIsAnimatingCustomProperties(true);
+ // TODO(alancutter): Use the base computed style optimisation in the
+ // presence of custom property animations that don't affect pre-animated
+ // computed values.
+ return nullptr;
+ }
+
+ return elementAnimations->baseComputedStyle();
+}
+
+static void updateBaseComputedStyle(StyleResolverState& state,
+ Element* animatingElement) {
+ if (!animatingElement || state.isAnimatingCustomProperties())
+ return;
+
+ ElementAnimations* elementAnimations = animatingElement->elementAnimations();
+ if (elementAnimations)
+ elementAnimations->updateBaseComputedStyle(state.style());
+}
+
PassRefPtr<ComputedStyle> StyleResolver::styleForElement(
Element* element,
const ComputedStyle* defaultParent,
@@ -679,9 +710,8 @@ PassRefPtr<ComputedStyle> StyleResolver::styleForElement(
StyleResolverState state(document(), elementContext, defaultParent);
- ElementAnimations* elementAnimations = element->elementAnimations();
const ComputedStyle* baseComputedStyle =
- elementAnimations ? elementAnimations->baseComputedStyle() : nullptr;
+ calculateBaseComputedStyle(state, element);
if (baseComputedStyle) {
state.setStyle(ComputedStyle::clone(*baseComputedStyle));
@@ -764,7 +794,8 @@ PassRefPtr<ComputedStyle> StyleResolver::styleForElement(
if (state.hasDirAutoAttribute())
state.style()->setSelfOrAncestorHasDirAutoAttribute(true);
- applyMatchedProperties(state, collector.matchedResult());
+ applyMatchedPropertiesAndCustomPropertyAnimations(
+ state, collector.matchedResult(), element);
applyCallbackSelectors(state);
// Cache our original display.
@@ -772,8 +803,7 @@ PassRefPtr<ComputedStyle> StyleResolver::styleForElement(
adjustComputedStyle(state, element);
- if (elementAnimations)
- elementAnimations->updateBaseComputedStyle(state.style());
+ updateBaseComputedStyle(state, element);
} else {
INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), baseStylesUsed, 1);
}
@@ -782,7 +812,7 @@ PassRefPtr<ComputedStyle> StyleResolver::styleForElement(
// applied before important rules, but this currently happens here as we
// require adjustment to have happened before deciding which properties to
// transition.
- if (applyAnimatedProperties(state, element)) {
+ if (applyAnimatedStandardProperties(state, element)) {
INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), stylesAnimated, 1);
adjustComputedStyle(state, element);
}
@@ -892,10 +922,8 @@ bool StyleResolver::pseudoStyleForElementInternal(
Element* pseudoElement = element.pseudoElement(pseudoStyleRequest.pseudoId);
- ElementAnimations* elementAnimations =
- pseudoElement ? pseudoElement->elementAnimations() : nullptr;
const ComputedStyle* baseComputedStyle =
- elementAnimations ? elementAnimations->baseComputedStyle() : nullptr;
+ calculateBaseComputedStyle(state, pseudoElement);
if (baseComputedStyle) {
state.setStyle(ComputedStyle::clone(*baseComputedStyle));
@@ -929,7 +957,8 @@ bool StyleResolver::pseudoStyleForElementInternal(
if (!collector.matchedResult().hasMatchedProperties())
return false;
- applyMatchedProperties(state, collector.matchedResult());
+ applyMatchedPropertiesAndCustomPropertyAnimations(
+ state, collector.matchedResult(), pseudoElement);
applyCallbackSelectors(state);
// Cache our original display.
@@ -939,15 +968,14 @@ bool StyleResolver::pseudoStyleForElementInternal(
// in the adjustComputedStyle code.
adjustComputedStyle(state, 0);
- if (elementAnimations)
- elementAnimations->updateBaseComputedStyle(state.style());
+ updateBaseComputedStyle(state, pseudoElement);
}
// FIXME: The CSSWG wants to specify that the effects of animations are
// applied before important rules, but this currently happens here as we
// require adjustment to have happened before deciding which properties to
// transition.
- if (applyAnimatedProperties(state, pseudoElement))
+ if (applyAnimatedStandardProperties(state, pseudoElement))
adjustComputedStyle(state, 0);
document().styleEngine().incStyleForElementCount();
@@ -1105,8 +1133,9 @@ void StyleResolver::collectPseudoRulesForElement(
}
}
-bool StyleResolver::applyAnimatedProperties(StyleResolverState& state,
- const Element* animatingElement) {
+bool StyleResolver::applyAnimatedStandardProperties(
+ StyleResolverState& state,
+ const Element* animatingElement) {
Element* element = state.element();
DCHECK(element);
@@ -1116,13 +1145,17 @@ bool StyleResolver::applyAnimatedProperties(StyleResolverState& state,
DCHECK(animatingElement == element || !animatingElement ||
animatingElement->parentOrShadowHostElement() == element);
- if (!(animatingElement && animatingElement->hasAnimations()) &&
- !state.style()->transitions() && !state.style()->animations())
+ if (state.style()->animations() ||
+ (animatingElement && animatingElement->hasAnimations())) {
+ if (!state.isAnimationInterpolationMapReady())
+ calculateAnimationUpdate(state, animatingElement);
+ } else if (!state.style()->transitions()) {
return false;
+ }
- CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(),
- state.parentStyle(), state.animationUpdate(),
- this);
+ CSSAnimations::calculateCompositorAndTransitionUpdate(
+ animatingElement, *element, *state.style(), state.parentStyle(),
+ state.animationUpdate());
CSSAnimations::snapshotCompositorKeyframes(
*element, state.animationUpdate(), *state.style(), state.parentStyle());
@@ -1590,20 +1623,46 @@ void StyleResolver::notifyResizeForViewportUnits() {
m_matchedPropertiesCache.clearViewportDependent();
}
-void StyleResolver::applyMatchedProperties(StyleResolverState& state,
- const MatchResult& matchResult) {
+void StyleResolver::applyMatchedPropertiesAndCustomPropertyAnimations(
+ StyleResolverState& state,
+ const MatchResult& matchResult,
+ const Element* animatingElement) {
+ CacheSuccess cacheSuccess = applyMatchedCache(state, matchResult);
+ NeedsApplyPass needsApplyPass;
+ if (!cacheSuccess.isFullCacheHit()) {
+ applyCustomProperties(state, matchResult, false, cacheSuccess,
+ needsApplyPass);
+ applyMatchedAnimationProperties(state, matchResult, cacheSuccess,
+ needsApplyPass);
+ }
+ if (state.style()->animations() ||
+ (animatingElement && animatingElement->hasAnimations())) {
+ calculateAnimationUpdate(state, animatingElement);
+ if (state.isAnimatingCustomProperties()) {
+ cacheSuccess.setFailed();
+ applyCustomProperties(state, matchResult, true, cacheSuccess,
+ needsApplyPass);
+ }
+ }
+ if (!cacheSuccess.isFullCacheHit()) {
+ applyMatchedStandardProperties(state, matchResult, cacheSuccess,
+ needsApplyPass);
+ }
+}
+
+StyleResolver::CacheSuccess StyleResolver::applyMatchedCache(
+ StyleResolverState& state,
+ const MatchResult& matchResult) {
const Element* element = state.element();
DCHECK(element);
- INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), matchedPropertyApply,
- 1);
-
unsigned cacheHash =
matchResult.isCacheable()
? computeMatchedPropertiesHash(matchResult.matchedProperties().data(),
matchResult.matchedProperties().size())
: 0;
- bool applyInheritedOnly = false;
+ bool isInheritedCacheHit = false;
+ bool isNonInheritedCacheHit = false;
const CachedMatchedProperties* cachedMatchedProperties =
cacheHash
? m_matchedPropertiesCache.find(cacheHash, state,
@@ -1639,22 +1698,36 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state,
state.style()->setInsideLink(linkStatus);
updateFont(state);
-
- return;
+ isInheritedCacheHit = true;
}
- applyInheritedOnly = true;
+
+ isNonInheritedCacheHit = true;
}
- NeedsApplyPass needsApplyPass;
+ return CacheSuccess(isInheritedCacheHit, isNonInheritedCacheHit, cacheHash,
+ cachedMatchedProperties);
+}
+
+void StyleResolver::applyCustomProperties(StyleResolverState& state,
+ const MatchResult& matchResult,
+ bool applyAnimations,
+ const CacheSuccess& cacheSuccess,
+ NeedsApplyPass& needsApplyPass) {
+ DCHECK(!cacheSuccess.isFullCacheHit());
+ bool applyInheritedOnly = cacheSuccess.shouldApplyInheritedOnly();
- // TODO(leviw): We need the proper bit for tracking whether we need to do this
- // work.
+ // TODO(leviw): We need the proper bit for tracking whether we need to do
+ // this work.
applyMatchedProperties<ResolveVariables, UpdateNeedsApplyPass>(
state, matchResult.authorRules(), false, applyInheritedOnly,
needsApplyPass);
applyMatchedProperties<ResolveVariables, CheckNeedsApplyPass>(
state, matchResult.authorRules(), true, applyInheritedOnly,
needsApplyPass);
+ if (applyAnimations) {
+ applyAnimatedProperties<ResolveVariables>(
+ state, state.animationUpdate().activeInterpolationsForAnimations());
+ }
// TODO(leviw): stop recalculating every time
CSSVariableResolver::resolveVariableDefinitions(state);
@@ -1667,15 +1740,62 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state,
applyMatchedProperties<ResolveVariables, CheckNeedsApplyPass>(
state, matchResult.authorRules(), true, applyInheritedOnly,
needsApplyPass);
+ if (applyAnimations) {
+ applyAnimatedProperties<ResolveVariables>(
+ state, state.animationUpdate().activeInterpolationsForAnimations());
+ }
CSSVariableResolver::resolveVariableDefinitions(state);
}
}
+}
+
+void StyleResolver::applyMatchedAnimationProperties(
+ StyleResolverState& state,
+ const MatchResult& matchResult,
+ const CacheSuccess& cacheSuccess,
+ NeedsApplyPass& needsApplyPass) {
+ DCHECK(!cacheSuccess.isFullCacheHit());
+ bool applyInheritedOnly = cacheSuccess.shouldApplyInheritedOnly();
- // Apply animation affecting properties.
applyMatchedProperties<AnimationPropertyPriority, UpdateNeedsApplyPass>(
state, matchResult.allRules(), false, applyInheritedOnly, needsApplyPass);
applyMatchedProperties<AnimationPropertyPriority, CheckNeedsApplyPass>(
state, matchResult.allRules(), true, applyInheritedOnly, needsApplyPass);
+}
+
+void StyleResolver::calculateAnimationUpdate(StyleResolverState& state,
+ const Element* animatingElement) {
+ DCHECK(state.style()->animations() ||
+ (animatingElement && animatingElement->hasAnimations()));
+ DCHECK(!state.isAnimationInterpolationMapReady());
+
+ CSSAnimations::calculateAnimationUpdate(
+ state.animationUpdate(), animatingElement, *state.element(),
+ *state.style(), state.parentStyle(), this);
+
+ state.setIsAnimationInterpolationMapReady();
+
+ if (state.isAnimatingCustomProperties())
+ return;
+ for (const auto& propertyHandle :
+ state.animationUpdate().activeInterpolationsForAnimations().keys()) {
+ if (CSSAnimations::isCustomPropertyHandle(propertyHandle)) {
+ state.setIsAnimatingCustomProperties(true);
+ return;
+ }
+ }
+}
+
+void StyleResolver::applyMatchedStandardProperties(
+ StyleResolverState& state,
+ const MatchResult& matchResult,
+ const CacheSuccess& cacheSuccess,
+ NeedsApplyPass& needsApplyPass) {
+ INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), matchedPropertyApply,
+ 1);
+
+ DCHECK(!cacheSuccess.isFullCacheHit());
+ bool applyInheritedOnly = cacheSuccess.shouldApplyInheritedOnly();
// Now we have all of the matched rules in the appropriate order. Walk the
// rules and apply high-priority properties first, i.e., those properties that
@@ -1691,7 +1811,7 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state,
applyMatchedProperties<HighPropertyPriority, CheckNeedsApplyPass>(
state, matchResult.uaRules(), true, applyInheritedOnly, needsApplyPass);
- if (UNLIKELY(isSVGForeignObjectElement(element))) {
+ if (UNLIKELY(isSVGForeignObjectElement(state.element()))) {
// LayoutSVGRoot handles zooming for the whole SVG subtree, so foreignObject
// content should not be scaled again.
//
@@ -1705,8 +1825,8 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state,
state.setEffectiveZoom(ComputedStyle::initialZoom());
}
- if (cachedMatchedProperties &&
- cachedMatchedProperties->computedStyle->effectiveZoom() !=
+ if (cacheSuccess.cachedMatchedProperties &&
+ cacheSuccess.cachedMatchedProperties->computedStyle->effectiveZoom() !=
state.style()->effectiveZoom()) {
state.fontBuilder().didChangeEffectiveZoom();
applyInheritedOnly = false;
@@ -1717,9 +1837,9 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state,
// Many properties depend on the font. If it changes we just apply all
// properties.
- if (cachedMatchedProperties &&
- cachedMatchedProperties->computedStyle->getFontDescription() !=
- state.style()->getFontDescription())
+ if (cacheSuccess.cachedMatchedProperties &&
+ cacheSuccess.cachedMatchedProperties->computedStyle
+ ->getFontDescription() != state.style()->getFontDescription())
applyInheritedOnly = false;
// Registered custom properties are computed after high priority properties.
@@ -1756,12 +1876,14 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state,
loadPendingResources(state);
- if (!cachedMatchedProperties && cacheHash &&
+ if (!state.isAnimatingCustomProperties() &&
+ !cacheSuccess.cachedMatchedProperties && cacheSuccess.cacheHash &&
MatchedPropertiesCache::isCacheable(state)) {
INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(),
matchedPropertyCacheAdded, 1);
m_matchedPropertiesCache.add(*state.style(), *state.parentStyle(),
- cacheHash, matchResult.matchedProperties());
+ cacheSuccess.cacheHash,
+ matchResult.matchedProperties());
}
DCHECK(!state.fontBuilder().fontDirty());

Powered by Google App Engine
This is Rietveld 408576698