27de2b5d576b2d8751af424cd1a00baa42f627f1
[WebKit-https.git] / Source / WebCore / platform / graphics / ca / win / PlatformCAAnimationWin.cpp
1 /*
2  * Copyright (C) 2014 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 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 PLATFORM(WIN) && USE(CA)
29 #include "PlatformCAAnimationWin.h"
30
31 #include "FloatConversion.h"
32 #include "TimingFunction.h"
33 #include <QuartzCore/CACFAnimation.h>
34 #include <QuartzCore/CACFTiming.h>
35 #include <QuartzCore/CACFTimingFunction.h>
36 #include <QuartzCore/CACFValueFunction.h>
37 #include <QuartzCore/CACFVector.h>
38 #include <wtf/text/WTFString.h>
39
40 using namespace WebCore;
41
42 static CFStringRef toCACFFillModeType(PlatformCAAnimation::FillModeType type)
43 {
44     switch (type) {
45     case PlatformCAAnimation::NoFillMode:
46     case PlatformCAAnimation::Forwards: return kCACFFillModeForwards;
47     case PlatformCAAnimation::Backwards: return kCACFFillModeBackwards;
48     case PlatformCAAnimation::Both: return kCACFFillModeBoth;
49     }
50     ASSERT_NOT_REACHED();
51     return 0;
52 }
53
54 static PlatformCAAnimation::FillModeType fromCACFFillModeType(CFStringRef string)
55 {
56     if (string == kCACFFillModeBackwards)
57         return PlatformCAAnimation::Backwards;
58
59     if (string == kCACFFillModeBoth)
60         return PlatformCAAnimation::Both;
61
62     return PlatformCAAnimation::Forwards;
63 }
64
65 static CFStringRef toCACFValueFunctionType(PlatformCAAnimation::ValueFunctionType type)
66 {
67     switch (type) {
68     case PlatformCAAnimation::NoValueFunction: return 0;
69     case PlatformCAAnimation::RotateX: return kCACFValueFunctionRotateX;
70     case PlatformCAAnimation::RotateY: return kCACFValueFunctionRotateY;
71     case PlatformCAAnimation::RotateZ: return kCACFValueFunctionRotateZ;
72     case PlatformCAAnimation::ScaleX: return kCACFValueFunctionScaleX;
73     case PlatformCAAnimation::ScaleY: return kCACFValueFunctionScaleY;
74     case PlatformCAAnimation::ScaleZ: return kCACFValueFunctionScaleZ;
75     case PlatformCAAnimation::Scale: return kCACFValueFunctionScale;
76     case PlatformCAAnimation::TranslateX: return kCACFValueFunctionTranslateX;
77     case PlatformCAAnimation::TranslateY: return kCACFValueFunctionTranslateY;
78     case PlatformCAAnimation::TranslateZ: return kCACFValueFunctionTranslateZ;
79     case PlatformCAAnimation::Translate: return kCACFValueFunctionTranslate;
80     }
81     ASSERT_NOT_REACHED();
82     return 0;
83 }
84
85 static PlatformCAAnimation::ValueFunctionType fromCACFValueFunctionType(CFStringRef string)
86 {
87     if (string == kCACFValueFunctionRotateX)
88         return PlatformCAAnimation::RotateX;
89
90     if (string == kCACFValueFunctionRotateY)
91         return PlatformCAAnimation::RotateY;
92
93     if (string == kCACFValueFunctionRotateZ)
94         return PlatformCAAnimation::RotateZ;
95
96     if (string == kCACFValueFunctionScaleX)
97         return PlatformCAAnimation::ScaleX;
98
99     if (string == kCACFValueFunctionScaleY)
100         return PlatformCAAnimation::ScaleY;
101
102     if (string == kCACFValueFunctionScaleZ)
103         return PlatformCAAnimation::ScaleZ;
104
105     if (string == kCACFValueFunctionScale)
106         return PlatformCAAnimation::Scale;
107
108     if (string == kCACFValueFunctionTranslateX)
109         return PlatformCAAnimation::TranslateX;
110
111     if (string == kCACFValueFunctionTranslateY)
112         return PlatformCAAnimation::TranslateY;
113
114     if (string == kCACFValueFunctionTranslateZ)
115         return PlatformCAAnimation::TranslateZ;
116
117     if (string == kCACFValueFunctionTranslate)
118         return PlatformCAAnimation::Translate;
119
120     return PlatformCAAnimation::NoValueFunction;
121 }
122
123 static RetainPtr<CACFTimingFunctionRef> toCACFTimingFunction(const TimingFunction* timingFunction, bool reverse)
124 {
125     ASSERT(timingFunction);
126     if (timingFunction->isCubicBezierTimingFunction()) {
127         RefPtr<CubicBezierTimingFunction> reversed;
128         const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
129
130         if (reverse) {
131             reversed = ctf->createReversed();
132             ctf = reversed.get();
133         }
134
135         float x1 = static_cast<float>(ctf->x1());
136         float y1 = static_cast<float>(ctf->y1());
137         float x2 = static_cast<float>(ctf->x2());
138         float y2 = static_cast<float>(ctf->y2());
139         return adoptCF(CACFTimingFunctionCreate(x1, y1, x2, y2));
140     }
141     
142     return CACFTimingFunctionGetFunctionWithName(kCACFTimingFunctionLinear);
143 }
144
145 PassRefPtr<PlatformCAAnimation> PlatformCAAnimationWin::create(AnimationType type, const String& keyPath)
146 {
147     return adoptRef(new PlatformCAAnimationWin(type, keyPath));
148 }
149
150 PassRefPtr<PlatformCAAnimation> PlatformCAAnimationWin::create(PlatformAnimationRef animation)
151 {
152     return adoptRef(new PlatformCAAnimationWin(animation));
153 }
154
155 PlatformCAAnimationWin::PlatformCAAnimationWin(AnimationType type, const String& keyPath)
156     : PlatformCAAnimation(type)
157 {
158     if (type == Basic)
159         m_animation = adoptCF(CACFAnimationCreate(kCACFBasicAnimation));
160     else
161         m_animation = adoptCF(CACFAnimationCreate(kCACFKeyframeAnimation));
162     
163     CACFAnimationSetKeyPath(m_animation.get(), keyPath.createCFString().get());
164 }
165
166 PlatformCAAnimationWin::PlatformCAAnimationWin(PlatformAnimationRef animation)
167 {
168     if (CACFAnimationGetClass(animation) == kCACFBasicAnimation)
169         setType(Basic);
170     else if (CACFAnimationGetClass(animation) == kCACFKeyframeAnimation)
171         setType(Keyframe);
172     else {
173         ASSERT_NOT_REACHED();
174         return;
175     }
176     
177     m_animation = animation;
178 }
179
180 PassRefPtr<PlatformCAAnimation> PlatformCAAnimationWin::copy() const
181 {
182     RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
183     
184     animation->setBeginTime(beginTime());
185     animation->setDuration(duration());
186     animation->setSpeed(speed());
187     animation->setTimeOffset(timeOffset());
188     animation->setRepeatCount(repeatCount());
189     animation->setAutoreverses(autoreverses());
190     animation->setFillMode(fillMode());
191     animation->setRemovedOnCompletion(isRemovedOnCompletion());
192     animation->setAdditive(isAdditive());
193     animation->copyTimingFunctionFrom(*this);
194     if (valueFunction())
195         animation->setValueFunction(valueFunction());
196     
197     // Copy the specific Basic or Keyframe values
198     if (animationType() == Keyframe) {
199         animation->copyValuesFrom(*this);
200         animation->copyKeyTimesFrom(*this);
201         animation->copyTimingFunctionsFrom(*this);
202     } else {
203         animation->copyFromValueFrom(*this);
204         animation->copyToValueFrom(*this);
205     }
206     
207     return animation;
208 }
209
210 PlatformCAAnimationWin::~PlatformCAAnimationWin()
211 {
212 }
213
214 PlatformAnimationRef PlatformCAAnimationWin::platformAnimation() const
215 {
216     return m_animation.get();
217 }
218
219 String PlatformCAAnimationWin::keyPath() const
220 {
221     return CACFAnimationGetKeyPath(m_animation.get());
222 }
223
224 CFTimeInterval PlatformCAAnimationWin::beginTime() const
225 {
226     return CACFAnimationGetBeginTime(m_animation.get());
227 }
228
229 void PlatformCAAnimationWin::setBeginTime(CFTimeInterval value)
230 {
231     CACFAnimationSetBeginTime(m_animation.get(), value);
232 }
233
234 CFTimeInterval PlatformCAAnimationWin::duration() const
235 {
236     return CACFAnimationGetDuration(m_animation.get());
237 }
238
239 void PlatformCAAnimationWin::setDuration(CFTimeInterval value)
240 {
241     CACFAnimationSetDuration(m_animation.get(), value);
242 }
243
244 float PlatformCAAnimationWin::speed() const
245 {
246     return CACFAnimationGetSpeed(m_animation.get());
247 }
248
249 void PlatformCAAnimationWin::setSpeed(float value)
250 {
251     CACFAnimationSetSpeed(m_animation.get(), value);
252 }
253
254 CFTimeInterval PlatformCAAnimationWin::timeOffset() const
255 {
256     return CACFAnimationGetTimeOffset(m_animation.get());
257 }
258
259 void PlatformCAAnimationWin::setTimeOffset(CFTimeInterval value)
260 {
261     CACFAnimationSetTimeOffset(m_animation.get(), value);
262 }
263
264 float PlatformCAAnimationWin::repeatCount() const
265 {
266     return CACFAnimationGetRepeatCount(m_animation.get());
267 }
268
269 void PlatformCAAnimationWin::setRepeatCount(float value)
270 {
271     CACFAnimationSetRepeatCount(m_animation.get(), value);
272 }
273
274 bool PlatformCAAnimationWin::autoreverses() const
275 {
276     return CACFAnimationGetAutoreverses(m_animation.get());
277 }
278
279 void PlatformCAAnimationWin::setAutoreverses(bool value)
280 {
281     CACFAnimationSetAutoreverses(m_animation.get(), value);
282 }
283
284 PlatformCAAnimationWin::FillModeType PlatformCAAnimationWin::fillMode() const
285 {
286     return fromCACFFillModeType(CACFAnimationGetFillMode(m_animation.get()));
287 }
288
289 void PlatformCAAnimationWin::setFillMode(FillModeType value)
290 {
291     CACFAnimationSetFillMode(m_animation.get(), toCACFFillModeType(value));
292 }
293
294 void PlatformCAAnimationWin::setTimingFunction(const TimingFunction* value, bool reverse)
295 {
296     UNUSED_PARAM(reverse);
297     CACFAnimationSetTimingFunction(m_animation.get(), toCACFTimingFunction(value, reverse).get());
298 }
299
300 void PlatformCAAnimationWin::copyTimingFunctionFrom(const PlatformCAAnimation& value)
301 {
302     CACFTimingFunctionRef timingFunc = CACFAnimationGetTimingFunction(downcast<PlatformCAAnimationWin>(value).m_animation.get());
303     if (timingFunc)
304         CACFAnimationSetTimingFunction(m_animation.get(), timingFunc);
305 }
306
307 bool PlatformCAAnimationWin::isRemovedOnCompletion() const
308 {
309     return CACFAnimationIsRemovedOnCompletion(m_animation.get());
310 }
311
312 void PlatformCAAnimationWin::setRemovedOnCompletion(bool value)
313 {
314     CACFAnimationSetRemovedOnCompletion(m_animation.get(), value);
315 }
316
317 bool PlatformCAAnimationWin::isAdditive() const
318 {
319     return CACFAnimationIsAdditive(m_animation.get());
320 }
321
322 void PlatformCAAnimationWin::setAdditive(bool value)
323 {
324     CACFAnimationSetAdditive(m_animation.get(), value);
325 }
326
327 PlatformCAAnimation::ValueFunctionType PlatformCAAnimationWin::valueFunction() const
328 {
329     CACFValueFunctionRef func = CACFAnimationGetValueFunction(m_animation.get());
330     return func ? fromCACFValueFunctionType(CACFValueFunctionGetName(func)) : NoValueFunction;
331 }
332
333 void PlatformCAAnimationWin::setValueFunction(ValueFunctionType value)
334 {
335     CFStringRef valueString = toCACFValueFunctionType(value);
336     CACFAnimationSetValueFunction(m_animation.get(), valueString ? CACFValueFunctionGetFunctionWithName(valueString) : 0);
337 }
338
339 void PlatformCAAnimationWin::setFromValue(float value)
340 {
341     if (animationType() != Basic)
342         return;
343
344     RetainPtr<CFNumberRef> v = adoptCF(CFNumberCreate(0, kCFNumberFloatType, &value));
345     CACFAnimationSetFromValue(m_animation.get(), v.get());
346 }
347
348 void PlatformCAAnimationWin::setFromValue(const WebCore::TransformationMatrix& value)
349 {
350     if (animationType() != Basic)
351         return;
352     
353     RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreateTransform(value));
354     CACFAnimationSetFromValue(m_animation.get(), v.get());
355 }
356
357 void PlatformCAAnimationWin::setFromValue(const FloatPoint3D& value)
358 {
359     if (animationType() != Basic)
360         return;
361
362     CGFloat a[3] = { value.x(), value.y(), value.z() };
363     RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreate(3, a));
364     CACFAnimationSetFromValue(m_animation.get(), v.get());
365 }
366
367 void PlatformCAAnimationWin::setFromValue(const WebCore::Color& value)
368 {
369     if (animationType() != Basic)
370         return;
371
372     CGFloat a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
373     RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreate(4, a));
374     CACFAnimationSetFromValue(m_animation.get(), v.get());
375 }
376
377 void PlatformCAAnimationWin::setFromValue(const FilterOperation*, int)
378 {
379     // FIXME: Hardware filter animation not implemented on Windows
380 }
381
382 void PlatformCAAnimationWin::copyFromValueFrom(const PlatformCAAnimation& value)
383 {
384     if (animationType() != Basic || value.animationType() != Basic)
385         return;
386     
387     CACFAnimationSetFromValue(m_animation.get(), CACFAnimationGetFromValue(downcast<PlatformCAAnimationWin>(value).platformAnimation()));
388 }
389
390 void PlatformCAAnimationWin::setToValue(float value)
391 {
392     if (animationType() != Basic)
393         return;
394
395     RetainPtr<CFNumberRef> v = adoptCF(CFNumberCreate(0, kCFNumberFloatType, &value));
396     CACFAnimationSetToValue(m_animation.get(), v.get());
397 }
398
399 void PlatformCAAnimationWin::setToValue(const WebCore::TransformationMatrix& value)
400 {
401     if (animationType() != Basic)
402         return;
403
404     RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreateTransform(value));
405     CACFAnimationSetToValue(m_animation.get(), v.get());
406 }
407
408 void PlatformCAAnimationWin::setToValue(const FloatPoint3D& value)
409 {
410     if (animationType() != Basic)
411         return;
412
413     CGFloat a[3] = { value.x(), value.y(), value.z() };
414     RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreate(3, a));
415     CACFAnimationSetToValue(m_animation.get(), v.get());
416 }
417
418 void PlatformCAAnimationWin::setToValue(const WebCore::Color& value)
419 {
420     if (animationType() != Basic)
421         return;
422
423     CGFloat a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
424     RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreate(4, a));
425     CACFAnimationSetToValue(m_animation.get(), v.get());
426 }
427
428 void PlatformCAAnimationWin::setToValue(const FilterOperation*, int)
429 {
430     // FIXME: Hardware filter animation not implemented on Windows
431 }
432
433 void PlatformCAAnimationWin::copyToValueFrom(const PlatformCAAnimation& value)
434 {
435     if (animationType() != Basic || value.animationType() != Basic)
436         return;
437         
438     CACFAnimationSetToValue(m_animation.get(), CACFAnimationGetToValue(downcast<PlatformCAAnimationWin>(value).platformAnimation()));
439 }
440
441 // Keyframe-animation properties.
442 void PlatformCAAnimationWin::setValues(const Vector<float>& value)
443 {
444     if (animationType() != Keyframe)
445         return;
446
447     RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
448     for (size_t i = 0; i < value.size(); ++i) {
449         RetainPtr<CFNumberRef> v = adoptCF(CFNumberCreate(0, kCFNumberFloatType, &value[i]));
450         CFArrayAppendValue(array.get(), v.get());
451     }
452
453     CACFAnimationSetValues(m_animation.get(), array.get());
454 }
455
456 void PlatformCAAnimationWin::setValues(const Vector<WebCore::TransformationMatrix>& value)
457 {
458     if (animationType() != Keyframe)
459         return;
460
461     RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
462     for (size_t i = 0; i < value.size(); ++i) {
463         RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreateTransform(value[i]));
464         CFArrayAppendValue(array.get(), v.get());
465     }
466
467     CACFAnimationSetValues(m_animation.get(), array.get());
468 }
469
470 void PlatformCAAnimationWin::setValues(const Vector<FloatPoint3D>& value)
471 {
472     if (animationType() != Keyframe)
473         return;
474         
475     RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
476     for (size_t i = 0; i < value.size(); ++i) {
477         CGFloat a[3] = { value[i].x(), value[i].y(), value[i].z() };
478         RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreate(3, a));
479         CFArrayAppendValue(array.get(), v.get());
480     }
481
482     CACFAnimationSetValues(m_animation.get(), array.get());
483 }
484
485 void PlatformCAAnimationWin::setValues(const Vector<WebCore::Color>& value)
486 {
487     if (animationType() != Keyframe)
488         return;
489         
490     RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
491     for (size_t i = 0; i < value.size(); ++i) {
492         CGFloat a[4] = { value[i].red(), value[i].green(), value[i].blue(), value[i].alpha() };
493         RetainPtr<CACFVectorRef> v = adoptCF(CACFVectorCreate(4, a));
494         CFArrayAppendValue(array.get(), v.get());
495     }
496
497     CACFAnimationSetValues(m_animation.get(), array.get());
498 }
499
500 void PlatformCAAnimationWin::setValues(const Vector<RefPtr<FilterOperation> >&, int)
501 {
502     // FIXME: Hardware filter animation not implemented on Windows
503 }
504
505 void PlatformCAAnimationWin::copyValuesFrom(const PlatformCAAnimation& value)
506 {
507     if (animationType() != Keyframe || value.animationType() != Keyframe)
508         return;
509     
510     CACFAnimationSetValues(m_animation.get(), CACFAnimationGetValues(downcast<PlatformCAAnimationWin>(value).platformAnimation()));
511 }
512
513 void PlatformCAAnimationWin::setKeyTimes(const Vector<float>& value)
514 {
515     if (animationType() != Keyframe)
516         return;
517         
518     RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
519     for (size_t i = 0; i < value.size(); ++i) {
520         RetainPtr<CFNumberRef> v = adoptCF(CFNumberCreate(0, kCFNumberFloatType, &value[i]));
521         CFArrayAppendValue(array.get(), v.get());
522     }
523
524     CACFAnimationSetKeyTimes(m_animation.get(), array.get());
525 }
526
527 void PlatformCAAnimationWin::copyKeyTimesFrom(const PlatformCAAnimation& value)
528 {
529     if (animationType() != Keyframe)
530         return;
531
532     CACFAnimationSetKeyTimes(m_animation.get(), CACFAnimationGetKeyTimes(downcast<PlatformCAAnimationWin>(value).platformAnimation()));
533 }
534
535 void PlatformCAAnimationWin::setTimingFunctions(const Vector<const TimingFunction*>& value, bool reverse)
536 {
537     UNUSED_PARAM(reverse);
538     if (animationType() != Keyframe)
539         return;
540
541     RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
542     for (size_t i = 0; i < value.size(); ++i) {
543         RetainPtr<CFNumberRef> v = adoptCF(CFNumberCreate(0, kCFNumberFloatType, &value[i]));
544         CFArrayAppendValue(array.get(), toCACFTimingFunction(value[i], reverse).get());
545     }
546
547     CACFAnimationSetTimingFunctions(m_animation.get(), array.get());
548 }
549
550 void PlatformCAAnimationWin::copyTimingFunctionsFrom(const PlatformCAAnimation& value)
551 {
552     CACFAnimationSetTimingFunctions(m_animation.get(), CACFAnimationGetTimingFunctions(downcast<PlatformCAAnimationWin>(value).platformAnimation()));
553 }
554
555 #endif // PLATFORM(WIN)