2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "core/frame/animation/CSSPropertyAnimation.h"
34 #include "StylePropertyShorthand.h"
35 #include "core/animation/css/CSSAnimations.h"
36 #include "core/css/CSSCrossfadeValue.h"
37 #include "core/css/CSSImageValue.h"
38 #include "core/css/CSSPrimitiveValue.h"
39 #include "core/fetch/ImageResource.h"
40 #include "core/frame/animation/AnimationBase.h"
41 #include "core/rendering/ClipPathOperation.h"
42 #include "core/rendering/RenderBox.h"
43 #include "core/rendering/style/RenderStyle.h"
44 #include "core/rendering/style/ShadowList.h"
45 #include "core/rendering/style/StyleFetchedImage.h"
46 #include "core/rendering/style/StyleGeneratedImage.h"
47 #include "platform/FloatConversion.h"
48 #include "wtf/Noncopyable.h"
53 static inline T blendFunc(const AnimationBase*, T from, T to, double progress)
55 return blend(from, to, progress);
58 static inline float blendFunc(const AnimationBase*, float from, float to, double progress)
60 return narrowPrecisionToFloat(from + (to - from) * progress);
63 static inline Color blendFunc(const AnimationBase*, const Color& from, const Color& to, double progress)
65 return blend(from, to, progress);
68 static inline Length blendFunc(const AnimationBase*, const Length& from, const Length& to, double progress)
70 return to.blend(from, progress, ValueRangeAll);
73 static inline BorderImageLength blendFunc(const AnimationBase* anim, const BorderImageLength& from, const BorderImageLength& to, double progress)
75 if (from.isNumber() && to.isNumber())
76 return BorderImageLength(blendFunc(anim, from.number(), to.number(), progress));
78 if (from.isLength() && to.isLength())
79 return BorderImageLength(blendFunc(anim, from.length(), to.length(), progress));
81 // FIXME: Converting numbers to lengths using the computed border
82 // width would make it possible to interpolate between numbers and
84 // https://code.google.com/p/chromium/issues/detail?id=316164
88 static inline BorderImageLengthBox blendFunc(const AnimationBase* anim, const BorderImageLengthBox& from,
89 const BorderImageLengthBox& to, double progress)
91 return BorderImageLengthBox(blendFunc(anim, from.top(), to.top(), progress),
92 blendFunc(anim, from.right(), to.right(), progress),
93 blendFunc(anim, from.bottom(), to.bottom(), progress),
94 blendFunc(anim, from.left(), to.left(), progress));
97 static inline LengthSize blendFunc(const AnimationBase* anim, const LengthSize& from, const LengthSize& to, double progress)
99 return LengthSize(blendFunc(anim, from.width(), to.width(), progress),
100 blendFunc(anim, from.height(), to.height(), progress));
103 static inline LengthPoint blendFunc(const AnimationBase* anim, const LengthPoint& from, const LengthPoint& to, double progress)
105 return LengthPoint(blendFunc(anim, from.x(), to.x(), progress), blendFunc(anim, from.y(), to.y(), progress));
108 static inline TransformOperations blendFunc(const AnimationBase* anim, const TransformOperations& from, const TransformOperations& to, double progress)
110 if (anim->isTransformFunctionListValid())
111 return to.blendByMatchingOperations(from, progress);
112 return to.blendByUsingMatrixInterpolation(from, progress);
115 static inline PassRefPtr<ClipPathOperation> blendFunc(const AnimationBase*, ClipPathOperation* from, ClipPathOperation* to, double progress)
117 // Other clip-path operations than BasicShapes can not be animated.
118 if (!from || !to || from->type() != ClipPathOperation::SHAPE || to->type() != ClipPathOperation::SHAPE)
121 const BasicShape* fromShape = toShapeClipPathOperation(from)->basicShape();
122 const BasicShape* toShape = toShapeClipPathOperation(to)->basicShape();
124 if (!fromShape->canBlend(toShape))
127 return ShapeClipPathOperation::create(toShape->blend(fromShape, progress));
130 static inline PassRefPtr<ShapeValue> blendFunc(const AnimationBase*, ShapeValue* from, ShapeValue* to, double progress)
132 // FIXME Bug 102723: Shape-inside should be able to animate a value of 'outside-shape' when shape-outside is set to a BasicShape
133 if (!from || !to || from->type() != ShapeValue::Shape || to->type() != ShapeValue::Shape)
136 const BasicShape* fromShape = from->shape();
137 const BasicShape* toShape = to->shape();
139 if (!fromShape->canBlend(toShape))
142 return ShapeValue::createShapeValue(toShape->blend(fromShape, progress));
145 static inline FilterOperations blendFunc(const AnimationBase* anim, const FilterOperations& from, const FilterOperations& to, double progress)
147 FilterOperations result;
149 // If we have a filter function list, use that to do a per-function animation.
150 if (anim->filterFunctionListsMatch()) {
151 size_t fromSize = from.operations().size();
152 size_t toSize = to.operations().size();
153 size_t size = max(fromSize, toSize);
154 for (size_t i = 0; i < size; i++) {
155 const FilterOperation* fromOp = (i < fromSize) ? from.operations()[i].get() : 0;
156 const FilterOperation* toOp = (i < toSize) ? to.operations()[i].get() : 0;
157 RefPtr<FilterOperation> blendedOp = FilterOperation::blend(fromOp, toOp, progress);
159 result.operations().append(blendedOp);
161 ASSERT_NOT_REACHED();
164 // If the filter function lists don't match, we could try to cross-fade, but don't yet have a way to represent that in CSS.
165 // For now we'll just fail to animate.
172 static inline EVisibility blendFunc(const AnimationBase* anim, EVisibility from, EVisibility to, double progress)
174 // Any non-zero result means we consider the object to be visible. Only at 0 do we consider the object to be
175 // invisible. The invisible value we use (HIDDEN vs. COLLAPSE) depends on the specified from/to values.
176 double fromVal = from == VISIBLE ? 1. : 0.;
177 double toVal = to == VISIBLE ? 1. : 0.;
178 if (fromVal == toVal)
180 double result = blendFunc(anim, fromVal, toVal, progress);
181 return result > 0. ? VISIBLE : (to != VISIBLE ? to : from);
184 static inline LengthBox blendFunc(const AnimationBase* anim, const LengthBox& from, const LengthBox& to, double progress)
186 // Length types have to match to animate
187 if (from.top().type() != to.top().type()
188 || from.right().type() != to.right().type()
189 || from.bottom().type() != to.bottom().type()
190 || from.left().type() != to.left().type())
193 LengthBox result(blendFunc(anim, from.top(), to.top(), progress),
194 blendFunc(anim, from.right(), to.right(), progress),
195 blendFunc(anim, from.bottom(), to.bottom(), progress),
196 blendFunc(anim, from.left(), to.left(), progress));
200 static inline PassRefPtr<SVGLength> blendFunc(const AnimationBase*, PassRefPtr<SVGLength> from, PassRefPtr<SVGLength> to, double progress)
202 return to->blend(from, narrowPrecisionToFloat(progress));
205 static inline PassRefPtr<SVGLengthList> blendFunc(const AnimationBase*, PassRefPtr<SVGLengthList> passFrom, PassRefPtr<SVGLengthList> passTo, double progress)
207 RefPtr<SVGLengthList> from = passFrom;
208 RefPtr<SVGLengthList> to = passTo;
210 size_t fromLength = from->numberOfItems();
211 size_t toLength = to->numberOfItems();
213 return !progress ? from->clone() : to->clone();
215 return progress == 1 ? from->clone() : to->clone();
217 size_t resultLength = fromLength;
218 if (fromLength != toLength) {
219 if (!(fromLength % toLength))
220 resultLength = fromLength;
221 else if (!(toLength % fromLength))
222 resultLength = toLength;
224 resultLength = fromLength * toLength;
226 RefPtr<SVGLengthList> result = SVGLengthList::create();
227 for (size_t i = 0; i < resultLength; ++i)
228 result->append(to->at(i % toLength)->blend(from->at(i % fromLength), narrowPrecisionToFloat(progress)));
232 static inline PassRefPtr<StyleImage> crossfadeBlend(const AnimationBase*, StyleFetchedImage* fromStyleImage, StyleFetchedImage* toStyleImage, double progress)
234 // If progress is at one of the extremes, we want getComputedStyle to show the image,
235 // not a completed cross-fade, so we hand back one of the existing images.
237 return fromStyleImage;
241 ImageResource* fromImageResource = static_cast<ImageResource*>(fromStyleImage->data());
242 ImageResource* toImageResource = static_cast<ImageResource*>(toStyleImage->data());
244 RefPtr<CSSImageValue> fromImageValue = CSSImageValue::create(fromImageResource->url(), fromStyleImage);
245 RefPtr<CSSImageValue> toImageValue = CSSImageValue::create(toImageResource->url(), toStyleImage);
246 RefPtr<CSSCrossfadeValue> crossfadeValue = CSSCrossfadeValue::create(fromImageValue, toImageValue);
248 crossfadeValue->setPercentage(CSSPrimitiveValue::create(progress, CSSPrimitiveValue::CSS_NUMBER));
250 return StyleGeneratedImage::create(crossfadeValue.get());
253 static inline PassRefPtr<StyleImage> blendFunc(const AnimationBase* anim, StyleImage* from, StyleImage* to, double progress)
258 if (from->isImageResource() && to->isImageResource())
259 return crossfadeBlend(anim, toStyleFetchedImage(from), toStyleFetchedImage(to), progress);
261 // FIXME: Support transitioning generated images as well. (gradients, etc.)
266 class AnimationPropertyWrapperBase {
267 WTF_MAKE_NONCOPYABLE(AnimationPropertyWrapperBase);
268 WTF_MAKE_FAST_ALLOCATED;
270 AnimationPropertyWrapperBase(CSSPropertyID prop)
275 virtual ~AnimationPropertyWrapperBase() { }
277 virtual bool isShorthandWrapper() const { return false; }
278 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const = 0;
279 virtual void blend(const AnimationBase*, RenderStyle*, const RenderStyle*, const RenderStyle*, double) const = 0;
281 CSSPropertyID property() const { return m_prop; }
283 virtual bool animationIsAccelerated() const { return false; }
286 CSSPropertyID m_prop;
289 static int gPropertyWrapperMap[numCSSProperties];
290 static const int cInvalidPropertyWrapperIndex = -1;
291 static Vector<AnimationPropertyWrapperBase*>* gPropertyWrappers = 0;
293 static void addPropertyWrapper(CSSPropertyID propertyID, AnimationPropertyWrapperBase* wrapper)
295 int propIndex = propertyID - firstCSSProperty;
297 ASSERT(gPropertyWrapperMap[propIndex] == cInvalidPropertyWrapperIndex);
299 unsigned wrapperIndex = gPropertyWrappers->size();
300 gPropertyWrappers->append(wrapper);
301 gPropertyWrapperMap[propIndex] = wrapperIndex;
304 static AnimationPropertyWrapperBase* wrapperForProperty(CSSPropertyID propertyID)
306 int propIndex = propertyID - firstCSSProperty;
307 if (propIndex >= 0 && propIndex < numCSSProperties) {
308 int wrapperIndex = gPropertyWrapperMap[propIndex];
309 if (wrapperIndex >= 0)
310 return (*gPropertyWrappers)[wrapperIndex];
315 template <typename T>
316 class PropertyWrapperGetter : public AnimationPropertyWrapperBase {
318 PropertyWrapperGetter(CSSPropertyID prop, T (RenderStyle::*getter)() const)
319 : AnimationPropertyWrapperBase(prop)
324 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
326 // If the style pointers are the same, don't bother doing the test.
327 // If either is null, return false. If both are null, return true.
328 if ((!a && !b) || a == b)
332 return (a->*m_getter)() == (b->*m_getter)();
336 T (RenderStyle::*m_getter)() const;
339 template <typename T>
340 class PropertyWrapper : public PropertyWrapperGetter<T> {
342 PropertyWrapper(CSSPropertyID prop, T (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T))
343 : PropertyWrapperGetter<T>(prop, getter)
348 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
350 (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T>::m_getter)(), (b->*PropertyWrapperGetter<T>::m_getter)(), progress));
354 void (RenderStyle::*m_setter)(T);
357 class NonNegativeLengthWrapper FINAL : public PropertyWrapper<Length> {
359 NonNegativeLengthWrapper(CSSPropertyID prop, Length (RenderStyle::*getter)() const, void (RenderStyle::*setter)(Length))
360 : PropertyWrapper<Length>(prop, getter, setter)
364 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
366 Length from = (a->*PropertyWrapperGetter<Length>::m_getter)();
367 Length to = (b->*PropertyWrapperGetter<Length>::m_getter)();
368 (dst->*PropertyWrapper<Length>::m_setter)(to.blend(from, progress, ValueRangeNonNegative));
372 template <typename T>
373 class RefCountedPropertyWrapper : public PropertyWrapperGetter<T*> {
375 RefCountedPropertyWrapper(CSSPropertyID prop, T* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<T>))
376 : PropertyWrapperGetter<T*>(prop, getter)
381 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
383 (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T*>::m_getter)(), (b->*PropertyWrapperGetter<T*>::m_getter)(), progress));
386 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
392 const T* aValue = (a->*this->m_getter)();
393 const T* bValue = (b->*this->m_getter)();
394 if (aValue == bValue)
396 if (!aValue || !bValue)
398 return *aValue == *bValue;
402 void (RenderStyle::*m_setter)(PassRefPtr<T>);
406 class PropertyWrapperClipPath : public RefCountedPropertyWrapper<ClipPathOperation> {
408 PropertyWrapperClipPath(CSSPropertyID prop, ClipPathOperation* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ClipPathOperation>))
409 : RefCountedPropertyWrapper<ClipPathOperation>(prop, getter, setter)
414 class PropertyWrapperShape : public RefCountedPropertyWrapper<ShapeValue> {
416 PropertyWrapperShape(CSSPropertyID prop, ShapeValue* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ShapeValue>))
417 : RefCountedPropertyWrapper<ShapeValue>(prop, getter, setter)
422 class StyleImagePropertyWrapper FINAL : public RefCountedPropertyWrapper<StyleImage> {
424 StyleImagePropertyWrapper(CSSPropertyID prop, StyleImage* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<StyleImage>))
425 : RefCountedPropertyWrapper<StyleImage>(prop, getter, setter)
429 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
431 // If the style pointers are the same, don't bother doing the test.
432 // If either is null, return false. If both are null, return true.
438 StyleImage* imageA = (a->*m_getter)();
439 StyleImage* imageB = (b->*m_getter)();
440 return StyleImage::imagesEquivalent(imageA, imageB);
444 class PropertyWrapperColor FINAL : public PropertyWrapperGetter<Color> {
446 PropertyWrapperColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&))
447 : PropertyWrapperGetter<Color>(prop, getter)
452 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
454 (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<Color>::m_getter)(), (b->*PropertyWrapperGetter<Color>::m_getter)(), progress));
458 void (RenderStyle::*m_setter)(const Color&);
461 class PropertyWrapperAcceleratedOpacity FINAL : public PropertyWrapper<float> {
463 PropertyWrapperAcceleratedOpacity()
464 : PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity)
468 virtual bool animationIsAccelerated() const OVERRIDE { return true; }
470 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
472 float fromOpacity = a->opacity();
474 // This makes sure we put the object being animated into a RenderLayer during the animation
475 dst->setOpacity(blendFunc(anim, (fromOpacity == 1) ? 0.999999f : fromOpacity, b->opacity(), progress));
479 class PropertyWrapperAcceleratedTransform FINAL : public PropertyWrapper<const TransformOperations&> {
481 PropertyWrapperAcceleratedTransform()
482 : PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform)
486 virtual bool animationIsAccelerated() const OVERRIDE { return true; }
488 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
490 dst->setTransform(blendFunc(anim, a->transform(), b->transform(), progress));
494 class PropertyWrapperAcceleratedFilter FINAL : public PropertyWrapper<const FilterOperations&> {
496 PropertyWrapperAcceleratedFilter()
497 : PropertyWrapper<const FilterOperations&>(CSSPropertyWebkitFilter, &RenderStyle::filter, &RenderStyle::setFilter)
501 virtual bool animationIsAccelerated() const OVERRIDE { return true; }
503 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
505 dst->setFilter(blendFunc(anim, a->filter(), b->filter(), progress));
509 class PropertyWrapperShadow FINAL : public AnimationPropertyWrapperBase {
511 PropertyWrapperShadow(CSSPropertyID prop, ShadowList* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ShadowList>))
512 : AnimationPropertyWrapperBase(prop)
518 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
520 const ShadowList* shadowA = (a->*m_getter)();
521 const ShadowList* shadowB = (b->*m_getter)();
522 if (shadowA == shadowB)
524 if (shadowA && shadowB)
525 return *shadowA == *shadowB;
529 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
531 (dst->*m_setter)(ShadowList::blend((a->*m_getter)(), (b->*m_getter)(), progress));
534 ShadowList* (RenderStyle::*m_getter)() const;
535 void (RenderStyle::*m_setter)(PassRefPtr<ShadowList>);
538 class PropertyWrapperMaybeInvalidStyleColor FINAL : public AnimationPropertyWrapperBase {
540 PropertyWrapperMaybeInvalidStyleColor(CSSPropertyID prop, StyleColor (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const StyleColor&))
541 : AnimationPropertyWrapperBase(prop)
547 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
549 StyleColor fromColor = (a->*m_getter)();
550 StyleColor toColor = (b->*m_getter)();
552 if (fromColor.isCurrentColor() && toColor.isCurrentColor())
555 return fromColor.resolve(a->color()) == toColor.resolve(b->color());
558 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
560 StyleColor fromColor = (a->*m_getter)();
561 StyleColor toColor = (b->*m_getter)();
563 if (fromColor.isCurrentColor() && toColor.isCurrentColor())
566 (dst->*m_setter)(blendFunc(anim, fromColor.resolve(a->color()), toColor.resolve(b->color()), progress));
570 StyleColor (RenderStyle::*m_getter)() const;
571 void (RenderStyle::*m_setter)(const StyleColor&);
575 class PropertyWrapperVisitedAffectedColor FINAL : public AnimationPropertyWrapperBase {
577 PropertyWrapperVisitedAffectedColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&),
578 Color (RenderStyle::*visitedGetter)() const, void (RenderStyle::*visitedSetter)(const Color&))
579 : AnimationPropertyWrapperBase(prop)
580 , m_wrapper(adoptPtr(new PropertyWrapperColor(prop, getter, setter)))
581 , m_visitedWrapper(adoptPtr(new PropertyWrapperColor(prop, visitedGetter, visitedSetter)))
584 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
586 return m_wrapper->equals(a, b) && m_visitedWrapper->equals(a, b);
588 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
590 m_wrapper->blend(anim, dst, a, b, progress);
591 m_visitedWrapper->blend(anim, dst, a, b, progress);
595 OwnPtr<AnimationPropertyWrapperBase> m_wrapper;
596 OwnPtr<AnimationPropertyWrapperBase> m_visitedWrapper;
599 class PropertyWrapperVisitedAffectedStyleColor FINAL : public AnimationPropertyWrapperBase {
601 PropertyWrapperVisitedAffectedStyleColor(CSSPropertyID prop, StyleColor (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const StyleColor&),
602 StyleColor (RenderStyle::*visitedGetter)() const, void (RenderStyle::*visitedSetter)(const StyleColor&))
603 : AnimationPropertyWrapperBase(prop)
604 , m_wrapper(adoptPtr(new PropertyWrapperMaybeInvalidStyleColor(prop, getter, setter)))
605 , m_visitedWrapper(adoptPtr(new PropertyWrapperMaybeInvalidStyleColor(prop, visitedGetter, visitedSetter)))
608 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
610 return m_wrapper->equals(a, b) && m_visitedWrapper->equals(a, b);
612 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
614 m_wrapper->blend(anim, dst, a, b, progress);
615 m_visitedWrapper->blend(anim, dst, a, b, progress);
619 OwnPtr<AnimationPropertyWrapperBase> m_wrapper;
620 OwnPtr<AnimationPropertyWrapperBase> m_visitedWrapper;
623 // Wrapper base class for an animatable property in a FillLayer
624 class FillLayerAnimationPropertyWrapperBase {
626 FillLayerAnimationPropertyWrapperBase()
630 virtual ~FillLayerAnimationPropertyWrapperBase() { }
632 virtual bool equals(const FillLayer*, const FillLayer*) const = 0;
633 virtual void blend(const AnimationBase*, FillLayer*, const FillLayer*, const FillLayer*, double) const = 0;
636 template <typename T>
637 class FillLayerPropertyWrapperGetter : public FillLayerAnimationPropertyWrapperBase {
638 WTF_MAKE_NONCOPYABLE(FillLayerPropertyWrapperGetter);
640 FillLayerPropertyWrapperGetter(T (FillLayer::*getter)() const)
645 virtual bool equals(const FillLayer* a, const FillLayer* b) const
647 // If the style pointers are the same, don't bother doing the test.
648 // If either is null, return false. If both are null, return true.
649 if ((!a && !b) || a == b)
653 return (a->*m_getter)() == (b->*m_getter)();
657 T (FillLayer::*m_getter)() const;
660 template <typename T>
661 class FillLayerPropertyWrapper FINAL : public FillLayerPropertyWrapperGetter<T> {
663 FillLayerPropertyWrapper(T (FillLayer::*getter)() const, void (FillLayer::*setter)(T))
664 : FillLayerPropertyWrapperGetter<T>(getter)
669 virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const OVERRIDE
671 (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T>::m_getter)(), progress));
675 void (FillLayer::*m_setter)(T);
678 template <typename T>
679 class FillLayerRefCountedPropertyWrapper : public FillLayerPropertyWrapperGetter<T*> {
681 FillLayerRefCountedPropertyWrapper(T* (FillLayer::*getter)() const, void (FillLayer::*setter)(PassRefPtr<T>))
682 : FillLayerPropertyWrapperGetter<T*>(getter)
687 virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const
689 (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), progress));
693 void (FillLayer::*m_setter)(PassRefPtr<T>);
696 class FillLayerStyleImagePropertyWrapper FINAL : public FillLayerRefCountedPropertyWrapper<StyleImage> {
698 FillLayerStyleImagePropertyWrapper(StyleImage* (FillLayer::*getter)() const, void (FillLayer::*setter)(PassRefPtr<StyleImage>))
699 : FillLayerRefCountedPropertyWrapper<StyleImage>(getter, setter)
703 virtual bool equals(const FillLayer* a, const FillLayer* b) const OVERRIDE
705 // If the style pointers are the same, don't bother doing the test.
706 // If either is null, return false. If both are null, return true.
712 StyleImage* imageA = (a->*m_getter)();
713 StyleImage* imageB = (b->*m_getter)();
714 return StyleImage::imagesEquivalent(imageA, imageB);
719 class FillLayersPropertyWrapper FINAL : public AnimationPropertyWrapperBase {
721 typedef const FillLayer* (RenderStyle::*LayersGetter)() const;
722 typedef FillLayer* (RenderStyle::*LayersAccessor)();
724 FillLayersPropertyWrapper(CSSPropertyID prop, LayersGetter getter, LayersAccessor accessor)
725 : AnimationPropertyWrapperBase(prop)
726 , m_layersGetter(getter)
727 , m_layersAccessor(accessor)
730 case CSSPropertyBackgroundPositionX:
731 case CSSPropertyWebkitMaskPositionX:
732 m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::xPosition, &FillLayer::setXPosition);
734 case CSSPropertyBackgroundPositionY:
735 case CSSPropertyWebkitMaskPositionY:
736 m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::yPosition, &FillLayer::setYPosition);
738 case CSSPropertyBackgroundSize:
739 case CSSPropertyWebkitBackgroundSize:
740 case CSSPropertyWebkitMaskSize:
741 m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<LengthSize>(&FillLayer::sizeLength, &FillLayer::setSizeLength);
743 case CSSPropertyBackgroundImage:
744 m_fillLayerPropertyWrapper = new FillLayerStyleImagePropertyWrapper(&FillLayer::image, &FillLayer::setImage);
751 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
753 const FillLayer* fromLayer = (a->*m_layersGetter)();
754 const FillLayer* toLayer = (b->*m_layersGetter)();
756 while (fromLayer && toLayer) {
757 if (!m_fillLayerPropertyWrapper->equals(fromLayer, toLayer))
760 fromLayer = fromLayer->next();
761 toLayer = toLayer->next();
767 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
769 const FillLayer* aLayer = (a->*m_layersGetter)();
770 const FillLayer* bLayer = (b->*m_layersGetter)();
771 FillLayer* dstLayer = (dst->*m_layersAccessor)();
773 while (aLayer && bLayer && dstLayer) {
774 m_fillLayerPropertyWrapper->blend(anim, dstLayer, aLayer, bLayer, progress);
775 aLayer = aLayer->next();
776 bLayer = bLayer->next();
777 dstLayer = dstLayer->next();
782 FillLayerAnimationPropertyWrapperBase* m_fillLayerPropertyWrapper;
784 LayersGetter m_layersGetter;
785 LayersAccessor m_layersAccessor;
788 class ShorthandPropertyWrapper FINAL : public AnimationPropertyWrapperBase {
790 ShorthandPropertyWrapper(CSSPropertyID property, const StylePropertyShorthand& shorthand)
791 : AnimationPropertyWrapperBase(property)
793 for (unsigned i = 0; i < shorthand.length(); ++i) {
794 AnimationPropertyWrapperBase* wrapper = wrapperForProperty(shorthand.properties()[i]);
796 m_propertyWrappers.append(wrapper);
800 virtual bool isShorthandWrapper() const OVERRIDE { return true; }
802 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
804 Vector<AnimationPropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end();
805 for (Vector<AnimationPropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) {
806 if (!(*it)->equals(a, b))
812 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
814 Vector<AnimationPropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end();
815 for (Vector<AnimationPropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it)
816 (*it)->blend(anim, dst, a, b, progress);
819 const Vector<AnimationPropertyWrapperBase*> propertyWrappers() const { return m_propertyWrappers; }
822 Vector<AnimationPropertyWrapperBase*> m_propertyWrappers;
825 class PropertyWrapperFlex FINAL : public AnimationPropertyWrapperBase {
827 PropertyWrapperFlex()
828 : AnimationPropertyWrapperBase(CSSPropertyFlex)
832 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
834 // If the style pointers are the same, don't bother doing the test.
835 // If either is null, return false. If both are null, return true.
836 if ((!a && !b) || a == b)
841 return a->flexBasis() == b->flexBasis() && a->flexGrow() == b->flexGrow() && a->flexShrink() == b->flexShrink();
844 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
846 dst->setFlexBasis(blendFunc(anim, a->flexBasis(), b->flexBasis(), progress));
847 dst->setFlexGrow(blendFunc(anim, a->flexGrow(), b->flexGrow(), progress));
848 dst->setFlexShrink(blendFunc(anim, a->flexShrink(), b->flexShrink(), progress));
852 class PropertyWrapperSVGPaint FINAL : public AnimationPropertyWrapperBase {
854 PropertyWrapperSVGPaint(CSSPropertyID prop, const SVGPaint::SVGPaintType& (RenderStyle::*paintTypeGetter)() const, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&))
855 : AnimationPropertyWrapperBase(prop)
856 , m_paintTypeGetter(paintTypeGetter)
862 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
864 if ((a->*m_paintTypeGetter)() != (b->*m_paintTypeGetter)())
867 // We only support animations between SVGPaints that are pure Color values.
868 // For everything else we must return true for this method, otherwise
869 // we will try to animate between values forever.
870 if ((a->*m_paintTypeGetter)() == SVGPaint::SVG_PAINTTYPE_RGBCOLOR) {
871 Color fromColor = (a->*m_getter)();
872 Color toColor = (b->*m_getter)();
873 return fromColor == toColor;
878 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const OVERRIDE
880 if ((a->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR
881 || (b->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR)
884 Color fromColor = (a->*m_getter)();
885 Color toColor = (b->*m_getter)();
887 (dst->*m_setter)(blendFunc(anim, fromColor, toColor, progress));
891 const SVGPaint::SVGPaintType& (RenderStyle::*m_paintTypeGetter)() const;
892 Color (RenderStyle::*m_getter)() const;
893 void (RenderStyle::*m_setter)(const Color&);
896 template <typename T>
897 class RefCountedSVGPropertyWrapper : public AnimationPropertyWrapperBase {
899 RefCountedSVGPropertyWrapper(CSSPropertyID prop, PassRefPtr<T> (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<T>))
900 : AnimationPropertyWrapperBase(prop)
906 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
908 (dst->*m_setter)(blendFunc(anim, (a->*m_getter)(), (b->*m_getter)(), progress));
911 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const OVERRIDE
917 RefPtr<T> aValue = (a->*this->m_getter)();
918 RefPtr<T> bValue = (b->*this->m_getter)();
919 if (aValue == bValue)
921 if (!aValue || !bValue)
923 return *aValue == *bValue;
927 PassRefPtr<T> (RenderStyle::*m_getter)() const;
928 void (RenderStyle::*m_setter)(PassRefPtr<T>);
931 static void addShorthandProperties()
933 static const CSSPropertyID animatableShorthandProperties[] = {
934 CSSPropertyBackground, // for background-color, background-position, background-image
935 CSSPropertyBackgroundPosition,
936 CSSPropertyFont, // for font-size, font-weight
937 CSSPropertyWebkitMask, // for mask-position
938 CSSPropertyWebkitMaskPosition,
939 CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft,
940 CSSPropertyBorderColor,
941 CSSPropertyBorderRadius,
942 CSSPropertyBorderWidth,
944 CSSPropertyBorderImage,
945 CSSPropertyBorderSpacing,
946 CSSPropertyListStyle, // for list-style-image
950 CSSPropertyWebkitTextStroke,
951 CSSPropertyWebkitColumnRule,
952 CSSPropertyWebkitBorderRadius,
953 CSSPropertyWebkitTransformOrigin
956 for (size_t i = 0; i < WTF_ARRAY_LENGTH(animatableShorthandProperties); ++i) {
957 CSSPropertyID propertyID = animatableShorthandProperties[i];
958 StylePropertyShorthand shorthand = shorthandForProperty(propertyID);
959 if (shorthand.length() > 0)
960 addPropertyWrapper(propertyID, new ShorthandPropertyWrapper(propertyID, shorthand));
964 void CSSPropertyAnimation::ensurePropertyMap()
966 // FIXME: This data is never destroyed. Maybe we should ref count it and toss it when the last AnimationController is destroyed?
967 if (gPropertyWrappers)
970 gPropertyWrappers = new Vector<AnimationPropertyWrapperBase*>();
972 // build the list of property wrappers to do the comparisons and blends
973 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLeft, &RenderStyle::left, &RenderStyle::setLeft));
974 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight));
975 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop));
976 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom));
978 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth));
979 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinWidth, &RenderStyle::minWidth, &RenderStyle::setMinWidth));
980 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxWidth, &RenderStyle::maxWidth, &RenderStyle::setMaxWidth));
982 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight));
983 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinHeight, &RenderStyle::minHeight, &RenderStyle::setMinHeight));
984 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxHeight, &RenderStyle::maxHeight, &RenderStyle::setMaxHeight));
986 if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled())
987 gPropertyWrappers->append(new PropertyWrapperFlex());
989 gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderLeftWidth, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth));
990 gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderRightWidth, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth));
991 gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderTopWidth, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth));
992 gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderBottomWidth, &RenderStyle::borderBottomWidth, &RenderStyle::setBorderBottomWidth));
993 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginLeft, &RenderStyle::marginLeft, &RenderStyle::setMarginLeft));
994 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginRight, &RenderStyle::marginRight, &RenderStyle::setMarginRight));
995 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginTop, &RenderStyle::marginTop, &RenderStyle::setMarginTop));
996 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginBottom, &RenderStyle::marginBottom, &RenderStyle::setMarginBottom));
997 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingLeft, &RenderStyle::paddingLeft, &RenderStyle::setPaddingLeft));
998 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingRight, &RenderStyle::paddingRight, &RenderStyle::setPaddingRight));
999 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop));
1000 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom));
1001 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyColor, &RenderStyle::color, &RenderStyle::setColor, &RenderStyle::visitedLinkColor, &RenderStyle::setVisitedLinkColor));
1003 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedStyleColor(CSSPropertyBackgroundColor, &RenderStyle::backgroundColor, &RenderStyle::setBackgroundColor, &RenderStyle::visitedLinkBackgroundColor, &RenderStyle::setVisitedLinkBackgroundColor));
1005 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundImage, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers));
1006 gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyListStyleImage, &RenderStyle::listStyleImage, &RenderStyle::setListStyleImage));
1007 gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyWebkitMaskImage, &RenderStyle::maskImage, &RenderStyle::setMaskImage));
1009 gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyBorderImageSource, &RenderStyle::borderImageSource, &RenderStyle::setBorderImageSource));
1010 gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyBorderImageSlice, &RenderStyle::borderImageSlices, &RenderStyle::setBorderImageSlices));
1011 gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyBorderImageWidth, &RenderStyle::borderImageWidth, &RenderStyle::setBorderImageWidth));
1012 gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyBorderImageOutset, &RenderStyle::borderImageOutset, &RenderStyle::setBorderImageOutset));
1014 gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyWebkitMaskBoxImageSource, &RenderStyle::maskBoxImageSource, &RenderStyle::setMaskBoxImageSource));
1015 gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyWebkitMaskBoxImageSlice, &RenderStyle::maskBoxImageSlices, &RenderStyle::setMaskBoxImageSlices));
1016 gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyWebkitMaskBoxImageWidth, &RenderStyle::maskBoxImageWidth, &RenderStyle::setMaskBoxImageWidth));
1017 gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyWebkitMaskBoxImageOutset, &RenderStyle::maskBoxImageOutset, &RenderStyle::setMaskBoxImageOutset));
1019 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionX, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers));
1020 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionY, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers));
1021 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers));
1022 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers));
1024 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionX, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers));
1025 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionY, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers));
1026 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskSize, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers));
1028 gPropertyWrappers->append(new PropertyWrapper<LengthPoint>(CSSPropertyObjectPosition, &RenderStyle::objectPosition, &RenderStyle::setObjectPosition));
1030 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFontSize,
1031 // Must pass a specified size to setFontSize if Text Autosizing is enabled, but a computed size
1032 // if text zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
1033 // FIXME: Should we introduce an option to pass the computed font size here, allowing consumers to
1034 // enable text zoom rather than Text Autosizing? See http://crbug.com/227545.
1035 &RenderStyle::specifiedFontSize,
1036 &RenderStyle::setFontSize));
1037 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnRuleWidth, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth));
1038 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap));
1039 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnCount, &RenderStyle::columnCount, &RenderStyle::setColumnCount));
1040 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnWidth, &RenderStyle::columnWidth, &RenderStyle::setColumnWidth));
1041 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderHorizontalSpacing, &RenderStyle::horizontalBorderSpacing, &RenderStyle::setHorizontalBorderSpacing));
1042 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderVerticalSpacing, &RenderStyle::verticalBorderSpacing, &RenderStyle::setVerticalBorderSpacing));
1043 gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyZIndex, &RenderStyle::zIndex, &RenderStyle::setZIndex));
1044 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyOrphans, &RenderStyle::orphans, &RenderStyle::setOrphans));
1045 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWidows, &RenderStyle::widows, &RenderStyle::setWidows));
1046 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLineHeight, &RenderStyle::specifiedLineHeight, &RenderStyle::setLineHeight));
1047 gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyOutlineOffset, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset));
1048 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth));
1049 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing));
1050 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing));
1051 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent));
1053 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective));
1054 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX));
1055 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY));
1056 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX));
1057 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY));
1058 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitTransformOriginZ, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ));
1059 gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius));
1060 gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius));
1061 gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius));
1062 gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius));
1063 gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility));
1064 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoomWithoutReturnValue));
1066 gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyClip, &RenderStyle::clip, &RenderStyle::setClip));
1068 gPropertyWrappers->append(new PropertyWrapperAcceleratedOpacity());
1069 gPropertyWrappers->append(new PropertyWrapperAcceleratedTransform());
1070 gPropertyWrappers->append(new PropertyWrapperAcceleratedFilter());
1072 gPropertyWrappers->append(new PropertyWrapperClipPath(CSSPropertyWebkitClipPath, &RenderStyle::clipPath, &RenderStyle::setClipPath));
1074 gPropertyWrappers->append(new PropertyWrapperShape(CSSPropertyShapeInside, &RenderStyle::shapeInside, &RenderStyle::setShapeInside));
1075 gPropertyWrappers->append(new PropertyWrapperShape(CSSPropertyShapeOutside, &RenderStyle::shapeOutside, &RenderStyle::setShapeOutside));
1076 gPropertyWrappers->append(new NonNegativeLengthWrapper(CSSPropertyShapeMargin, &RenderStyle::shapeMargin, &RenderStyle::setShapeMargin));
1077 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyShapeImageThreshold, &RenderStyle::shapeImageThreshold, &RenderStyle::setShapeImageThreshold));
1079 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedStyleColor(CSSPropertyWebkitColumnRuleColor, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor, &RenderStyle::visitedLinkColumnRuleColor, &RenderStyle::setVisitedLinkColumnRuleColor));
1080 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedStyleColor(CSSPropertyWebkitTextStrokeColor, &RenderStyle::textStrokeColor, &RenderStyle::setTextStrokeColor, &RenderStyle::visitedLinkTextStrokeColor, &RenderStyle::setVisitedLinkTextStrokeColor));
1081 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedStyleColor(CSSPropertyBorderLeftColor, &RenderStyle::borderLeftColor, &RenderStyle::setBorderLeftColor, &RenderStyle::visitedLinkBorderLeftColor, &RenderStyle::setVisitedLinkBorderLeftColor));
1082 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedStyleColor(CSSPropertyBorderRightColor, &RenderStyle::borderRightColor, &RenderStyle::setBorderRightColor, &RenderStyle::visitedLinkBorderRightColor, &RenderStyle::setVisitedLinkBorderRightColor));
1083 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedStyleColor(CSSPropertyBorderTopColor, &RenderStyle::borderTopColor, &RenderStyle::setBorderTopColor, &RenderStyle::visitedLinkBorderTopColor, &RenderStyle::setVisitedLinkBorderTopColor));
1084 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedStyleColor(CSSPropertyBorderBottomColor, &RenderStyle::borderBottomColor, &RenderStyle::setBorderBottomColor, &RenderStyle::visitedLinkBorderBottomColor, &RenderStyle::setVisitedLinkBorderBottomColor));
1085 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedStyleColor(CSSPropertyOutlineColor, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor, &RenderStyle::visitedLinkOutlineColor, &RenderStyle::setVisitedLinkOutlineColor));
1087 gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow));
1088 gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyWebkitBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow));
1089 gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyTextShadow, &RenderStyle::textShadow, &RenderStyle::setTextShadow));
1091 gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyFill, &RenderStyle::fillPaintType, &RenderStyle::fillPaintColor, &RenderStyle::setFillPaintColor));
1092 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFillOpacity, &RenderStyle::fillOpacity, &RenderStyle::setFillOpacity));
1094 gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyStroke, &RenderStyle::strokePaintType, &RenderStyle::strokePaintColor, &RenderStyle::setStrokePaintColor));
1095 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeOpacity, &RenderStyle::strokeOpacity, &RenderStyle::setStrokeOpacity));
1096 gPropertyWrappers->append(new RefCountedSVGPropertyWrapper<SVGLength>(CSSPropertyStrokeWidth, &RenderStyle::strokeWidth, &RenderStyle::setStrokeWidth));
1097 gPropertyWrappers->append(new RefCountedSVGPropertyWrapper<SVGLengthList>(CSSPropertyStrokeDasharray, &RenderStyle::strokeDashArray, &RenderStyle::setStrokeDashArray));
1098 gPropertyWrappers->append(new RefCountedSVGPropertyWrapper<SVGLength>(CSSPropertyStrokeDashoffset, &RenderStyle::strokeDashOffset, &RenderStyle::setStrokeDashOffset));
1099 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeMiterlimit, &RenderStyle::strokeMiterLimit, &RenderStyle::setStrokeMiterLimit));
1101 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFloodOpacity, &RenderStyle::floodOpacity, &RenderStyle::setFloodOpacity));
1102 gPropertyWrappers->append(new PropertyWrapperColor(CSSPropertyFloodColor, &RenderStyle::floodColor, &RenderStyle::setFloodColor));
1104 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStopOpacity, &RenderStyle::stopOpacity, &RenderStyle::setStopOpacity));
1105 gPropertyWrappers->append(new PropertyWrapperColor(CSSPropertyStopColor, &RenderStyle::stopColor, &RenderStyle::setStopColor));
1107 gPropertyWrappers->append(new PropertyWrapperColor(CSSPropertyLightingColor, &RenderStyle::lightingColor, &RenderStyle::setLightingColor));
1109 gPropertyWrappers->append(new RefCountedSVGPropertyWrapper<SVGLength>(CSSPropertyBaselineShift, &RenderStyle::baselineShiftValue, &RenderStyle::setBaselineShiftValue));
1110 gPropertyWrappers->append(new RefCountedSVGPropertyWrapper<SVGLength>(CSSPropertyKerning, &RenderStyle::kerning, &RenderStyle::setKerning));
1112 if (RuntimeEnabledFeatures::webAnimationsCSSEnabled()) {
1113 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFlexGrow, &RenderStyle::flexGrow, &RenderStyle::setFlexGrow));
1114 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFlexShrink, &RenderStyle::flexShrink, &RenderStyle::setFlexShrink));
1115 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyFlexBasis, &RenderStyle::flexBasis, &RenderStyle::setFlexBasis));
1120 // CSSPropertyVerticalAlign
1122 // Compound properties that have components that should be animatable:
1124 // CSSPropertyWebkitColumns
1125 // CSSPropertyWebkitBoxReflect
1127 // Make sure unused slots have a value
1128 for (unsigned int i = 0; i < static_cast<unsigned int>(numCSSProperties); ++i)
1129 gPropertyWrapperMap[i] = cInvalidPropertyWrapperIndex;
1131 // First we put the non-shorthand property wrappers into the map, so the shorthand-building
1132 // code can find them.
1133 size_t n = gPropertyWrappers->size();
1134 for (unsigned int i = 0; i < n; ++i) {
1135 CSSPropertyID property = (*gPropertyWrappers)[i]->property();
1136 ASSERT_WITH_MESSAGE(RuntimeEnabledFeatures::webAnimationsCSSEnabled() || CSSAnimations::isAnimatableProperty(property), "%s is not whitelisted for animation", getPropertyNameString(property).utf8().data());
1137 ASSERT(property - firstCSSProperty < numCSSProperties);
1138 gPropertyWrapperMap[property - firstCSSProperty] = i;
1141 // Now add the shorthand wrappers.
1142 addShorthandProperties();
1145 // Returns true if we need to start animation timers
1146 bool CSSPropertyAnimation::blendProperties(const AnimationBase* anim, CSSPropertyID prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress)
1148 ASSERT(prop != CSSPropertyInvalid);
1150 ensurePropertyMap();
1152 AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop);
1154 wrapper->blend(anim, dst, a, b, progress);
1155 return !wrapper->animationIsAccelerated() || !anim->isAccelerated();
1161 bool CSSPropertyAnimation::animationOfPropertyIsAccelerated(CSSPropertyID prop)
1163 ensurePropertyMap();
1164 AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop);
1165 return wrapper ? wrapper->animationIsAccelerated() : false;
1168 bool CSSPropertyAnimation::propertiesEqual(CSSPropertyID prop, const RenderStyle* a, const RenderStyle* b)
1170 ensurePropertyMap();
1172 AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop);
1174 return wrapper->equals(a, b);
1178 CSSPropertyID CSSPropertyAnimation::getPropertyAtIndex(int i, bool& isShorthand)
1180 ensurePropertyMap();
1182 if (i < 0 || i >= getNumProperties())
1183 return CSSPropertyInvalid;
1185 AnimationPropertyWrapperBase* wrapper = (*gPropertyWrappers)[i];
1186 isShorthand = wrapper->isShorthandWrapper();
1187 return wrapper->property();
1190 int CSSPropertyAnimation::getNumProperties()
1192 ensurePropertyMap();
1194 return gPropertyWrappers->size();