1 /*
2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26 #include "config.h"
27
28 #if USE(ACCELERATED_COMPOSITING)
29
30 #include "PlatformCAAnimation.h"
31
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>
41
42 using namespace WebCore;
43
toCACFFillModeType(PlatformCAAnimation::FillModeType type)44 static CFStringRef toCACFFillModeType(PlatformCAAnimation::FillModeType type)
45 {
46 switch (type) {
47 case PlatformCAAnimation::NoFillMode:
48 case PlatformCAAnimation::Forwards: return kCACFFillModeForwards;
49 case PlatformCAAnimation::Backwards: return kCACFFillModeBackwards;
50 case PlatformCAAnimation::Both: return kCACFFillModeBoth;
51 }
52 ASSERT_NOT_REACHED();
53 return 0;
54 }
55
fromCACFFillModeType(CFStringRef string)56 static PlatformCAAnimation::FillModeType fromCACFFillModeType(CFStringRef string)
57 {
58 if (string == kCACFFillModeBackwards)
59 return PlatformCAAnimation::Backwards;
60
61 if (string == kCACFFillModeBoth)
62 return PlatformCAAnimation::Both;
63
64 return PlatformCAAnimation::Forwards;
65 }
66
toCACFValueFunctionType(PlatformCAAnimation::ValueFunctionType type)67 static CFStringRef toCACFValueFunctionType(PlatformCAAnimation::ValueFunctionType type)
68 {
69 switch (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;
82 }
83 ASSERT_NOT_REACHED();
84 return 0;
85 }
86
fromCACFValueFunctionType(CFStringRef string)87 static PlatformCAAnimation::ValueFunctionType fromCACFValueFunctionType(CFStringRef string)
88 {
89 if (string == kCACFValueFunctionRotateX)
90 return PlatformCAAnimation::RotateX;
91
92 if (string == kCACFValueFunctionRotateY)
93 return PlatformCAAnimation::RotateY;
94
95 if (string == kCACFValueFunctionRotateZ)
96 return PlatformCAAnimation::RotateZ;
97
98 if (string == kCACFValueFunctionScaleX)
99 return PlatformCAAnimation::ScaleX;
100
101 if (string == kCACFValueFunctionScaleY)
102 return PlatformCAAnimation::ScaleY;
103
104 if (string == kCACFValueFunctionScaleZ)
105 return PlatformCAAnimation::ScaleZ;
106
107 if (string == kCACFValueFunctionScale)
108 return PlatformCAAnimation::Scale;
109
110 if (string == kCACFValueFunctionTranslateX)
111 return PlatformCAAnimation::TranslateX;
112
113 if (string == kCACFValueFunctionTranslateY)
114 return PlatformCAAnimation::TranslateY;
115
116 if (string == kCACFValueFunctionTranslateZ)
117 return PlatformCAAnimation::TranslateZ;
118
119 if (string == kCACFValueFunctionTranslate)
120 return PlatformCAAnimation::Translate;
121
122 return PlatformCAAnimation::NoValueFunction;
123 }
124
toCACFTimingFunction(const TimingFunction * timingFunction)125 static RetainPtr<CACFTimingFunctionRef> toCACFTimingFunction(const TimingFunction* timingFunction)
126 {
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())));
131 }
132
133 return CACFTimingFunctionGetFunctionWithName(kCACFTimingFunctionLinear);
134 }
135
create(AnimationType type,const String & keyPath)136 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(AnimationType type, const String& keyPath)
137 {
138 return adoptRef(new PlatformCAAnimation(type, keyPath));
139 }
140
create(PlatformAnimationRef animation)141 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(PlatformAnimationRef animation)
142 {
143 return adoptRef(new PlatformCAAnimation(animation));
144 }
145
PlatformCAAnimation(AnimationType type,const String & keyPath)146 PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath)
147 : m_type(type)
148 {
149 if (type == Basic)
150 m_animation.adoptCF(CACFAnimationCreate(kCACFBasicAnimation));
151 else
152 m_animation.adoptCF(CACFAnimationCreate(kCACFKeyframeAnimation));
153
154 RetainPtr<CFStringRef> s(AdoptCF, keyPath.createCFString());
155 CACFAnimationSetKeyPath(m_animation.get(), s.get());
156 }
157
PlatformCAAnimation(PlatformAnimationRef animation)158 PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation)
159 {
160 if (CACFAnimationGetClass(animation) == kCACFBasicAnimation)
161 m_type = Basic;
162 else if (CACFAnimationGetClass(animation) == kCACFKeyframeAnimation)
163 m_type = Keyframe;
164 else {
165 ASSERT_NOT_REACHED();
166 return;
167 }
168
169 m_animation = animation;
170 }
171
copy() const172 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::copy() const
173 {
174 RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
175
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());
187
188 // Copy the specific Basic or Keyframe values
189 if (animationType() == Keyframe) {
190 animation->copyValuesFrom(this);
191 animation->copyKeyTimesFrom(this);
192 animation->copyTimingFunctionsFrom(this);
193 } else {
194 animation->copyFromValueFrom(this);
195 animation->copyToValueFrom(this);
196 }
197
198 return animation;
199 }
200
~PlatformCAAnimation()201 PlatformCAAnimation::~PlatformCAAnimation()
202 {
203 }
204
supportsValueFunction()205 bool PlatformCAAnimation::supportsValueFunction()
206 {
207 return true;
208 }
209
platformAnimation() const210 PlatformAnimationRef PlatformCAAnimation::platformAnimation() const
211 {
212 return m_animation.get();
213 }
214
keyPath() const215 String PlatformCAAnimation::keyPath() const
216 {
217 return CACFAnimationGetKeyPath(m_animation.get());
218 }
219
beginTime() const220 CFTimeInterval PlatformCAAnimation::beginTime() const
221 {
222 return CACFAnimationGetBeginTime(m_animation.get());
223 }
224
setBeginTime(CFTimeInterval value)225 void PlatformCAAnimation::setBeginTime(CFTimeInterval value)
226 {
227 CACFAnimationSetBeginTime(m_animation.get(), value);
228 }
229
duration() const230 CFTimeInterval PlatformCAAnimation::duration() const
231 {
232 return CACFAnimationGetDuration(m_animation.get());
233 }
234
setDuration(CFTimeInterval value)235 void PlatformCAAnimation::setDuration(CFTimeInterval value)
236 {
237 CACFAnimationSetDuration(m_animation.get(), value);
238 }
239
speed() const240 float PlatformCAAnimation::speed() const
241 {
242 return CACFAnimationGetSpeed(m_animation.get());
243 }
244
setSpeed(float value)245 void PlatformCAAnimation::setSpeed(float value)
246 {
247 CACFAnimationSetSpeed(m_animation.get(), value);
248 }
249
timeOffset() const250 CFTimeInterval PlatformCAAnimation::timeOffset() const
251 {
252 return CACFAnimationGetTimeOffset(m_animation.get());
253 }
254
setTimeOffset(CFTimeInterval value)255 void PlatformCAAnimation::setTimeOffset(CFTimeInterval value)
256 {
257 CACFAnimationSetTimeOffset(m_animation.get(), value);
258 }
259
repeatCount() const260 float PlatformCAAnimation::repeatCount() const
261 {
262 return CACFAnimationGetRepeatCount(m_animation.get());
263 }
264
setRepeatCount(float value)265 void PlatformCAAnimation::setRepeatCount(float value)
266 {
267 CACFAnimationSetRepeatCount(m_animation.get(), value);
268 }
269
autoreverses() const270 bool PlatformCAAnimation::autoreverses() const
271 {
272 return CACFAnimationGetAutoreverses(m_animation.get());
273 }
274
setAutoreverses(bool value)275 void PlatformCAAnimation::setAutoreverses(bool value)
276 {
277 CACFAnimationSetAutoreverses(m_animation.get(), value);
278 }
279
fillMode() const280 PlatformCAAnimation::FillModeType PlatformCAAnimation::fillMode() const
281 {
282 return fromCACFFillModeType(CACFAnimationGetFillMode(m_animation.get()));
283 }
284
setFillMode(FillModeType value)285 void PlatformCAAnimation::setFillMode(FillModeType value)
286 {
287 CACFAnimationSetFillMode(m_animation.get(), toCACFFillModeType(value));
288 }
289
setTimingFunction(const TimingFunction * value)290 void PlatformCAAnimation::setTimingFunction(const TimingFunction* value)
291 {
292 CACFAnimationSetTimingFunction(m_animation.get(), toCACFTimingFunction(value).get());
293 }
294
copyTimingFunctionFrom(const PlatformCAAnimation * value)295 void PlatformCAAnimation::copyTimingFunctionFrom(const PlatformCAAnimation* value)
296 {
297 CACFAnimationSetTimingFunction(m_animation.get(), CACFAnimationGetTimingFunction(value->m_animation.get()));
298 }
299
isRemovedOnCompletion() const300 bool PlatformCAAnimation::isRemovedOnCompletion() const
301 {
302 return CACFAnimationIsRemovedOnCompletion(m_animation.get());
303 }
304
setRemovedOnCompletion(bool value)305 void PlatformCAAnimation::setRemovedOnCompletion(bool value)
306 {
307 CACFAnimationSetRemovedOnCompletion(m_animation.get(), value);
308 }
309
isAdditive() const310 bool PlatformCAAnimation::isAdditive() const
311 {
312 return CACFAnimationIsAdditive(m_animation.get());
313 }
314
setAdditive(bool value)315 void PlatformCAAnimation::setAdditive(bool value)
316 {
317 CACFAnimationSetAdditive(m_animation.get(), value);
318 }
319
valueFunction() const320 PlatformCAAnimation::ValueFunctionType PlatformCAAnimation::valueFunction() const
321 {
322 return fromCACFValueFunctionType(CACFValueFunctionGetName(CACFAnimationGetValueFunction(m_animation.get())));
323 }
324
setValueFunction(ValueFunctionType value)325 void PlatformCAAnimation::setValueFunction(ValueFunctionType value)
326 {
327 CACFAnimationSetValueFunction(m_animation.get(), CACFValueFunctionGetFunctionWithName(toCACFValueFunctionType(value)));
328 }
329
setFromValue(float value)330 void PlatformCAAnimation::setFromValue(float value)
331 {
332 if (animationType() != Basic)
333 return;
334
335 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value));
336 CACFAnimationSetFromValue(m_animation.get(), v.get());
337 }
338
setFromValue(const WebCore::TransformationMatrix & value)339 void PlatformCAAnimation::setFromValue(const WebCore::TransformationMatrix& value)
340 {
341 if (animationType() != Basic)
342 return;
343
344 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreateTransform(value));
345 CACFAnimationSetFromValue(m_animation.get(), v.get());
346 }
347
setFromValue(const FloatPoint3D & value)348 void PlatformCAAnimation::setFromValue(const FloatPoint3D& value)
349 {
350 if (animationType() != Basic)
351 return;
352
353 float a[3] = { value.x(), value.y(), value.z() };
354 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(3, a));
355 CACFAnimationSetFromValue(m_animation.get(), v.get());
356 }
357
setFromValue(const WebCore::Color & value)358 void PlatformCAAnimation::setFromValue(const WebCore::Color& value)
359 {
360 if (animationType() != Basic)
361 return;
362
363 float a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
364 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(4, a));
365 CACFAnimationSetFromValue(m_animation.get(), v.get());
366 }
367
copyFromValueFrom(const PlatformCAAnimation * value)368 void PlatformCAAnimation::copyFromValueFrom(const PlatformCAAnimation* value)
369 {
370 if (animationType() != Basic || value->animationType() != Basic)
371 return;
372
373 CACFAnimationSetFromValue(m_animation.get(), CACFAnimationGetFromValue(value->platformAnimation()));
374 }
375
setToValue(float value)376 void PlatformCAAnimation::setToValue(float value)
377 {
378 if (animationType() != Basic)
379 return;
380
381 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value));
382 CACFAnimationSetToValue(m_animation.get(), v.get());
383 }
384
setToValue(const WebCore::TransformationMatrix & value)385 void PlatformCAAnimation::setToValue(const WebCore::TransformationMatrix& value)
386 {
387 if (animationType() != Basic)
388 return;
389
390 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreateTransform(value));
391 CACFAnimationSetToValue(m_animation.get(), v.get());
392 }
393
setToValue(const FloatPoint3D & value)394 void PlatformCAAnimation::setToValue(const FloatPoint3D& value)
395 {
396 if (animationType() != Basic)
397 return;
398
399 float a[3] = { value.x(), value.y(), value.z() };
400 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(3, a));
401 CACFAnimationSetToValue(m_animation.get(), v.get());
402 }
403
setToValue(const WebCore::Color & value)404 void PlatformCAAnimation::setToValue(const WebCore::Color& value)
405 {
406 if (animationType() != Basic)
407 return;
408
409 float a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
410 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(4, a));
411 CACFAnimationSetToValue(m_animation.get(), v.get());
412 }
413
copyToValueFrom(const PlatformCAAnimation * value)414 void PlatformCAAnimation::copyToValueFrom(const PlatformCAAnimation* value)
415 {
416 if (animationType() != Basic || value->animationType() != Basic)
417 return;
418
419 CACFAnimationSetToValue(m_animation.get(), CACFAnimationGetToValue(value->platformAnimation()));
420 }
421
422
423 // Keyframe-animation properties.
setValues(const Vector<float> & value)424 void PlatformCAAnimation::setValues(const Vector<float>& value)
425 {
426 if (animationType() != Keyframe)
427 return;
428
429 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
430 for (size_t i = 0; i < value.size(); ++i) {
431 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i]));
432 CFArrayAppendValue(array.get(), v.get());
433 }
434
435 CACFAnimationSetValues(m_animation.get(), array.get());
436 }
437
setValues(const Vector<WebCore::TransformationMatrix> & value)438 void PlatformCAAnimation::setValues(const Vector<WebCore::TransformationMatrix>& value)
439 {
440 if (animationType() != Keyframe)
441 return;
442
443 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
444 for (size_t i = 0; i < value.size(); ++i) {
445 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreateTransform(value[i]));
446 CFArrayAppendValue(array.get(), v.get());
447 }
448
449 CACFAnimationSetValues(m_animation.get(), array.get());
450 }
451
setValues(const Vector<FloatPoint3D> & value)452 void PlatformCAAnimation::setValues(const Vector<FloatPoint3D>& value)
453 {
454 if (animationType() != Keyframe)
455 return;
456
457 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
458 for (size_t i = 0; i < value.size(); ++i) {
459 float a[3] = { value[i].x(), value[i].y(), value[i].z() };
460 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(3, a));
461 CFArrayAppendValue(array.get(), v.get());
462 }
463
464 CACFAnimationSetValues(m_animation.get(), array.get());
465 }
466
setValues(const Vector<WebCore::Color> & value)467 void PlatformCAAnimation::setValues(const Vector<WebCore::Color>& value)
468 {
469 if (animationType() != Keyframe)
470 return;
471
472 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
473 for (size_t i = 0; i < value.size(); ++i) {
474 float a[4] = { value[i].red(), value[i].green(), value[i].blue(), value[i].alpha() };
475 RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(4, a));
476 CFArrayAppendValue(array.get(), v.get());
477 }
478
479 CACFAnimationSetValues(m_animation.get(), array.get());
480 }
481
copyValuesFrom(const PlatformCAAnimation * value)482 void PlatformCAAnimation::copyValuesFrom(const PlatformCAAnimation* value)
483 {
484 if (animationType() != Keyframe || value->animationType() != Keyframe)
485 return;
486
487 CACFAnimationSetValues(m_animation.get(), CACFAnimationGetValues(value->platformAnimation()));
488 }
489
setKeyTimes(const Vector<float> & value)490 void PlatformCAAnimation::setKeyTimes(const Vector<float>& value)
491 {
492 if (animationType() != Keyframe)
493 return;
494
495 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
496 for (size_t i = 0; i < value.size(); ++i) {
497 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i]));
498 CFArrayAppendValue(array.get(), v.get());
499 }
500
501 CACFAnimationSetKeyTimes(m_animation.get(), array.get());
502 }
503
copyKeyTimesFrom(const PlatformCAAnimation * value)504 void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value)
505 {
506 if (animationType() != Keyframe)
507 return;
508
509 CACFAnimationSetKeyTimes(m_animation.get(), CACFAnimationGetKeyTimes(value->platformAnimation()));
510 }
511
setTimingFunctions(const Vector<const TimingFunction * > & value)512 void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value)
513 {
514 if (animationType() != Keyframe)
515 return;
516
517 RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
518 for (size_t i = 0; i < value.size(); ++i) {
519 RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i]));
520 CFArrayAppendValue(array.get(), toCACFTimingFunction(value[i]).get());
521 }
522
523 CACFAnimationSetTimingFunctions(m_animation.get(), array.get());
524 }
525
copyTimingFunctionsFrom(const PlatformCAAnimation * value)526 void PlatformCAAnimation::copyTimingFunctionsFrom(const PlatformCAAnimation* value)
527 {
528 CACFAnimationSetTimingFunctions(m_animation.get(), CACFAnimationGetTimingFunctions(value->platformAnimation()));
529 }
530
531 #endif // USE(ACCELERATED_COMPOSITING)
532