2 * Copyright (C) 2011 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 #include "PlatformCAAnimation.h"
32 #include "FloatConversion.h"
33 #include "PlatformString.h"
34 #include "TimingFunction.h"
35 #include <QuartzCore/CACFAnimation.h>
36 #include <QuartzCore/CACFTiming.h>
37 #include <QuartzCore/CACFTimingFunction.h>
38 #include <QuartzCore/CACFValueFunction.h>
39 #include <QuartzCore/CACFVector.h>
40 #include <wtf/UnusedParam.h>
42 using namespace WebCore;
44 static CFStringRef toCACFFillModeType(PlatformCAAnimation::FillModeType type)
47 case PlatformCAAnimation::NoFillMode:
48 case PlatformCAAnimation::Forwards: return kCACFFillModeForwards;
49 case PlatformCAAnimation::Backwards: return kCACFFillModeBackwards;
50 case PlatformCAAnimation::Both: return kCACFFillModeBoth;
56 static PlatformCAAnimation::FillModeType fromCACFFillModeType(CFStringRef string)
58 if (string == kCACFFillModeBackwards)
59 return PlatformCAAnimation::Backwards;
61 if (string == kCACFFillModeBoth)
62 return PlatformCAAnimation::Both;
64 return PlatformCAAnimation::Forwards;
67 static CFStringRef toCACFValueFunctionType(PlatformCAAnimation::ValueFunctionType type)
70 case PlatformCAAnimation::NoValueFunction: return 0;
71 case PlatformCAAnimation::RotateX: return kCACFValueFunctionRotateX;
72 case PlatformCAAnimation::RotateY: return kCACFValueFunctionRotateY;
73 case PlatformCAAnimation::RotateZ: return kCACFValueFunctionRotateZ;
74 case PlatformCAAnimation::ScaleX: return kCACFValueFunctionScaleX;
75 case PlatformCAAnimation::ScaleY: return kCACFValueFunctionScaleY;
76 case PlatformCAAnimation::ScaleZ: return kCACFValueFunctionScaleZ;
77 case PlatformCAAnimation::Scale: return kCACFValueFunctionScale;
78 case PlatformCAAnimation::TranslateX: return kCACFValueFunctionTranslateX;
79 case PlatformCAAnimation::TranslateY: return kCACFValueFunctionTranslateY;
80 case PlatformCAAnimation::TranslateZ: return kCACFValueFunctionTranslateZ;
81 case PlatformCAAnimation::Translate: return kCACFValueFunctionTranslate;
87 static PlatformCAAnimation::ValueFunctionType fromCACFValueFunctionType(CFStringRef string)
89 if (string == kCACFValueFunctionRotateX)
90 return PlatformCAAnimation::RotateX;
92 if (string == kCACFValueFunctionRotateY)
93 return PlatformCAAnimation::RotateY;
95 if (string == kCACFValueFunctionRotateZ)
96 return PlatformCAAnimation::RotateZ;
98 if (string == kCACFValueFunctionScaleX)
99 return PlatformCAAnimation::ScaleX;
101 if (string == kCACFValueFunctionScaleY)
102 return PlatformCAAnimation::ScaleY;
104 if (string == kCACFValueFunctionScaleZ)
105 return PlatformCAAnimation::ScaleZ;
107 if (string == kCACFValueFunctionScale)
108 return PlatformCAAnimation::Scale;
110 if (string == kCACFValueFunctionTranslateX)
111 return PlatformCAAnimation::TranslateX;
113 if (string == kCACFValueFunctionTranslateY)
114 return PlatformCAAnimation::TranslateY;
116 if (string == kCACFValueFunctionTranslateZ)
117 return PlatformCAAnimation::TranslateZ;
119 if (string == kCACFValueFunctionTranslate)
120 return PlatformCAAnimation::Translate;
122 return PlatformCAAnimation::NoValueFunction;
125 static RetainPtr<CACFTimingFunctionRef> toCACFTimingFunction(const TimingFunction* timingFunction)
127 ASSERT(timingFunction);
128 if (timingFunction->isCubicBezierTimingFunction()) {
129 const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
130 return RetainPtr<CACFTimingFunctionRef>(AdoptCF, CACFTimingFunctionCreate(static_cast<float>(ctf->x1()), static_cast<float>(ctf->y1()), static_cast<float>(ctf->x2()), static_cast<float>(ctf->y2())));
133 return CACFTimingFunctionGetFunctionWithName(kCACFTimingFunctionLinear);
136 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(AnimationType type, const String& keyPath)
138 return adoptRef(new PlatformCAAnimation(type, keyPath));
141 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(PlatformAnimationRef animation)
143 return adoptRef(new PlatformCAAnimation(animation));
146 PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath)
150 m_animation.adoptCF(CACFAnimationCreate(kCACFBasicAnimation));
152 m_animation.adoptCF(CACFAnimationCreate(kCACFKeyframeAnimation));
154 RetainPtr<CFStringRef> s(AdoptCF, keyPath.createCFString());
155 CACFAnimationSetKeyPath(m_animation.get(), s.get());
158 PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation)
160 if (CACFAnimationGetClass(animation) == kCACFBasicAnimation)
162 else if (CACFAnimationGetClass(animation) == kCACFKeyframeAnimation)
165 ASSERT_NOT_REACHED();
169 m_animation = animation;
172 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::copy() const
174 RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
176 animation->setBeginTime(beginTime());
177 animation->setDuration(duration());
178 animation->setSpeed(speed());
179 animation->setTimeOffset(timeOffset());
180 animation->setRepeatCount(repeatCount());
181 animation->setAutoreverses(autoreverses());
182 animation->setFillMode(fillMode());
183 animation->setRemovedOnCompletion(isRemovedOnCompletion());
184 animation->setAdditive(isAdditive());
185 animation->copyTimingFunctionFrom(this);
186 animation->setValueFunction(valueFunction());
188 // Copy the specific Basic or Keyframe values
189 if (animationType() == Keyframe) {
190 animation->copyValuesFrom(this);
191 animation->copyKeyTimesFrom(this);
192 animation->copyTimingFunctionsFrom(this);
194 animation->copyFromValueFrom(this);
195 animation->copyToValueFrom(this);
201 PlatformCAAnimation::~PlatformCAAnimation()
205 bool PlatformCAAnimation::supportsValueFunction()
210 PlatformAnimationRef PlatformCAAnimation::platformAnimation() const
212 return m_animation.get();
215 String PlatformCAAnimation::keyPath() const
217 return CACFAnimationGetKeyPath(m_animation.get());
220 CFTimeInterval PlatformCAAnimation::beginTime() const
222 return CACFAnimationGetBeginTime(m_animation.get());
225 void PlatformCAAnimation::setBeginTime(CFTimeInterval value)
227 CACFAnimationSetBeginTime(m_animation.get(), value);
230 CFTimeInterval PlatformCAAnimation::duration() const
232 return CACFAnimationGetDuration(m_animation.get());
235 void PlatformCAAnimation::setDuration(CFTimeInterval value)
237 CACFAnimationSetDuration(m_animation.get(), value);
240 float PlatformCAAnimation::speed() const
242 return CACFAnimationGetSpeed(m_animation.get());
245 void PlatformCAAnimation::setSpeed(float value)
247 CACFAnimationSetSpeed(m_animation.get(), value);
250 CFTimeInterval PlatformCAAnimation::timeOffset() const
252 return CACFAnimationGetTimeOffset(m_animation.get());
255 void PlatformCAAnimation::setTimeOffset(CFTimeInterval value)
257 CACFAnimationSetTimeOffset(m_animation.get(), value);
260 float PlatformCAAnimation::repeatCount() const
262 return CACFAnimationGetRepeatCount(m_animation.get());
265 void PlatformCAAnimation::setRepeatCount(float value)
267 CACFAnimationSetRepeatCount(m_animation.get(), value);
270 bool PlatformCAAnimation::autoreverses() const
272 return CACFAnimationGetAutoreverses(m_animation.get());
275 void PlatformCAAnimation::setAutoreverses(bool value)
277 CACFAnimationSetAutoreverses(m_animation.get(), value);
280 PlatformCAAnimation::FillModeType PlatformCAAnimation::fillMode() const
282 return fromCACFFillModeType(CACFAnimationGetFillMode(m_animation.get()));
285 void PlatformCAAnimation::setFillMode(FillModeType value)
287 CACFAnimationSetFillMode(m_animation.get(), toCACFFillModeType(value));
290 void PlatformCAAnimation::setTimingFunction(const TimingFunction* value)
292 CACFAnimationSetTimingFunction(m_animation.get(), toCACFTimingFunction(value).get());
295 void PlatformCAAnimation::copyTimingFunctionFrom(const PlatformCAAnimation* value)
297 CACFAnimationSetTimingFunction(m_animation.get(), CACFAnimationGetTimingFunction(value->m_animation.get()));
300 bool PlatformCAAnimation::isRemovedOnCompletion() const
302 return CACFAnimationIsRemovedOnCompletion(m_animation.get());
305 void PlatformCAAnimation::setRemovedOnCompletion(bool value)
307 CACFAnimationSetRemovedOnCompletion(m_animation.get(), value);
310 bool PlatformCAAnimation::isAdditive() const
312 return CACFAnimationIsAdditive(m_animation.get());
315 void PlatformCAAnimation::setAdditive(bool value)
317 CACFAnimationSetAdditive(m_animation.get(), value);
320 PlatformCAAnimation::ValueFunctionType PlatformCAAnimation::valueFunction() const
322 CACFValueFunctionRef func = CACFAnimationGetValueFunction(m_animation.get());
323 return func ? fromCACFValueFunctionType(CACFValueFunctionGetName(func)) : NoValueFunction;
326 void PlatformCAAnimation::setValueFunction(ValueFunctionType value)
328 CFStringRef valueString = toCACFValueFunctionType(value);
329 CACFAnimationSetValueFunction(m_animation.get(), valueString ? CACFValueFunctionGetFunctionWithName(valueString) : 0);
332 void PlatformCAAnimation::setFromValue(float value)
334 if (animationType() != Basic)
337 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value));
338 CACFAnimationSetFromValue(m_animation.get(), v.get());
341 void PlatformCAAnimation::setFromValue(const WebCore::TransformationMatrix& value)
343 if (animationType() != Basic)
346 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreateTransform(value));
347 CACFAnimationSetFromValue(m_animation.get(), v.get());
350 void PlatformCAAnimation::setFromValue(const FloatPoint3D& value)
352 if (animationType() != Basic)
355 float a[3] = { value.x(), value.y(), value.z() };
356 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(3, a));
357 CACFAnimationSetFromValue(m_animation.get(), v.get());
360 void PlatformCAAnimation::setFromValue(const WebCore::Color& value)
362 if (animationType() != Basic)
365 float a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
366 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(4, a));
367 CACFAnimationSetFromValue(m_animation.get(), v.get());
370 void PlatformCAAnimation::copyFromValueFrom(const PlatformCAAnimation* value)
372 if (animationType() != Basic || value->animationType() != Basic)
375 CACFAnimationSetFromValue(m_animation.get(), CACFAnimationGetFromValue(value->platformAnimation()));
378 void PlatformCAAnimation::setToValue(float value)
380 if (animationType() != Basic)
383 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value));
384 CACFAnimationSetToValue(m_animation.get(), v.get());
387 void PlatformCAAnimation::setToValue(const WebCore::TransformationMatrix& value)
389 if (animationType() != Basic)
392 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreateTransform(value));
393 CACFAnimationSetToValue(m_animation.get(), v.get());
396 void PlatformCAAnimation::setToValue(const FloatPoint3D& value)
398 if (animationType() != Basic)
401 float a[3] = { value.x(), value.y(), value.z() };
402 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(3, a));
403 CACFAnimationSetToValue(m_animation.get(), v.get());
406 void PlatformCAAnimation::setToValue(const WebCore::Color& value)
408 if (animationType() != Basic)
411 float a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
412 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(4, a));
413 CACFAnimationSetToValue(m_animation.get(), v.get());
416 void PlatformCAAnimation::copyToValueFrom(const PlatformCAAnimation* value)
418 if (animationType() != Basic || value->animationType() != Basic)
421 CACFAnimationSetToValue(m_animation.get(), CACFAnimationGetToValue(value->platformAnimation()));
425 // Keyframe-animation properties.
426 void PlatformCAAnimation::setValues(const Vector<float>& value)
428 if (animationType() != Keyframe)
431 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
432 for (size_t i = 0; i < value.size(); ++i) {
433 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i]));
434 CFArrayAppendValue(array.get(), v.get());
437 CACFAnimationSetValues(m_animation.get(), array.get());
440 void PlatformCAAnimation::setValues(const Vector<WebCore::TransformationMatrix>& value)
442 if (animationType() != Keyframe)
445 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
446 for (size_t i = 0; i < value.size(); ++i) {
447 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreateTransform(value[i]));
448 CFArrayAppendValue(array.get(), v.get());
451 CACFAnimationSetValues(m_animation.get(), array.get());
454 void PlatformCAAnimation::setValues(const Vector<FloatPoint3D>& value)
456 if (animationType() != Keyframe)
459 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
460 for (size_t i = 0; i < value.size(); ++i) {
461 float a[3] = { value[i].x(), value[i].y(), value[i].z() };
462 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(3, a));
463 CFArrayAppendValue(array.get(), v.get());
466 CACFAnimationSetValues(m_animation.get(), array.get());
469 void PlatformCAAnimation::setValues(const Vector<WebCore::Color>& value)
471 if (animationType() != Keyframe)
474 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
475 for (size_t i = 0; i < value.size(); ++i) {
476 float a[4] = { value[i].red(), value[i].green(), value[i].blue(), value[i].alpha() };
477 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(4, a));
478 CFArrayAppendValue(array.get(), v.get());
481 CACFAnimationSetValues(m_animation.get(), array.get());
484 void PlatformCAAnimation::copyValuesFrom(const PlatformCAAnimation* value)
486 if (animationType() != Keyframe || value->animationType() != Keyframe)
489 CACFAnimationSetValues(m_animation.get(), CACFAnimationGetValues(value->platformAnimation()));
492 void PlatformCAAnimation::setKeyTimes(const Vector<float>& value)
494 if (animationType() != Keyframe)
497 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
498 for (size_t i = 0; i < value.size(); ++i) {
499 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i]));
500 CFArrayAppendValue(array.get(), v.get());
503 CACFAnimationSetKeyTimes(m_animation.get(), array.get());
506 void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value)
508 if (animationType() != Keyframe)
511 CACFAnimationSetKeyTimes(m_animation.get(), CACFAnimationGetKeyTimes(value->platformAnimation()));
514 void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value)
516 if (animationType() != Keyframe)
519 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
520 for (size_t i = 0; i < value.size(); ++i) {
521 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i]));
522 CFArrayAppendValue(array.get(), toCACFTimingFunction(value[i]).get());
525 CACFAnimationSetTimingFunctions(m_animation.get(), array.get());
528 void PlatformCAAnimation::copyTimingFunctionsFrom(const PlatformCAAnimation* value)
530 CACFAnimationSetTimingFunctions(m_animation.get(), CACFAnimationGetTimingFunctions(value->platformAnimation()));
533 #endif // USE(ACCELERATED_COMPOSITING)