18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1.  Redistributions of source code must retain the above copyright
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2.  Redistributions in binary form must reproduce the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer in the
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     documentation and/or other materials provided with the distribution.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     its contributors may be used to endorse or promote products derived
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     from this software without specific prior written permission.
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AnimationBase.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "AnimationControllerPrivate.h"
33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "CSSMutableStyleDeclaration.h"
34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "CSSPropertyLonghand.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSPropertyNames.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CompositeAnimation.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "EventNames.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FloatConversion.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "IdentityTransformOperation.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ImplicitAnimation.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "KeyframeAnimation.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MatrixTransformOperation.h"
458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "Matrix3DTransformOperation.h"
468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "RenderBox.h"
470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "RenderLayer.h"
480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "RenderLayerBacking.h"
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderStyle.h"
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "UnitBezier.h"
518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <algorithm>
52cad810f21b803229eb11403f9209855525a25d57Steve Block#include <wtf/CurrentTime.h>
538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianusing namespace std;
558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// The epsilon value we pass to UnitBezier::solve given that the animation is going to run over |dur| seconds. The longer the
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// animation, the more precision we need in the timing function result to avoid ugly discontinuities.
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline double solveEpsilon(double duration)
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 1.0 / (200.0 * duration);
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline double solveCubicBezierFunction(double p1x, double p1y, double p2x, double p2y, double t, double duration)
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Convert from input time to parametric value in curve, then from
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // that to output time.
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UnitBezier bezier(p1x, p1y, p2x, p2y);
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return bezier.solve(t, solveEpsilon(duration));
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
735abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrickstatic inline double solveStepsFunction(int numSteps, bool stepAtStart, double t)
745abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick{
755abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    if (stepAtStart)
765abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return min(1.0, (floor(numSteps * t) + 1) / numSteps);
775abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    return floor(numSteps * t) / numSteps;
785abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick}
795abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
80635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline int blendFunc(const AnimationBase*, int from, int to, double progress)
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return int(from + (to - from) * progress);
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
85635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline double blendFunc(const AnimationBase*, double from, double to, double progress)
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return from + (to - from) * progress;
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
90635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline float blendFunc(const AnimationBase*, float from, float to, double progress)
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return narrowPrecisionToFloat(from + (to - from) * progress);
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline Color blendFunc(const AnimationBase* anim, const Color& from, const Color& to, double progress)
96635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
97635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // We need to preserve the state of the valid flag at the end of the animation
98635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (progress == 1 && !to.isValid())
99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return Color();
100635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
101d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Contrary to the name, RGBA32 actually stores ARGB, so we can initialize Color directly from premultipliedARGBFromColor().
102d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Also, premultipliedARGBFromColor() bails on zero alpha, so special-case that.
103d0825bca7fe65beaee391d30da42e937db621564Steve Block    Color premultFrom = from.alpha() ? premultipliedARGBFromColor(from) : 0;
104d0825bca7fe65beaee391d30da42e937db621564Steve Block    Color premultTo = to.alpha() ? premultipliedARGBFromColor(to) : 0;
105d0825bca7fe65beaee391d30da42e937db621564Steve Block
106d0825bca7fe65beaee391d30da42e937db621564Steve Block    Color premultBlended(blendFunc(anim, premultFrom.red(), premultTo.red(), progress),
107d0825bca7fe65beaee391d30da42e937db621564Steve Block                 blendFunc(anim, premultFrom.green(), premultTo.green(), progress),
108d0825bca7fe65beaee391d30da42e937db621564Steve Block                 blendFunc(anim, premultFrom.blue(), premultTo.blue(), progress),
109d0825bca7fe65beaee391d30da42e937db621564Steve Block                 blendFunc(anim, premultFrom.alpha(), premultTo.alpha(), progress));
110d0825bca7fe65beaee391d30da42e937db621564Steve Block
111d0825bca7fe65beaee391d30da42e937db621564Steve Block    return Color(colorFromPremultipliedARGB(premultBlended.rgb()));
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline Length blendFunc(const AnimationBase*, const Length& from, const Length& to, double progress)
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1162bde8e466a4451c7319e3a072d118917957d6554Steve Block    return to.blend(from, narrowPrecisionToFloat(progress));
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic inline LengthSize blendFunc(const AnimationBase* anim, const LengthSize& from, const LengthSize& to, double progress)
1205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return LengthSize(blendFunc(anim, from.width(), to.width(), progress),
1225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                      blendFunc(anim, from.height(), to.height(), progress));
1235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline IntSize blendFunc(const AnimationBase* anim, const IntSize& from, const IntSize& to, double progress)
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return IntSize(blendFunc(anim, from.width(), to.width(), progress),
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                   blendFunc(anim, from.height(), to.height(), progress));
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic inline ShadowStyle blendFunc(const AnimationBase* anim, ShadowStyle from, ShadowStyle to, double progress)
1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (from == to)
1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return to;
1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    double fromVal = from == Normal ? 1 : 0;
1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    double toVal = to == Normal ? 1 : 0;
1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    double result = blendFunc(anim, fromVal, toVal, progress);
1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return result > 0 ? Normal : Inset;
1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline ShadowData* blendFunc(const AnimationBase* anim, const ShadowData* from, const ShadowData* to, double progress)
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(from && to);
1452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (from->style() != to->style())
1462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return new ShadowData(*to);
1472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
148cad810f21b803229eb11403f9209855525a25d57Steve Block    return new ShadowData(blendFunc(anim, from->x(), to->x(), progress),
149cad810f21b803229eb11403f9209855525a25d57Steve Block                          blendFunc(anim, from->y(), to->y(), progress),
150cad810f21b803229eb11403f9209855525a25d57Steve Block                          blendFunc(anim, from->blur(), to->blur(), progress),
151cad810f21b803229eb11403f9209855525a25d57Steve Block                          blendFunc(anim, from->spread(), to->spread(), progress),
152cad810f21b803229eb11403f9209855525a25d57Steve Block                          blendFunc(anim, from->style(), to->style(), progress),
153cad810f21b803229eb11403f9209855525a25d57Steve Block                          from->isWebkitBoxShadow(),
154cad810f21b803229eb11403f9209855525a25d57Steve Block                          blendFunc(anim, from->color(), to->color(), progress));
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline TransformOperations blendFunc(const AnimationBase* anim, const TransformOperations& from, const TransformOperations& to, double progress)
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TransformOperations result;
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If we have a transform function list, use that to do a per-function animation. Otherwise do a Matrix animation
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (anim->isTransformFunctionListValid()) {
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned fromSize = from.operations().size();
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned toSize = to.operations().size();
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned size = max(fromSize, toSize);
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (unsigned i = 0; i < size; i++) {
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RefPtr<TransformOperation> fromOp = (i < fromSize) ? from.operations()[i].get() : 0;
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RefPtr<TransformOperation> toOp = (i < toSize) ? to.operations()[i].get() : 0;
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RefPtr<TransformOperation> blendedOp = toOp ? toOp->blend(fromOp.get(), progress) : (fromOp ? fromOp->blend(0, progress, true) : 0);
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (blendedOp)
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                result.operations().append(blendedOp);
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else {
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                RefPtr<TransformOperation> identityOp = IdentityTransformOperation::create();
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (progress > 0.5)
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    result.operations().append(toOp ? toOp : identityOp);
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                else
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    result.operations().append(fromOp ? fromOp : identityOp);
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Convert the TransformOperations into matrices
182635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        IntSize size = anim->renderer()->isBox() ? toRenderBox(anim->renderer())->borderBoxRect().size() : IntSize();
183635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        TransformationMatrix fromT;
184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        TransformationMatrix toT;
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        from.apply(size, fromT);
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        to.apply(size, toT);
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        toT.blend(fromT, progress);
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Append the result
1918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        result.operations().append(Matrix3DTransformOperation::create(toT));
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline EVisibility blendFunc(const AnimationBase* anim, EVisibility from, EVisibility to, double progress)
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Any non-zero result means we consider the object to be visible.  Only at 0 do we consider the object to be
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // invisible.   The invisible value we use (HIDDEN vs. COLLAPSE) depends on the specified from/to values.
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    double fromVal = from == VISIBLE ? 1. : 0.;
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    double toVal = to == VISIBLE ? 1. : 0.;
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (fromVal == toVal)
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return to;
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    double result = blendFunc(anim, fromVal, toVal, progress);
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result > 0. ? VISIBLE : (to != VISIBLE ? to : from);
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
20806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenstatic inline LengthBox blendFunc(const AnimationBase* anim, const LengthBox& from, const LengthBox& to, double progress)
20906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
21006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Length types have to match to animate
21106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (from.top().type() != to.top().type()
21206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        || from.right().type() != to.right().type()
21306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        || from.bottom().type() != to.bottom().type()
21406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        || from.left().type() != to.left().type())
21506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        return to;
21606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
21706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    LengthBox result(blendFunc(anim, from.top(), to.top(), progress),
21806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                     blendFunc(anim, from.right(), to.right(), progress),
21906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                     blendFunc(anim, from.bottom(), to.bottom(), progress),
22006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                     blendFunc(anim, from.left(), to.left(), progress));
22106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    return result;
22206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
22306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
224635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectclass PropertyWrapperBase;
225635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
226635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void addShorthandProperties();
227635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic PropertyWrapperBase* wrapperForProperty(int propertyID);
228635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
229ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochclass PropertyWrapperBase {
230ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WTF_MAKE_NONCOPYABLE(PropertyWrapperBase); WTF_MAKE_FAST_ALLOCATED;
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic:
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PropertyWrapperBase(int prop)
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        : m_prop(prop)
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual ~PropertyWrapperBase() { }
238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
239635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    virtual bool isShorthandWrapper() const { return false; }
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual bool equals(const RenderStyle* a, const RenderStyle* b) const = 0;
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const = 0;
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int property() const { return m_prop; }
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#if USE(ACCELERATED_COMPOSITING)
2468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual bool animationIsAccelerated() const { return false; }
2478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif
2488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate:
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int m_prop;
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate <typename T>
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectclass PropertyWrapperGetter : public PropertyWrapperBase {
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic:
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PropertyWrapperGetter(int prop, T (RenderStyle::*getter)() const)
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        : PropertyWrapperBase(prop)
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_getter(getter)
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project       // If the style pointers are the same, don't bother doing the test.
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project       // If either is null, return false. If both are null, return true.
2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian       if ((!a && !b) || a == b)
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project           return true;
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project       if (!a || !b)
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return (a->*m_getter)() == (b->*m_getter)();
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprotected:
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    T (RenderStyle::*m_getter)() const;
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate <typename T>
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectclass PropertyWrapper : public PropertyWrapperGetter<T> {
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic:
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PropertyWrapper(int prop, T (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T))
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        : PropertyWrapperGetter<T>(prop, getter)
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_setter(setter)
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T>::m_getter)(), (b->*PropertyWrapperGetter<T>::m_getter)(), progress));
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprotected:
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    void (RenderStyle::*m_setter)(T);
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#if USE(ACCELERATED_COMPOSITING)
2968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianclass PropertyWrapperAcceleratedOpacity : public PropertyWrapper<float> {
2978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianpublic:
2988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    PropertyWrapperAcceleratedOpacity()
2998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        : PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity)
3008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
3018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
3028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual bool animationIsAccelerated() const { return true; }
3048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
3068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
3078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        float fromOpacity = a->opacity();
3088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // This makes sure we put the object being animated into a RenderLayer during the animation
3108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        dst->setOpacity(blendFunc(anim, (fromOpacity == 1) ? 0.999999f : fromOpacity, b->opacity(), progress));
3118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
3128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian};
3138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianclass PropertyWrapperAcceleratedTransform : public PropertyWrapper<const TransformOperations&> {
3158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianpublic:
3168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    PropertyWrapperAcceleratedTransform()
3178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        : PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform)
3188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
3198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
3208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual bool animationIsAccelerated() const { return true; }
3228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
3248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
3258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        dst->setTransform(blendFunc(anim, a->transform(), b->transform(), progress));
3268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
3278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian};
3288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif // USE(ACCELERATED_COMPOSITING)
3298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
330dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockclass PropertyWrapperShadow : public PropertyWrapperBase {
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic:
332dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    PropertyWrapperShadow(int prop, const ShadowData* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(ShadowData*, bool))
333dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        : PropertyWrapperBase(prop)
334dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        , m_getter(getter)
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_setter(setter)
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
341dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        const ShadowData* shadowA = (a->*m_getter)();
342dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        const ShadowData* shadowB = (b->*m_getter)();
343231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
344231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        while (true) {
345231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (!shadowA && !shadowB)   // end of both lists
346231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return true;
347231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
348231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (!shadowA || !shadowB)   // end of just one of the lists
349231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return false;
350231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
351231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (*shadowA != *shadowB)
352231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return false;
353231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
354dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            shadowA = shadowA->next();
355dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            shadowB = shadowB->next();
356231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
363dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        const ShadowData* shadowA = (a->*m_getter)();
364dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        const ShadowData* shadowB = (b->*m_getter)();
365cad810f21b803229eb11403f9209855525a25d57Steve Block        ShadowData defaultShadowData(0, 0, 0, 0, Normal, property() == CSSPropertyWebkitBoxShadow, Color::transparent);
3662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ShadowData defaultInsetShadowData(0, 0, 0, 0, Inset, property() == CSSPropertyWebkitBoxShadow, Color::transparent);
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
368231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ShadowData* newShadowData = 0;
369f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        ShadowData* lastShadow = 0;
370231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
371231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        while (shadowA || shadowB) {
3722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            const ShadowData* srcShadow = shadowA ? shadowA : (shadowB->style() == Inset ? &defaultInsetShadowData : &defaultShadowData);
3732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            const ShadowData* dstShadow = shadowB ? shadowB : (shadowA->style() == Inset ? &defaultInsetShadowData : &defaultShadowData);
3742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
375f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            ShadowData* blendedShadow = blendFunc(anim, srcShadow, dstShadow, progress);
376f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (!lastShadow)
377f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                newShadowData = blendedShadow;
378231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            else
379f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                lastShadow->setNext(blendedShadow);
380f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
381f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            lastShadow = blendedShadow;
382231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
383dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            shadowA = shadowA ? shadowA->next() : 0;
384dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            shadowB = shadowB ? shadowB->next() : 0;
385231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
386231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
387231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        (dst->*m_setter)(newShadowData, false);
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate:
391dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    const ShadowData* (RenderStyle::*m_getter)() const;
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    void (RenderStyle::*m_setter)(ShadowData*, bool);
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectclass PropertyWrapperMaybeInvalidColor : public PropertyWrapperBase {
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic:
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PropertyWrapperMaybeInvalidColor(int prop, const Color& (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&))
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        : PropertyWrapperBase(prop)
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_getter(getter)
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_setter(setter)
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color fromColor = (a->*m_getter)();
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color toColor = (b->*m_getter)();
408231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
409231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!fromColor.isValid() && !toColor.isValid())
410231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return true;
411231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!fromColor.isValid())
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            fromColor = a->color();
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!toColor.isValid())
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            toColor = b->color();
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return fromColor == toColor;
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color fromColor = (a->*m_getter)();
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color toColor = (b->*m_getter)();
424231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
425231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!fromColor.isValid() && !toColor.isValid())
426231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return;
427231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!fromColor.isValid())
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            fromColor = a->color();
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!toColor.isValid())
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            toColor = b->color();
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        (dst->*m_setter)(blendFunc(anim, fromColor, toColor, progress));
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate:
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const Color& (RenderStyle::*m_getter)() const;
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    void (RenderStyle::*m_setter)(const Color&);
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
440231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// Wrapper base class for an animatable property in a FillLayer
441231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockclass FillLayerPropertyWrapperBase {
442231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockpublic:
443231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    FillLayerPropertyWrapperBase()
444231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
445231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
446231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
447231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual ~FillLayerPropertyWrapperBase() { }
448231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
449231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual bool equals(const FillLayer* a, const FillLayer* b) const = 0;
450231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const = 0;
451231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block};
452231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
453231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocktemplate <typename T>
454ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochclass FillLayerPropertyWrapperGetter : public FillLayerPropertyWrapperBase {
455ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WTF_MAKE_NONCOPYABLE(FillLayerPropertyWrapperGetter);
456231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockpublic:
457231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    FillLayerPropertyWrapperGetter(T (FillLayer::*getter)() const)
458231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        : m_getter(getter)
459231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
460231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
461231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
462231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual bool equals(const FillLayer* a, const FillLayer* b) const
463231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
464231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block       // If the style pointers are the same, don't bother doing the test.
465231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block       // If either is null, return false. If both are null, return true.
466231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block       if ((!a && !b) || a == b)
467231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block           return true;
468231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block       if (!a || !b)
469231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
470231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return (a->*m_getter)() == (b->*m_getter)();
471231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
472231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
473231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockprotected:
474231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    T (FillLayer::*m_getter)() const;
475231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block};
476231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
477231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocktemplate <typename T>
478231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockclass FillLayerPropertyWrapper : public FillLayerPropertyWrapperGetter<T> {
479231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockpublic:
480231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    FillLayerPropertyWrapper(T (FillLayer::*getter)() const, void (FillLayer::*setter)(T))
481231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        : FillLayerPropertyWrapperGetter<T>(getter)
482231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        , m_setter(setter)
483231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
484231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
485231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
486231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const
487231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
488231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T>::m_getter)(), progress));
489231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
490231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
491231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockprotected:
492231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    void (FillLayer::*m_setter)(T);
493231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block};
494231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
495231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
496231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockclass FillLayersPropertyWrapper : public PropertyWrapperBase {
497231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockpublic:
498231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    typedef const FillLayer* (RenderStyle::*LayersGetter)() const;
499231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    typedef FillLayer* (RenderStyle::*LayersAccessor)();
500231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
501231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    FillLayersPropertyWrapper(int prop, LayersGetter getter, LayersAccessor accessor)
502231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        : PropertyWrapperBase(prop)
503231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        , m_layersGetter(getter)
504231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        , m_layersAccessor(accessor)
505231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
506231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        switch (prop) {
507231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case CSSPropertyBackgroundPositionX:
508231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case CSSPropertyWebkitMaskPositionX:
509231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::xPosition, &FillLayer::setXPosition);
510231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
511231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case CSSPropertyBackgroundPositionY:
512231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case CSSPropertyWebkitMaskPositionY:
513231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::yPosition, &FillLayer::setYPosition);
514231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
515231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case CSSPropertyBackgroundSize:
516cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            case CSSPropertyWebkitBackgroundSize:
517231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case CSSPropertyWebkitMaskSize:
518231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<LengthSize>(&FillLayer::sizeLength, &FillLayer::setSizeLength);
519231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
520231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
521231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
522231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
523231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
524231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
525231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        const FillLayer* fromLayer = (a->*m_layersGetter)();
526231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        const FillLayer* toLayer = (b->*m_layersGetter)();
527231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
528231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        while (fromLayer && toLayer) {
529231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (!m_fillLayerPropertyWrapper->equals(fromLayer, toLayer))
530231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return false;
531231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
532231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            fromLayer = fromLayer->next();
533231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            toLayer = toLayer->next();
534231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
535231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
536231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
537231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
538231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
539231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
540231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
541231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        const FillLayer* aLayer = (a->*m_layersGetter)();
542231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        const FillLayer* bLayer = (b->*m_layersGetter)();
543231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        FillLayer* dstLayer = (dst->*m_layersAccessor)();
544231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
545231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        while (aLayer && bLayer && dstLayer) {
546231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_fillLayerPropertyWrapper->blend(anim, dstLayer, aLayer, bLayer, progress);
547231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            aLayer = aLayer->next();
548231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            bLayer = bLayer->next();
549231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            dstLayer = dstLayer->next();
550231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
551231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
552231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
553231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockprivate:
554231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    FillLayerPropertyWrapperBase* m_fillLayerPropertyWrapper;
555231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
556231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    LayersGetter m_layersGetter;
557231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    LayersAccessor m_layersAccessor;
558231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block};
559231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
560635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectclass ShorthandPropertyWrapper : public PropertyWrapperBase {
561635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectpublic:
562635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ShorthandPropertyWrapper(int property, const CSSPropertyLonghand& longhand)
563635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        : PropertyWrapperBase(property)
564635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    {
565635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        for (unsigned i = 0; i < longhand.length(); ++i) {
566635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            PropertyWrapperBase* wrapper = wrapperForProperty(longhand.properties()[i]);
567635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (wrapper)
568635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                m_propertyWrappers.append(wrapper);
569635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
570635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
571635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
572635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    virtual bool isShorthandWrapper() const { return true; }
573635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
574635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
575635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    {
576635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        Vector<PropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end();
577635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        for (Vector<PropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) {
578635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (!(*it)->equals(a, b))
579635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                return false;
580635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
581635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return true;
582635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
583635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
584635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
585635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    {
586635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        Vector<PropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end();
587635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        for (Vector<PropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it)
588635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            (*it)->blend(anim, dst, a, b, progress);
589635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
590635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
591f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    const Vector<PropertyWrapperBase*> propertyWrappers() const { return m_propertyWrappers; }
592f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
593635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectprivate:
594635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    Vector<PropertyWrapperBase*> m_propertyWrappers;
595635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project};
596635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
597635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Vector<PropertyWrapperBase*>* gPropertyWrappers = 0;
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic int gPropertyWrapperMap[numCSSProperties];
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
601635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic const int cInvalidPropertyWrapperIndex = -1;
602635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
603635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
604e78cbe89e6f337f2f1fe40315be88f742b547151Steve Blockvoid AnimationBase::ensurePropertyMap()
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: This data is never destroyed. Maybe we should ref count it and toss it when the last AnimationController is destroyed?
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (gPropertyWrappers == 0) {
6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers = new Vector<PropertyWrapperBase*>();
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // build the list of property wrappers to do the comparisons and blends
6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLeft, &RenderStyle::left, &RenderStyle::setLeft));
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight));
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop));
6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom));
6150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth));
6170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinWidth, &RenderStyle::minWidth, &RenderStyle::setMinWidth));
6180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxWidth, &RenderStyle::maxWidth, &RenderStyle::setMaxWidth));
6190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight));
6210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinHeight, &RenderStyle::minHeight, &RenderStyle::setMinHeight));
6220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxHeight, &RenderStyle::maxHeight, &RenderStyle::setMaxHeight));
6230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderLeftWidth, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth));
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderRightWidth, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth));
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderTopWidth, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth));
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderBottomWidth, &RenderStyle::borderBottomWidth, &RenderStyle::setBorderBottomWidth));
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginLeft, &RenderStyle::marginLeft, &RenderStyle::setMarginLeft));
6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginRight, &RenderStyle::marginRight, &RenderStyle::setMarginRight));
6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginTop, &RenderStyle::marginTop, &RenderStyle::setMarginTop));
6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginBottom, &RenderStyle::marginBottom, &RenderStyle::setMarginBottom));
6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingLeft, &RenderStyle::paddingLeft, &RenderStyle::setPaddingLeft));
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingRight, &RenderStyle::paddingRight, &RenderStyle::setPaddingRight));
6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop));
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom));
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<const Color&>(CSSPropertyColor, &RenderStyle::color, &RenderStyle::setColor));
6375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<const Color&>(CSSPropertyBackgroundColor, &RenderStyle::backgroundColor, &RenderStyle::setBackgroundColor));
6395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
640231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionX, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers));
641231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionY, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers));
642231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers));
643cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers));
644231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
645231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionX, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers));
646231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionY, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers));
647231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskSize, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers));
6485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyFontSize, &RenderStyle::fontSize, &RenderStyle::setBlendedFontSize));
6508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnRuleWidth, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth));
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap));
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnCount, &RenderStyle::columnCount, &RenderStyle::setColumnCount));
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnWidth, &RenderStyle::columnWidth, &RenderStyle::setColumnWidth));
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderHorizontalSpacing, &RenderStyle::horizontalBorderSpacing, &RenderStyle::setHorizontalBorderSpacing));
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderVerticalSpacing, &RenderStyle::verticalBorderSpacing, &RenderStyle::setVerticalBorderSpacing));
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyZIndex, &RenderStyle::zIndex, &RenderStyle::setZIndex));
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLineHeight, &RenderStyle::lineHeight, &RenderStyle::setLineHeight));
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyOutlineOffset, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset));
6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth));
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing));
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing));
6620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent));
6630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective));
6658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX));
6668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY));
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX));
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY));
6698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitTransformOriginZ, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ));
6705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        gPropertyWrappers->append(new PropertyWrapper<const LengthSize&>(CSSPropertyBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius));
6715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        gPropertyWrappers->append(new PropertyWrapper<const LengthSize&>(CSSPropertyBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius));
6725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        gPropertyWrappers->append(new PropertyWrapper<const LengthSize&>(CSSPropertyBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius));
6735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        gPropertyWrappers->append(new PropertyWrapper<const LengthSize&>(CSSPropertyBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius));
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility));
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoom));
67606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
67706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyClip, &RenderStyle::clip, &RenderStyle::setClip));
6788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#if USE(ACCELERATED_COMPOSITING)
6808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        gPropertyWrappers->append(new PropertyWrapperAcceleratedOpacity());
6818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        gPropertyWrappers->append(new PropertyWrapperAcceleratedTransform());
6828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#else
6838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity));
6848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        gPropertyWrappers->append(new PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform));
6858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif
6868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyWebkitColumnRuleColor, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor));
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyWebkitTextStrokeColor, &RenderStyle::textStrokeColor, &RenderStyle::setTextStrokeColor));
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyWebkitTextFillColor, &RenderStyle::textFillColor, &RenderStyle::setTextFillColor));
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyBorderLeftColor, &RenderStyle::borderLeftColor, &RenderStyle::setBorderLeftColor));
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyBorderRightColor, &RenderStyle::borderRightColor, &RenderStyle::setBorderRightColor));
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyBorderTopColor, &RenderStyle::borderTopColor, &RenderStyle::setBorderTopColor));
6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyBorderBottomColor, &RenderStyle::borderBottomColor, &RenderStyle::setBorderBottomColor));
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyOutlineColor, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor));
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
696cad810f21b803229eb11403f9209855525a25d57Steve Block        gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow));
697231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyWebkitBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow));
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyTextShadow, &RenderStyle::textShadow, &RenderStyle::setTextShadow));
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG)
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFillOpacity, &RenderStyle::fillOpacity, &RenderStyle::setFillOpacity));
7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFloodOpacity, &RenderStyle::floodOpacity, &RenderStyle::setFloodOpacity));
7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeOpacity, &RenderStyle::strokeOpacity, &RenderStyle::setStrokeOpacity));
7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
706635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // TODO:
707635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //
708635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //  CSSPropertyVerticalAlign
709635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //
710635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Compound properties that have components that should be animatable:
711635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //
712635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //  CSSPropertyWebkitColumns
713635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //  CSSPropertyWebkitBoxReflect
714635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Make sure unused slots have a value
716635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        for (unsigned int i = 0; i < static_cast<unsigned int>(numCSSProperties); ++i)
717635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            gPropertyWrapperMap[i] = cInvalidPropertyWrapperIndex;
7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
719635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // First we put the non-shorthand property wrappers into the map, so the shorthand-building
720635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // code can find them.
7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        size_t n = gPropertyWrappers->size();
7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (unsigned int i = 0; i < n; ++i) {
7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT((*gPropertyWrappers)[i]->property() - firstCSSProperty < numCSSProperties);
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gPropertyWrapperMap[(*gPropertyWrappers)[i]->property() - firstCSSProperty] = i;
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
726635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
727635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Now add the shorthand wrappers.
728635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        addShorthandProperties();
7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
732635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void addPropertyWrapper(int propertyID, PropertyWrapperBase* wrapper)
733635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
734635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    int propIndex = propertyID - firstCSSProperty;
735635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
736635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(gPropertyWrapperMap[propIndex] == cInvalidPropertyWrapperIndex);
737635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
738635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    unsigned wrapperIndex = gPropertyWrappers->size();
739635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    gPropertyWrappers->append(wrapper);
740635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    gPropertyWrapperMap[propIndex] = wrapperIndex;
741635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
742635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
743635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void addShorthandProperties()
744635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
745635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static const int animatableShorthandProperties[] = {
7465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        CSSPropertyBackground,      // for background-color, background-position
7475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        CSSPropertyBackgroundPosition,
7485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        CSSPropertyWebkitMask,      // for mask-position
7495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        CSSPropertyWebkitMaskPosition,
750635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft,
751f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        CSSPropertyBorderColor,
752f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        CSSPropertyBorderRadius,
753635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyBorderWidth,
754635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyBorder,
755635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyBorderSpacing,
756635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyMargin,
757635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyOutline,
758635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyPadding,
759635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyWebkitTextStroke,
760635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyWebkitColumnRule,
761635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyWebkitBorderRadius,
762635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyWebkitTransformOrigin
763635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    };
764635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7654576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    for (size_t i = 0; i < WTF_ARRAY_LENGTH(animatableShorthandProperties); ++i) {
766635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        int propertyID = animatableShorthandProperties[i];
767635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyLonghand longhand = longhandForProperty(propertyID);
768635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (longhand.length() > 0)
769635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            addPropertyWrapper(propertyID, new ShorthandPropertyWrapper(propertyID, longhand));
770635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
771635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
772635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // 'font' is not in the shorthand map.
773635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static const int animatableFontProperties[] = {
774635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyFontSize,
775635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        CSSPropertyFontWeight
776635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    };
777635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7784576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    CSSPropertyLonghand fontLonghand(animatableFontProperties, WTF_ARRAY_LENGTH(animatableFontProperties));
779635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    addPropertyWrapper(CSSPropertyFont, new ShorthandPropertyWrapper(CSSPropertyFont, fontLonghand));
780635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
781635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
782635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic PropertyWrapperBase* wrapperForProperty(int propertyID)
783635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
784635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    int propIndex = propertyID - firstCSSProperty;
785635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (propIndex >= 0 && propIndex < numCSSProperties) {
786635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        int wrapperIndex = gPropertyWrapperMap[propIndex];
787635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (wrapperIndex >= 0)
788635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return (*gPropertyWrappers)[wrapperIndex];
789635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
790635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return 0;
791635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
792635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectAnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim)
7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_animState(AnimationStateNew)
7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_isAnimating(false)
7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_startTime(0)
7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_pauseTime(-1)
798635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    , m_requestedStartTime(0)
7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_object(renderer)
8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_animation(const_cast<Animation*>(transition))
8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_compAnim(compAnim)
802967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    , m_isAccelerated(false)
8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_transformFunctionListValid(false)
804635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    , m_nextIterationDuration(-1)
8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
806635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Compute the total duration
807635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_totalDuration = -1;
808635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_animation->iterationCount() > 0)
809635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_totalDuration = m_animation->duration() * m_animation->iterationCount();
8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AnimationBase::propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b)
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ensurePropertyMap();
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (prop == cAnimateAll) {
8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        size_t n = gPropertyWrappers->size();
8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (unsigned int i = 0; i < n; ++i) {
818635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i];
819635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // No point comparing shorthand wrappers for 'all'.
820635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (!wrapper->isShorthandWrapper() && !wrapper->equals(a, b))
8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
824635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        PropertyWrapperBase* wrapper = wrapperForProperty(prop);
825635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (wrapper)
826635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return wrapper->equals(a, b);
8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
831635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectint AnimationBase::getPropertyAtIndex(int i, bool& isShorthand)
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ensurePropertyMap();
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (i < 0 || i >= static_cast<int>(gPropertyWrappers->size()))
8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return CSSPropertyInvalid;
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
837635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i];
838635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    isShorthand = wrapper->isShorthandWrapper();
839635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return wrapper->property();
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint AnimationBase::getNumProperties()
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ensurePropertyMap();
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return gPropertyWrappers->size();
8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns true if we need to start animation timers
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AnimationBase::blendProperties(const AnimationBase* anim, int prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress)
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(prop != cAnimateAll);
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
853635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ensurePropertyMap();
854635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    PropertyWrapperBase* wrapper = wrapperForProperty(prop);
855635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (wrapper) {
856635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        wrapper->blend(anim, dst, a, b, progress);
8578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#if USE(ACCELERATED_COMPOSITING)
858967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        return !wrapper->animationIsAccelerated() || !anim->isAccelerated();
8598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#else
860635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return true;
8618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#if USE(ACCELERATED_COMPOSITING)
8688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool AnimationBase::animationOfPropertyIsAccelerated(int prop)
8698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
8708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ensurePropertyMap();
8718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    PropertyWrapperBase* wrapper = wrapperForProperty(prop);
8728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return wrapper ? wrapper->animationIsAccelerated() : false;
8738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
8748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif
8758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
876f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic bool gatherEnclosingShorthandProperties(int property, PropertyWrapperBase* wrapper, HashSet<int>& propertySet)
877f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
878f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!wrapper->isShorthandWrapper())
879f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return false;
880f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
881f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ShorthandPropertyWrapper* shorthandWrapper = static_cast<ShorthandPropertyWrapper*>(wrapper);
882f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
883f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    bool contained = false;
884f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    for (size_t i = 0; i < shorthandWrapper->propertyWrappers().size(); ++i) {
885f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        PropertyWrapperBase* currWrapper = shorthandWrapper->propertyWrappers()[i];
886f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
887f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (gatherEnclosingShorthandProperties(property, currWrapper, propertySet) || currWrapper->property() == property)
888f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            contained = true;
889f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
890f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
891f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (contained)
892f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        propertySet.add(wrapper->property());
893f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
894f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return contained;
895f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
896f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
897f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// Note: this is inefficient. It's only called from pauseTransitionAtTime().
898f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochHashSet<int> AnimationBase::animatableShorthandsAffectingProperty(int property)
899f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
900f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ensurePropertyMap();
901f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
902f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    HashSet<int> foundProperties;
903f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    for (int i = 0; i < getNumProperties(); ++i)
904f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        gatherEnclosingShorthandProperties(property, (*gPropertyWrappers)[i], foundProperties);
905f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
906f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return foundProperties;
907f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
908f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
9095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid AnimationBase::setNeedsStyleRecalc(Node* node)
9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!node || (node->document() && !node->document()->inPageCache()));
912635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (node)
913231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        node->setNeedsStyleRecalc(SyntheticStyleChange);
9148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectdouble AnimationBase::duration() const
9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_animation->duration();
9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AnimationBase::playStatePlaying() const
9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
923635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return m_animation->playState() == AnimPlayStatePlaying;
9248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AnimationBase::animationsMatch(const Animation* anim) const
9278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_animation->animationsMatch(anim);
9298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AnimationBase::updateStateMachine(AnimStateInput input, double param)
9328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_compAnim)
9342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
9352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If we get AnimationStateInputRestartAnimation then we force a new animation, regardless of state.
9378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (input == AnimationStateInputMakeNew) {
9388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_animState == AnimationStateStartWaitStyleAvailable)
9392bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this);
9408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_animState = AnimationStateNew;
9418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_startTime = 0;
9428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_pauseTime = -1;
943635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_requestedStartTime = 0;
944635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_nextIterationDuration = -1;
945d0825bca7fe65beaee391d30da42e937db621564Steve Block        endAnimation();
9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (input == AnimationStateInputRestartAnimation) {
9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_animState == AnimationStateStartWaitStyleAvailable)
9512bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this);
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_animState = AnimationStateNew;
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_startTime = 0;
9548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_pauseTime = -1;
955635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_requestedStartTime = 0;
956635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_nextIterationDuration = -1;
957d0825bca7fe65beaee391d30da42e937db621564Steve Block        endAnimation();
9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!paused())
9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            updateStateMachine(AnimationStateInputStartAnimation, -1);
9618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
9628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (input == AnimationStateInputEndAnimation) {
9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_animState == AnimationStateStartWaitStyleAvailable)
9662bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this);
9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_animState = AnimationStateDone;
968d0825bca7fe65beaee391d30da42e937db621564Steve Block        endAnimation();
9698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (input == AnimationStateInputPauseOverride) {
9738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_animState == AnimationStateStartWaitResponse) {
9748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If we are in AnimationStateStartWaitResponse, the animation will get canceled before
9758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // we get a response, so move to the next state.
976d0825bca7fe65beaee391d30da42e937db621564Steve Block            endAnimation();
977635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime());
9788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
9808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (input == AnimationStateInputResumeOverride) {
9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_animState == AnimationStateLooping || m_animState == AnimationStateEnding) {
9848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Start the animation
985d0825bca7fe65beaee391d30da42e937db621564Steve Block            startAnimation(beginAnimationUpdateTime() - m_startTime);
9868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
9878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Execute state machine
9918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    switch (m_animState) {
9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStateNew:
993dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            ASSERT(input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunning || input == AnimationStateInputPlayStatePaused);
994dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunning) {
995635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                m_requestedStartTime = beginAnimationUpdateTime();
9968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_animState = AnimationStateStartWaitTimer;
9978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
9988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStateStartWaitTimer:
10008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(input == AnimationStateInputStartTimerFired || input == AnimationStateInputPlayStatePaused);
10018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (input == AnimationStateInputStartTimerFired) {
10038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ASSERT(param >= 0);
10048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Start timer has fired, tell the animation to start and wait for it to respond with start time
10058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_animState = AnimationStateStartWaitStyleAvailable;
10062bde8e466a4451c7319e3a072d118917957d6554Steve Block                m_compAnim->animationController()->addToAnimationsWaitingForStyle(this);
10078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Trigger a render so we can start the animation
1009635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                if (m_object)
10105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                    m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node());
10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
10128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ASSERT(!paused());
10138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // We're waiting for the start timer to fire and we got a pause. Cancel the timer, pause and wait
1014635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                m_pauseTime = beginAnimationUpdateTime();
10158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_animState = AnimationStatePausedWaitTimer;
10168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
10188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStateStartWaitStyleAvailable:
10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(input == AnimationStateInputStyleAvailable || input == AnimationStateInputPlayStatePaused);
10208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10210617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            if (input == AnimationStateInputStyleAvailable) {
10220617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                // Start timer has fired, tell the animation to start and wait for it to respond with start time
10230617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                m_animState = AnimationStateStartWaitResponse;
10248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10250617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                overrideAnimations();
10260617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
10270617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                // Start the animation
10280617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                if (overridden()) {
10290617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    // We won't try to start accelerated animations if we are overridden and
10300617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    // just move on to the next state.
10310617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    m_animState = AnimationStateStartWaitResponse;
10320617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    m_isAccelerated = false;
10330617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime());
10340617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                } else {
10350617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    double timeOffset = 0;
10360617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    // If the value for 'animation-delay' is negative then the animation appears to have started in the past.
10370617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    if (m_animation->delay() < 0)
10380617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                        timeOffset = -m_animation->delay();
10390617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    bool started = startAnimation(timeOffset);
10408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10412bde8e466a4451c7319e3a072d118917957d6554Steve Block                    m_compAnim->animationController()->addToAnimationsWaitingForStartTimeResponse(this, started);
10420617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    m_isAccelerated = started;
10430617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                }
10440617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            } else {
10450617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                // We're waiting for the style to be available and we got a pause. Pause and wait
10460617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                m_pauseTime = beginAnimationUpdateTime();
10470617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                m_animState = AnimationStatePausedWaitStyleAvailable;
10488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            }
10498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
10508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStateStartWaitResponse:
10518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(input == AnimationStateInputStartTimeSet || input == AnimationStateInputPlayStatePaused);
10528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (input == AnimationStateInputStartTimeSet) {
10548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ASSERT(param >= 0);
10558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // We have a start time, set it, unless the startTime is already set
1056d0825bca7fe65beaee391d30da42e937db621564Steve Block                if (m_startTime <= 0) {
10578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    m_startTime = param;
1058d0825bca7fe65beaee391d30da42e937db621564Steve Block                    // If the value for 'animation-delay' is negative then the animation appears to have started in the past.
1059d0825bca7fe65beaee391d30da42e937db621564Steve Block                    if (m_animation->delay() < 0)
1060d0825bca7fe65beaee391d30da42e937db621564Steve Block                        m_startTime += m_animation->delay();
1061d0825bca7fe65beaee391d30da42e937db621564Steve Block                }
10628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
106321939df44de1705786c545cd1bf519d47250322dBen Murdoch                // Now that we know the start time, fire the start event.
106421939df44de1705786c545cd1bf519d47250322dBen Murdoch                onAnimationStart(0); // The elapsedTime is 0.
106521939df44de1705786c545cd1bf519d47250322dBen Murdoch
1066635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                // Decide whether to go into looping or ending state
1067635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                goIntoEndingOrLoopingState();
10688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                // Dispatch updateStyleIfNeeded so we can start the animation
1070635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                if (m_object)
10715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                    m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node());
10728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
10738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // We are pausing while waiting for a start response. Cancel the animation and wait. When
10748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // we unpause, we will act as though the start timer just fired
10752bde8e466a4451c7319e3a072d118917957d6554Steve Block                m_pauseTime = beginAnimationUpdateTime();
1076d0825bca7fe65beaee391d30da42e937db621564Steve Block                pauseAnimation(beginAnimationUpdateTime() - m_startTime);
10778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_animState = AnimationStatePausedWaitResponse;
10788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
10798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
10808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStateLooping:
10818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(input == AnimationStateInputLoopTimerFired || input == AnimationStateInputPlayStatePaused);
10828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (input == AnimationStateInputLoopTimerFired) {
10848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ASSERT(param >= 0);
10858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Loop timer fired, loop again or end.
10868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                onAnimationIteration(param);
1087635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1088635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                // Decide whether to go into looping or ending state
1089635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                goIntoEndingOrLoopingState();
10908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
10918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // We are pausing while running. Cancel the animation and wait
1092635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                m_pauseTime = beginAnimationUpdateTime();
1093d0825bca7fe65beaee391d30da42e937db621564Steve Block                pauseAnimation(beginAnimationUpdateTime() - m_startTime);
10948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_animState = AnimationStatePausedRun;
10958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
10968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
10978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStateEnding:
10988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(input == AnimationStateInputEndTimerFired || input == AnimationStateInputPlayStatePaused);
10998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (input == AnimationStateInputEndTimerFired) {
1101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
11028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ASSERT(param >= 0);
11038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // End timer fired, finish up
11048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                onAnimationEnd(param);
11058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_animState = AnimationStateDone;
1107635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1108635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                if (m_object) {
1109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    if (m_animation->fillsForwards())
1110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        m_animState = AnimationStateFillingForwards;
1111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    else
1112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        resumeOverriddenAnimations();
1113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                    // Fire off another style change so we can set the final value
11155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                    m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node());
1116635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                }
11178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
11188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // We are pausing while running. Cancel the animation and wait
1119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                m_pauseTime = beginAnimationUpdateTime();
1120d0825bca7fe65beaee391d30da42e937db621564Steve Block                pauseAnimation(beginAnimationUpdateTime() - m_startTime);
11218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_animState = AnimationStatePausedRun;
11228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
11238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // |this| may be deleted here
11248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
11258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStatePausedWaitTimer:
1126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            ASSERT(input == AnimationStateInputPlayStateRunning);
11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(paused());
11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Update the times
1129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            m_startTime += beginAnimationUpdateTime() - m_pauseTime;
11308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_pauseTime = -1;
11318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // we were waiting for the start timer to fire, go back and wait again
11338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_animState = AnimationStateNew;
11348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            updateStateMachine(AnimationStateInputStartAnimation, 0);
11358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
11368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStatePausedWaitResponse:
11370617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        case AnimationStatePausedWaitStyleAvailable:
11388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStatePausedRun:
11398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We treat these two cases the same. The only difference is that, when we are in
11408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // AnimationStatePausedWaitResponse, we don't yet have a valid startTime, so we send 0 to startAnimation.
11418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // When the AnimationStateInputStartTimeSet comes in and we were in AnimationStatePausedRun, we will notice
11428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // that we have already set the startTime and will ignore it.
11430617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            ASSERT(input == AnimationStateInputPlayStateRunning || input == AnimationStateInputStartTimeSet || input == AnimationStateInputStyleAvailable);
11448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(paused());
11458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11460617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            if (input == AnimationStateInputPlayStateRunning) {
11470617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                // Update the times
11480617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                if (m_animState == AnimationStatePausedRun)
11490617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    m_startTime += beginAnimationUpdateTime() - m_pauseTime;
11500617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                else
11510617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    m_startTime = 0;
11520617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                m_pauseTime = -1;
11530617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
11540617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                if (m_animState == AnimationStatePausedWaitStyleAvailable)
11550617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    m_animState = AnimationStateStartWaitStyleAvailable;
11560617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                else {
11570617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    // We were either running or waiting for a begin time response from the animation.
11580617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    // Either way we need to restart the animation (possibly with an offset if we
11590617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    // had already been running) and wait for it to start.
11600617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    m_animState = AnimationStateStartWaitResponse;
11610617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
11620617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    // Start the animation
11630617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    if (overridden()) {
11640617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                        // We won't try to start accelerated animations if we are overridden and
11650617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                        // just move on to the next state.
11660617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                        updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime());
11670617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                        m_isAccelerated = true;
11680617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    } else {
11690617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                        bool started = startAnimation(beginAnimationUpdateTime() - m_startTime);
11702bde8e466a4451c7319e3a072d118917957d6554Steve Block                        m_compAnim->animationController()->addToAnimationsWaitingForStartTimeResponse(this, started);
11715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        m_isAccelerated = started;
11720617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                    }
11730617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                }
11740617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                break;
11750617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            }
11760617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
11770617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            if (input == AnimationStateInputStartTimeSet) {
11780617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                ASSERT(m_animState == AnimationStatePausedWaitResponse);
11790617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
11800617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                // We are paused but we got the callback that notifies us that an accelerated animation started.
11810617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen                // We ignore the start time and just move into the paused-run state.
11828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_animState = AnimationStatePausedRun;
11838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                ASSERT(m_startTime == 0);
11848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_startTime = param;
11858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_pauseTime += m_startTime;
11868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                break;
11878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            }
11888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11890617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            ASSERT(m_animState == AnimationStatePausedWaitStyleAvailable);
11900617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            // We are paused but we got the callback that notifies us that style has been updated.
11910617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            // We move to the AnimationStatePausedWaitResponse state
11920617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            m_animState = AnimationStatePausedWaitResponse;
11930617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            overrideAnimations();
11948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1195dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        case AnimationStateFillingForwards:
11968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        case AnimationStateDone:
11978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We're done. Stay in this state until we are deleted
11988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
11998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
12008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1202635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid AnimationBase::fireAnimationEventsIfNeeded()
12038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_compAnim)
12052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
12062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1207635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // If we are waiting for the delay time to expire and it has, go to the next state
1208635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_animState != AnimationStateStartWaitTimer && m_animState != AnimationStateLooping && m_animState != AnimationStateEnding)
1209635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
12108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1211635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // We have to make sure to keep a ref to the this pointer, because it could get destroyed
1212635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // during an animation callback that might get called. Since the owner is a CompositeAnimation
1213635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // and it ref counts this object, we will keep a ref to that instead. That way the AnimationBase
1214635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // can still access the resources of its CompositeAnimation as needed.
1215635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RefPtr<AnimationBase> protector(this);
1216635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RefPtr<CompositeAnimation> compProtector(m_compAnim);
1217635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1218635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Check for start timeout
1219635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_animState == AnimationStateStartWaitTimer) {
1220635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (beginAnimationUpdateTime() - m_requestedStartTime >= m_animation->delay())
1221635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            updateStateMachine(AnimationStateInputStartTimerFired, 0);
1222635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
1223635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
1224635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1225635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    double elapsedDuration = beginAnimationUpdateTime() - m_startTime;
12268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // FIXME: we need to ensure that elapsedDuration is never < 0. If it is, this suggests that
12278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // we had a recalcStyle() outside of beginAnimationUpdate()/endAnimationUpdate().
12288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Also check in getTimeToNextEvent().
12298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    elapsedDuration = max(elapsedDuration, 0.0);
1230635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1231635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Check for end timeout
1232635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_totalDuration >= 0 && elapsedDuration >= m_totalDuration) {
123368513a70bcd92384395513322f1b801e7bf9c729Steve Block        // We may still be in AnimationStateLooping if we've managed to skip a
123468513a70bcd92384395513322f1b801e7bf9c729Steve Block        // whole iteration, in which case we should jump to the end state.
123568513a70bcd92384395513322f1b801e7bf9c729Steve Block        m_animState = AnimationStateEnding;
123668513a70bcd92384395513322f1b801e7bf9c729Steve Block
1237635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Fire an end event
1238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        updateStateMachine(AnimationStateInputEndTimerFired, m_totalDuration);
12398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else {
1240635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Check for iteration timeout
1241635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (m_nextIterationDuration < 0) {
1242635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Hasn't been set yet, set it
1243635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            double durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration());
1244635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            m_nextIterationDuration = elapsedDuration + durationLeft;
1245635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
1246635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1247635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (elapsedDuration >= m_nextIterationDuration) {
1248635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Set to the next iteration
1249635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            double previous = m_nextIterationDuration;
1250635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            double durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration());
1251635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            m_nextIterationDuration = elapsedDuration + durationLeft;
1252635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1253635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Send the event
1254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            updateStateMachine(AnimationStateInputLoopTimerFired, previous);
1255635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
12568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
12578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
125928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid AnimationBase::updatePlayState(EAnimPlayState playState)
12608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_compAnim)
12622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
12632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
126428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // When we get here, we can have one of 4 desired states: running, paused, suspended, paused & suspended.
126528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // The state machine can be in one of two states: running, paused.
126628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    // Set the state machine to the desired state.
126728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    bool pause = playState == AnimPlayStatePaused || m_compAnim->suspended();
126828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
126928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (pause == paused() && !isNew())
127028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        return;
127128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
127228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    updateStateMachine(pause ?  AnimationStateInputPlayStatePaused : AnimationStateInputPlayStateRunning, -1);
12738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qiandouble AnimationBase::timeToNextService()
1276635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
1277635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Returns the time at which next service is required. -1 means no service is required. 0 means
1278635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // service is required now, and > 0 means service is required that many seconds in the future.
1279dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (paused() || isNew() || m_animState == AnimationStateFillingForwards)
1280635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return -1;
12818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1282635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_animState == AnimationStateStartWaitTimer) {
1283635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        double timeFromNow = m_animation->delay() - (beginAnimationUpdateTime() - m_requestedStartTime);
12848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return max(timeFromNow, 0.0);
1285635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
1286635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
12878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    fireAnimationEventsIfNeeded();
12888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1289635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // In all other cases, we need service right away.
1290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return 0;
1291635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
1292635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
12938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectdouble AnimationBase::progress(double scale, double offset, const TimingFunction* tf) const
12948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (preActive())
12968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
12978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1298635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    double elapsedTime = getElapsedTime();
12998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    double dur = m_animation->duration();
13018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_animation->iterationCount() > 0)
13028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dur *= m_animation->iterationCount();
13038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1304dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (postActive() || !m_animation->duration())
13058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 1.0;
1306dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_animation->iterationCount() > 0 && elapsedTime >= dur)
1307dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return (m_animation->iterationCount() % 2) ? 1.0 : 0.0;
13088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Compute the fractional time, taking into account direction.
13108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // There is no need to worry about iterations, we assume that we would have
13118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // short circuited above if we were done.
13128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    double fractionalTime = elapsedTime / m_animation->duration();
13138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int integralTime = static_cast<int>(fractionalTime);
13148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    fractionalTime -= integralTime;
13158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if ((m_animation->direction() == Animation::AnimationDirectionAlternate) && (integralTime & 1))
13178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        fractionalTime = 1 - fractionalTime;
13188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (scale != 1 || offset)
13208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        fractionalTime = (fractionalTime - offset) * scale;
13218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!tf)
13235abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        tf = m_animation->timingFunction().get();
13245abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
13255abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    if (tf->isCubicBezierTimingFunction()) {
13265abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(tf);
13275abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return solveCubicBezierFunction(ctf->x1(),
13285abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick                                        ctf->y1(),
13295abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick                                        ctf->x2(),
13305abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick                                        ctf->y2(),
13315abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick                                        fractionalTime, m_animation->duration());
13325abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    } else if (tf->isStepsTimingFunction()) {
13335abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(tf);
13345abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return solveStepsFunction(stf->numberOfSteps(), stf->stepAtStart(), fractionalTime);
13355abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    } else
13368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return fractionalTime;
13378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
13388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid AnimationBase::getTimeToNextEvent(double& time, bool& isLooping) const
13408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
13418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Decide when the end or loop event needs to fire
13428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const double elapsedDuration = max(beginAnimationUpdateTime() - m_startTime, 0.0);
13438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    double durationLeft = 0;
13448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double nextIterationTime = m_totalDuration;
1345635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
13468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_totalDuration < 0 || elapsedDuration < m_totalDuration) {
13470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        durationLeft = m_animation->duration() > 0 ? (m_animation->duration() - fmod(elapsedDuration, m_animation->duration())) : 0;
13488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        nextIterationTime = elapsedDuration + durationLeft;
13498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
13508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
13518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_totalDuration < 0 || nextIterationTime < m_totalDuration) {
1352635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // We are not at the end yet
13538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(nextIterationTime > 0);
13548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        isLooping = true;
13558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1356635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // We are at the end
13578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        isLooping = false;
13588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
13598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
13608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    time = durationLeft;
13618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
13628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
13638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid AnimationBase::goIntoEndingOrLoopingState()
13648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
13658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double t;
13668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool isLooping;
13678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    getTimeToNextEvent(t, isLooping);
13688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_animState = isLooping ? AnimationStateLooping : AnimationStateEnding;
13698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
13708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid AnimationBase::freezeAtTime(double t)
1372635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
13732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_compAnim)
13742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
13752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1376cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!m_startTime) {
1377cad810f21b803229eb11403f9209855525a25d57Steve Block        // If we haven't started yet, just generate the start event now
1378cad810f21b803229eb11403f9209855525a25d57Steve Block        m_compAnim->animationController()->receivedStartTimeResponse(currentTime());
1379cad810f21b803229eb11403f9209855525a25d57Steve Block    }
1380cad810f21b803229eb11403f9209855525a25d57Steve Block
13810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(m_startTime);        // if m_startTime is zero, we haven't started yet, so we'll get a bad pause time.
1382635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_pauseTime = m_startTime + t - m_animation->delay();
13830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
13840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if USE(ACCELERATED_COMPOSITING)
13850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_object && m_object->hasLayer()) {
13860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
13870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (layer->isComposited())
13880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            layer->backing()->suspendAnimations(m_pauseTime);
13890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
13900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
1391635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
1392635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1393635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectdouble AnimationBase::beginAnimationUpdateTime() const
1394635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
13952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_compAnim)
13962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
13972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return m_compAnim->animationController()->beginAnimationUpdateTime();
1399635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
1400635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1401635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectdouble AnimationBase::getElapsedTime() const
1402635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
1403635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (paused())
1404635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return m_pauseTime - m_startTime;
1405635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_startTime <= 0)
1406635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return 0;
1407635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (postActive())
1408635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return 1;
1409cad810f21b803229eb11403f9209855525a25d57Steve Block
1410635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return beginAnimationUpdateTime() - m_startTime;
1411635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
14122bde8e466a4451c7319e3a072d118917957d6554Steve Block
14132bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid AnimationBase::setElapsedTime(double time)
14142bde8e466a4451c7319e3a072d118917957d6554Steve Block{
14152bde8e466a4451c7319e3a072d118917957d6554Steve Block    // FIXME: implement this method
14162bde8e466a4451c7319e3a072d118917957d6554Steve Block    UNUSED_PARAM(time);
14172bde8e466a4451c7319e3a072d118917957d6554Steve Block}
14182bde8e466a4451c7319e3a072d118917957d6554Steve Block
14192bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid AnimationBase::play()
14202bde8e466a4451c7319e3a072d118917957d6554Steve Block{
14212bde8e466a4451c7319e3a072d118917957d6554Steve Block    // FIXME: implement this method
14222bde8e466a4451c7319e3a072d118917957d6554Steve Block}
14232bde8e466a4451c7319e3a072d118917957d6554Steve Block
14242bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid AnimationBase::pause()
14252bde8e466a4451c7319e3a072d118917957d6554Steve Block{
14262bde8e466a4451c7319e3a072d118917957d6554Steve Block    // FIXME: implement this method
14272bde8e466a4451c7319e3a072d118917957d6554Steve Block}
14282bde8e466a4451c7319e3a072d118917957d6554Steve Block
14298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
1430