summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/mac/GraphicsLayerCA.mm')
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm243
1 files changed, 114 insertions, 129 deletions
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index 395a691..d4cd851 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -55,6 +55,8 @@ using namespace std;
namespace WebCore {
+static NSString * const WebKitAnimationBeginTimeSetKey = @"WebKitAnimationBeginTimeSet";
+
// The threshold width or height above which a tiled layer will be used. This should be
// large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL
// texture size limit on all supported hardware.
@@ -101,11 +103,8 @@ static double mediaTimeToCurrentTime(CFTimeInterval t)
- (void)animationDidStart:(CAAnimation *)animation
{
- if (!m_graphicsLayer)
- return;
-
- double startTime = WebCore::mediaTimeToCurrentTime([animation beginTime]);
- m_graphicsLayer->client()->notifyAnimationStarted(m_graphicsLayer, startTime);
+ if (m_graphicsLayer)
+ m_graphicsLayer->animationDidStart(animation);
}
- (WebCore::GraphicsLayerCA*)graphicsLayer
@@ -197,7 +196,7 @@ static NSValue* getTransformFunctionValue(const TransformOperation* transformOp,
}
#if HAVE_MODERN_QUARTZCORE
-static NSString* getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
+static NSString *getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
{
// Use literal strings to avoid link-time dependency on those symbols.
switch (transformType) {
@@ -247,20 +246,9 @@ static String propertyIdToString(AnimatedPropertyID property)
return "";
}
-static String animationIdentifier(AnimatedPropertyID property, const String& keyframesName, int index)
+static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index)
{
- StringBuilder builder;
-
- builder.append(propertyIdToString(property));
- builder.append("_");
-
- if (!keyframesName.isEmpty()) {
- builder.append(keyframesName);
- builder.append("_");
- }
- builder.append("_");
- builder.append(String::number(index));
- return builder.toString();
+ return animationName + String::format("_%d_%d", property, index);
}
static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction* timingFunction)
@@ -550,39 +538,40 @@ void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t)
noteLayerPropertyChanged(ChildrenTransformChanged);
}
-void GraphicsLayerCA::moveOrCopyAllAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, const String& keyframesName, CALayer *fromLayer, CALayer *toLayer)
+void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, CALayer *fromLayer, CALayer *toLayer)
{
- for (int index = 0; ; ++index) {
- String animName = animationIdentifier(property, keyframesName, index);
+ NSString *animationID = animationIdentifier;
+ CAAnimation *anim = [fromLayer animationForKey:animationID];
+ if (!anim)
+ return;
- CAAnimation* anim = [fromLayer animationForKey:animName];
- if (!anim)
+ switch (operation) {
+ case Move:
+ [anim retain];
+ [fromLayer removeAnimationForKey:animationID];
+ [toLayer addAnimation:anim forKey:animationID];
+ [anim release];
break;
- switch (operation) {
- case Move:
- [anim retain];
- [fromLayer removeAnimationForKey:animName];
- [toLayer addAnimation:anim forKey:animName];
- [anim release];
- break;
-
- case Copy:
- [toLayer addAnimation:anim forKey:animName];
- break;
- }
+ case Copy:
+ [toLayer addAnimation:anim forKey:animationID];
+ break;
}
}
void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, CALayer *fromLayer, CALayer *toLayer)
{
- // Move transitions for this property.
- moveOrCopyAllAnimationsForProperty(operation, property, "", fromLayer, toLayer);
-
// Look for running animations affecting this property.
- KeyframeAnimationsMap::const_iterator end = m_runningKeyframeAnimations.end();
- for (KeyframeAnimationsMap::const_iterator it = m_runningKeyframeAnimations.begin(); it != end; ++it)
- moveOrCopyAllAnimationsForProperty(operation, property, it->first, fromLayer, toLayer);
+ AnimationsMap::const_iterator end = m_runningAnimations.end();
+ for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
+ const Vector<LayerPropertyAnimation>& propertyAnimations = it->second;
+ size_t numAnimations = propertyAnimations.size();
+ for (size_t i = 0; i < numAnimations; ++i) {
+ const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
+ if (currAnimation.m_property == property)
+ moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index), fromLayer, toLayer);
+ }
+ }
}
void GraphicsLayerCA::setPreserves3D(bool preserves3D)
@@ -704,8 +693,10 @@ void GraphicsLayerCA::setContentsRect(const IntRect& rect)
noteLayerPropertyChanged(ContentsRectChanged);
}
-bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
+bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset)
{
+ ASSERT(!animationName.isEmpty());
+
if (forceSoftwareAnimation() || !anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
return false;
@@ -723,9 +714,9 @@ bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const Int
bool createdAnimations = false;
if (valueList.property() == AnimatedPropertyWebkitTransform)
- createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, keyframesName, timeOffset, boxSize);
+ createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize);
else
- createdAnimations = createAnimationFromKeyframes(valueList, anim, keyframesName, timeOffset);
+ createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset);
if (createdAnimations)
noteLayerPropertyChanged(AnimationChanged);
@@ -733,39 +724,46 @@ bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const Int
return createdAnimations;
}
-void GraphicsLayerCA::removeAnimationsForProperty(AnimatedPropertyID property)
+void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset)
{
- if (m_transitionPropertiesToRemove.find(property) != m_transitionPropertiesToRemove.end())
+ if (!animationIsRunning(animationName))
return;
- m_transitionPropertiesToRemove.add(property);
+ AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName);
+ if (it != m_animationsToProcess.end()) {
+ AnimationProcessingAction& processingInfo = it->second;
+ // If an animation is scheduled to be removed, don't change the remove to a pause.
+ if (processingInfo.action != Remove)
+ processingInfo.action = Pause;
+ } else
+ m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset));
+
noteLayerPropertyChanged(AnimationChanged);
}
-void GraphicsLayerCA::removeAnimationsForKeyframes(const String& animationName)
+void GraphicsLayerCA::removeAnimation(const String& animationName)
{
if (!animationIsRunning(animationName))
return;
- m_keyframeAnimationsToProcess.add(animationName, AnimationProcessingAction(Remove));
+ m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove));
noteLayerPropertyChanged(AnimationChanged);
}
-void GraphicsLayerCA::pauseAnimation(const String& keyframesName, double timeOffset)
+void GraphicsLayerCA::animationDidStart(CAAnimation* caAnimation)
{
- if (!animationIsRunning(keyframesName))
- return;
+ bool hadNonZeroBeginTime = [[caAnimation valueForKey:WebKitAnimationBeginTimeSetKey] boolValue];
- AnimationsToProcessMap::iterator it = m_keyframeAnimationsToProcess.find(keyframesName);
- if (it != m_keyframeAnimationsToProcess.end()) {
- AnimationProcessingAction& processingInfo = it->second;
- // If an animation is scheduled to be removed, don't change the remove to a pause.
- if (processingInfo.action != Remove)
- processingInfo.action = Pause;
+ double startTime;
+ if (hadNonZeroBeginTime) {
+ // We don't know what time CA used to commit the animation, so just use the current time
+ // (even though this will be slightly off).
+ startTime = WebCore::mediaTimeToCurrentTime(CACurrentMediaTime());
} else
- m_keyframeAnimationsToProcess.add(keyframesName, AnimationProcessingAction(Pause, timeOffset));
+ startTime = WebCore::mediaTimeToCurrentTime([caAnimation beginTime]);
- noteLayerPropertyChanged(AnimationChanged);
+ if (m_client)
+ m_client->notifyAnimationStarted(this, startTime);
}
void GraphicsLayerCA::setContentsToImage(Image* image)
@@ -1496,68 +1494,49 @@ CALayer *GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState)
void GraphicsLayerCA::updateLayerAnimations()
{
- if (m_transitionPropertiesToRemove.size()) {
- HashSet<int>::const_iterator end = m_transitionPropertiesToRemove.end();
- for (HashSet<AnimatedProperty>::const_iterator it = m_transitionPropertiesToRemove.begin(); it != end; ++it) {
- AnimatedPropertyID currProperty = static_cast<AnimatedPropertyID>(*it);
- // Remove all animations with this property in the key.
- for (int index = 0; ; ++index) {
- if (!removeAnimationFromLayer(currProperty, "", index))
- break;
- }
- }
-
- m_transitionPropertiesToRemove.clear();
- }
-
- if (m_keyframeAnimationsToProcess.size()) {
- AnimationsToProcessMap::const_iterator end = m_keyframeAnimationsToProcess.end();
- for (AnimationsToProcessMap::const_iterator it = m_keyframeAnimationsToProcess.begin(); it != end; ++it) {
- const String& currKeyframeName = it->first;
- KeyframeAnimationsMap::iterator animationIt = m_runningKeyframeAnimations.find(currKeyframeName);
- if (animationIt == m_runningKeyframeAnimations.end())
+ if (m_animationsToProcess.size()) {
+ AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end();
+ for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) {
+ const String& currAnimationName = it->first;
+ AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName);
+ if (animationIt == m_runningAnimations.end())
continue;
const AnimationProcessingAction& processingInfo = it->second;
- const Vector<AnimationPair>& animations = animationIt->second;
+ const Vector<LayerPropertyAnimation>& animations = animationIt->second;
for (size_t i = 0; i < animations.size(); ++i) {
- const AnimationPair& currPair = animations[i];
+ const LayerPropertyAnimation& currAnimation = animations[i];
switch (processingInfo.action) {
case Remove:
- removeAnimationFromLayer(static_cast<AnimatedPropertyID>(currPair.first), currKeyframeName, currPair.second);
+ removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index);
break;
case Pause:
- pauseAnimationOnLayer(static_cast<AnimatedPropertyID>(currPair.first), currKeyframeName, currPair.second, processingInfo.timeOffset);
+ pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, processingInfo.timeOffset);
break;
}
}
if (processingInfo.action == Remove)
- m_runningKeyframeAnimations.remove(currKeyframeName);
+ m_runningAnimations.remove(currAnimationName);
}
- m_keyframeAnimationsToProcess.clear();
+ m_animationsToProcess.clear();
}
size_t numAnimations;
if ((numAnimations = m_uncomittedAnimations.size())) {
for (size_t i = 0; i < numAnimations; ++i) {
- const LayerAnimation& pendingAnimation = m_uncomittedAnimations[i];
- setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_keyframesName, pendingAnimation.m_index, pendingAnimation.m_timeOffset);
+ const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i];
+ setCAAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_timeOffset);
- if (!pendingAnimation.m_keyframesName.isEmpty()) {
- // If this is a keyframe anim, we have to remember the association of keyframes name to property/index pairs,
- // so we can remove the animations later if needed.
- // For transitions, we can just generate animation names with property and index.
- KeyframeAnimationsMap::iterator it = m_runningKeyframeAnimations.find(pendingAnimation.m_keyframesName);
- if (it == m_runningKeyframeAnimations.end()) {
- Vector<AnimationPair> firstPair;
- firstPair.append(AnimationPair(pendingAnimation.m_property, pendingAnimation.m_index));
- m_runningKeyframeAnimations.add(pendingAnimation.m_keyframesName, firstPair);
- } else {
- Vector<AnimationPair>& animPairs = it->second;
- animPairs.append(AnimationPair(pendingAnimation.m_property, pendingAnimation.m_index));
- }
+ AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name);
+ if (it == m_runningAnimations.end()) {
+ Vector<LayerPropertyAnimation> animations;
+ animations.append(pendingAnimation);
+ m_runningAnimations.add(pendingAnimation.m_name, animations);
+ } else {
+ Vector<LayerPropertyAnimation>& animations = it->second;
+ animations.append(pendingAnimation);
}
}
@@ -1565,16 +1544,19 @@ void GraphicsLayerCA::updateLayerAnimations()
}
}
-void GraphicsLayerCA::setAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, const String& keyframesName, int index, double timeOffset)
+void GraphicsLayerCA::setCAAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
{
PlatformLayer* layer = animatedLayer(property);
- [caAnim setTimeOffset:timeOffset];
-
- String animationName = animationIdentifier(property, keyframesName, index);
-
- [layer removeAnimationForKey:animationName];
- [layer addAnimation:caAnim forKey:animationName];
+ if (timeOffset) {
+ [caAnim setBeginTime:CACurrentMediaTime() - timeOffset];
+ [caAnim setValue:[NSNumber numberWithBool:YES] forKey:WebKitAnimationBeginTimeSetKey];
+ }
+
+ NSString *animationID = animationIdentifier(animationName, property, index);
+
+ [layer removeAnimationForKey:animationID];
+ [layer addAnimation:caAnim forKey:animationID];
if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
LayerMap::const_iterator end = layerCloneMap->end();
@@ -1583,8 +1565,8 @@ void GraphicsLayerCA::setAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedP
if (m_replicaLayer && isReplicatedRootClone(it->first))
continue;
CALayer *currLayer = it->second.get();
- [currLayer removeAnimationForKey:animationName];
- [currLayer addAnimation:caAnim forKey:animationName];
+ [currLayer removeAnimationForKey:animationID];
+ [currLayer addAnimation:caAnim forKey:animationID];
}
}
}
@@ -1604,16 +1586,16 @@ static void bug7311367Workaround(CALayer* transformLayer, const TransformationMa
[transformLayer setTransform:caTransform];
}
-bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, const String& keyframesName, int index)
+bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index)
{
PlatformLayer* layer = animatedLayer(property);
- String animationName = animationIdentifier(property, keyframesName, index);
+ NSString *animationID = animationIdentifier(animationName, property, index);
- if (![layer animationForKey:animationName])
+ if (![layer animationForKey:animationID])
return false;
- [layer removeAnimationForKey:animationName];
+ [layer removeAnimationForKey:animationID];
bug7311367Workaround(m_structuralLayer.get(), m_transform);
if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
@@ -1624,7 +1606,7 @@ bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, cons
continue;
CALayer *currLayer = it->second.get();
- [currLayer removeAnimationForKey:animationName];
+ [currLayer removeAnimationForKey:animationID];
}
}
return true;
@@ -1644,15 +1626,18 @@ static void copyAnimationProperties(CAPropertyAnimation* from, CAPropertyAnimati
#if HAVE_MODERN_QUARTZCORE
[to setValueFunction:[from valueFunction]];
#endif
+
+ if (id object = [from valueForKey:WebKitAnimationBeginTimeSetKey])
+ [to setValue:object forKey:WebKitAnimationBeginTimeSetKey];
}
-void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, const String& keyframesName, int index, double timeOffset)
+void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
{
PlatformLayer* layer = animatedLayer(property);
- String animationName = animationIdentifier(property, keyframesName, index);
+ NSString *animationID = animationIdentifier(animationName, property, index);
- CAAnimation* caAnim = [layer animationForKey:animationName];
+ CAAnimation *caAnim = [layer animationForKey:animationID];
if (!caAnim)
return;
@@ -1679,7 +1664,7 @@ void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, const S
[pausedAnim setSpeed:0];
[pausedAnim setTimeOffset:timeOffset];
- [layer addAnimation:pausedAnim forKey:animationName]; // This will replace the running animation.
+ [layer addAnimation:pausedAnim forKey:animationID]; // This will replace the running animation.
// Pause the animations on the clones too.
if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
@@ -1689,7 +1674,7 @@ void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, const S
if (m_replicaLayer && isReplicatedRootClone(it->first))
continue;
CALayer *currLayer = it->second.get();
- [currLayer addAnimation:pausedAnim forKey:animationName];
+ [currLayer addAnimation:pausedAnim forKey:animationID];
}
}
}
@@ -1726,7 +1711,7 @@ void GraphicsLayerCA::updateContentsNeedsDisplay()
[m_contentsLayer.get() setNeedsDisplay];
}
-bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double timeOffset)
+bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)
{
ASSERT(valueList.property() != AnimatedPropertyWebkitTransform);
@@ -1752,14 +1737,14 @@ bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valu
if (!valuesOK)
return false;
- m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, timeOffset));
+ m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
END_BLOCK_OBJC_EXCEPTIONS;
return true;
}
-bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double timeOffset, const IntSize& boxSize)
+bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize)
{
ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
@@ -1810,7 +1795,7 @@ bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValue
if (!validMatrices)
break;
- m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, timeOffset));
+ m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
}
END_BLOCK_OBJC_EXCEPTIONS;
@@ -1844,7 +1829,7 @@ void GraphicsLayerCA::setupAnimation(CAPropertyAnimation* propertyAnim, const An
else if (anim->direction() == Animation::AnimationDirectionAlternate)
repeatCount /= 2;
- NSString* fillMode = 0;
+ NSString *fillMode = 0;
switch (anim->fillMode()) {
case AnimationFillModeNone:
fillMode = kCAFillModeForwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash.
@@ -1983,7 +1968,7 @@ bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& va
[basicAnim setToValue:toValue];
#if HAVE_MODERN_QUARTZCORE
- if (NSString* valueFunctionName = getValueFunctionNameForTransformOperation(transformOp))
+ if (NSString *valueFunctionName = getValueFunctionNameForTransformOperation(transformOp))
[basicAnim setValueFunction:[CAValueFunction functionWithName:valueFunctionName]];
#endif
@@ -2028,7 +2013,7 @@ bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& va
[keyframeAnim setTimingFunctions:timingFunctions.get()];
#if HAVE_MODERN_QUARTZCORE
- if (NSString* valueFunctionName = getValueFunctionNameForTransformOperation(transformOpType))
+ if (NSString *valueFunctionName = getValueFunctionNameForTransformOperation(transformOpType))
[keyframeAnim setValueFunction:[CAValueFunction functionWithName:valueFunctionName]];
#endif
return true;
@@ -2045,7 +2030,7 @@ void GraphicsLayerCA::suspendAnimations(double time)
LayerMap::const_iterator end = layerCloneMap->end();
for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
CALayer *currLayer = it->second.get();
- [currLayer setSpeed:0 ];
+ [currLayer setSpeed:0];
[currLayer setTimeOffset:t];
}
}