2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #if USE(ACCELERATED_COMPOSITING)
30 #import "PlatformCAAnimation.h"
32 #import "FloatConversion.h"
33 #import "PlatformString.h"
34 #import "TimingFunction.h"
35 #import <QuartzCore/QuartzCore.h>
36 #import <wtf/UnusedParam.h>
38 #define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
40 using namespace WebCore;
42 // This value must be the same as in PlatformCALayerMac.mm
43 static NSString * const WKNonZeroBeginTimeFlag = @"WKPlatformCAAnimationNonZeroBeginTimeFlag";
45 static bool hasNonZeroBeginTimeFlag(const PlatformCAAnimation* animation)
47 return [[animation->platformAnimation() valueForKey:WKNonZeroBeginTimeFlag] boolValue];
50 static void setNonZeroBeginTimeFlag(PlatformCAAnimation* animation, bool value)
52 [animation->platformAnimation() setValue:[NSNumber numberWithBool:value] forKey:WKNonZeroBeginTimeFlag];
55 static NSString* toCAFillModeType(PlatformCAAnimation::FillModeType type)
58 case PlatformCAAnimation::NoFillMode:
59 case PlatformCAAnimation::Forwards: return kCAFillModeForwards;
60 case PlatformCAAnimation::Backwards: return kCAFillModeBackwards;
61 case PlatformCAAnimation::Both: return kCAFillModeBoth;
66 static PlatformCAAnimation::FillModeType fromCAFillModeType(NSString* string)
68 if ([string isEqualToString:kCAFillModeBackwards])
69 return PlatformCAAnimation::Backwards;
71 if ([string isEqualToString:kCAFillModeBoth])
72 return PlatformCAAnimation::Both;
74 return PlatformCAAnimation::Forwards;
77 #if HAVE_MODERN_QUARTZCORE
78 static NSString* toCAValueFunctionType(PlatformCAAnimation::ValueFunctionType type)
81 case PlatformCAAnimation::NoValueFunction: return @"";
82 case PlatformCAAnimation::RotateX: return kCAValueFunctionRotateX;
83 case PlatformCAAnimation::RotateY: return kCAValueFunctionRotateY;
84 case PlatformCAAnimation::RotateZ: return kCAValueFunctionRotateZ;
85 case PlatformCAAnimation::ScaleX: return kCAValueFunctionScaleX;
86 case PlatformCAAnimation::ScaleY: return kCAValueFunctionScaleY;
87 case PlatformCAAnimation::ScaleZ: return kCAValueFunctionScaleZ;
88 case PlatformCAAnimation::Scale: return kCAValueFunctionScale;
89 case PlatformCAAnimation::TranslateX: return kCAValueFunctionTranslateX;
90 case PlatformCAAnimation::TranslateY: return kCAValueFunctionTranslateY;
91 case PlatformCAAnimation::TranslateZ: return kCAValueFunctionTranslateZ;
92 case PlatformCAAnimation::Translate: return kCAValueFunctionTranslate;
97 static PlatformCAAnimation::ValueFunctionType fromCAValueFunctionType(NSString* string)
99 if ([string isEqualToString:kCAValueFunctionRotateX])
100 return PlatformCAAnimation::RotateX;
102 if ([string isEqualToString:kCAValueFunctionRotateY])
103 return PlatformCAAnimation::RotateY;
105 if ([string isEqualToString:kCAValueFunctionRotateZ])
106 return PlatformCAAnimation::RotateZ;
108 if ([string isEqualToString:kCAValueFunctionScaleX])
109 return PlatformCAAnimation::ScaleX;
111 if ([string isEqualToString:kCAValueFunctionScaleY])
112 return PlatformCAAnimation::ScaleY;
114 if ([string isEqualToString:kCAValueFunctionScaleZ])
115 return PlatformCAAnimation::ScaleZ;
117 if ([string isEqualToString:kCAValueFunctionScale])
118 return PlatformCAAnimation::Scale;
120 if ([string isEqualToString:kCAValueFunctionTranslateX])
121 return PlatformCAAnimation::TranslateX;
123 if ([string isEqualToString:kCAValueFunctionTranslateY])
124 return PlatformCAAnimation::TranslateY;
126 if ([string isEqualToString:kCAValueFunctionTranslateZ])
127 return PlatformCAAnimation::TranslateZ;
129 if ([string isEqualToString:kCAValueFunctionTranslate])
130 return PlatformCAAnimation::Translate;
132 return PlatformCAAnimation::NoValueFunction;
136 static CAMediaTimingFunction* toCAMediaTimingFunction(const TimingFunction* timingFunction)
139 return [CAMediaTimingFunction functionWithControlPoints:0.25f :0.1f :0.25f :0.1f];
141 if (timingFunction->isCubicBezierTimingFunction()) {
142 const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
143 return [CAMediaTimingFunction functionWithControlPoints:static_cast<float>(ctf->x1()) :static_cast<float>(ctf->y1())
144 :static_cast<float>(ctf->x2()) :static_cast<float>(ctf->y2())];
147 return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
152 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(AnimationType type, const String& keyPath)
154 return adoptRef(new PlatformCAAnimation(type, keyPath));
157 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(PlatformAnimationRef animation)
159 return adoptRef(new PlatformCAAnimation(animation));
162 PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath)
166 m_animation.adoptNS([[CABasicAnimation animationWithKeyPath:keyPath] retain]);
168 m_animation.adoptNS([[CAKeyframeAnimation animationWithKeyPath:keyPath] retain]);
171 PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation)
173 if ([static_cast<CAAnimation*>(animation) isKindOfClass:[CABasicAnimation class]])
175 else if ([static_cast<CAAnimation*>(animation) isKindOfClass:[CAKeyframeAnimation class]])
182 m_animation = static_cast<CAPropertyAnimation*>(animation);
185 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::copy() const
187 RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
189 animation->setBeginTime(beginTime());
190 animation->setDuration(duration());
191 animation->setSpeed(speed());
192 animation->setTimeOffset(timeOffset());
193 animation->setRepeatCount(repeatCount());
194 animation->setAutoreverses(autoreverses());
195 animation->setFillMode(fillMode());
196 animation->setRemovedOnCompletion(isRemovedOnCompletion());
197 animation->setAdditive(isAdditive());
198 animation->copyTimingFunctionFrom(this);
199 animation->setValueFunction(valueFunction());
201 setNonZeroBeginTimeFlag(animation.get(), hasNonZeroBeginTimeFlag(this));
203 // Copy the specific Basic or Keyframe values
204 if (animationType() == Keyframe) {
205 animation->copyValuesFrom(this);
206 animation->copyKeyTimesFrom(this);
207 animation->copyTimingFunctionsFrom(this);
209 animation->copyFromValueFrom(this);
210 animation->copyToValueFrom(this);
215 PlatformCAAnimation::~PlatformCAAnimation()
219 bool PlatformCAAnimation::supportsValueFunction()
221 static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
222 return sHaveValueFunction;
225 PlatformAnimationRef PlatformCAAnimation::platformAnimation() const
227 return m_animation.get();
230 String PlatformCAAnimation::keyPath() const
232 return [m_animation.get() keyPath];
235 CFTimeInterval PlatformCAAnimation::beginTime() const
237 return [m_animation.get() beginTime];
240 void PlatformCAAnimation::setBeginTime(CFTimeInterval value)
242 [m_animation.get() setBeginTime:value];
244 // Also set a flag to tell us if we've passed in a 0 value.
245 // The flag is needed because later beginTime will get changed
246 // to the time at which it fired and we need to know whether
247 // or not it was 0 to begin with.
249 setNonZeroBeginTimeFlag(this, true);
252 CFTimeInterval PlatformCAAnimation::duration() const
254 return [m_animation.get() duration];
257 void PlatformCAAnimation::setDuration(CFTimeInterval value)
259 [m_animation.get() setDuration:value];
262 float PlatformCAAnimation::speed() const
264 return [m_animation.get() speed];
267 void PlatformCAAnimation::setSpeed(float value)
269 [m_animation.get() setSpeed:value];
272 CFTimeInterval PlatformCAAnimation::timeOffset() const
274 return [m_animation.get() timeOffset];
277 void PlatformCAAnimation::setTimeOffset(CFTimeInterval value)
279 [m_animation.get() setTimeOffset:value];
282 float PlatformCAAnimation::repeatCount() const
284 return [m_animation.get() repeatCount];
287 void PlatformCAAnimation::setRepeatCount(float value)
289 [m_animation.get() setRepeatCount:value];
292 bool PlatformCAAnimation::autoreverses() const
294 return [m_animation.get() autoreverses];
297 void PlatformCAAnimation::setAutoreverses(bool value)
299 [m_animation.get() setAutoreverses:value];
302 PlatformCAAnimation::FillModeType PlatformCAAnimation::fillMode() const
304 return fromCAFillModeType([m_animation.get() fillMode]);
307 void PlatformCAAnimation::setFillMode(FillModeType value)
309 [m_animation.get() setFillMode:toCAFillModeType(value)];
312 void PlatformCAAnimation::setTimingFunction(const TimingFunction* value)
314 [m_animation.get() setTimingFunction:toCAMediaTimingFunction(value)];
317 void PlatformCAAnimation::copyTimingFunctionFrom(const PlatformCAAnimation* value)
319 [m_animation.get() setTimingFunction:[value->m_animation.get() timingFunction]];
322 bool PlatformCAAnimation::isRemovedOnCompletion() const
324 return [m_animation.get() isRemovedOnCompletion];
327 void PlatformCAAnimation::setRemovedOnCompletion(bool value)
329 [m_animation.get() setRemovedOnCompletion:value];
332 bool PlatformCAAnimation::isAdditive() const
334 return [m_animation.get() isAdditive];
337 void PlatformCAAnimation::setAdditive(bool value)
339 [m_animation.get() setAdditive:value];
342 PlatformCAAnimation::ValueFunctionType PlatformCAAnimation::valueFunction() const
344 #if HAVE_MODERN_QUARTZCORE
345 CAValueFunction* vf = [m_animation.get() valueFunction];
346 return fromCAValueFunctionType([vf name]);
348 return NoValueFunction;
352 void PlatformCAAnimation::setValueFunction(ValueFunctionType value)
354 #if HAVE_MODERN_QUARTZCORE
355 [m_animation.get() setValueFunction:[CAValueFunction functionWithName:toCAValueFunctionType(value)]];
361 void PlatformCAAnimation::setFromValue(float value)
363 if (animationType() != Basic)
365 [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[NSNumber numberWithDouble:value]];
368 void PlatformCAAnimation::setFromValue(const WebCore::TransformationMatrix& value)
370 if (animationType() != Basic)
373 [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[NSValue valueWithCATransform3D:value]];
376 void PlatformCAAnimation::setFromValue(const FloatPoint3D& value)
378 if (animationType() != Basic)
381 NSArray* array = [NSArray arrayWithObjects:
382 [NSNumber numberWithDouble:value.x()],
383 [NSNumber numberWithDouble:value.y()],
384 [NSNumber numberWithDouble:value.z()],
386 [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:array];
389 void PlatformCAAnimation::setFromValue(const WebCore::Color& value)
391 if (animationType() != Basic)
394 NSArray* array = [NSArray arrayWithObjects:
395 [NSNumber numberWithDouble:value.red()],
396 [NSNumber numberWithDouble:value.green()],
397 [NSNumber numberWithDouble:value.blue()],
398 [NSNumber numberWithDouble:value.alpha()],
400 [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:array];
403 void PlatformCAAnimation::copyFromValueFrom(const PlatformCAAnimation* value)
405 if (animationType() != Basic || value->animationType() != Basic)
408 CABasicAnimation* otherAnimation = static_cast<CABasicAnimation*>(value->m_animation.get());
409 [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[otherAnimation fromValue]];
412 void PlatformCAAnimation::setToValue(float value)
414 if (animationType() != Basic)
416 [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[NSNumber numberWithDouble:value]];
419 void PlatformCAAnimation::setToValue(const WebCore::TransformationMatrix& value)
421 if (animationType() != Basic)
424 [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[NSValue valueWithCATransform3D:value]];
427 void PlatformCAAnimation::setToValue(const FloatPoint3D& value)
429 if (animationType() != Basic)
432 NSArray* array = [NSArray arrayWithObjects:
433 [NSNumber numberWithDouble:value.x()],
434 [NSNumber numberWithDouble:value.y()],
435 [NSNumber numberWithDouble:value.z()],
437 [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:array];
440 void PlatformCAAnimation::setToValue(const WebCore::Color& value)
442 if (animationType() != Basic)
445 NSArray* array = [NSArray arrayWithObjects:
446 [NSNumber numberWithDouble:value.red()],
447 [NSNumber numberWithDouble:value.green()],
448 [NSNumber numberWithDouble:value.blue()],
449 [NSNumber numberWithDouble:value.alpha()],
451 [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:array];
454 void PlatformCAAnimation::copyToValueFrom(const PlatformCAAnimation* value)
456 if (animationType() != Basic || value->animationType() != Basic)
459 CABasicAnimation* otherAnimation = static_cast<CABasicAnimation*>(value->m_animation.get());
460 [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[otherAnimation toValue]];
464 // Keyframe-animation properties.
465 void PlatformCAAnimation::setValues(const Vector<float>& value)
467 if (animationType() != Keyframe)
470 NSMutableArray* array = [NSMutableArray array];
471 for (size_t i = 0; i < value.size(); ++i)
472 [array addObject:[NSNumber numberWithDouble:value[i]]];
473 [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
476 void PlatformCAAnimation::setValues(const Vector<WebCore::TransformationMatrix>& value)
478 if (animationType() != Keyframe)
481 NSMutableArray* array = [NSMutableArray array];
483 for (size_t i = 0; i < value.size(); ++i)
484 [array addObject:[NSValue valueWithCATransform3D:value[i]]];
486 [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
489 void PlatformCAAnimation::setValues(const Vector<FloatPoint3D>& value)
491 if (animationType() != Keyframe)
494 NSMutableArray* array = [NSMutableArray array];
496 for (size_t i = 0; i < value.size(); ++i) {
497 NSArray* object = [NSArray arrayWithObjects:
498 [NSNumber numberWithDouble:value[i].x()],
499 [NSNumber numberWithDouble:value[i].y()],
500 [NSNumber numberWithDouble:value[i].z()],
502 [array addObject:object];
504 [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
507 void PlatformCAAnimation::setValues(const Vector<WebCore::Color>& value)
509 if (animationType() != Keyframe)
512 NSMutableArray* array = [NSMutableArray array];
514 for (size_t i = 0; i < value.size(); ++i) {
515 NSArray* object = [NSArray arrayWithObjects:
516 [NSNumber numberWithDouble:value[i].red()],
517 [NSNumber numberWithDouble:value[i].green()],
518 [NSNumber numberWithDouble:value[i].blue()],
519 [NSNumber numberWithDouble:value[i].alpha()],
521 [array addObject:object];
523 [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
526 void PlatformCAAnimation::copyValuesFrom(const PlatformCAAnimation* value)
528 if (animationType() != Keyframe || value->animationType() != Keyframe)
531 CAKeyframeAnimation* otherAnimation = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
532 [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:[otherAnimation values]];
535 void PlatformCAAnimation::setKeyTimes(const Vector<float>& value)
537 NSMutableArray* array = [NSMutableArray array];
539 for (size_t i = 0; i < value.size(); ++i)
540 [array addObject:[NSNumber numberWithFloat:value[i]]];
542 [static_cast<CAKeyframeAnimation*>(m_animation.get()) setKeyTimes:array];
545 void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value)
547 CAKeyframeAnimation* other = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
548 [static_cast<CAKeyframeAnimation*>(m_animation.get()) setKeyTimes:[other keyTimes]];
551 void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value)
553 NSMutableArray* array = [NSMutableArray array];
555 for (size_t i = 0; i < value.size(); ++i)
556 [array addObject:toCAMediaTimingFunction(value[i])];
558 [static_cast<CAKeyframeAnimation*>(m_animation.get()) setTimingFunctions:array];
561 void PlatformCAAnimation::copyTimingFunctionsFrom(const PlatformCAAnimation* value)
563 CAKeyframeAnimation* other = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
564 [static_cast<CAKeyframeAnimation*>(m_animation.get()) setTimingFunctions:[other timingFunctions]];
567 #endif // USE(ACCELERATED_COMPOSITING)