• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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