summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/animation/css
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/core/animation/css
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/animation/css')
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp173
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.h6
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSAnimationData.cpp54
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSAnimationData.h61
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp726
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.h146
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSPendingAnimations.cpp94
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSPendingAnimations.h56
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.cpp318
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.h21
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSTimingData.cpp36
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSTimingData.h50
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSTransitionData.cpp37
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/CSSTransitionData.h81
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/TransitionTimeline.cpp52
-rw-r--r--chromium/third_party/WebKit/Source/core/animation/css/TransitionTimeline.h48
16 files changed, 1193 insertions, 766 deletions
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
index 41138cdd177..b401069725e 100644
--- a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
@@ -31,7 +31,7 @@
#include "config.h"
#include "core/animation/css/CSSAnimatableValueFactory.h"
-#include "CSSValueKeywords.h"
+#include "core/CSSValueKeywords.h"
#include "core/animation/AnimatableClipPathOperation.h"
#include "core/animation/AnimatableColor.h"
#include "core/animation/AnimatableDouble.h"
@@ -41,6 +41,7 @@
#include "core/animation/AnimatableLengthBox.h"
#include "core/animation/AnimatableLengthBoxAndBool.h"
#include "core/animation/AnimatableLengthPoint.h"
+#include "core/animation/AnimatableLengthPoint3D.h"
#include "core/animation/AnimatableLengthSize.h"
#include "core/animation/AnimatableRepeatable.h"
#include "core/animation/AnimatableSVGLength.h"
@@ -61,23 +62,13 @@
namespace WebCore {
-static PassRefPtr<AnimatableValue> createFromLength(const Length& length, const RenderStyle& style)
+static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLength(const Length& length, const RenderStyle& style)
{
switch (length.type()) {
case Fixed:
- return AnimatableLength::create(adjustFloatForAbsoluteZoom(length.value(), style), AnimatableLength::UnitTypePixels);
case Percent:
- return AnimatableLength::create(length.value(), AnimatableLength::UnitTypePercentage);
- case ViewportPercentageWidth:
- return AnimatableLength::create(length.value(), AnimatableLength::UnitTypeViewportWidth);
- case ViewportPercentageHeight:
- return AnimatableLength::create(length.value(), AnimatableLength::UnitTypeViewportHeight);
- case ViewportPercentageMin:
- return AnimatableLength::create(length.value(), AnimatableLength::UnitTypeViewportMin);
- case ViewportPercentageMax:
- return AnimatableLength::create(length.value(), AnimatableLength::UnitTypeViewportMax);
case Calculated:
- return AnimatableLength::create(CSSCalcValue::createExpressionNode(length.calculationValue()->expression(), style.effectiveZoom()));
+ return AnimatableLength::create(length, style.effectiveZoom());
case Auto:
case Intrinsic:
case MinIntrinsic:
@@ -85,18 +76,20 @@ static PassRefPtr<AnimatableValue> createFromLength(const Length& length, const
case MaxContent:
case FillAvailable:
case FitContent:
- return AnimatableUnknown::create(CSSPrimitiveValue::create(length));
+ return AnimatableUnknown::create(CSSPrimitiveValue::create(length, 1));
case Undefined:
return AnimatableUnknown::create(CSSValueNone);
case ExtendToZoom: // Does not apply to elements.
+ case DeviceWidth:
+ case DeviceHeight:
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
-static PassRefPtr<AnimatableValue> createFromLineHeight(const Length& length, const RenderStyle& style)
+static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLineHeight(const Length& length, const RenderStyle& style)
{
if (length.type() == Percent) {
double value = length.value();
@@ -108,12 +101,12 @@ static PassRefPtr<AnimatableValue> createFromLineHeight(const Length& length, co
return createFromLength(length, style);
}
-inline static PassRefPtr<AnimatableValue> createFromDouble(double value, AnimatableDouble::Constraint constraint = AnimatableDouble::Unconstrained)
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromDouble(double value, AnimatableDouble::Constraint constraint = AnimatableDouble::Unconstrained)
{
return AnimatableDouble::create(value, constraint);
}
-inline static PassRefPtr<AnimatableValue> createFromLengthBox(const LengthBox& lengthBox, const RenderStyle& style)
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLengthBox(const LengthBox& lengthBox, const RenderStyle& style)
{
return AnimatableLengthBox::create(
createFromLength(lengthBox.left(), style),
@@ -122,14 +115,14 @@ inline static PassRefPtr<AnimatableValue> createFromLengthBox(const LengthBox& l
createFromLength(lengthBox.bottom(), style));
}
-static PassRefPtr<AnimatableValue> createFromBorderImageLength(const BorderImageLength& borderImageLength, const RenderStyle& style)
+static PassRefPtrWillBeRawPtr<AnimatableValue> createFromBorderImageLength(const BorderImageLength& borderImageLength, const RenderStyle& style)
{
if (borderImageLength.isNumber())
return createFromDouble(borderImageLength.number());
return createFromLength(borderImageLength.length(), style);
}
-inline static PassRefPtr<AnimatableValue> createFromBorderImageLengthBox(const BorderImageLengthBox& borderImageLengthBox, const RenderStyle& style)
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromBorderImageLengthBox(const BorderImageLengthBox& borderImageLengthBox, const RenderStyle& style)
{
return AnimatableLengthBox::create(
createFromBorderImageLength(borderImageLengthBox.left(), style),
@@ -138,35 +131,37 @@ inline static PassRefPtr<AnimatableValue> createFromBorderImageLengthBox(const B
createFromBorderImageLength(borderImageLengthBox.bottom(), style));
}
-inline static PassRefPtr<AnimatableValue> createFromLengthBoxAndBool(const LengthBox lengthBox, const bool flag, const RenderStyle& style)
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLengthBoxAndBool(const LengthBox lengthBox, const bool flag, const RenderStyle& style)
{
return AnimatableLengthBoxAndBool::create(
createFromLengthBox(lengthBox, style),
flag);
}
-inline static PassRefPtr<AnimatableValue> createFromLengthPoint(const LengthPoint& lengthPoint, const RenderStyle& style)
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLengthPoint(const LengthPoint& lengthPoint, const RenderStyle& style)
{
return AnimatableLengthPoint::create(
createFromLength(lengthPoint.x(), style),
createFromLength(lengthPoint.y(), style));
}
-inline static PassRefPtr<AnimatableValue> createFromLengthSize(const LengthSize& lengthSize, const RenderStyle& style)
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromLengthSize(const LengthSize& lengthSize, const RenderStyle& style)
{
return AnimatableLengthSize::create(
createFromLength(lengthSize.width(), style),
createFromLength(lengthSize.height(), style));
}
-inline static PassRefPtr<AnimatableValue> createFromStyleImage(StyleImage* image)
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromStyleImage(StyleImage* image)
{
- if (image)
- return AnimatableImage::create(image);
+ if (image) {
+ if (RefPtrWillBeRawPtr<CSSValue> cssValue = image->cssValue())
+ return AnimatableImage::create(cssValue.release());
+ }
return AnimatableUnknown::create(CSSValueNone);
}
-inline static PassRefPtr<AnimatableValue> createFromFillSize(const FillSize& fillSize, const RenderStyle& style)
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromFillSize(const FillSize& fillSize, const RenderStyle& style)
{
switch (fillSize.type) {
case SizeLength:
@@ -177,15 +172,22 @@ inline static PassRefPtr<AnimatableValue> createFromFillSize(const FillSize& fil
return AnimatableUnknown::create(CSSPrimitiveValue::create(fillSize.type));
default:
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
}
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromBackgroundPosition(const Length& length, bool originIsSet, BackgroundEdgeOrigin origin, const RenderStyle& style)
+{
+ if (!originIsSet || origin == LeftEdge || origin == TopEdge)
+ return createFromLength(length, style);
+ return createFromLength(length.subtractFromOneHundredPercent(), style);
+}
+
template<CSSPropertyID property>
-inline static PassRefPtr<AnimatableValue> createFromFillLayers(const FillLayer* fillLayer, const RenderStyle& style)
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromFillLayers(const FillLayer* fillLayer, const RenderStyle& style)
{
ASSERT(fillLayer);
- Vector<RefPtr<AnimatableValue> > values;
+ WillBeHeapVector<RefPtrWillBeMember<AnimatableValue> > values;
while (fillLayer) {
if (property == CSSPropertyBackgroundImage || property == CSSPropertyWebkitMaskImage) {
if (!fillLayer->isImageSet())
@@ -194,11 +196,11 @@ inline static PassRefPtr<AnimatableValue> createFromFillLayers(const FillLayer*
} else if (property == CSSPropertyBackgroundPositionX || property == CSSPropertyWebkitMaskPositionX) {
if (!fillLayer->isXPositionSet())
break;
- values.append(createFromLength(fillLayer->xPosition(), style));
+ values.append(createFromBackgroundPosition(fillLayer->xPosition(), fillLayer->isBackgroundXOriginSet(), fillLayer->backgroundXOrigin(), style));
} else if (property == CSSPropertyBackgroundPositionY || property == CSSPropertyWebkitMaskPositionY) {
if (!fillLayer->isYPositionSet())
break;
- values.append(createFromLength(fillLayer->yPosition(), style));
+ values.append(createFromBackgroundPosition(fillLayer->yPosition(), fillLayer->isBackgroundYOriginSet(), fillLayer->backgroundYOrigin(), style));
} else if (property == CSSPropertyBackgroundSize || property == CSSPropertyWebkitMaskSize) {
if (!fillLayer->isSizeSet())
break;
@@ -211,42 +213,56 @@ inline static PassRefPtr<AnimatableValue> createFromFillLayers(const FillLayer*
return AnimatableRepeatable::create(values);
}
-PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::createFromColor(CSSPropertyID property, const RenderStyle& style)
+PassRefPtrWillBeRawPtr<AnimatableValue> CSSAnimatableValueFactory::createFromColor(CSSPropertyID property, const RenderStyle& style)
{
Color color = style.colorIncludingFallback(property, false);
Color visitedLinkColor = style.colorIncludingFallback(property, true);
- Color fallbackColor = style.color();
- Color fallbackVisitedLinkColor = style.visitedLinkColor();
- Color resolvedColor;
+ return AnimatableColor::create(color, visitedLinkColor);
+}
+
+inline static PassRefPtrWillBeRawPtr<AnimatableValue> createFromShapeValue(ShapeValue* value)
+{
+ if (value)
+ return AnimatableShapeValue::create(value);
+ return AnimatableUnknown::create(CSSValueNone);
+}
- if (property == CSSPropertyBackgroundColor) {
- // For background-color, invalid color means transparent and not currentColor.
- fallbackColor = Color::transparent;
- fallbackVisitedLinkColor = Color::transparent;
+static double fontWeightToDouble(FontWeight fontWeight)
+{
+ switch (fontWeight) {
+ case FontWeight100:
+ return 100;
+ case FontWeight200:
+ return 200;
+ case FontWeight300:
+ return 300;
+ case FontWeight400:
+ return 400;
+ case FontWeight500:
+ return 500;
+ case FontWeight600:
+ return 600;
+ case FontWeight700:
+ return 700;
+ case FontWeight800:
+ return 800;
+ case FontWeight900:
+ return 900;
}
- if (color.isValid())
- resolvedColor = color;
- else
- resolvedColor = fallbackColor;
- Color resolvedVisitedLinkColor;
- if (visitedLinkColor.isValid())
- resolvedVisitedLinkColor = visitedLinkColor;
- else
- resolvedVisitedLinkColor = fallbackVisitedLinkColor;
- return AnimatableColor::create(resolvedColor, resolvedVisitedLinkColor);
+ ASSERT_NOT_REACHED();
+ return 400;
}
-inline static PassRefPtr<AnimatableValue> createFromShapeValue(ShapeValue* value)
+static PassRefPtrWillBeRawPtr<AnimatableValue> createFromFontWeight(FontWeight fontWeight)
{
- if (value)
- return AnimatableShapeValue::create(value);
- return AnimatableUnknown::create(CSSValueAuto);
+ return createFromDouble(fontWeightToDouble(fontWeight));
}
// FIXME: Generate this function.
-PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID property, const RenderStyle& style)
+PassRefPtrWillBeRawPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID property, const RenderStyle& style)
{
+ ASSERT(CSSAnimations::isAnimatableProperty(property));
switch (property) {
case CSSPropertyBackgroundColor:
return createFromColor(property, style);
@@ -307,7 +323,10 @@ PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID prop
case CSSPropertyFillOpacity:
return createFromDouble(style.fillOpacity());
case CSSPropertyFill:
- return AnimatableSVGPaint::create(style.svgStyle()->fillPaintType(), style.svgStyle()->fillPaintColor(), style.svgStyle()->fillPaintUri());
+ return AnimatableSVGPaint::create(
+ style.svgStyle()->fillPaintType(), style.svgStyle()->visitedLinkFillPaintType(),
+ style.svgStyle()->fillPaintColor(), style.svgStyle()->visitedLinkFillPaintColor(),
+ style.svgStyle()->fillPaintUri(), style.svgStyle()->visitedLinkFillPaintUri());
case CSSPropertyFlexGrow:
return createFromDouble(style.flexGrow(), AnimatableDouble::InterpolationIsNonContinuousWithZero);
case CSSPropertyFlexShrink:
@@ -324,10 +343,10 @@ PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID prop
// FIXME: Should we introduce an option to pass the computed font size here, allowing consumers to
// enable text zoom rather than Text Autosizing? See http://crbug.com/227545.
return createFromDouble(style.specifiedFontSize());
+ case CSSPropertyFontWeight:
+ return createFromFontWeight(style.fontWeight());
case CSSPropertyHeight:
return createFromLength(style.height(), style);
- case CSSPropertyKerning:
- return AnimatableSVGLength::create(style.kerning());
case CSSPropertyLightingColor:
return createFromColor(property, style);
case CSSPropertyListStyleImage:
@@ -391,9 +410,12 @@ PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID prop
case CSSPropertyStrokeOpacity:
return createFromDouble(style.strokeOpacity());
case CSSPropertyStroke:
- return AnimatableSVGPaint::create(style.svgStyle()->strokePaintType(), style.svgStyle()->strokePaintColor(), style.svgStyle()->strokePaintUri());
+ return AnimatableSVGPaint::create(
+ style.svgStyle()->strokePaintType(), style.svgStyle()->visitedLinkStrokePaintType(),
+ style.svgStyle()->strokePaintColor(), style.svgStyle()->visitedLinkStrokePaintColor(),
+ style.svgStyle()->strokePaintUri(), style.svgStyle()->visitedLinkStrokePaintUri());
case CSSPropertyTextDecorationColor:
- return createFromColor(property, style);
+ return AnimatableColor::create(style.textDecorationColor().resolve(style.color()), style.visitedLinkTextDecorationColor().resolve(style.visitedLinkColor()));
case CSSPropertyTextIndent:
return createFromLength(style.textIndent(), style);
case CSSPropertyTextShadow:
@@ -436,14 +458,19 @@ PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID prop
return createFromFillLayers<CSSPropertyWebkitMaskPositionY>(style.maskLayers(), style);
case CSSPropertyWebkitMaskSize:
return createFromFillLayers<CSSPropertyWebkitMaskSize>(style.maskLayers(), style);
- case CSSPropertyWebkitPerspective:
+ case CSSPropertyPerspective:
return createFromDouble(style.perspective());
+ case CSSPropertyPerspectiveOrigin:
+ ASSERT(RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
+ return AnimatableLengthPoint::create(
+ createFromLength(style.perspectiveOriginX(), style),
+ createFromLength(style.perspectiveOriginY(), style));
case CSSPropertyWebkitPerspectiveOriginX:
+ ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
return createFromLength(style.perspectiveOriginX(), style);
case CSSPropertyWebkitPerspectiveOriginY:
+ ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
return createFromLength(style.perspectiveOriginY(), style);
- case CSSPropertyShapeInside:
- return createFromShapeValue(style.shapeInside());
case CSSPropertyShapeOutside:
return createFromShapeValue(style.shapeOutside());
case CSSPropertyShapeMargin:
@@ -452,13 +479,22 @@ PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID prop
return createFromDouble(style.shapeImageThreshold());
case CSSPropertyWebkitTextStrokeColor:
return createFromColor(property, style);
- case CSSPropertyWebkitTransform:
+ case CSSPropertyTransform:
return AnimatableTransform::create(style.transform());
+ case CSSPropertyTransformOrigin:
+ ASSERT(RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
+ return AnimatableLengthPoint3D::create(
+ createFromLength(style.transformOriginX(), style),
+ createFromLength(style.transformOriginY(), style),
+ createFromDouble(style.transformOriginZ()));
case CSSPropertyWebkitTransformOriginX:
+ ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
return createFromLength(style.transformOriginX(), style);
case CSSPropertyWebkitTransformOriginY:
+ ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
return createFromLength(style.transformOriginY(), style);
case CSSPropertyWebkitTransformOriginZ:
+ ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled());
return createFromDouble(style.transformOriginZ());
case CSSPropertyWidows:
return createFromDouble(style.widows());
@@ -466,6 +502,10 @@ PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID prop
return createFromLength(style.width(), style);
case CSSPropertyWordSpacing:
return createFromDouble(style.wordSpacing());
+ case CSSPropertyVerticalAlign:
+ if (style.verticalAlign() == LENGTH)
+ return createFromLength(style.verticalAlignLength(), style);
+ return AnimatableUnknown::create(CSSPrimitiveValue::create(style.verticalAlign()));
case CSSPropertyVisibility:
return AnimatableVisibility::create(style.visibility());
case CSSPropertyZIndex:
@@ -473,10 +513,9 @@ PassRefPtr<AnimatableValue> CSSAnimatableValueFactory::create(CSSPropertyID prop
case CSSPropertyZoom:
return createFromDouble(style.zoom());
default:
- ASSERT_WITH_MESSAGE(!CSSAnimations::isAnimatableProperty(property), "Web Animations not yet implemented: Create AnimatableValue from render style: %s", getPropertyNameString(property).utf8().data());
ASSERT_NOT_REACHED();
// This return value is to avoid a release crash if possible.
- return AnimatableUnknown::create(0);
+ return AnimatableUnknown::create(nullptr);
}
}
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.h b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.h
index bac18c19241..7e6ea3dc03d 100644
--- a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.h
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.h
@@ -31,7 +31,7 @@
#ifndef CSSAnimatableValueFactory_h
#define CSSAnimatableValueFactory_h
-#include "CSSPropertyNames.h"
+#include "core/CSSPropertyNames.h"
#include "core/animation/AnimatableValue.h"
#include "wtf/PassRefPtr.h"
@@ -41,9 +41,9 @@ class RenderStyle;
class CSSAnimatableValueFactory {
public:
- static PassRefPtr<AnimatableValue> create(CSSPropertyID, const RenderStyle&);
+ static PassRefPtrWillBeRawPtr<AnimatableValue> create(CSSPropertyID, const RenderStyle&);
private:
- static PassRefPtr<AnimatableValue> createFromColor(CSSPropertyID, const RenderStyle&);
+ static PassRefPtrWillBeRawPtr<AnimatableValue> createFromColor(CSSPropertyID, const RenderStyle&);
};
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimationData.cpp b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimationData.cpp
new file mode 100644
index 00000000000..bda53a4f535
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimationData.cpp
@@ -0,0 +1,54 @@
+// Copyright 2014 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 "config.h"
+#include "core/animation/css/CSSAnimationData.h"
+
+#include "core/animation/Timing.h"
+
+namespace WebCore {
+
+CSSAnimationData::CSSAnimationData()
+{
+ m_nameList.append(initialName());
+ m_iterationCountList.append(initialIterationCount());
+ m_directionList.append(initialDirection());
+ m_fillModeList.append(initialFillMode());
+ m_playStateList.append(initialPlayState());
+}
+
+CSSAnimationData::CSSAnimationData(const CSSAnimationData& other)
+ : CSSTimingData(other)
+ , m_nameList(other.m_nameList)
+ , m_iterationCountList(other.m_iterationCountList)
+ , m_directionList(other.m_directionList)
+ , m_fillModeList(other.m_fillModeList)
+ , m_playStateList(other.m_playStateList)
+{
+}
+
+const AtomicString& CSSAnimationData::initialName()
+{
+ DEFINE_STATIC_LOCAL(const AtomicString, name, ("none", AtomicString::ConstructFromLiteral));
+ return name;
+}
+
+bool CSSAnimationData::animationsMatchForStyleRecalc(const CSSAnimationData& other) const
+{
+ return m_nameList == other.m_nameList && m_playStateList == other.m_playStateList;
+}
+
+Timing CSSAnimationData::convertToTiming(size_t index) const
+{
+ ASSERT(index < m_nameList.size());
+ Timing timing = CSSTimingData::convertToTiming(index);
+
+ timing.iterationCount = getRepeated(m_iterationCountList, index);
+ timing.direction = getRepeated(m_directionList, index);
+ timing.fillMode = getRepeated(m_fillModeList, index);
+ timing.assertValid();
+ return timing;
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimationData.h b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimationData.h
new file mode 100644
index 00000000000..5a23feedcc4
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimationData.h
@@ -0,0 +1,61 @@
+// Copyright 2014 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 CSSAnimationData_h
+#define CSSAnimationData_h
+
+#include "core/animation/Timing.h"
+#include "core/animation/css/CSSTimingData.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+
+namespace WebCore {
+
+class CSSAnimationData FINAL : public CSSTimingData {
+public:
+ static PassOwnPtrWillBeRawPtr<CSSAnimationData> create()
+ {
+ return adoptPtrWillBeNoop(new CSSAnimationData);
+ }
+
+ static PassOwnPtrWillBeRawPtr<CSSAnimationData> create(const CSSAnimationData& animationData)
+ {
+ return adoptPtrWillBeNoop(new CSSAnimationData(animationData));
+ }
+
+ bool animationsMatchForStyleRecalc(const CSSAnimationData& other) const;
+
+ Timing convertToTiming(size_t index) const;
+
+ const Vector<AtomicString>& nameList() const { return m_nameList; }
+ const Vector<double>& iterationCountList() const { return m_iterationCountList; }
+ const Vector<Timing::PlaybackDirection>& directionList() const { return m_directionList; }
+ const Vector<Timing::FillMode>& fillModeList() const { return m_fillModeList; }
+ const Vector<EAnimPlayState>& playStateList() const { return m_playStateList; }
+
+ Vector<AtomicString>& nameList() { return m_nameList; }
+ Vector<double>& iterationCountList() { return m_iterationCountList; }
+ Vector<Timing::PlaybackDirection>& directionList() { return m_directionList; }
+ Vector<Timing::FillMode>& fillModeList() { return m_fillModeList; }
+ Vector<EAnimPlayState>& playStateList() { return m_playStateList; }
+
+ static const AtomicString& initialName();
+ static Timing::PlaybackDirection initialDirection() { return Timing::PlaybackDirectionNormal; }
+ static Timing::FillMode initialFillMode() { return Timing::FillModeNone; }
+ static double initialIterationCount() { return 1.0; }
+ static EAnimPlayState initialPlayState() { return AnimPlayStatePlaying; }
+
+private:
+ CSSAnimationData();
+ explicit CSSAnimationData(const CSSAnimationData&);
+
+ Vector<AtomicString> m_nameList;
+ Vector<double> m_iterationCountList;
+ Vector<Timing::PlaybackDirection> m_directionList;
+ Vector<Timing::FillMode> m_fillModeList;
+ Vector<EAnimPlayState> m_playStateList;
+};
+
+} // namespace WebCore
+
+#endif // CSSAnimationData_h
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
index 807c59096b5..05e358ec619 100644
--- a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
@@ -31,25 +31,26 @@
#include "config.h"
#include "core/animation/css/CSSAnimations.h"
-#include "StylePropertyShorthand.h"
+#include "core/StylePropertyShorthand.h"
#include "core/animation/ActiveAnimations.h"
+#include "core/animation/AnimationTimeline.h"
#include "core/animation/CompositorAnimations.h"
-#include "core/animation/DocumentTimeline.h"
-#include "core/animation/KeyframeAnimationEffect.h"
+#include "core/animation/KeyframeEffectModel.h"
#include "core/animation/css/CSSAnimatableValueFactory.h"
+#include "core/animation/css/CSSPropertyEquality.h"
+#include "core/animation/interpolation/LegacyStyleInterpolation.h"
#include "core/css/CSSKeyframeRule.h"
+#include "core/css/resolver/CSSToStyleMap.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Element.h"
#include "core/dom/PseudoElement.h"
-#include "core/events/ThreadLocalEventNames.h"
#include "core/events/TransitionEvent.h"
#include "core/events/WebKitAnimationEvent.h"
#include "core/frame/UseCounter.h"
-#include "core/frame/animation/CSSPropertyAnimation.h"
-#include "core/platform/animation/CSSAnimationDataList.h"
-#include "core/platform/animation/TimingFunction.h"
+#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/style/KeyframeList.h"
+#include "platform/animation/TimingFunction.h"
#include "public/platform/Platform.h"
#include "wtf/BitArray.h"
#include "wtf/HashSet.h"
@@ -58,90 +59,81 @@ namespace WebCore {
namespace {
-bool isEarlierPhase(TimedItem::Phase target, TimedItem::Phase reference)
+CSSPropertyID propertyForAnimation(CSSPropertyID property)
{
- ASSERT(target != TimedItem::PhaseNone);
- ASSERT(reference != TimedItem::PhaseNone);
- return target < reference;
-}
-
-bool isLaterPhase(TimedItem::Phase target, TimedItem::Phase reference)
-{
- ASSERT(target != TimedItem::PhaseNone);
- ASSERT(reference != TimedItem::PhaseNone);
- return target > reference;
-}
-
-static PassRefPtr<TimingFunction> generateTimingFunction(const KeyframeAnimationEffect::KeyframeVector keyframes, const HashMap<double, RefPtr<TimingFunction> > perKeyframeTimingFunctions)
-{
- // Generate the chained timing function. Note that timing functions apply
- // from the keyframe in which they're specified to the next keyframe.
- bool isTimingFunctionLinearThroughout = true;
- RefPtr<ChainedTimingFunction> chainedTimingFunction = ChainedTimingFunction::create();
- for (size_t i = 0; i < keyframes.size() - 1; ++i) {
- double lowerBound = keyframes[i]->offset();
- ASSERT(lowerBound >=0 && lowerBound < 1);
- double upperBound = keyframes[i + 1]->offset();
- ASSERT(upperBound > 0 && upperBound <= 1);
- TimingFunction* timingFunction = perKeyframeTimingFunctions.get(lowerBound);
- isTimingFunctionLinearThroughout &= timingFunction->type() == TimingFunction::LinearFunction;
- chainedTimingFunction->appendSegment(upperBound, timingFunction);
- }
- if (isTimingFunctionLinearThroughout)
- return LinearTimingFunction::create();
- return chainedTimingFunction;
+ switch (property) {
+ case CSSPropertyWebkitPerspective:
+ return CSSPropertyPerspective;
+ case CSSPropertyWebkitTransform:
+ return CSSPropertyTransform;
+ case CSSPropertyWebkitPerspectiveOriginX:
+ case CSSPropertyWebkitPerspectiveOriginY:
+ if (RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled())
+ return CSSPropertyPerspectiveOrigin;
+ break;
+ case CSSPropertyWebkitTransformOriginX:
+ case CSSPropertyWebkitTransformOriginY:
+ case CSSPropertyWebkitTransformOriginZ:
+ if (RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled())
+ return CSSPropertyTransformOrigin;
+ break;
+ default:
+ break;
+ }
+ return property;
}
static void resolveKeyframes(StyleResolver* resolver, Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, const AtomicString& name, TimingFunction* defaultTimingFunction,
- Vector<std::pair<KeyframeAnimationEffect::KeyframeVector, RefPtr<TimingFunction> > >& keyframesAndTimingFunctions)
+ AnimatableValueKeyframeVector& keyframes)
{
- ASSERT(RuntimeEnabledFeatures::webAnimationsCSSEnabled());
// When the element is null, use its parent for scoping purposes.
const Element* elementForScoping = element ? element : &parentElement;
const StyleRuleKeyframes* keyframesRule = CSSAnimations::matchScopedKeyframesRule(resolver, elementForScoping, name.impl());
if (!keyframesRule)
return;
- const Vector<RefPtr<StyleKeyframe> >& styleKeyframes = keyframesRule->keyframes();
+ const WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >& styleKeyframes = keyframesRule->keyframes();
if (styleKeyframes.isEmpty())
return;
// Construct and populate the style for each keyframe
- PropertySet specifiedProperties;
- KeyframeAnimationEffect::KeyframeVector keyframes;
- HashMap<double, RefPtr<TimingFunction> > perKeyframeTimingFunctions;
+ PropertySet specifiedPropertiesForUseCounter;
for (size_t i = 0; i < styleKeyframes.size(); ++i) {
const StyleKeyframe* styleKeyframe = styleKeyframes[i].get();
// It's OK to pass a null element here.
RefPtr<RenderStyle> keyframeStyle = resolver->styleForKeyframe(element, style, parentStyle, styleKeyframe, name);
- RefPtr<Keyframe> keyframe = Keyframe::create();
+ RefPtrWillBeRawPtr<AnimatableValueKeyframe> keyframe = AnimatableValueKeyframe::create();
const Vector<double>& offsets = styleKeyframe->keys();
ASSERT(!offsets.isEmpty());
keyframe->setOffset(offsets[0]);
- TimingFunction* timingFunction = defaultTimingFunction;
- const StylePropertySet* properties = styleKeyframe->properties();
- for (unsigned j = 0; j < properties->propertyCount(); j++) {
- CSSPropertyID property = properties->propertyAt(j).id();
- specifiedProperties.add(property);
- if (property == CSSPropertyWebkitAnimationTimingFunction || property == CSSPropertyAnimationTimingFunction)
- timingFunction = KeyframeValue::timingFunction(*keyframeStyle);
- else if (CSSAnimations::isAnimatableProperty(property))
+ keyframe->setEasing(defaultTimingFunction);
+ const StylePropertySet& properties = styleKeyframe->properties();
+ for (unsigned j = 0; j < properties.propertyCount(); j++) {
+ specifiedPropertiesForUseCounter.add(properties.propertyAt(j).id());
+ CSSPropertyID property = propertyForAnimation(properties.propertyAt(j).id());
+ if (property == CSSPropertyWebkitAnimationTimingFunction || property == CSSPropertyAnimationTimingFunction) {
+ CSSValue* value = properties.propertyAt(j).value();
+ RefPtr<TimingFunction> timingFunction;
+ if (value->isInheritedValue() && parentStyle->animations())
+ timingFunction = parentStyle->animations()->timingFunctionList()[0];
+ else if (value->isInheritedValue() || value->isInitialValue())
+ timingFunction = CSSTimingData::initialTimingFunction();
+ else
+ timingFunction = CSSToStyleMap::mapAnimationTimingFunction(toCSSValueList(value)->item(0));
+ keyframe->setEasing(timingFunction.release());
+ } else if (CSSAnimations::isAnimatableProperty(property)) {
keyframe->setPropertyValue(property, CSSAnimatableValueFactory::create(property, *keyframeStyle).get());
+ }
}
keyframes.append(keyframe);
// The last keyframe specified at a given offset is used.
- perKeyframeTimingFunctions.set(offsets[0], timingFunction);
for (size_t j = 1; j < offsets.size(); ++j) {
- keyframes.append(keyframe->cloneWithOffset(offsets[j]));
- perKeyframeTimingFunctions.set(offsets[j], timingFunction);
+ keyframes.append(toAnimatableValueKeyframe(keyframe->cloneWithOffset(offsets[j]).get()));
}
}
ASSERT(!keyframes.isEmpty());
- if (!perKeyframeTimingFunctions.contains(0))
- perKeyframeTimingFunctions.set(0, defaultTimingFunction);
-
- for (PropertySet::const_iterator iter = specifiedProperties.begin(); iter != specifiedProperties.end(); ++iter) {
+ for (PropertySet::const_iterator iter = specifiedPropertiesForUseCounter.begin(); iter != specifiedPropertiesForUseCounter.end(); ++iter) {
const CSSPropertyID property = *iter;
ASSERT(property != CSSPropertyInvalid);
blink::Platform::current()->histogramSparse("WebCore.Animation.CSSProperties", UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(property));
@@ -159,16 +151,18 @@ static void resolveKeyframes(StyleResolver* resolver, Element* element, const El
keyframes.shrink(targetIndex + 1);
// Add 0% and 100% keyframes if absent.
- RefPtr<Keyframe> startKeyframe = keyframes[0];
+ RefPtrWillBeRawPtr<AnimatableValueKeyframe> startKeyframe = keyframes[0];
if (startKeyframe->offset()) {
- startKeyframe = Keyframe::create();
+ startKeyframe = AnimatableValueKeyframe::create();
startKeyframe->setOffset(0);
+ startKeyframe->setEasing(defaultTimingFunction);
keyframes.prepend(startKeyframe);
}
- RefPtr<Keyframe> endKeyframe = keyframes[keyframes.size() - 1];
+ RefPtrWillBeRawPtr<AnimatableValueKeyframe> endKeyframe = keyframes[keyframes.size() - 1];
if (endKeyframe->offset() != 1) {
- endKeyframe = Keyframe::create();
+ endKeyframe = AnimatableValueKeyframe::create();
endKeyframe->setOffset(1);
+ endKeyframe->setEasing(defaultTimingFunction);
keyframes.append(endKeyframe);
}
ASSERT(keyframes.size() >= 2);
@@ -194,7 +188,7 @@ static void resolveKeyframes(StyleResolver* resolver, Element* element, const El
bool endNeedsValue = missingEndValues && !endKeyframeProperties.contains(property);
if (!startNeedsValue && !endNeedsValue)
continue;
- RefPtr<AnimatableValue> snapshotValue = CSSAnimatableValueFactory::create(property, style);
+ RefPtrWillBeRawPtr<AnimatableValue> snapshotValue = CSSAnimatableValueFactory::create(property, style);
if (startNeedsValue)
startKeyframe->setPropertyValue(property, snapshotValue.get());
if (endNeedsValue)
@@ -203,129 +197,6 @@ static void resolveKeyframes(StyleResolver* resolver, Element* element, const El
}
ASSERT(startKeyframe->properties().size() == allProperties.size());
ASSERT(endKeyframe->properties().size() == allProperties.size());
-
- // Determine how many keyframes specify each property. Note that this must
- // be done after we've filled in end keyframes.
- typedef HashCountedSet<CSSPropertyID> PropertyCountedSet;
- PropertyCountedSet propertyCounts;
- for (size_t i = 0; i < numKeyframes; ++i) {
- const PropertySet& properties = keyframes[i]->properties();
- for (PropertySet::const_iterator iter = properties.begin(); iter != properties.end(); ++iter)
- propertyCounts.add(*iter);
- }
-
- // Split keyframes into groups, where each group contains only keyframes
- // which specify all properties used in that group. Each group is animated
- // in a separate animation, to allow per-keyframe timing functions to be
- // applied correctly.
- for (PropertyCountedSet::const_iterator iter = propertyCounts.begin(); iter != propertyCounts.end(); ++iter) {
- const CSSPropertyID property = iter->key;
- const size_t count = iter->value;
- ASSERT(count <= numKeyframes);
- if (count == numKeyframes)
- continue;
- KeyframeAnimationEffect::KeyframeVector splitOutKeyframes;
- for (size_t i = 0; i < numKeyframes; i++) {
- Keyframe* keyframe = keyframes[i].get();
- if (!keyframe->properties().contains(property)) {
- ASSERT(i && i != numKeyframes - 1);
- continue;
- }
- RefPtr<Keyframe> clonedKeyframe = Keyframe::create();
- clonedKeyframe->setOffset(keyframe->offset());
- clonedKeyframe->setComposite(keyframe->composite());
- clonedKeyframe->setPropertyValue(property, keyframe->propertyValue(property));
- splitOutKeyframes.append(clonedKeyframe);
- // Note that it's OK if this keyframe ends up having no
- // properties. This can only happen when none of the properties
- // are specified in all keyframes, in which case we won't animate
- // anything with these keyframes.
- keyframe->clearPropertyValue(property);
- }
- ASSERT(!splitOutKeyframes.first()->offset());
- ASSERT(splitOutKeyframes.last()->offset() == 1);
-#ifndef NDEBUG
- for (size_t j = 0; j < splitOutKeyframes.size(); ++j)
- ASSERT(splitOutKeyframes[j]->properties().size() == 1);
-#endif
- keyframesAndTimingFunctions.append(std::make_pair(splitOutKeyframes, generateTimingFunction(splitOutKeyframes, perKeyframeTimingFunctions)));
- }
-
- unsigned numPropertiesSpecifiedInAllKeyframes = keyframes.first()->properties().size();
-#ifndef NDEBUG
- for (size_t i = 1; i < numKeyframes; ++i)
- ASSERT(keyframes[i]->properties().size() == numPropertiesSpecifiedInAllKeyframes);
-#endif
-
- // If the animation specifies any keyframes, we always provide at least one
- // vector of resolved keyframes, even if no properties are animated.
- if (numPropertiesSpecifiedInAllKeyframes || keyframesAndTimingFunctions.isEmpty())
- keyframesAndTimingFunctions.append(std::make_pair(keyframes, generateTimingFunction(keyframes, perKeyframeTimingFunctions)));
-}
-
-// Returns the default timing function.
-const PassRefPtr<TimingFunction> timingFromAnimationData(const CSSAnimationData* animationData, Timing& timing, bool& isPaused)
-{
- if (animationData->isDelaySet())
- timing.startDelay = animationData->delay();
- if (animationData->isDurationSet()) {
- timing.iterationDuration = animationData->duration();
- timing.hasIterationDuration = true;
- }
- if (animationData->isIterationCountSet()) {
- if (animationData->iterationCount() == CSSAnimationData::IterationCountInfinite)
- timing.iterationCount = std::numeric_limits<double>::infinity();
- else
- timing.iterationCount = animationData->iterationCount();
- }
- if (animationData->isFillModeSet()) {
- switch (animationData->fillMode()) {
- case AnimationFillModeForwards:
- timing.fillMode = Timing::FillModeForwards;
- break;
- case AnimationFillModeBackwards:
- timing.fillMode = Timing::FillModeBackwards;
- break;
- case AnimationFillModeBoth:
- timing.fillMode = Timing::FillModeBoth;
- break;
- case AnimationFillModeNone:
- timing.fillMode = Timing::FillModeNone;
- break;
- default:
- ASSERT_NOT_REACHED();
- }
- } else {
- timing.fillMode = Timing::FillModeNone;
- }
- if (animationData->isDirectionSet()) {
- switch (animationData->direction()) {
- case CSSAnimationData::AnimationDirectionNormal:
- timing.direction = Timing::PlaybackDirectionNormal;
- break;
- case CSSAnimationData::AnimationDirectionAlternate:
- timing.direction = Timing::PlaybackDirectionAlternate;
- break;
- case CSSAnimationData::AnimationDirectionReverse:
- timing.direction = Timing::PlaybackDirectionReverse;
- break;
- case CSSAnimationData::AnimationDirectionAlternateReverse:
- timing.direction = Timing::PlaybackDirectionAlternateReverse;
- break;
- default:
- ASSERT_NOT_REACHED();
- }
- }
-
- // For CSS, the constraints on the timing properties are tighter than in
- // the general case of the Web Animations model.
- timing.assertValid();
- ASSERT(!timing.iterationStart);
- ASSERT(timing.playbackRate == 1);
- ASSERT(timing.iterationDuration >= 0 && std::isfinite(timing.iterationDuration));
-
- isPaused = animationData->isPlayStateSet() && animationData->playState() == AnimPlayStatePaused;
- return animationData->isTimingFunctionSet() ? animationData->timingFunction() : CSSAnimationData::initialAnimationTimingFunction();
}
} // namespace
@@ -347,21 +218,32 @@ const StyleRuleKeyframes* CSSAnimations::matchScopedKeyframesRule(StyleResolver*
return 0;
}
-PassOwnPtr<CSSAnimationUpdate> CSSAnimations::calculateUpdate(Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, StyleResolver* resolver)
+CSSAnimations::CSSAnimations()
{
- ASSERT(RuntimeEnabledFeatures::webAnimationsCSSEnabled());
- OwnPtr<CSSAnimationUpdate> update = adoptPtr(new CSSAnimationUpdate());
+}
+
+PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> CSSAnimations::calculateUpdate(Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, StyleResolver* resolver)
+{
+ OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = adoptPtrWillBeNoop(new CSSAnimationUpdate());
calculateAnimationUpdate(update.get(), element, parentElement, style, parentStyle, resolver);
- calculateAnimationCompositableValues(update.get(), element);
+ calculateAnimationActiveInterpolations(update.get(), element, parentElement.document().timeline().currentTimeInternal());
calculateTransitionUpdate(update.get(), element, style);
- calculateTransitionCompositableValues(update.get(), element);
+ calculateTransitionActiveInterpolations(update.get(), element, parentElement.document().timeline().currentTimeInternal());
return update->isEmpty() ? nullptr : update.release();
}
void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, StyleResolver* resolver)
{
const ActiveAnimations* activeAnimations = element ? element->activeAnimations() : 0;
- const CSSAnimationDataList* animationDataList = style.animations();
+
+#if !ASSERT_ENABLED
+ // If we're in an animation style change, no animations can have started, been cancelled or changed play state.
+ // When ASSERT is enabled, we verify this optimization.
+ if (activeAnimations && activeAnimations->isAnimationStyleChange())
+ return;
+#endif
+
+ const CSSAnimationData* animationData = style.animations();
const CSSAnimations* cssAnimations = activeAnimations ? &activeAnimations->cssAnimations() : 0;
HashSet<AtomicString> inactive;
@@ -370,12 +252,12 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, Element
inactive.add(iter->key);
if (style.display() != NONE) {
- for (size_t i = 0; animationDataList && i < animationDataList->size(); ++i) {
- const CSSAnimationData* animationData = animationDataList->animation(i);
- if (animationData->isNoneAnimation())
+ for (size_t i = 0; animationData && i < animationData->nameList().size(); ++i) {
+ AtomicString animationName(animationData->nameList()[i]);
+ if (animationName == CSSAnimationData::initialName())
continue;
- ASSERT(animationData->isValidAnimation());
- AtomicString animationName(animationData->name());
+
+ bool isPaused = CSSTimingData::getRepeated(animationData->playStateList(), i) == AnimPlayStatePaused;
// Keyframes and animation properties are snapshotted when the
// animation starts, so we don't need to track changes to these,
@@ -384,85 +266,76 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, Element
AnimationMap::const_iterator existing(cssAnimations->m_animations.find(animationName));
if (existing != cssAnimations->m_animations.end()) {
inactive.remove(animationName);
- const HashSet<RefPtr<Player> >& players = existing->value;
- ASSERT(!players.isEmpty());
- bool isFirstPlayerPaused = (*players.begin())->paused();
-#ifndef NDEBUG
- for (HashSet<RefPtr<Player> >::const_iterator iter = players.begin(); iter != players.end(); ++iter)
- ASSERT((*iter)->paused() == isFirstPlayerPaused);
-#endif
- if ((animationData->playState() == AnimPlayStatePaused) != isFirstPlayerPaused)
+ AnimationPlayer* player = existing->value.get();
+ if (isPaused != player->paused()) {
+ ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange());
update->toggleAnimationPaused(animationName);
+ }
continue;
}
}
- Timing timing;
- bool isPaused;
- RefPtr<TimingFunction> defaultTimingFunction = timingFromAnimationData(animationData, timing, isPaused);
- Vector<std::pair<KeyframeAnimationEffect::KeyframeVector, RefPtr<TimingFunction> > > keyframesAndTimingFunctions;
- resolveKeyframes(resolver, element, parentElement, style, parentStyle, animationName, defaultTimingFunction.get(), keyframesAndTimingFunctions);
- if (!keyframesAndTimingFunctions.isEmpty()) {
- HashSet<RefPtr<InertAnimation> > animations;
- for (size_t j = 0; j < keyframesAndTimingFunctions.size(); ++j) {
- ASSERT(!keyframesAndTimingFunctions[j].first.isEmpty());
- timing.timingFunction = keyframesAndTimingFunctions[j].second;
- // FIXME: crbug.com/268791 - Keyframes are already normalized, perhaps there should be a flag on KeyframeAnimationEffect to skip normalization.
- animations.add(InertAnimation::create(KeyframeAnimationEffect::create(keyframesAndTimingFunctions[j].first), timing, isPaused));
- }
- update->startAnimation(animationName, animations);
+ Timing timing = animationData->convertToTiming(i);
+ RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunction;
+ timing.timingFunction = Timing::defaults().timingFunction;
+ AnimatableValueKeyframeVector resolvedKeyframes;
+ resolveKeyframes(resolver, element, parentElement, style, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes);
+ if (!resolvedKeyframes.isEmpty()) {
+ ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange());
+ update->startAnimation(animationName, InertAnimation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused));
}
}
}
ASSERT(inactive.isEmpty() || cssAnimations);
- for (HashSet<AtomicString>::const_iterator iter = inactive.begin(); iter != inactive.end(); ++iter)
- update->cancelAnimation(*iter, cssAnimations->m_animations.get(*iter));
+ for (HashSet<AtomicString>::const_iterator iter = inactive.begin(); iter != inactive.end(); ++iter) {
+ ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange());
+ update->cancelAnimation(*iter, *cssAnimations->m_animations.get(*iter));
+ }
}
void CSSAnimations::maybeApplyPendingUpdate(Element* element)
{
if (!m_pendingUpdate) {
- m_previousCompositableValuesForAnimations.clear();
+ m_previousActiveInterpolationsForAnimations.clear();
return;
}
- OwnPtr<CSSAnimationUpdate> update = m_pendingUpdate.release();
+ OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = m_pendingUpdate.release();
+
+ m_previousActiveInterpolationsForAnimations.swap(update->activeInterpolationsForAnimations());
- m_previousCompositableValuesForAnimations.swap(update->compositableValuesForAnimations());
+ // FIXME: cancelling, pausing, unpausing animations all query compositingState, which is not necessarily up to date here
+ // since we call this from recalc style.
+ // https://code.google.com/p/chromium/issues/detail?id=339847
+ DisableCompositingQueryAsserts disabler;
for (Vector<AtomicString>::const_iterator iter = update->cancelledAnimationNames().begin(); iter != update->cancelledAnimationNames().end(); ++iter) {
- const HashSet<RefPtr<Player> >& players = m_animations.take(*iter);
- for (HashSet<RefPtr<Player> >::const_iterator iter = players.begin(); iter != players.end(); ++iter)
- (*iter)->cancel();
+ RefPtr<AnimationPlayer> player = m_animations.take(*iter);
+ player->cancel();
+ player->update(TimingUpdateOnDemand);
}
for (Vector<AtomicString>::const_iterator iter = update->animationsWithPauseToggled().begin(); iter != update->animationsWithPauseToggled().end(); ++iter) {
- const HashSet<RefPtr<Player> >& players = m_animations.get(*iter);
- ASSERT(!players.isEmpty());
- bool isFirstPlayerPaused = (*players.begin())->paused();
- for (HashSet<RefPtr<Player> >::const_iterator iter = players.begin(); iter != players.end(); ++iter) {
- Player* player = iter->get();
- ASSERT(player->paused() == isFirstPlayerPaused);
- player->setPaused(!isFirstPlayerPaused);
- }
+ AnimationPlayer* player = m_animations.get(*iter);
+ if (player->paused())
+ player->unpause();
+ else
+ player->pause();
+ if (player->outdated())
+ player->update(TimingUpdateOnDemand);
}
- for (Vector<CSSAnimationUpdate::NewAnimation>::const_iterator iter = update->newAnimations().begin(); iter != update->newAnimations().end(); ++iter) {
+ for (WillBeHeapVector<CSSAnimationUpdate::NewAnimation>::const_iterator iter = update->newAnimations().begin(); iter != update->newAnimations().end(); ++iter) {
+ const InertAnimation* inertAnimation = iter->animation.get();
OwnPtr<AnimationEventDelegate> eventDelegate = adoptPtr(new AnimationEventDelegate(element, iter->name));
- HashSet<RefPtr<Player> > players;
- for (HashSet<RefPtr<InertAnimation> >::const_iterator animationsIter = iter->animations.begin(); animationsIter != iter->animations.end(); ++animationsIter) {
- const InertAnimation* inertAnimation = animationsIter->get();
- // The event delegate is set on the the first animation only. We
- // rely on the behavior of OwnPtr::release() to achieve this.
- RefPtr<Animation> animation = Animation::create(element, inertAnimation->effect(), inertAnimation->specified(), Animation::DefaultPriority, eventDelegate.release());
- Player* player = element->document().timeline()->createPlayer(animation.get());
- player->setPaused(inertAnimation->paused());
- element->document().cssPendingAnimations().add(player);
- player->update();
- players.add(player);
- }
- m_animations.set(iter->name, players);
+ RefPtrWillBeRawPtr<Animation> animation = Animation::create(element, inertAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPriority, eventDelegate.release());
+ RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timeline().createAnimationPlayer(animation.get());
+ element->document().compositorPendingAnimations().add(player.get());
+ if (inertAnimation->paused())
+ player->pause();
+ player->update(TimingUpdateOnDemand);
+ m_animations.set(iter->name, player.get());
}
// Transitions that are run on the compositor only update main-thread state
@@ -470,15 +343,17 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element)
// be when transitions are retargeted. Instead of triggering complete style
// recalculation, we find these cases by searching for new transitions that
// have matching cancelled animation property IDs on the compositor.
- HashMap<CSSPropertyID, std::pair<RefPtr<Animation>, double> > retargetedCompositorTransitions;
- const ActiveAnimations* activeAnimations = element->activeAnimations();
+ WillBeHeapHashMap<CSSPropertyID, std::pair<RefPtrWillBeMember<Animation>, double> > retargetedCompositorTransitions;
for (HashSet<CSSPropertyID>::iterator iter = update->cancelledTransitions().begin(); iter != update->cancelledTransitions().end(); ++iter) {
CSSPropertyID id = *iter;
ASSERT(m_transitions.contains(id));
- Player* player = m_transitions.take(id).transition->player();
- if (activeAnimations && activeAnimations->hasActiveAnimationsOnCompositor(id) && update->newTransitions().find(id) != update->newTransitions().end())
- retargetedCompositorTransitions.add(id, std::pair<RefPtr<Animation>, double>(toAnimation(player->source()), player->startTime()));
+
+ RefPtrWillBeRawPtr<AnimationPlayer> player = m_transitions.take(id).player;
+ Animation* animation = toAnimation(player->source());
+ if (animation->hasActiveAnimationsOnCompositor(id) && update->newTransitions().find(id) != update->newTransitions().end())
+ retargetedCompositorTransitions.add(id, std::pair<RefPtrWillBeMember<Animation>, double>(animation, player->startTimeInternal()));
player->cancel();
+ player->update(TimingUpdateOnDemand);
}
for (CSSAnimationUpdate::NewTransitionMap::const_iterator iter = update->newTransitions().begin(); iter != update->newTransitions().end(); ++iter) {
@@ -490,42 +365,46 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element)
CSSPropertyID id = newTransition.id;
InertAnimation* inertAnimation = newTransition.animation.get();
- OwnPtr<TransitionEventDelegate> eventDelegate = adoptPtr(new TransitionEventDelegate(element, id));
+ OwnPtr<TransitionEventDelegate> eventDelegate = adoptPtr(new TransitionEventDelegate(element, newTransition.eventId));
- RefPtr<AnimationEffect> effect = inertAnimation->effect();
+ RefPtrWillBeRawPtr<AnimationEffect> effect = inertAnimation->effect();
if (retargetedCompositorTransitions.contains(id)) {
- const std::pair<RefPtr<Animation>, double>& oldTransition = retargetedCompositorTransitions.get(id);
- RefPtr<Animation> oldAnimation = oldTransition.first;
+ const std::pair<RefPtrWillBeMember<Animation>, double>& oldTransition = retargetedCompositorTransitions.get(id);
+ RefPtrWillBeRawPtr<Animation> oldAnimation = oldTransition.first;
double oldStartTime = oldTransition.second;
- double inheritedTime = isNull(oldStartTime) ? 0 : element->document().transitionTimeline()->currentTime() - oldStartTime;
- oldAnimation->updateInheritedTime(inheritedTime);
- KeyframeAnimationEffect* oldEffect = toKeyframeAnimationEffect(inertAnimation->effect());
- const KeyframeAnimationEffect::KeyframeVector& frames = oldEffect->getFrames();
- KeyframeAnimationEffect::KeyframeVector newFrames;
- newFrames.append(frames[0]->clone());
+ double inheritedTime = isNull(oldStartTime) ? 0 : element->document().timeline().currentTimeInternal() - oldStartTime;
+
+ AnimatableValueKeyframeEffectModel* oldEffect = toAnimatableValueKeyframeEffectModel(inertAnimation->effect());
+ const KeyframeVector& frames = oldEffect->getFrames();
+
+ AnimatableValueKeyframeVector newFrames;
+ newFrames.append(toAnimatableValueKeyframe(frames[0]->clone().get()));
+ newFrames.append(toAnimatableValueKeyframe(frames[1]->clone().get()));
+
newFrames[0]->clearPropertyValue(id);
- ASSERT(oldAnimation->compositableValues()->size() == 1);
- const AnimationEffect::CompositableValue* compositableValue = oldAnimation->compositableValues()->at(0).second.get();
- ASSERT(!compositableValue->dependsOnUnderlyingValue());
- newFrames[0]->setPropertyValue(id, compositableValue->compositeOnto(0).get());
- newFrames.append(frames[1]->clone());
- effect = KeyframeAnimationEffect::create(newFrames);
+ RefPtrWillBeRawPtr<InertAnimation> inertAnimationForSampling = InertAnimation::create(oldAnimation->effect(), oldAnimation->specifiedTiming(), false);
+ OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation> > > sample = inertAnimationForSampling->sample(inheritedTime);
+ ASSERT(sample->size() == 1);
+ newFrames[0]->setPropertyValue(id, toLegacyStyleInterpolation(sample->at(0).get())->currentValue());
+
+ effect = AnimatableValueKeyframeEffectModel::create(newFrames);
}
- RefPtr<Animation> transition = Animation::create(element, effect, inertAnimation->specified(), Animation::TransitionPriority, eventDelegate.release());
- RefPtr<Player> player = element->document().transitionTimeline()->createPlayer(transition.get());
- player->update();
- element->document().cssPendingAnimations().add(player.get());
- runningTransition.transition = transition.get();
+
+ RefPtrWillBeRawPtr<Animation> transition = Animation::create(element, effect, inertAnimation->specifiedTiming(), Animation::TransitionPriority, eventDelegate.release());
+ RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timeline().createAnimationPlayer(transition.get());
+ element->document().compositorPendingAnimations().add(player.get());
+ player->update(TimingUpdateOnDemand);
+ runningTransition.player = player;
m_transitions.set(id, runningTransition);
ASSERT(id != CSSPropertyInvalid);
blink::Platform::current()->histogramSparse("WebCore.Animation.CSSProperties", UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(id));
}
}
-void CSSAnimations::calculateTransitionUpdateForProperty(CSSPropertyID id, const CSSAnimationData* anim, const RenderStyle& oldStyle, const RenderStyle& style, const TransitionMap* activeTransitions, CSSAnimationUpdate* update, const Element* element)
+void CSSAnimations::calculateTransitionUpdateForProperty(CSSPropertyID id, CSSPropertyID eventId, const CSSTransitionData& transitionData, size_t transitionIndex, const RenderStyle& oldStyle, const RenderStyle& style, const TransitionMap* activeTransitions, CSSAnimationUpdate* update, const Element* element)
{
- RefPtr<AnimatableValue> to;
+ RefPtrWillBeRawPtr<AnimatableValue> to = nullptr;
if (activeTransitions) {
TransitionMap::const_iterator activeTransitionIter = activeTransitions->find(id);
if (activeTransitionIter != activeTransitions->end()) {
@@ -538,44 +417,37 @@ void CSSAnimations::calculateTransitionUpdateForProperty(CSSPropertyID id, const
}
}
- if (anim->duration() + anim->delay() <= 0)
+ if (CSSPropertyEquality::propertiesEqual(id, oldStyle, style))
return;
-
- if (CSSPropertyAnimation::propertiesEqual(id, &oldStyle, &style))
- return;
-
if (!to)
to = CSSAnimatableValueFactory::create(id, style);
- RefPtr<AnimatableValue> from = CSSAnimatableValueFactory::create(id, oldStyle);
+ RefPtrWillBeRawPtr<AnimatableValue> from = CSSAnimatableValueFactory::create(id, oldStyle);
// If we have multiple transitions on the same property, we will use the
// last one since we iterate over them in order.
- if (!from->usesNonDefaultInterpolationWith(to.get()))
+ if (AnimatableValue::usesDefaultInterpolation(to.get(), from.get()))
+ return;
+
+ Timing timing = transitionData.convertToTiming(transitionIndex);
+ if (timing.startDelay + timing.iterationDuration <= 0)
return;
- KeyframeAnimationEffect::KeyframeVector keyframes;
+ AnimatableValueKeyframeVector keyframes;
- RefPtr<Keyframe> startKeyframe = Keyframe::create();
+ RefPtrWillBeRawPtr<AnimatableValueKeyframe> startKeyframe = AnimatableValueKeyframe::create();
startKeyframe->setPropertyValue(id, from.get());
startKeyframe->setOffset(0);
+ startKeyframe->setEasing(timing.timingFunction.release());
+ timing.timingFunction = LinearTimingFunction::shared();
keyframes.append(startKeyframe);
- RefPtr<Keyframe> endKeyframe = Keyframe::create();
+ RefPtrWillBeRawPtr<AnimatableValueKeyframe> endKeyframe = AnimatableValueKeyframe::create();
endKeyframe->setPropertyValue(id, to.get());
endKeyframe->setOffset(1);
keyframes.append(endKeyframe);
- RefPtr<KeyframeAnimationEffect> effect = KeyframeAnimationEffect::create(keyframes);
-
- Timing timing;
- bool isPaused;
- RefPtr<TimingFunction> timingFunction = timingFromAnimationData(anim, timing, isPaused);
- ASSERT(!isPaused);
- timing.timingFunction = timingFunction;
- // Note that the backwards part is required for delay to work.
- timing.fillMode = Timing::FillModeBoth;
-
- update->startTransition(id, from.get(), to.get(), InertAnimation::create(effect, timing, isPaused));
+ RefPtrWillBeRawPtr<AnimatableValueKeyframeEffectModel> effect = AnimatableValueKeyframeEffectModel::create(keyframes);
+ update->startTransition(id, eventId, from.get(), to.get(), InertAnimation::create(effect, timing, false));
ASSERT(!element->activeAnimations() || !element->activeAnimations()->isAnimationStyleChange());
}
@@ -586,37 +458,41 @@ void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate* update, const
ActiveAnimations* activeAnimations = element->activeAnimations();
const TransitionMap* activeTransitions = activeAnimations ? &activeAnimations->cssAnimations().m_transitions : 0;
+ const CSSTransitionData* transitionData = style.transitions();
-#if ASSERT_DISABLED
- // In release builds we avoid the cost of checking for new and interrupted transitions if the style recalc is due to animation.
- const bool animationStyleRecalc = activeAnimations && activeAnimations->isAnimationStyleChange();
-#else
+#if ASSERT_ENABLED
// In debug builds we verify that it would have been safe to avoid populating and testing listedProperties if the style recalc is due to animation.
const bool animationStyleRecalc = false;
+#else
+ // In release builds we avoid the cost of checking for new and interrupted transitions if the style recalc is due to animation.
+ const bool animationStyleRecalc = activeAnimations && activeAnimations->isAnimationStyleChange();
#endif
BitArray<numCSSProperties> listedProperties;
- bool anyTransitionHadAnimateAll = false;
+ bool anyTransitionHadTransitionAll = false;
const RenderObject* renderer = element->renderer();
- if (!animationStyleRecalc && style.display() != NONE && renderer && renderer->style() && style.transitions()) {
+ if (!animationStyleRecalc && style.display() != NONE && renderer && renderer->style() && transitionData) {
const RenderStyle& oldStyle = *renderer->style();
- for (size_t i = 0; i < style.transitions()->size(); ++i) {
- const CSSAnimationData* anim = style.transitions()->animation(i);
- CSSAnimationData::AnimationMode mode = anim->animationMode();
- if (mode == CSSAnimationData::AnimateNone)
+ for (size_t i = 0; i < transitionData->propertyList().size(); ++i) {
+ const CSSTransitionData::TransitionProperty& transitionProperty = transitionData->propertyList()[i];
+ CSSTransitionData::TransitionPropertyType mode = transitionProperty.propertyType;
+ CSSPropertyID property = transitionProperty.propertyId;
+ if (mode == CSSTransitionData::TransitionNone || mode == CSSTransitionData::TransitionUnknown)
continue;
- bool animateAll = mode == CSSAnimationData::AnimateAll;
- ASSERT(animateAll || mode == CSSAnimationData::AnimateSingleProperty);
+ bool animateAll = mode == CSSTransitionData::TransitionAll;
+ ASSERT(animateAll || mode == CSSTransitionData::TransitionSingleProperty);
if (animateAll)
- anyTransitionHadAnimateAll = true;
- const StylePropertyShorthand& propertyList = animateAll ? CSSAnimations::animatableProperties() : shorthandForProperty(anim->property());
+ anyTransitionHadTransitionAll = true;
+ const StylePropertyShorthand& propertyList = animateAll ? CSSAnimations::animatableProperties() : shorthandForProperty(property);
// If not a shorthand we only execute one iteration of this loop, and refer to the property directly.
for (unsigned j = 0; !j || j < propertyList.length(); ++j) {
- CSSPropertyID id = propertyList.length() ? propertyList.properties()[j] : anim->property();
+ CSSPropertyID id = propertyList.length() ? propertyList.properties()[j] : property;
+ CSSPropertyID eventId = id;
if (!animateAll) {
+ id = propertyForAnimation(id);
if (CSSAnimations::isAnimatableProperty(id))
listedProperties.set(id);
else
@@ -625,9 +501,9 @@ void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate* update, const
// FIXME: We should transition if an !important property changes even when an animation is running,
// but this is a bit hard to do with the current applyMatchedProperties system.
- if (!update->compositableValuesForAnimations().contains(id)
- && (!activeAnimations || !activeAnimations->cssAnimations().m_previousCompositableValuesForAnimations.contains(id))) {
- calculateTransitionUpdateForProperty(id, anim, oldStyle, style, activeTransitions, update, element);
+ if (!update->activeInterpolationsForAnimations().contains(id)
+ && (!activeAnimations || !activeAnimations->cssAnimations().m_previousActiveInterpolationsForAnimations.contains(id))) {
+ calculateTransitionUpdateForProperty(id, eventId, *transitionData, i, oldStyle, style, activeTransitions, update, element);
}
}
}
@@ -635,10 +511,11 @@ void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate* update, const
if (activeTransitions) {
for (TransitionMap::const_iterator iter = activeTransitions->begin(); iter != activeTransitions->end(); ++iter) {
- const TimedItem* timedItem = iter->value.transition;
+ const AnimationPlayer& player = *iter->value.player;
CSSPropertyID id = iter->key;
- if (timedItem->phase() == TimedItem::PhaseAfter || (!anyTransitionHadAnimateAll && !animationStyleRecalc && !listedProperties.get(id))) {
- ASSERT(timedItem->phase() == TimedItem::PhaseAfter || !(activeAnimations && activeAnimations->isAnimationStyleChange()));
+ if (player.finishedInternal() || (!anyTransitionHadTransitionAll && !animationStyleRecalc && !listedProperties.get(id))) {
+ // TODO: Figure out why this fails on Chrome OS login page. crbug.com/365507
+ // ASSERT(player.finishedInternal() || !(activeAnimations && activeAnimations->isAnimationStyleChange()));
update->cancelTransition(id);
}
}
@@ -648,130 +525,129 @@ void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate* update, const
void CSSAnimations::cancel()
{
for (AnimationMap::iterator iter = m_animations.begin(); iter != m_animations.end(); ++iter) {
- const HashSet<RefPtr<Player> >& players = iter->value;
- for (HashSet<RefPtr<Player> >::const_iterator animationsIter = players.begin(); animationsIter != players.end(); ++animationsIter)
- (*animationsIter)->cancel();
+ iter->value->cancel();
+ iter->value->update(TimingUpdateOnDemand);
}
- for (TransitionMap::iterator iter = m_transitions.begin(); iter != m_transitions.end(); ++iter)
- iter->value.transition->player()->cancel();
+ for (TransitionMap::iterator iter = m_transitions.begin(); iter != m_transitions.end(); ++iter) {
+ iter->value.player->cancel();
+ iter->value.player->update(TimingUpdateOnDemand);
+ }
m_animations.clear();
m_transitions.clear();
m_pendingUpdate = nullptr;
}
-void CSSAnimations::calculateAnimationCompositableValues(CSSAnimationUpdate* update, const Element* element)
+void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate* update, const Element* element, double timelineCurrentTime)
{
ActiveAnimations* activeAnimations = element ? element->activeAnimations() : 0;
AnimationStack* animationStack = activeAnimations ? &activeAnimations->defaultStack() : 0;
- if (update->newAnimations().isEmpty() && update->cancelledAnimationPlayers().isEmpty()) {
- AnimationEffect::CompositableValueMap compositableValuesForAnimations(AnimationStack::compositableValues(animationStack, 0, 0, Animation::DefaultPriority));
- update->adoptCompositableValuesForAnimations(compositableValuesForAnimations);
+ if (update->newAnimations().isEmpty() && update->cancelledAnimationAnimationPlayers().isEmpty()) {
+ WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, 0, 0, Animation::DefaultPriority, timelineCurrentTime));
+ update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations);
return;
}
- Vector<InertAnimation*> newAnimations;
+ WillBeHeapVector<RawPtrWillBeMember<InertAnimation> > newAnimations;
for (size_t i = 0; i < update->newAnimations().size(); ++i) {
- HashSet<RefPtr<InertAnimation> > animations = update->newAnimations()[i].animations;
- for (HashSet<RefPtr<InertAnimation> >::const_iterator animationsIter = animations.begin(); animationsIter != animations.end(); ++animationsIter)
- newAnimations.append(animationsIter->get());
+ newAnimations.append(update->newAnimations()[i].animation.get());
}
- AnimationEffect::CompositableValueMap compositableValuesForAnimations(AnimationStack::compositableValues(animationStack, &newAnimations, &update->cancelledAnimationPlayers(), Animation::DefaultPriority));
- update->adoptCompositableValuesForAnimations(compositableValuesForAnimations);
+ WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, &newAnimations, &update->cancelledAnimationAnimationPlayers(), Animation::DefaultPriority, timelineCurrentTime));
+ update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations);
}
-void CSSAnimations::calculateTransitionCompositableValues(CSSAnimationUpdate* update, const Element* element)
+void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate* update, const Element* element, double timelineCurrentTime)
{
ActiveAnimations* activeAnimations = element ? element->activeAnimations() : 0;
AnimationStack* animationStack = activeAnimations ? &activeAnimations->defaultStack() : 0;
- AnimationEffect::CompositableValueMap compositableValuesForTransitions;
+ WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > activeInterpolationsForTransitions;
if (update->newTransitions().isEmpty() && update->cancelledTransitions().isEmpty()) {
- compositableValuesForTransitions = AnimationStack::compositableValues(animationStack, 0, 0, Animation::TransitionPriority);
+ activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, 0, 0, Animation::TransitionPriority, timelineCurrentTime);
} else {
- Vector<InertAnimation*> newTransitions;
+ WillBeHeapVector<RawPtrWillBeMember<InertAnimation> > newTransitions;
for (CSSAnimationUpdate::NewTransitionMap::const_iterator iter = update->newTransitions().begin(); iter != update->newTransitions().end(); ++iter)
newTransitions.append(iter->value.animation.get());
- HashSet<const Player*> cancelledPlayers;
+ WillBeHeapHashSet<RawPtrWillBeMember<const AnimationPlayer> > cancelledAnimationPlayers;
if (!update->cancelledTransitions().isEmpty()) {
ASSERT(activeAnimations);
const TransitionMap& transitionMap = activeAnimations->cssAnimations().m_transitions;
for (HashSet<CSSPropertyID>::iterator iter = update->cancelledTransitions().begin(); iter != update->cancelledTransitions().end(); ++iter) {
ASSERT(transitionMap.contains(*iter));
- cancelledPlayers.add(transitionMap.get(*iter).transition->player());
+ cancelledAnimationPlayers.add(transitionMap.get(*iter).player.get());
}
}
- compositableValuesForTransitions = AnimationStack::compositableValues(animationStack, &newTransitions, &cancelledPlayers, Animation::TransitionPriority);
+ activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, &newTransitions, &cancelledAnimationPlayers, Animation::TransitionPriority, timelineCurrentTime);
}
// Properties being animated by animations don't get values from transitions applied.
- if (!update->compositableValuesForAnimations().isEmpty() && !compositableValuesForTransitions.isEmpty()) {
- for (AnimationEffect::CompositableValueMap::const_iterator iter = update->compositableValuesForAnimations().begin(); iter != update->compositableValuesForAnimations().end(); ++iter)
- compositableValuesForTransitions.remove(iter->key);
+ if (!update->activeInterpolationsForAnimations().isEmpty() && !activeInterpolationsForTransitions.isEmpty()) {
+ for (WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >::const_iterator iter = update->activeInterpolationsForAnimations().begin(); iter != update->activeInterpolationsForAnimations().end(); ++iter)
+ activeInterpolationsForTransitions.remove(iter->key);
}
- update->adoptCompositableValuesForTransitions(compositableValuesForTransitions);
+ update->adoptActiveInterpolationsForTransitions(activeInterpolationsForTransitions);
}
void CSSAnimations::AnimationEventDelegate::maybeDispatch(Document::ListenerType listenerType, const AtomicString& eventName, double elapsedTime)
{
- if (m_target->document().hasListenerType(listenerType))
- m_target->document().timeline()->addEventToDispatch(m_target, WebKitAnimationEvent::create(eventName, m_name, elapsedTime));
+ if (m_target->document().hasListenerType(listenerType)) {
+ RefPtrWillBeRawPtr<WebKitAnimationEvent> event = WebKitAnimationEvent::create(eventName, m_name, elapsedTime);
+ event->setTarget(m_target);
+ m_target->document().enqueueAnimationFrameEvent(event);
+ }
}
-void CSSAnimations::AnimationEventDelegate::onEventCondition(const TimedItem* timedItem, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration)
+void CSSAnimations::AnimationEventDelegate::onEventCondition(const AnimationNode* animationNode)
{
- // Events for a single document are queued and dispatched as a group at
- // the end of DocumentTimeline::serviceAnimations.
- // FIXME: Events which are queued outside of serviceAnimations should
- // trigger a timer to dispatch when control is released.
- const TimedItem::Phase currentPhase = timedItem->phase();
- const double currentIteration = timedItem->currentIteration();
-
- // Note that the elapsedTime is measured from when the animation starts playing.
- if (!isFirstSample && previousPhase == TimedItem::PhaseActive && currentPhase == TimedItem::PhaseActive && previousIteration != currentIteration) {
- ASSERT(!isNull(previousIteration));
- ASSERT(!isNull(currentIteration));
+ const AnimationNode::Phase currentPhase = animationNode->phase();
+ const double currentIteration = animationNode->currentIteration();
+
+ if (m_previousPhase != currentPhase
+ && (currentPhase == AnimationNode::PhaseActive || currentPhase == AnimationNode::PhaseAfter)
+ && (m_previousPhase == AnimationNode::PhaseNone || m_previousPhase == AnimationNode::PhaseBefore)) {
+ // The spec states that the elapsed time should be
+ // 'delay < 0 ? -delay : 0', but we always use 0 to match the existing
+ // implementation. See crbug.com/279611
+ maybeDispatch(Document::ANIMATIONSTART_LISTENER, EventTypeNames::animationstart, 0);
+ }
+
+ if (currentPhase == AnimationNode::PhaseActive && m_previousPhase == currentPhase && m_previousIteration != currentIteration) {
// We fire only a single event for all iterations thast terminate
// between a single pair of samples. See http://crbug.com/275263. For
// compatibility with the existing implementation, this event uses
// the elapsedTime for the first iteration in question.
- ASSERT(timedItem->specified().hasIterationDuration);
- const double elapsedTime = timedItem->specified().iterationDuration * (previousIteration + 1);
+ ASSERT(!std::isnan(animationNode->specifiedTiming().iterationDuration));
+ const double elapsedTime = animationNode->specifiedTiming().iterationDuration * (m_previousIteration + 1);
maybeDispatch(Document::ANIMATIONITERATION_LISTENER, EventTypeNames::animationiteration, elapsedTime);
- return;
}
- if ((isFirstSample || previousPhase == TimedItem::PhaseBefore) && isLaterPhase(currentPhase, TimedItem::PhaseBefore)) {
- ASSERT(timedItem->specified().startDelay > 0 || isFirstSample);
- // The spec states that the elapsed time should be
- // 'delay < 0 ? -delay : 0', but we always use 0 to match the existing
- // implementation. See crbug.com/279611
- maybeDispatch(Document::ANIMATIONSTART_LISTENER, EventTypeNames::animationstart, 0);
- }
- if ((isFirstSample || isEarlierPhase(previousPhase, TimedItem::PhaseAfter)) && currentPhase == TimedItem::PhaseAfter)
- maybeDispatch(Document::ANIMATIONEND_LISTENER, EventTypeNames::animationend, timedItem->activeDuration());
+
+ if (currentPhase == AnimationNode::PhaseAfter && m_previousPhase != AnimationNode::PhaseAfter)
+ maybeDispatch(Document::ANIMATIONEND_LISTENER, EventTypeNames::animationend, animationNode->activeDurationInternal());
+
+ m_previousPhase = currentPhase;
+ m_previousIteration = currentIteration;
}
-void CSSAnimations::TransitionEventDelegate::onEventCondition(const TimedItem* timedItem, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration)
+void CSSAnimations::TransitionEventDelegate::onEventCondition(const AnimationNode* animationNode)
{
- // Events for a single document are queued and dispatched as a group at
- // the end of DocumentTimeline::serviceAnimations.
- // FIXME: Events which are queued outside of serviceAnimations should
- // trigger a timer to dispatch when control is released.
- const TimedItem::Phase currentPhase = timedItem->phase();
- if (currentPhase == TimedItem::PhaseAfter && (isFirstSample || previousPhase != currentPhase) && m_target->document().hasListenerType(Document::TRANSITIONEND_LISTENER)) {
+ const AnimationNode::Phase currentPhase = animationNode->phase();
+ if (currentPhase == AnimationNode::PhaseAfter && currentPhase != m_previousPhase && m_target->document().hasListenerType(Document::TRANSITIONEND_LISTENER)) {
String propertyName = getPropertyNameString(m_property);
- const Timing& timing = timedItem->specified();
+ const Timing& timing = animationNode->specifiedTiming();
double elapsedTime = timing.iterationDuration;
const AtomicString& eventType = EventTypeNames::transitionend;
String pseudoElement = PseudoElement::pseudoElementNameForEvents(m_target->pseudoId());
- m_target->document().transitionTimeline()->addEventToDispatch(m_target, TransitionEvent::create(eventType, propertyName, elapsedTime, pseudoElement));
+ RefPtrWillBeRawPtr<TransitionEvent> event = TransitionEvent::create(eventType, propertyName, elapsedTime, pseudoElement);
+ event->setTarget(m_target);
+ m_target->document().enqueueAnimationFrameEvent(event);
}
-}
+ m_previousPhase = currentPhase;
+}
bool CSSAnimations::isAnimatableProperty(CSSPropertyID property)
{
@@ -810,8 +686,8 @@ bool CSSAnimations::isAnimatableProperty(CSSPropertyID property)
case CSSPropertyFloodColor:
case CSSPropertyFloodOpacity:
case CSSPropertyFontSize:
+ case CSSPropertyFontWeight:
case CSSPropertyHeight:
- case CSSPropertyKerning:
case CSSPropertyLeft:
case CSSPropertyLetterSpacing:
case CSSPropertyLightingColor:
@@ -848,6 +724,7 @@ bool CSSAnimations::isAnimatableProperty(CSSPropertyID property)
case CSSPropertyTextIndent:
case CSSPropertyTextShadow:
case CSSPropertyTop:
+ case CSSPropertyVerticalAlign:
case CSSPropertyVisibility:
case CSSPropertyWebkitBackgroundSize:
case CSSPropertyWebkitBorderHorizontalSpacing:
@@ -868,29 +745,27 @@ bool CSSAnimations::isAnimatableProperty(CSSPropertyID property)
case CSSPropertyWebkitMaskPositionX:
case CSSPropertyWebkitMaskPositionY:
case CSSPropertyWebkitMaskSize:
- case CSSPropertyWebkitPerspective:
- case CSSPropertyWebkitPerspectiveOriginX:
- case CSSPropertyWebkitPerspectiveOriginY:
- case CSSPropertyShapeInside:
+ case CSSPropertyPerspective:
case CSSPropertyShapeOutside:
case CSSPropertyShapeMargin:
case CSSPropertyShapeImageThreshold:
case CSSPropertyWebkitTextStrokeColor:
- case CSSPropertyWebkitTransform:
- case CSSPropertyWebkitTransformOriginX:
- case CSSPropertyWebkitTransformOriginY:
- case CSSPropertyWebkitTransformOriginZ:
+ case CSSPropertyTransform:
case CSSPropertyWidows:
case CSSPropertyWidth:
case CSSPropertyWordSpacing:
case CSSPropertyZIndex:
case CSSPropertyZoom:
return true;
- // FIXME: Shorthands should not be present in this list, but
- // CSSPropertyAnimation implements animation of these shorthands
- // directly and makes use of this method.
- case CSSPropertyFlex:
- return !RuntimeEnabledFeatures::webAnimationsCSSEnabled();
+ case CSSPropertyPerspectiveOrigin:
+ case CSSPropertyTransformOrigin:
+ return RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled();
+ case CSSPropertyWebkitPerspectiveOriginX:
+ case CSSPropertyWebkitPerspectiveOriginY:
+ case CSSPropertyWebkitTransformOriginX:
+ case CSSPropertyWebkitTransformOriginY:
+ case CSSPropertyWebkitTransformOriginZ:
+ return !RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled();
default:
return false;
}
@@ -911,4 +786,61 @@ const StylePropertyShorthand& CSSAnimations::animatableProperties()
return propertyShorthand;
}
+// Animation properties are not allowed to be affected by Web Animations.
+// http://dev.w3.org/fxtf/web-animations/#not-animatable
+bool CSSAnimations::isAllowedAnimation(CSSPropertyID property)
+{
+ switch (property) {
+ case CSSPropertyAnimation:
+ case CSSPropertyAnimationDelay:
+ case CSSPropertyAnimationDirection:
+ case CSSPropertyAnimationDuration:
+ case CSSPropertyAnimationFillMode:
+ case CSSPropertyAnimationIterationCount:
+ case CSSPropertyAnimationName:
+ case CSSPropertyAnimationPlayState:
+ case CSSPropertyAnimationTimingFunction:
+ case CSSPropertyDisplay:
+ case CSSPropertyTransition:
+ case CSSPropertyTransitionDelay:
+ case CSSPropertyTransitionDuration:
+ case CSSPropertyTransitionProperty:
+ case CSSPropertyTransitionTimingFunction:
+ case CSSPropertyWebkitAnimation:
+ case CSSPropertyWebkitAnimationDelay:
+ case CSSPropertyWebkitAnimationDirection:
+ case CSSPropertyWebkitAnimationDuration:
+ case CSSPropertyWebkitAnimationFillMode:
+ case CSSPropertyWebkitAnimationIterationCount:
+ case CSSPropertyWebkitAnimationName:
+ case CSSPropertyWebkitAnimationPlayState:
+ case CSSPropertyWebkitAnimationTimingFunction:
+ case CSSPropertyWebkitTransition:
+ case CSSPropertyWebkitTransitionDelay:
+ case CSSPropertyWebkitTransitionDuration:
+ case CSSPropertyWebkitTransitionProperty:
+ case CSSPropertyWebkitTransitionTimingFunction:
+ return false;
+ default:
+ return true;
+ }
+}
+
+void CSSAnimations::trace(Visitor* visitor)
+{
+ visitor->trace(m_transitions);
+ visitor->trace(m_pendingUpdate);
+ visitor->trace(m_animations);
+ visitor->trace(m_previousActiveInterpolationsForAnimations);
+}
+
+void CSSAnimationUpdate::trace(Visitor* visitor)
+{
+ visitor->trace(m_newTransitions);
+ visitor->trace(m_activeInterpolationsForAnimations);
+ visitor->trace(m_activeInterpolationsForTransitions);
+ visitor->trace(m_newAnimations);
+ visitor->trace(m_cancelledAnimationPlayers);
+}
+
} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.h b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.h
index fb553d96232..31159f908ec 100644
--- a/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.h
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSAnimations.h
@@ -32,11 +32,11 @@
#define CSSAnimations_h
#include "core/animation/Animation.h"
+#include "core/animation/AnimationPlayer.h"
#include "core/animation/InertAnimation.h"
-#include "core/animation/Player.h"
+#include "core/animation/interpolation/Interpolation.h"
#include "core/css/StylePropertySet.h"
#include "core/dom/Document.h"
-#include "core/platform/animation/CSSAnimationData.h"
#include "core/rendering/style/RenderStyleConstants.h"
#include "wtf/HashMap.h"
#include "wtf/Vector.h"
@@ -44,39 +44,40 @@
namespace WebCore {
+class CSSTransitionData;
class Element;
class StylePropertyShorthand;
class StyleResolver;
class StyleRuleKeyframes;
// This class stores the CSS Animations/Transitions information we use during a style recalc.
-// This includes updates to animations/transitions as well as the CompositableValueMaps to be applied.
-class CSSAnimationUpdate FINAL {
+// This includes updates to animations/transitions as well as the Interpolations to be applied.
+class CSSAnimationUpdate FINAL : public NoBaseWillBeGarbageCollectedFinalized<CSSAnimationUpdate> {
public:
- void startAnimation(AtomicString& animationName, const HashSet<RefPtr<InertAnimation> >& animations)
+ void startAnimation(AtomicString& animationName, PassRefPtrWillBeRawPtr<InertAnimation> animation)
{
NewAnimation newAnimation;
newAnimation.name = animationName;
- newAnimation.animations = animations;
+ newAnimation.animation = animation;
m_newAnimations.append(newAnimation);
}
// Returns whether player has been cancelled and should be filtered during style application.
- bool isCancelledAnimation(const Player* player) const { return m_cancelledAnimationPlayers.contains(player); }
- void cancelAnimation(const AtomicString& name, const HashSet<RefPtr<Player> >& players)
+ bool isCancelledAnimation(const AnimationPlayer* player) const { return m_cancelledAnimationPlayers.contains(player); }
+ void cancelAnimation(const AtomicString& name, AnimationPlayer& player)
{
m_cancelledAnimationNames.append(name);
- for (HashSet<RefPtr<Player> >::const_iterator iter = players.begin(); iter != players.end(); ++iter)
- m_cancelledAnimationPlayers.add(iter->get());
+ m_cancelledAnimationPlayers.add(&player);
}
void toggleAnimationPaused(const AtomicString& name)
{
m_animationsWithPauseToggled.append(name);
}
- void startTransition(CSSPropertyID id, const AnimatableValue* from, const AnimatableValue* to, PassRefPtr<InertAnimation> animation)
+ void startTransition(CSSPropertyID id, CSSPropertyID eventId, const AnimatableValue* from, const AnimatableValue* to, PassRefPtrWillBeRawPtr<InertAnimation> animation)
{
NewTransition newTransition;
newTransition.id = id;
+ newTransition.eventId = eventId;
newTransition.from = from;
newTransition.to = to;
newTransition.animation = animation;
@@ -86,29 +87,46 @@ public:
void cancelTransition(CSSPropertyID id) { m_cancelledTransitions.add(id); }
struct NewAnimation {
+ ALLOW_ONLY_INLINE_ALLOCATION();
+ public:
+ void trace(Visitor* visitor)
+ {
+ visitor->trace(animation);
+ }
+
AtomicString name;
- HashSet<RefPtr<InertAnimation> > animations;
+ RefPtrWillBeMember<InertAnimation> animation;
};
- const Vector<NewAnimation>& newAnimations() const { return m_newAnimations; }
+ const WillBeHeapVector<NewAnimation>& newAnimations() const { return m_newAnimations; }
const Vector<AtomicString>& cancelledAnimationNames() const { return m_cancelledAnimationNames; }
- const HashSet<const Player*>& cancelledAnimationPlayers() const { return m_cancelledAnimationPlayers; }
+ const WillBeHeapHashSet<RawPtrWillBeMember<const AnimationPlayer> >& cancelledAnimationAnimationPlayers() const { return m_cancelledAnimationPlayers; }
const Vector<AtomicString>& animationsWithPauseToggled() const { return m_animationsWithPauseToggled; }
struct NewTransition {
+ ALLOW_ONLY_INLINE_ALLOCATION();
+ public:
+ void trace(Visitor* visitor)
+ {
+ visitor->trace(from);
+ visitor->trace(to);
+ visitor->trace(animation);
+ }
+
CSSPropertyID id;
- const AnimatableValue* from;
- const AnimatableValue* to;
- RefPtr<InertAnimation> animation;
+ CSSPropertyID eventId;
+ RawPtrWillBeMember<const AnimatableValue> from;
+ RawPtrWillBeMember<const AnimatableValue> to;
+ RefPtrWillBeMember<InertAnimation> animation;
};
- typedef HashMap<CSSPropertyID, NewTransition> NewTransitionMap;
+ typedef WillBeHeapHashMap<CSSPropertyID, NewTransition> NewTransitionMap;
const NewTransitionMap& newTransitions() const { return m_newTransitions; }
const HashSet<CSSPropertyID>& cancelledTransitions() const { return m_cancelledTransitions; }
- void adoptCompositableValuesForAnimations(AnimationEffect::CompositableValueMap& newMap) { newMap.swap(m_compositableValuesForAnimations); }
- void adoptCompositableValuesForTransitions(AnimationEffect::CompositableValueMap& newMap) { newMap.swap(m_compositableValuesForTransitions); }
- const AnimationEffect::CompositableValueMap& compositableValuesForAnimations() const { return m_compositableValuesForAnimations; }
- const AnimationEffect::CompositableValueMap& compositableValuesForTransitions() const { return m_compositableValuesForTransitions; }
- AnimationEffect::CompositableValueMap& compositableValuesForAnimations() { return m_compositableValuesForAnimations; }
+ void adoptActiveInterpolationsForAnimations(WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& newMap) { newMap.swap(m_activeInterpolationsForAnimations); }
+ void adoptActiveInterpolationsForTransitions(WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& newMap) { newMap.swap(m_activeInterpolationsForTransitions); }
+ const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForAnimations() const { return m_activeInterpolationsForAnimations; }
+ const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForTransitions() const { return m_activeInterpolationsForTransitions; }
+ WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForAnimations() { return m_activeInterpolationsForAnimations; }
bool isEmpty() const
{
@@ -118,28 +136,35 @@ public:
&& m_animationsWithPauseToggled.isEmpty()
&& m_newTransitions.isEmpty()
&& m_cancelledTransitions.isEmpty()
- && m_compositableValuesForAnimations.isEmpty()
- && m_compositableValuesForTransitions.isEmpty();
+ && m_activeInterpolationsForAnimations.isEmpty()
+ && m_activeInterpolationsForTransitions.isEmpty();
}
+
+ void trace(Visitor*);
+
private:
// Order is significant since it defines the order in which new animations
// will be started. Note that there may be multiple animations present
// with the same name, due to the way in which we split up animations with
// incomplete keyframes.
- Vector<NewAnimation> m_newAnimations;
+ WillBeHeapVector<NewAnimation> m_newAnimations;
Vector<AtomicString> m_cancelledAnimationNames;
- HashSet<const Player*> m_cancelledAnimationPlayers;
+ WillBeHeapHashSet<RawPtrWillBeMember<const AnimationPlayer> > m_cancelledAnimationPlayers;
Vector<AtomicString> m_animationsWithPauseToggled;
NewTransitionMap m_newTransitions;
HashSet<CSSPropertyID> m_cancelledTransitions;
- AnimationEffect::CompositableValueMap m_compositableValuesForAnimations;
- AnimationEffect::CompositableValueMap m_compositableValuesForTransitions;
+ WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > m_activeInterpolationsForAnimations;
+ WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > m_activeInterpolationsForTransitions;
};
class CSSAnimations FINAL {
+ WTF_MAKE_NONCOPYABLE(CSSAnimations);
+ DISALLOW_ALLOCATION();
public:
+ CSSAnimations();
+
// FIXME: This method is only used here and in the legacy animations
// implementation. It should be made private or file-scope when the legacy
// engine is removed.
@@ -147,68 +172,91 @@ public:
static bool isAnimatableProperty(CSSPropertyID);
static const StylePropertyShorthand& animatableProperties();
+ static bool isAllowedAnimation(CSSPropertyID);
// FIXME: This should take a const ScopedStyleTree instead of a StyleResolver.
// We should also change the Element* to a const Element*
- static PassOwnPtr<CSSAnimationUpdate> calculateUpdate(Element*, const Element& parentElement, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
+ static PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> calculateUpdate(Element*, const Element& parentElement, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
- void setPendingUpdate(PassOwnPtr<CSSAnimationUpdate> update) { m_pendingUpdate = update; }
+ void setPendingUpdate(PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> update) { m_pendingUpdate = update; }
void maybeApplyPendingUpdate(Element*);
bool isEmpty() const { return m_animations.isEmpty() && m_transitions.isEmpty() && !m_pendingUpdate; }
void cancel();
+ void trace(Visitor*);
+
private:
- // Note that a single animation name may map to multiple players due to
- // the way in which we split up animations with incomplete keyframes.
- // FIXME: Once the Web Animations model supports groups, we could use a
- // ParGroup to drive multiple animations from a single Player.
- typedef HashMap<AtomicString, HashSet<RefPtr<Player> > > AnimationMap;
struct RunningTransition {
- Animation* transition; // The TransitionTimeline keeps the Players alive
- const AnimatableValue* from;
- const AnimatableValue* to;
+ ALLOW_ONLY_INLINE_ALLOCATION();
+ public:
+ void trace(Visitor* visitor)
+ {
+ visitor->trace(from);
+ visitor->trace(to);
+ visitor->trace(player);
+ }
+
+ RefPtrWillBeMember<AnimationPlayer> player;
+ RawPtrWillBeMember<const AnimatableValue> from;
+ RawPtrWillBeMember<const AnimatableValue> to;
};
- typedef HashMap<CSSPropertyID, RunningTransition > TransitionMap;
+
+ typedef WillBeHeapHashMap<AtomicString, RefPtrWillBeMember<AnimationPlayer> > AnimationMap;
AnimationMap m_animations;
+
+ typedef WillBeHeapHashMap<CSSPropertyID, RunningTransition> TransitionMap;
TransitionMap m_transitions;
- OwnPtr<CSSAnimationUpdate> m_pendingUpdate;
- AnimationEffect::CompositableValueMap m_previousCompositableValuesForAnimations;
+ OwnPtrWillBeMember<CSSAnimationUpdate> m_pendingUpdate;
+
+ WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > m_previousActiveInterpolationsForAnimations;
static void calculateAnimationUpdate(CSSAnimationUpdate*, Element*, const Element& parentElement, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
static void calculateTransitionUpdate(CSSAnimationUpdate*, const Element*, const RenderStyle&);
- static void calculateTransitionUpdateForProperty(CSSPropertyID, const CSSAnimationData*, const RenderStyle& oldStyle, const RenderStyle&, const TransitionMap* activeTransitions, CSSAnimationUpdate*, const Element*);
+ static void calculateTransitionUpdateForProperty(CSSPropertyID, CSSPropertyID eventId, const CSSTransitionData&, size_t transitionIndex, const RenderStyle& oldStyle, const RenderStyle&, const TransitionMap* activeTransitions, CSSAnimationUpdate*, const Element*);
- static void calculateAnimationCompositableValues(CSSAnimationUpdate*, const Element*);
- static void calculateTransitionCompositableValues(CSSAnimationUpdate*, const Element*);
+ static void calculateAnimationActiveInterpolations(CSSAnimationUpdate*, const Element*, double timelineCurrentTime);
+ static void calculateTransitionActiveInterpolations(CSSAnimationUpdate*, const Element*, double timelineCurrentTime);
- class AnimationEventDelegate FINAL : public TimedItem::EventDelegate {
+ class AnimationEventDelegate FINAL : public AnimationNode::EventDelegate {
public:
AnimationEventDelegate(Element* target, const AtomicString& name)
: m_target(target)
, m_name(name)
+ , m_previousPhase(AnimationNode::PhaseNone)
+ , m_previousIteration(nullValue())
{
}
- virtual void onEventCondition(const TimedItem*, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration) OVERRIDE;
+ virtual void onEventCondition(const AnimationNode*) OVERRIDE;
private:
void maybeDispatch(Document::ListenerType, const AtomicString& eventName, double elapsedTime);
Element* m_target;
const AtomicString m_name;
+ AnimationNode::Phase m_previousPhase;
+ double m_previousIteration;
};
- class TransitionEventDelegate FINAL : public TimedItem::EventDelegate {
+ class TransitionEventDelegate FINAL : public AnimationNode::EventDelegate {
public:
TransitionEventDelegate(Element* target, CSSPropertyID property)
: m_target(target)
, m_property(property)
+ , m_previousPhase(AnimationNode::PhaseNone)
{
}
- virtual void onEventCondition(const TimedItem*, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration) OVERRIDE;
+ virtual void onEventCondition(const AnimationNode*) OVERRIDE;
private:
Element* m_target;
const CSSPropertyID m_property;
+ AnimationNode::Phase m_previousPhase;
};
};
} // namespace WebCore
+namespace WTF {
+template<> struct VectorTraits<WebCore::CSSAnimationUpdate::NewAnimation> : VectorTraitsBase<WebCore::CSSAnimationUpdate::NewAnimation> {
+ static const bool canInitializeWithMemset = true;
+};
+}
+
#endif
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSPendingAnimations.cpp b/chromium/third_party/WebKit/Source/core/animation/css/CSSPendingAnimations.cpp
deleted file mode 100644
index 3a4ec03d29e..00000000000
--- a/chromium/third_party/WebKit/Source/core/animation/css/CSSPendingAnimations.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "core/animation/css/CSSPendingAnimations.h"
-
-#include "core/animation/Animation.h"
-#include "core/animation/DocumentTimeline.h"
-#include "core/frame/FrameView.h"
-
-namespace WebCore {
-
-void CSSPendingAnimations::add(Player* player)
-{
- ASSERT(player->source()->isAnimation());
- // The actual start time is either this value, or the time that
- // this animation, or an animation that it is synchronized with
- // is started on the compositor.
- const double defaultStartTime = player->timeline().currentTime();
- m_pending.append(std::make_pair(player, defaultStartTime));
-}
-
-bool CSSPendingAnimations::startPendingAnimations()
-{
- bool startedOnCompositor = false;
- for (size_t i = 0; i < m_pending.size(); ++i) {
- if (m_pending[i].first->maybeStartAnimationOnCompositor())
- startedOnCompositor = true;
- }
-
- // If any animations were started on the compositor, all remaining
- // need to wait for a synchronized start time. Otherwise they may
- // start immediately.
- if (startedOnCompositor) {
- for (size_t i = 0; i < m_pending.size(); ++i)
- m_waitingForCompositorAnimationStart.append(m_pending[i].first);
- } else {
- for (size_t i = 0; i < m_pending.size(); ++i)
- m_pending[i].first->setStartTime(m_pending[i].second);
- }
- m_pending.clear();
-
- if (startedOnCompositor || m_waitingForCompositorAnimationStart.isEmpty())
- return !m_waitingForCompositorAnimationStart.isEmpty();
-
- // Check if we're still waiting for any compositor animations to start.
- for (size_t i = 0; i < m_waitingForCompositorAnimationStart.size(); ++i) {
- if (m_waitingForCompositorAnimationStart[i].get()->hasActiveAnimationsOnCompositor())
- return true;
- }
-
- // If not, go ahead and start any animations that were waiting.
- notifyCompositorAnimationStarted(monotonicallyIncreasingTime());
- return false;
-}
-
-void CSSPendingAnimations::notifyCompositorAnimationStarted(double monotonicAnimationStartTime)
-{
- for (size_t i = 0; i < m_waitingForCompositorAnimationStart.size(); ++i) {
- Player* player = m_waitingForCompositorAnimationStart[i].get();
- player->setStartTime(monotonicAnimationStartTime - player->timeline().zeroTime());
- }
-
- m_waitingForCompositorAnimationStart.clear();
-}
-
-} // namespace
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSPendingAnimations.h b/chromium/third_party/WebKit/Source/core/animation/css/CSSPendingAnimations.h
deleted file mode 100644
index 1bb3c28d4c0..00000000000
--- a/chromium/third_party/WebKit/Source/core/animation/css/CSSPendingAnimations.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CSSPendingAnimations_h
-#define CSSPendingAnimations_h
-
-#include "core/animation/Player.h"
-#include "wtf/Vector.h"
-
-namespace WebCore {
-
-// Used to synchronize the start of main-thread animations with compositor
-// animations when both classes of CSS Animations are triggered by the same recalc
-class CSSPendingAnimations FINAL {
-public:
- void add(Player*);
- // Returns whether we are waiting for an animation to start and should
- // service again on the next frame.
- bool startPendingAnimations();
- void notifyCompositorAnimationStarted(double monotonicAnimationStartTime);
-
-private:
- Vector<std::pair<RefPtr<Player>, double> > m_pending;
- Vector<RefPtr<Player> > m_waitingForCompositorAnimationStart;
-};
-
-} // namespace WebCore
-
-#endif
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.cpp b/chromium/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.cpp
new file mode 100644
index 00000000000..70ad01dbcb4
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.cpp
@@ -0,0 +1,318 @@
+// Copyright 2014 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 "config.h"
+#include "core/animation/css/CSSPropertyEquality.h"
+
+#include "core/animation/css/CSSAnimations.h"
+#include "core/rendering/style/DataEquivalency.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/ShadowList.h"
+
+namespace WebCore {
+
+namespace {
+
+template <CSSPropertyID property>
+bool fillLayersEqual(const FillLayer* aLayer, const FillLayer* bLayer)
+{
+ if (aLayer == bLayer)
+ return true;
+ if (!aLayer || !bLayer)
+ return false;
+ while (aLayer && bLayer) {
+ switch (property) {
+ case CSSPropertyBackgroundPositionX:
+ case CSSPropertyWebkitMaskPositionX:
+ if (aLayer->xPosition() != bLayer->xPosition())
+ return false;
+ break;
+ case CSSPropertyBackgroundPositionY:
+ case CSSPropertyWebkitMaskPositionY:
+ if (aLayer->yPosition() != bLayer->yPosition())
+ return false;
+ break;
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyWebkitBackgroundSize:
+ case CSSPropertyWebkitMaskSize:
+ if (!(aLayer->sizeLength() == bLayer->sizeLength()))
+ return false;
+ break;
+ case CSSPropertyBackgroundImage:
+ if (!dataEquivalent(aLayer->image(), bLayer->image()))
+ return false;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ return true;
+ }
+
+ aLayer = aLayer->next();
+ bLayer = bLayer->next();
+ }
+
+ // FIXME: Shouldn't this be return !aLayer && !bLayer; ?
+ return true;
+}
+
+}
+
+bool CSSPropertyEquality::propertiesEqual(CSSPropertyID prop, const RenderStyle& a, const RenderStyle& b)
+{
+ switch (prop) {
+ case CSSPropertyBackgroundColor:
+ return a.backgroundColor().resolve(a.color()) == b.backgroundColor().resolve(b.color())
+ && a.visitedLinkBackgroundColor().resolve(a.color()) == b.visitedLinkBackgroundColor().resolve(b.color());
+ case CSSPropertyBackgroundImage:
+ return fillLayersEqual<CSSPropertyBackgroundImage>(a.backgroundLayers(), b.backgroundLayers());
+ case CSSPropertyBackgroundPositionX:
+ return fillLayersEqual<CSSPropertyBackgroundPositionX>(a.backgroundLayers(), b.backgroundLayers());
+ case CSSPropertyBackgroundPositionY:
+ return fillLayersEqual<CSSPropertyBackgroundPositionY>(a.backgroundLayers(), b.backgroundLayers());
+ case CSSPropertyBackgroundSize:
+ return fillLayersEqual<CSSPropertyBackgroundSize>(a.backgroundLayers(), b.backgroundLayers());
+ case CSSPropertyBaselineShift:
+ return dataEquivalent(a.baselineShiftValue(), b.baselineShiftValue());
+ case CSSPropertyBorderBottomColor:
+ return a.borderBottomColor().resolve(a.color()) == b.borderBottomColor().resolve(b.color())
+ && a.visitedLinkBorderBottomColor().resolve(a.color()) == b.visitedLinkBorderBottomColor().resolve(b.color());
+ case CSSPropertyBorderBottomLeftRadius:
+ return a.borderBottomLeftRadius() == b.borderBottomLeftRadius();
+ case CSSPropertyBorderBottomRightRadius:
+ return a.borderBottomRightRadius() == b.borderBottomRightRadius();
+ case CSSPropertyBorderBottomWidth:
+ return a.borderBottomWidth() == b.borderBottomWidth();
+ case CSSPropertyBorderImageOutset:
+ return a.borderImageOutset() == b.borderImageOutset();
+ case CSSPropertyBorderImageSlice:
+ return a.borderImageSlices() == b.borderImageSlices();
+ case CSSPropertyBorderImageSource:
+ return dataEquivalent(a.borderImageSource(), b.borderImageSource());
+ case CSSPropertyBorderImageWidth:
+ return a.borderImageWidth() == b.borderImageWidth();
+ case CSSPropertyBorderLeftColor:
+ return a.borderLeftColor().resolve(a.color()) == b.borderLeftColor().resolve(b.color())
+ && a.visitedLinkBorderLeftColor().resolve(a.color()) == b.visitedLinkBorderLeftColor().resolve(b.color());
+ case CSSPropertyBorderLeftWidth:
+ return a.borderLeftWidth() == b.borderLeftWidth();
+ case CSSPropertyBorderRightColor:
+ return a.borderRightColor().resolve(a.color()) == b.borderRightColor().resolve(b.color())
+ && a.visitedLinkBorderRightColor().resolve(a.color()) == b.visitedLinkBorderRightColor().resolve(b.color());
+ case CSSPropertyBorderRightWidth:
+ return a.borderRightWidth() == b.borderRightWidth();
+ case CSSPropertyBorderTopColor:
+ return a.borderTopColor().resolve(a.color()) == b.borderTopColor().resolve(b.color())
+ && a.visitedLinkBorderTopColor().resolve(a.color()) == b.visitedLinkBorderTopColor().resolve(b.color());
+ case CSSPropertyBorderTopLeftRadius:
+ return a.borderTopLeftRadius() == b.borderTopLeftRadius();
+ case CSSPropertyBorderTopRightRadius:
+ return a.borderTopRightRadius() == b.borderTopRightRadius();
+ case CSSPropertyBorderTopWidth:
+ return a.borderTopWidth() == b.borderTopWidth();
+ case CSSPropertyBottom:
+ return a.bottom() == b.bottom();
+ case CSSPropertyBoxShadow:
+ return dataEquivalent(a.boxShadow(), b.boxShadow());
+ case CSSPropertyClip:
+ return a.clip() == b.clip();
+ case CSSPropertyColor:
+ return a.color() == b.color() && a.visitedLinkColor() == b.visitedLinkColor();
+ case CSSPropertyFill: {
+ const SVGRenderStyle& aSVG = *a.svgStyle();
+ const SVGRenderStyle& bSVG = *b.svgStyle();
+ return aSVG.fillPaintType() == bSVG.fillPaintType()
+ && (aSVG.fillPaintType() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR || aSVG.fillPaintColor() == bSVG.fillPaintColor())
+ && aSVG.visitedLinkFillPaintType() == bSVG.visitedLinkFillPaintType()
+ && (aSVG.visitedLinkFillPaintType() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR || aSVG.visitedLinkFillPaintColor() == bSVG.visitedLinkFillPaintColor());
+ }
+ case CSSPropertyFillOpacity:
+ return a.fillOpacity() == b.fillOpacity();
+ case CSSPropertyFlexBasis:
+ return a.flexBasis() == b.flexBasis();
+ case CSSPropertyFlexGrow:
+ return a.flexGrow() == b.flexGrow();
+ case CSSPropertyFlexShrink:
+ return a.flexShrink() == b.flexShrink();
+ case CSSPropertyFloodColor:
+ return a.floodColor() == b.floodColor();
+ case CSSPropertyFloodOpacity:
+ return a.floodOpacity() == b.floodOpacity();
+ case CSSPropertyFontSize:
+ // CSSPropertyFontSize: Must pass a specified size to setFontSize if Text Autosizing is enabled, but a computed size
+ // if text zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
+ // FIXME: Should we introduce an option to pass the computed font size here, allowing consumers to
+ // enable text zoom rather than Text Autosizing? See http://crbug.com/227545.
+ return a.specifiedFontSize() == b.specifiedFontSize();
+ case CSSPropertyFontWeight:
+ return a.fontWeight() == b.fontWeight();
+ case CSSPropertyHeight:
+ return a.height() == b.height();
+ case CSSPropertyLeft:
+ return a.left() == b.left();
+ case CSSPropertyLetterSpacing:
+ return a.letterSpacing() == b.letterSpacing();
+ case CSSPropertyLightingColor:
+ return a.lightingColor() == b.lightingColor();
+ case CSSPropertyLineHeight:
+ return a.specifiedLineHeight() == b.specifiedLineHeight();
+ case CSSPropertyListStyleImage:
+ return dataEquivalent(a.listStyleImage(), b.listStyleImage());
+ case CSSPropertyMarginBottom:
+ return a.marginBottom() == b.marginBottom();
+ case CSSPropertyMarginLeft:
+ return a.marginLeft() == b.marginLeft();
+ case CSSPropertyMarginRight:
+ return a.marginRight() == b.marginRight();
+ case CSSPropertyMarginTop:
+ return a.marginTop() == b.marginTop();
+ case CSSPropertyMaxHeight:
+ return a.maxHeight() == b.maxHeight();
+ case CSSPropertyMaxWidth:
+ return a.maxWidth() == b.maxWidth();
+ case CSSPropertyMinHeight:
+ return a.minHeight() == b.minHeight();
+ case CSSPropertyMinWidth:
+ return a.minWidth() == b.minWidth();
+ case CSSPropertyObjectPosition:
+ return a.objectPosition() == b.objectPosition();
+ case CSSPropertyOpacity:
+ return a.opacity() == b.opacity();
+ case CSSPropertyOrphans:
+ return a.orphans() == b.orphans();
+ case CSSPropertyOutlineColor:
+ return a.outlineColor().resolve(a.color()) == b.outlineColor().resolve(b.color())
+ && a.visitedLinkOutlineColor().resolve(a.color()) == b.visitedLinkOutlineColor().resolve(b.color());
+ case CSSPropertyOutlineOffset:
+ return a.outlineOffset() == b.outlineOffset();
+ case CSSPropertyOutlineWidth:
+ return a.outlineWidth() == b.outlineWidth();
+ case CSSPropertyPaddingBottom:
+ return a.paddingBottom() == b.paddingBottom();
+ case CSSPropertyPaddingLeft:
+ return a.paddingLeft() == b.paddingLeft();
+ case CSSPropertyPaddingRight:
+ return a.paddingRight() == b.paddingRight();
+ case CSSPropertyPaddingTop:
+ return a.paddingTop() == b.paddingTop();
+ case CSSPropertyRight:
+ return a.right() == b.right();
+ case CSSPropertyShapeImageThreshold:
+ return a.shapeImageThreshold() == b.shapeImageThreshold();
+ case CSSPropertyShapeMargin:
+ return a.shapeMargin() == b.shapeMargin();
+ case CSSPropertyShapeOutside:
+ return dataEquivalent(a.shapeOutside(), b.shapeOutside());
+ case CSSPropertyStopColor:
+ return a.stopColor() == b.stopColor();
+ case CSSPropertyStopOpacity:
+ return a.stopOpacity() == b.stopOpacity();
+ case CSSPropertyStroke: {
+ const SVGRenderStyle& aSVG = *a.svgStyle();
+ const SVGRenderStyle& bSVG = *b.svgStyle();
+ return aSVG.strokePaintType() == bSVG.strokePaintType()
+ && (aSVG.strokePaintType() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR || aSVG.strokePaintColor() == bSVG.strokePaintColor())
+ && aSVG.visitedLinkStrokePaintType() == bSVG.visitedLinkStrokePaintType()
+ && (aSVG.visitedLinkStrokePaintType() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR || aSVG.visitedLinkStrokePaintColor() == bSVG.visitedLinkStrokePaintColor());
+ }
+ case CSSPropertyStrokeDasharray:
+ return dataEquivalent(a.strokeDashArray(), b.strokeDashArray());
+ case CSSPropertyStrokeDashoffset:
+ return dataEquivalent(a.strokeDashOffset(), b.strokeDashOffset());
+ case CSSPropertyStrokeMiterlimit:
+ return a.strokeMiterLimit() == b.strokeMiterLimit();
+ case CSSPropertyStrokeOpacity:
+ return a.strokeOpacity() == b.strokeOpacity();
+ case CSSPropertyStrokeWidth:
+ return dataEquivalent(a.strokeWidth(), b.strokeWidth());
+ case CSSPropertyTextDecorationColor:
+ return a.textDecorationColor().resolve(a.color()) == b.textDecorationColor().resolve(b.color())
+ && a.visitedLinkTextDecorationColor().resolve(a.color()) == b.visitedLinkTextDecorationColor().resolve(b.color());
+ case CSSPropertyTextIndent:
+ return a.textIndent() == b.textIndent();
+ case CSSPropertyTextShadow:
+ return dataEquivalent(a.textShadow(), b.textShadow());
+ case CSSPropertyTop:
+ return a.top() == b.top();
+ case CSSPropertyVerticalAlign:
+ return a.verticalAlign() == b.verticalAlign()
+ && (a.verticalAlign() != LENGTH || a.verticalAlignLength() == b.verticalAlignLength());
+ case CSSPropertyVisibility:
+ return a.visibility() == b.visibility();
+ case CSSPropertyWebkitBackgroundSize:
+ return fillLayersEqual<CSSPropertyWebkitBackgroundSize>(a.backgroundLayers(), b.backgroundLayers());
+ case CSSPropertyWebkitBorderHorizontalSpacing:
+ return a.horizontalBorderSpacing() == b.horizontalBorderSpacing();
+ case CSSPropertyWebkitBorderVerticalSpacing:
+ return a.verticalBorderSpacing() == b.verticalBorderSpacing();
+ case CSSPropertyWebkitBoxShadow:
+ return dataEquivalent(a.boxShadow(), b.boxShadow());
+ case CSSPropertyWebkitClipPath:
+ return dataEquivalent(a.clipPath(), b.clipPath());
+ case CSSPropertyWebkitColumnCount:
+ return a.columnCount() == b.columnCount();
+ case CSSPropertyWebkitColumnGap:
+ return a.columnGap() == b.columnGap();
+ case CSSPropertyWebkitColumnRuleColor:
+ return a.columnRuleColor().resolve(a.color()) == b.columnRuleColor().resolve(b.color())
+ && a.visitedLinkColumnRuleColor().resolve(a.color()) == b.visitedLinkColumnRuleColor().resolve(b.color());
+ case CSSPropertyWebkitColumnRuleWidth:
+ return a.columnRuleWidth() == b.columnRuleWidth();
+ case CSSPropertyWebkitColumnWidth:
+ return a.columnWidth() == b.columnWidth();
+ case CSSPropertyWebkitFilter:
+ return a.filter() == b.filter();
+ case CSSPropertyWebkitMaskBoxImageOutset:
+ return a.maskBoxImageOutset() == b.maskBoxImageOutset();
+ case CSSPropertyWebkitMaskBoxImageSlice:
+ return a.maskBoxImageSlices() == b.maskBoxImageSlices();
+ case CSSPropertyWebkitMaskBoxImageSource:
+ return dataEquivalent(a.maskBoxImageSource(), b.maskBoxImageSource());
+ case CSSPropertyWebkitMaskBoxImageWidth:
+ return a.maskBoxImageWidth() == b.maskBoxImageWidth();
+ case CSSPropertyWebkitMaskImage:
+ return dataEquivalent(a.maskImage(), b.maskImage());
+ case CSSPropertyWebkitMaskPositionX:
+ return fillLayersEqual<CSSPropertyWebkitMaskPositionX>(a.maskLayers(), b.maskLayers());
+ case CSSPropertyWebkitMaskPositionY:
+ return fillLayersEqual<CSSPropertyWebkitMaskPositionY>(a.maskLayers(), b.maskLayers());
+ case CSSPropertyWebkitMaskSize:
+ return fillLayersEqual<CSSPropertyWebkitMaskSize>(a.maskLayers(), b.maskLayers());
+ case CSSPropertyPerspective:
+ return a.perspective() == b.perspective();
+ case CSSPropertyPerspectiveOrigin:
+ return a.perspectiveOriginX() == b.perspectiveOriginX() && a.perspectiveOriginY() == b.perspectiveOriginY();
+ case CSSPropertyWebkitPerspectiveOriginX:
+ return a.perspectiveOriginX() == b.perspectiveOriginX();
+ case CSSPropertyWebkitPerspectiveOriginY:
+ return a.perspectiveOriginY() == b.perspectiveOriginY();
+ case CSSPropertyWebkitTextStrokeColor:
+ return a.textStrokeColor().resolve(a.color()) == b.textStrokeColor().resolve(b.color())
+ && a.visitedLinkTextStrokeColor().resolve(a.color()) == b.visitedLinkTextStrokeColor().resolve(b.color());
+ case CSSPropertyTransform:
+ return a.transform() == b.transform();
+ case CSSPropertyTransformOrigin:
+ return a.transformOriginX() == b.transformOriginX() && a.transformOriginY() == b.transformOriginY() && a.transformOriginZ() == b.transformOriginZ();
+ case CSSPropertyWebkitTransformOriginX:
+ return a.transformOriginX() == b.transformOriginX();
+ case CSSPropertyWebkitTransformOriginY:
+ return a.transformOriginY() == b.transformOriginY();
+ case CSSPropertyWebkitTransformOriginZ:
+ return a.transformOriginZ() == b.transformOriginZ();
+ case CSSPropertyWidows:
+ return a.widows() == b.widows();
+ case CSSPropertyWidth:
+ return a.width() == b.width();
+ case CSSPropertyWordSpacing:
+ return a.wordSpacing() == b.wordSpacing();
+ case CSSPropertyZIndex:
+ return a.zIndex() == b.zIndex();
+ case CSSPropertyZoom:
+ return a.zoom() == b.zoom();
+ default:
+ ASSERT_NOT_REACHED();
+ return true;
+ }
+}
+
+}
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.h b/chromium/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.h
new file mode 100644
index 00000000000..0a436f0046c
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSPropertyEquality.h
@@ -0,0 +1,21 @@
+// Copyright 2014 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 CSSPropertyEquality_h
+#define CSSPropertyEquality_h
+
+#include "core/CSSPropertyNames.h"
+
+namespace WebCore {
+
+class RenderStyle;
+
+class CSSPropertyEquality {
+public:
+ static bool propertiesEqual(CSSPropertyID, const RenderStyle&, const RenderStyle&);
+};
+
+} // namespace WebCore
+
+#endif // CSSPropertyEquality_h
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSTimingData.cpp b/chromium/third_party/WebKit/Source/core/animation/css/CSSTimingData.cpp
new file mode 100644
index 00000000000..9d628bd32c3
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSTimingData.cpp
@@ -0,0 +1,36 @@
+// Copyright 2014 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 "config.h"
+#include "core/animation/css/CSSTimingData.h"
+
+#include "core/animation/Timing.h"
+
+namespace WebCore {
+
+CSSTimingData::CSSTimingData()
+{
+ m_delayList.append(initialDelay());
+ m_durationList.append(initialDuration());
+ m_timingFunctionList.append(initialTimingFunction());
+}
+
+CSSTimingData::CSSTimingData(const CSSTimingData& other)
+ : m_delayList(other.m_delayList)
+ , m_durationList(other.m_durationList)
+ , m_timingFunctionList(other.m_timingFunctionList)
+{
+}
+
+Timing CSSTimingData::convertToTiming(size_t index) const
+{
+ Timing timing;
+ timing.startDelay = getRepeated(m_delayList, index);
+ timing.iterationDuration = getRepeated(m_durationList, index);
+ timing.timingFunction = getRepeated(m_timingFunctionList, index);
+ timing.assertValid();
+ return timing;
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSTimingData.h b/chromium/third_party/WebKit/Source/core/animation/css/CSSTimingData.h
new file mode 100644
index 00000000000..33eab3b4b27
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSTimingData.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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 CSSTimingData_h
+#define CSSTimingData_h
+
+#include "platform/animation/TimingFunction.h"
+#include "platform/heap/Handle.h"
+#include "wtf/Vector.h"
+
+namespace WebCore {
+
+struct Timing;
+
+class CSSTimingData : public NoBaseWillBeGarbageCollectedFinalized<CSSTimingData> {
+public:
+ ~CSSTimingData() { }
+
+ void trace(Visitor*) { }
+
+ const Vector<double>& delayList() const { return m_delayList; }
+ const Vector<double>& durationList() const { return m_durationList; }
+ const Vector<RefPtr<TimingFunction> >& timingFunctionList() const { return m_timingFunctionList; }
+
+ Vector<double>& delayList() { return m_delayList; }
+ Vector<double>& durationList() { return m_durationList; }
+ Vector<RefPtr<TimingFunction> >& timingFunctionList() { return m_timingFunctionList; }
+
+ static double initialDelay() { return 0; }
+ static double initialDuration() { return 0; }
+ static PassRefPtr<TimingFunction> initialTimingFunction() { return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease); }
+
+ template <class T> static const T& getRepeated(const Vector<T>& v, size_t index) { return v[index % v.size()]; }
+
+protected:
+ CSSTimingData();
+ explicit CSSTimingData(const CSSTimingData&);
+
+ Timing convertToTiming(size_t index) const;
+
+private:
+ Vector<double> m_delayList;
+ Vector<double> m_durationList;
+ Vector<RefPtr<TimingFunction> > m_timingFunctionList;
+};
+
+} // namespace WebCore
+
+#endif // CSSTimingData_h
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSTransitionData.cpp b/chromium/third_party/WebKit/Source/core/animation/css/CSSTransitionData.cpp
new file mode 100644
index 00000000000..ad20621f30f
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSTransitionData.cpp
@@ -0,0 +1,37 @@
+// Copyright 2014 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 "config.h"
+#include "core/animation/css/CSSTransitionData.h"
+
+#include "core/animation/Timing.h"
+
+namespace WebCore {
+
+CSSTransitionData::CSSTransitionData()
+{
+ m_propertyList.append(initialProperty());
+}
+
+CSSTransitionData::CSSTransitionData(const CSSTransitionData& other)
+ : CSSTimingData(other)
+ , m_propertyList(other.m_propertyList)
+{
+}
+
+bool CSSTransitionData::transitionsMatchForStyleRecalc(const CSSTransitionData& other) const
+{
+ return m_propertyList == other.m_propertyList;
+}
+
+Timing CSSTransitionData::convertToTiming(size_t index) const
+{
+ ASSERT(index < m_propertyList.size());
+ // Note that the backwards fill part is required for delay to work.
+ Timing timing = CSSTimingData::convertToTiming(index);
+ timing.fillMode = Timing::FillModeBoth;
+ return timing;
+}
+
+} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/CSSTransitionData.h b/chromium/third_party/WebKit/Source/core/animation/css/CSSTransitionData.h
new file mode 100644
index 00000000000..792afc77afa
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/animation/css/CSSTransitionData.h
@@ -0,0 +1,81 @@
+// Copyright 2014 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 CSSTransitionData_h
+#define CSSTransitionData_h
+
+#include "core/CSSPropertyNames.h"
+#include "core/animation/css/CSSTimingData.h"
+#include "wtf/Vector.h"
+
+namespace WebCore {
+
+class CSSTransitionData FINAL : public CSSTimingData {
+public:
+ enum TransitionPropertyType {
+ TransitionNone,
+ TransitionSingleProperty,
+ TransitionUnknown,
+ TransitionAll
+ };
+
+ // FIXME: We shouldn't allow 'none' to be used alongside other properties.
+ struct TransitionProperty {
+ TransitionProperty(CSSPropertyID id)
+ : propertyType(TransitionSingleProperty)
+ , propertyId(id)
+ {
+ ASSERT(id != CSSPropertyInvalid);
+ }
+
+ TransitionProperty(const String& string)
+ : propertyType(TransitionUnknown)
+ , propertyId(CSSPropertyInvalid)
+ , propertyString(string)
+ {
+ }
+
+ TransitionProperty(TransitionPropertyType type)
+ : propertyType(type)
+ , propertyId(CSSPropertyInvalid)
+ {
+ ASSERT(type == TransitionNone || type == TransitionAll);
+ }
+
+ bool operator==(const TransitionProperty& other) const { return propertyType == other.propertyType && propertyId == other.propertyId && propertyString == other.propertyString; }
+
+ TransitionPropertyType propertyType;
+ CSSPropertyID propertyId;
+ String propertyString;
+ };
+
+ static PassOwnPtrWillBeRawPtr<CSSTransitionData> create()
+ {
+ return adoptPtrWillBeNoop(new CSSTransitionData);
+ }
+
+ static PassOwnPtrWillBeRawPtr<CSSTransitionData> create(const CSSTransitionData& transitionData)
+ {
+ return adoptPtrWillBeNoop(new CSSTransitionData(transitionData));
+ }
+
+ bool transitionsMatchForStyleRecalc(const CSSTransitionData& other) const;
+
+ Timing convertToTiming(size_t index) const;
+
+ const Vector<TransitionProperty>& propertyList() const { return m_propertyList; }
+ Vector<TransitionProperty>& propertyList() { return m_propertyList; }
+
+ static TransitionProperty initialProperty() { return TransitionProperty(TransitionAll); }
+
+private:
+ CSSTransitionData();
+ explicit CSSTransitionData(const CSSTransitionData&);
+
+ Vector<TransitionProperty> m_propertyList;
+};
+
+} // namespace WebCore
+
+#endif // CSSTransitionData_h
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/TransitionTimeline.cpp b/chromium/third_party/WebKit/Source/core/animation/css/TransitionTimeline.cpp
deleted file mode 100644
index 33ec27f2b0b..00000000000
--- a/chromium/third_party/WebKit/Source/core/animation/css/TransitionTimeline.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "core/animation/css/TransitionTimeline.h"
-
-#include "core/animation/ActiveAnimations.h"
-#include "core/animation/AnimationClock.h"
-#include "core/animation/AnimationStack.h"
-
-namespace WebCore {
-
-PassRefPtr<TransitionTimeline> TransitionTimeline::create(Document* document, PassOwnPtr<PlatformTiming> timing)
-{
- return adoptRef(new TransitionTimeline(document, timing));
-}
-
-TransitionTimeline::TransitionTimeline(Document* document, PassOwnPtr<PlatformTiming> timing)
- : DocumentTimeline(document, timing)
-{
- setZeroTime(document->animationClock().currentTime());
- document->animationClock().unfreeze();
-}
-
-} // namespace WebCore
diff --git a/chromium/third_party/WebKit/Source/core/animation/css/TransitionTimeline.h b/chromium/third_party/WebKit/Source/core/animation/css/TransitionTimeline.h
deleted file mode 100644
index 6d55f48772e..00000000000
--- a/chromium/third_party/WebKit/Source/core/animation/css/TransitionTimeline.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TransitionTimeline_h
-#define TransitionTimeline_h
-
-#include "core/animation/DocumentTimeline.h"
-
-namespace WebCore {
-
-class TransitionTimeline FINAL : public DocumentTimeline {
-public:
- static PassRefPtr<TransitionTimeline> create(Document*, PassOwnPtr<PlatformTiming> = nullptr);
-
-private:
- TransitionTimeline(Document*, PassOwnPtr<PlatformTiming>);
-};
-
-} // namespace WebCore
-
-#endif