Commit dbf9ff76 authored by alancutter's avatar alancutter Committed by Commit bot

Make InvalidatableInterpolation's InterpolationTypes decided at effect application time

This patch replaces PropertyInterpolationTypesMapping with CSS and SVG
InterpolationTypesMap classes that are provided to InvalidatableInterpolation
objects via the InterpolationEnvironment.

InvalidatableInterpolations are no longer provided with the list of
InterpolationTypes at construction, now they retrieve the list at effect
application time during applyStack().

This is in preparation for supporting smooth animation of registered
custom properties.

BUG=671904

Committed: https://crrev.com/3ac8b90fcbda4c6e3ef484140751cd0341b31c48
Review-Url: https://codereview.chromium.org/2555923003
Cr-Original-Commit-Position: refs/heads/master@{#437381}
Cr-Commit-Position: refs/heads/master@{#437474}
parent 075d11d7
......@@ -47,6 +47,8 @@ blink_core_sources("animation") {
"CSSImageSliceInterpolationType.h",
"CSSInterpolationType.cpp",
"CSSInterpolationType.h",
"CSSInterpolationTypesMap.cpp",
"CSSInterpolationTypesMap.h",
"CSSLengthInterpolationType.cpp",
"CSSLengthInterpolationType.h",
"CSSLengthListInterpolationType.cpp",
......@@ -119,6 +121,7 @@ blink_core_sources("animation") {
"InterpolationEffect.cpp",
"InterpolationEffect.h",
"InterpolationType.h",
"InterpolationTypesMap.h",
"InterpolationValue.h",
"InvalidatableInterpolation.cpp",
"InvalidatableInterpolation.h",
......@@ -152,8 +155,6 @@ blink_core_sources("animation") {
"PrimitiveInterpolation.h",
"PropertyHandle.cpp",
"PropertyHandle.h",
"PropertyInterpolationTypesMapping.cpp",
"PropertyInterpolationTypesMapping.h",
"SVGAngleInterpolationType.cpp",
"SVGAngleInterpolationType.h",
"SVGIntegerInterpolationType.cpp",
......@@ -162,6 +163,8 @@ blink_core_sources("animation") {
"SVGIntegerOptionalIntegerInterpolationType.h",
"SVGInterpolationType.cpp",
"SVGInterpolationType.h",
"SVGInterpolationTypesMap.cpp",
"SVGInterpolationTypesMap.h",
"SVGLengthInterpolationType.cpp",
"SVGLengthInterpolationType.h",
"SVGLengthListInterpolationType.cpp",
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CSSInterpolationTypesMap_h
#define CSSInterpolationTypesMap_h
#include "core/animation/InterpolationTypesMap.h"
#include "platform/heap/Handle.h"
namespace blink {
class PropertyRegistry;
class CSSInterpolationTypesMap : public InterpolationTypesMap {
public:
CSSInterpolationTypesMap(const PropertyRegistry* registry)
: m_registry(registry) {}
const InterpolationTypes& get(const PropertyHandle&) const final;
size_t version() const final;
private:
Member<const PropertyRegistry> m_registry;
};
} // namespace blink
#endif // CSSInterpolationTypesMap_h
......@@ -5,6 +5,7 @@
#ifndef InterpolationEnvironment_h
#define InterpolationEnvironment_h
#include "core/animation/InterpolationTypesMap.h"
#include "platform/heap/Handle.h"
#include "wtf/Allocator.h"
......@@ -18,15 +19,25 @@ class InterpolationEnvironment {
STACK_ALLOCATED();
public:
explicit InterpolationEnvironment(StyleResolverState& state)
: m_state(&state), m_svgElement(nullptr), m_svgBaseValue(nullptr) {}
explicit InterpolationEnvironment(const InterpolationTypesMap& map,
StyleResolverState& state)
: m_interpolationTypesMap(map),
m_state(&state),
m_svgElement(nullptr),
m_svgBaseValue(nullptr) {}
explicit InterpolationEnvironment(SVGElement& svgElement,
explicit InterpolationEnvironment(const InterpolationTypesMap& map,
SVGElement& svgElement,
const SVGPropertyBase& svgBaseValue)
: m_state(nullptr),
: m_interpolationTypesMap(map),
m_state(nullptr),
m_svgElement(&svgElement),
m_svgBaseValue(&svgBaseValue) {}
const InterpolationTypesMap& interpolationTypesMap() const {
return m_interpolationTypesMap;
}
StyleResolverState& state() {
DCHECK(m_state);
return *m_state;
......@@ -51,6 +62,7 @@ class InterpolationEnvironment {
}
private:
const InterpolationTypesMap& m_interpolationTypesMap;
StyleResolverState* m_state;
Member<SVGElement> m_svgElement;
Member<const SVGPropertyBase> m_svgBaseValue;
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PropertyInterpolationTypesMapping_h
#define PropertyInterpolationTypesMapping_h
#ifndef InterpolationTypesMap_h
#define InterpolationTypesMap_h
#include "wtf/Vector.h"
#include <memory>
......@@ -15,11 +15,14 @@ class PropertyHandle;
using InterpolationTypes = Vector<std::unique_ptr<const InterpolationType>>;
namespace PropertyInterpolationTypesMapping {
class InterpolationTypesMap {
STACK_ALLOCATED();
const InterpolationTypes& get(const PropertyHandle&);
public:
virtual const InterpolationTypes& get(const PropertyHandle&) const = 0;
virtual size_t version() const { return 0; }
};
} // namespace blink
#endif // PropertyInterpolationTypesMapping_h
#endif // InterpolationTypesMap_h
......@@ -32,7 +32,7 @@ InvalidatableInterpolation::maybeConvertPairwise(
const InterpolationEnvironment& environment,
const UnderlyingValueOwner& underlyingValueOwner) const {
DCHECK(m_currentFraction != 0 && m_currentFraction != 1);
for (const auto& interpolationType : m_interpolationTypes) {
for (const auto& interpolationType : *m_interpolationTypes) {
if ((m_startKeyframe->isNeutral() || m_endKeyframe->isNeutral()) &&
(!underlyingValueOwner ||
underlyingValueOwner.type() != *interpolationType))
......@@ -59,7 +59,7 @@ InvalidatableInterpolation::convertSingleKeyframe(
const UnderlyingValueOwner& underlyingValueOwner) const {
if (keyframe.isNeutral() && !underlyingValueOwner)
return nullptr;
for (const auto& interpolationType : m_interpolationTypes) {
for (const auto& interpolationType : *m_interpolationTypes) {
if (keyframe.isNeutral() &&
underlyingValueOwner.type() != *interpolationType)
continue;
......@@ -89,7 +89,7 @@ void InvalidatableInterpolation::addConversionCheckers(
std::unique_ptr<TypedInterpolationValue>
InvalidatableInterpolation::maybeConvertUnderlyingValue(
const InterpolationEnvironment& environment) const {
for (const auto& interpolationType : m_interpolationTypes) {
for (const auto& interpolationType : *m_interpolationTypes) {
InterpolationValue result =
interpolationType->maybeConvertUnderlyingValue(environment);
if (result)
......@@ -144,6 +144,9 @@ InvalidatableInterpolation::ensureValidConversion(
const InterpolationEnvironment& environment,
const UnderlyingValueOwner& underlyingValueOwner) const {
DCHECK(!std::isnan(m_currentFraction));
DCHECK(m_interpolationTypes &&
m_interpolationTypesVersion ==
environment.interpolationTypesMap().version());
if (isConversionCacheValid(environment, underlyingValueOwner))
return m_cachedValue.get();
clearConversionCache();
......@@ -172,6 +175,22 @@ InvalidatableInterpolation::ensureValidConversion(
return m_cachedValue.get();
}
void InvalidatableInterpolation::ensureValidInterpolationTypes(
const InterpolationEnvironment& environment) const {
const InterpolationTypesMap& map = environment.interpolationTypesMap();
size_t latestVersion = map.version();
if (m_interpolationTypes && m_interpolationTypesVersion == latestVersion) {
return;
}
const InterpolationTypes* latestInterpolationTypes = &map.get(m_property);
DCHECK(latestInterpolationTypes);
if (m_interpolationTypes != latestInterpolationTypes) {
clearConversionCache();
}
m_interpolationTypes = latestInterpolationTypes;
m_interpolationTypesVersion = latestVersion;
}
void InvalidatableInterpolation::setFlagIfInheritUsed(
InterpolationEnvironment& environment) const {
if (!m_property.isCSSProperty() && !m_property.isPresentationAttribute())
......@@ -208,6 +227,7 @@ void InvalidatableInterpolation::applyStack(
UnderlyingValueOwner underlyingValueOwner;
const InvalidatableInterpolation& firstInterpolation =
toInvalidatableInterpolation(*interpolations.at(startingIndex));
firstInterpolation.ensureValidInterpolationTypes(environment);
if (firstInterpolation.dependsOnUnderlyingValue()) {
underlyingValueOwner.set(
firstInterpolation.maybeConvertUnderlyingValue(environment));
......@@ -235,6 +255,7 @@ void InvalidatableInterpolation::applyStack(
const InvalidatableInterpolation& currentInterpolation =
toInvalidatableInterpolation(*interpolations.at(i));
DCHECK(currentInterpolation.dependsOnUnderlyingValue());
currentInterpolation.ensureValidInterpolationTypes(environment);
const TypedInterpolationValue* currentValue =
currentInterpolation.ensureValidConversion(environment,
underlyingValueOwner);
......
......@@ -6,8 +6,8 @@
#define InvalidatableInterpolation_h
#include "core/animation/InterpolationType.h"
#include "core/animation/InterpolationTypesMap.h"
#include "core/animation/PrimitiveInterpolation.h"
#include "core/animation/PropertyInterpolationTypesMapping.h"
#include "core/animation/StyleInterpolation.h"
#include "core/animation/TypedInterpolationValue.h"
#include <memory>
......@@ -21,12 +21,10 @@ class CORE_EXPORT InvalidatableInterpolation : public Interpolation {
public:
static PassRefPtr<InvalidatableInterpolation> create(
PropertyHandle property,
const InterpolationTypes& interpolationTypes,
PassRefPtr<PropertySpecificKeyframe> startKeyframe,
PassRefPtr<PropertySpecificKeyframe> endKeyframe) {
return adoptRef(new InvalidatableInterpolation(property, interpolationTypes,
std::move(startKeyframe),
std::move(endKeyframe)));
return adoptRef(new InvalidatableInterpolation(
property, std::move(startKeyframe), std::move(endKeyframe)));
}
PropertyHandle getProperty() const final { return m_property; }
......@@ -40,12 +38,12 @@ class CORE_EXPORT InvalidatableInterpolation : public Interpolation {
private:
InvalidatableInterpolation(PropertyHandle property,
const InterpolationTypes& interpolationTypes,
PassRefPtr<PropertySpecificKeyframe> startKeyframe,
PassRefPtr<PropertySpecificKeyframe> endKeyframe)
: Interpolation(nullptr, nullptr),
m_property(property),
m_interpolationTypes(interpolationTypes),
m_interpolationTypes(nullptr),
m_interpolationTypesVersion(0),
m_startKeyframe(startKeyframe),
m_endKeyframe(endKeyframe),
m_currentFraction(std::numeric_limits<double>::quiet_NaN()),
......@@ -58,6 +56,7 @@ class CORE_EXPORT InvalidatableInterpolation : public Interpolation {
const TypedInterpolationValue* ensureValidConversion(
const InterpolationEnvironment&,
const UnderlyingValueOwner&) const;
void ensureValidInterpolationTypes(const InterpolationEnvironment&) const;
void clearConversionCache() const;
bool isConversionCacheValid(const InterpolationEnvironment&,
const UnderlyingValueOwner&) const;
......@@ -75,7 +74,8 @@ class CORE_EXPORT InvalidatableInterpolation : public Interpolation {
double underlyingFraction() const;
const PropertyHandle m_property;
const InterpolationTypes& m_interpolationTypes;
mutable const InterpolationTypes* m_interpolationTypes;
mutable size_t m_interpolationTypesVersion;
RefPtr<PropertySpecificKeyframe> m_startKeyframe;
RefPtr<PropertySpecificKeyframe> m_endKeyframe;
double m_currentFraction;
......
......@@ -5,7 +5,6 @@
#include "core/animation/Keyframe.h"
#include "core/animation/InvalidatableInterpolation.h"
#include "core/animation/PropertyInterpolationTypesMapping.h"
namespace blink {
......@@ -15,8 +14,7 @@ Keyframe::PropertySpecificKeyframe::createInterpolation(
const Keyframe::PropertySpecificKeyframe& end) const {
// const_cast to take refs.
return InvalidatableInterpolation::create(
propertyHandle, PropertyInterpolationTypesMapping::get(propertyHandle),
const_cast<PropertySpecificKeyframe*>(this),
propertyHandle, const_cast<PropertySpecificKeyframe*>(this),
const_cast<PropertySpecificKeyframe*>(&end));
}
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/animation/SVGInterpolationTypesMap.h"
#include "core/HTMLNames.h"
#include "core/animation/SVGAngleInterpolationType.h"
#include "core/animation/SVGIntegerInterpolationType.h"
#include "core/animation/SVGIntegerOptionalIntegerInterpolationType.h"
#include "core/animation/SVGLengthInterpolationType.h"
#include "core/animation/SVGLengthListInterpolationType.h"
#include "core/animation/SVGNumberInterpolationType.h"
#include "core/animation/SVGNumberListInterpolationType.h"
#include "core/animation/SVGNumberOptionalNumberInterpolationType.h"
#include "core/animation/SVGPathInterpolationType.h"
#include "core/animation/SVGPointListInterpolationType.h"
#include "core/animation/SVGRectInterpolationType.h"
#include "core/animation/SVGTransformListInterpolationType.h"
#include "core/animation/SVGValueInterpolationType.h"
#include "core/css/CSSPropertyMetadata.h"
#include "wtf/PtrUtil.h"
#include <memory>
namespace blink {
const InterpolationTypes& SVGInterpolationTypesMap::get(
const PropertyHandle& property) const {
using ApplicableTypesMap =
HashMap<PropertyHandle, std::unique_ptr<const InterpolationTypes>>;
DEFINE_STATIC_LOCAL(ApplicableTypesMap, applicableTypesMap, ());
auto entry = applicableTypesMap.find(property);
if (entry != applicableTypesMap.end())
return *entry->value.get();
std::unique_ptr<InterpolationTypes> applicableTypes =
WTF::makeUnique<InterpolationTypes>();
const QualifiedName& attribute = property.svgAttribute();
if (attribute == SVGNames::orientAttr) {
applicableTypes->append(
WTF::makeUnique<SVGAngleInterpolationType>(attribute));
} else if (attribute == SVGNames::numOctavesAttr ||
attribute == SVGNames::targetXAttr ||
attribute == SVGNames::targetYAttr) {
applicableTypes->append(
WTF::makeUnique<SVGIntegerInterpolationType>(attribute));
} else if (attribute == SVGNames::orderAttr) {
applicableTypes->append(
WTF::makeUnique<SVGIntegerOptionalIntegerInterpolationType>(attribute));
} else if (attribute == SVGNames::cxAttr || attribute == SVGNames::cyAttr ||
attribute == SVGNames::fxAttr || attribute == SVGNames::fyAttr ||
attribute == SVGNames::heightAttr ||
attribute == SVGNames::markerHeightAttr ||
attribute == SVGNames::markerWidthAttr ||
attribute == SVGNames::rAttr || attribute == SVGNames::refXAttr ||
attribute == SVGNames::refYAttr || attribute == SVGNames::rxAttr ||
attribute == SVGNames::ryAttr ||
attribute == SVGNames::startOffsetAttr ||
attribute == SVGNames::textLengthAttr ||
attribute == SVGNames::widthAttr ||
attribute == SVGNames::x1Attr || attribute == SVGNames::x2Attr ||
attribute == SVGNames::y1Attr || attribute == SVGNames::y2Attr) {
applicableTypes->append(
WTF::makeUnique<SVGLengthInterpolationType>(attribute));
} else if (attribute == SVGNames::dxAttr || attribute == SVGNames::dyAttr) {
applicableTypes->append(
WTF::makeUnique<SVGNumberInterpolationType>(attribute));
applicableTypes->append(
WTF::makeUnique<SVGLengthListInterpolationType>(attribute));
} else if (attribute == SVGNames::xAttr || attribute == SVGNames::yAttr) {
applicableTypes->append(
WTF::makeUnique<SVGLengthInterpolationType>(attribute));
applicableTypes->append(
WTF::makeUnique<SVGLengthListInterpolationType>(attribute));
} else if (attribute == SVGNames::amplitudeAttr ||
attribute == SVGNames::azimuthAttr ||
attribute == SVGNames::biasAttr ||
attribute == SVGNames::diffuseConstantAttr ||
attribute == SVGNames::divisorAttr ||
attribute == SVGNames::elevationAttr ||
attribute == SVGNames::exponentAttr ||
attribute == SVGNames::interceptAttr ||
attribute == SVGNames::k1Attr || attribute == SVGNames::k2Attr ||
attribute == SVGNames::k3Attr || attribute == SVGNames::k4Attr ||
attribute == SVGNames::limitingConeAngleAttr ||
attribute == SVGNames::offsetAttr ||
attribute == SVGNames::pathLengthAttr ||
attribute == SVGNames::pointsAtXAttr ||
attribute == SVGNames::pointsAtYAttr ||
attribute == SVGNames::pointsAtZAttr ||
attribute == SVGNames::scaleAttr ||
attribute == SVGNames::seedAttr ||
attribute == SVGNames::slopeAttr ||
attribute == SVGNames::specularConstantAttr ||
attribute == SVGNames::specularExponentAttr ||
attribute == SVGNames::surfaceScaleAttr ||
attribute == SVGNames::zAttr) {
applicableTypes->append(
WTF::makeUnique<SVGNumberInterpolationType>(attribute));
} else if (attribute == SVGNames::kernelMatrixAttr ||
attribute == SVGNames::rotateAttr ||
attribute == SVGNames::tableValuesAttr ||
attribute == SVGNames::valuesAttr) {
applicableTypes->append(
WTF::makeUnique<SVGNumberListInterpolationType>(attribute));
} else if (attribute == SVGNames::baseFrequencyAttr ||
attribute == SVGNames::kernelUnitLengthAttr ||
attribute == SVGNames::radiusAttr ||
attribute == SVGNames::stdDeviationAttr) {
applicableTypes->append(
WTF::makeUnique<SVGNumberOptionalNumberInterpolationType>(attribute));
} else if (attribute == SVGNames::dAttr) {
applicableTypes->append(
WTF::makeUnique<SVGPathInterpolationType>(attribute));
} else if (attribute == SVGNames::pointsAttr) {
applicableTypes->append(
WTF::makeUnique<SVGPointListInterpolationType>(attribute));
} else if (attribute == SVGNames::viewBoxAttr) {
applicableTypes->append(
WTF::makeUnique<SVGRectInterpolationType>(attribute));
} else if (attribute == SVGNames::gradientTransformAttr ||
attribute == SVGNames::patternTransformAttr ||
attribute == SVGNames::transformAttr) {
applicableTypes->append(
WTF::makeUnique<SVGTransformListInterpolationType>(attribute));
} else if (attribute == HTMLNames::classAttr ||
attribute == SVGNames::clipPathUnitsAttr ||
attribute == SVGNames::edgeModeAttr ||
attribute == SVGNames::filterUnitsAttr ||
attribute == SVGNames::gradientUnitsAttr ||
attribute == SVGNames::hrefAttr || attribute == SVGNames::inAttr ||
attribute == SVGNames::in2Attr ||
attribute == SVGNames::lengthAdjustAttr ||
attribute == SVGNames::markerUnitsAttr ||
attribute == SVGNames::maskContentUnitsAttr ||
attribute == SVGNames::maskUnitsAttr ||
attribute == SVGNames::methodAttr ||
attribute == SVGNames::modeAttr ||
attribute == SVGNames::operatorAttr ||
attribute == SVGNames::patternContentUnitsAttr ||
attribute == SVGNames::patternUnitsAttr ||
attribute == SVGNames::preserveAlphaAttr ||
attribute == SVGNames::preserveAspectRatioAttr ||
attribute == SVGNames::primitiveUnitsAttr ||
attribute == SVGNames::resultAttr ||
attribute == SVGNames::spacingAttr ||
attribute == SVGNames::spreadMethodAttr ||
attribute == SVGNames::stitchTilesAttr ||
attribute == SVGNames::targetAttr ||
attribute == SVGNames::typeAttr ||
attribute == SVGNames::xChannelSelectorAttr ||
attribute == SVGNames::yChannelSelectorAttr) {
// Use default SVGValueInterpolationType.
} else {
NOTREACHED();
}
applicableTypes->append(
WTF::makeUnique<SVGValueInterpolationType>(attribute));
auto addResult = applicableTypesMap.add(property, std::move(applicableTypes));
return *addResult.storedValue->value.get();
}
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SVGInterpolationTypesMap_h
#define SVGInterpolationTypesMap_h
#include "core/animation/InterpolationTypesMap.h"
namespace blink {
class SVGInterpolationTypesMap : public InterpolationTypesMap {
public:
SVGInterpolationTypesMap() {}
const InterpolationTypes& get(const PropertyHandle&) const final;
};
} // namespace blink
#endif // SVGInterpolationTypesMap_h
......@@ -52,6 +52,7 @@ class PropertyRegistry : public GarbageCollected<PropertyRegistry> {
const CSSValue* initial,
PassRefPtr<CSSVariableData> initialVariableData);
const Registration* registration(const AtomicString&) const;
size_t registrationCount() const { return m_registrations.size(); }
DEFINE_INLINE_TRACE() { visitor->trace(m_registrations); }
......
......@@ -35,6 +35,7 @@
#include "core/MediaTypeNames.h"
#include "core/StylePropertyShorthand.h"
#include "core/animation/AnimationTimeline.h"
#include "core/animation/CSSInterpolationTypesMap.h"
#include "core/animation/ElementAnimations.h"
#include "core/animation/InterpolationEnvironment.h"
#include "core/animation/InvalidatableInterpolation.h"
......@@ -1230,7 +1231,8 @@ void StyleResolver::applyAnimatedProperties(
continue;
const Interpolation& interpolation = *entry.value.front();
if (interpolation.isInvalidatableInterpolation()) {
InterpolationEnvironment environment(state);
InterpolationEnvironment environment(
CSSInterpolationTypesMap(state.document().propertyRegistry()), state);
InvalidatableInterpolation::applyStack(entry.value, environment);
} else {
// TODO(alancutter): Remove this old code path once animations have
......
......@@ -33,6 +33,7 @@
#include "core/animation/ElementAnimations.h"
#include "core/animation/InterpolationEnvironment.h"
#include "core/animation/InvalidatableInterpolation.h"
#include "core/animation/SVGInterpolationTypesMap.h"
#include "core/css/CSSCursorImageValue.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Document.h"
......@@ -235,7 +236,8 @@ void SVGElement::applyActiveWebAnimations() {
for (auto& entry : activeInterpolationsMap) {
const QualifiedName& attribute = entry.key.svgAttribute();
InterpolationEnvironment environment(
*this, propertyFromAttribute(attribute)->baseValueBase());
SVGInterpolationTypesMap(), *this,
propertyFromAttribute(attribute)->baseValueBase());
InvalidatableInterpolation::applyStack(entry.value, environment);
}
svgRareData()->setWebAnimatedAttributesDirty(false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment