blob: 2c61b213e37229761467fdfe4c2f7a2edbd5e568 [file] [log] [blame]
/*
* Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef LayerAnimation_h
#define LayerAnimation_h
#include "GraphicsLayer.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#define DEBUG_LAYER_ANIMATION 0
namespace WebCore {
class Animation;
class LayerCompositingThread;
class TransformationMatrix;
class LayerAnimation : public ThreadSafeRefCounted<LayerAnimation> {
public:
// The setStartTime method is not threadsafe and must only be called on a newly
// created LayerAnimation before sending it off to the compositing thread.
static PassRefPtr<LayerAnimation> create(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& name, double timeOffset)
{
return adoptRef(new LayerAnimation(values, boxSize, animation, name, timeOffset));
}
PassRefPtr<LayerAnimation> clone(double timeOffset)
{
LayerAnimation* animation = new LayerAnimation(*this);
// The cloned animation should get a different timeOffset if it's paused.
animation->m_timeOffset = timeOffset;
return adoptRef(animation);
}
~LayerAnimation()
{
}
String name() const
{
if (m_name.isEmpty())
return String("");
return String(m_name);
}
void setStartTime(double time) { m_startTime = time; }
// These functions are thread safe (immutable state).
static int idFromAnimation(const Animation* animation) { return reinterpret_cast<int>(animation); }
bool isEqualToAnimation(const Animation* animation) const { return idFromAnimation(animation) == id(); }
int id() const { return m_id; }
AnimatedPropertyID property() const { return m_values.property(); }
IntSize boxSize() const { return m_boxSize; }
double timeOffset() const { return m_timeOffset; }
double startTime() const { return m_startTime; }
size_t valueCount() const { return m_values.size(); }
const TimingFunction* timingFunction() const { return m_timingFunction.get(); }
double duration() const { return m_duration; }
int iterationCount() const { return m_iterationCount; }
Animation::AnimationDirection direction() const { return m_direction; }
const AnimationValue* valueAt(size_t i) const { return m_values.at(i); }
bool finished() const { return m_finished; }
TransformationMatrix blendTransform(const TransformOperations* from, const TransformOperations*, double progress) const;
float blendOpacity(float from, float to, double progress) const;
void apply(LayerCompositingThread*, double elapsedTime);
private:
LayerAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& name, double timeOffset)
: m_id(reinterpret_cast<int>(animation))
, m_values(values)
, m_boxSize(boxSize)
, m_timeOffset(timeOffset)
, m_startTime(0)
, m_timingFunction(0)
, m_duration(animation->duration())
, m_iterationCount(animation->iterationCount())
, m_direction(animation->direction())
, m_finished(false)
{
if (animation->isTimingFunctionSet())
m_timingFunction = animation->timingFunction();
validateTransformLists();
setName(name);
}
LayerAnimation(const LayerAnimation& other)
: ThreadSafeRefCounted<LayerAnimation>()
, m_id(other.m_id)
, m_values(other.m_values)
, m_boxSize(other.m_boxSize)
, m_timeOffset(other.m_timeOffset)
, m_startTime(other.m_startTime)
, m_transformFunctionListValid(other.m_transformFunctionListValid)
, m_timingFunction(other.m_timingFunction)
, m_duration(other.m_duration)
, m_iterationCount(other.m_iterationCount)
, m_direction(other.m_direction)
, m_finished(false)
{
setName(other.name());
}
void validateTransformLists();
void setName(const String& name)
{
unsigned length = name.length();
m_name.resize(length);
if (length)
memcpy(m_name.data(), name.characters(), sizeof(UChar) * length);
}
int m_id;
// NOTE: Don't expose the KeyframeValueList directly, since its copy
// constructor mutates refcounts and thus is not thread safe.
KeyframeValueList m_values;
IntSize m_boxSize;
Vector<UChar> m_name; // Must not use String member when deriving from ThreadSafeRefCounted
double m_timeOffset;
double m_startTime;
bool m_transformFunctionListValid;
RefPtr<TimingFunction> m_timingFunction;
double m_duration;
int m_iterationCount;
Animation::AnimationDirection m_direction;
bool m_finished;
};
}
#endif // LayerAnimation_h