ce3a3f07dbbc728e6a37f56abd98b07fa0260d79
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebPage / mac / PlatformCAAnimationRemote.mm
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 #import "PlatformCAAnimationRemote.h"
28
29 #import "ArgumentCoders.h"
30 #import "RemoteLayerTreeHost.h"
31 #import "WebCoreArgumentCoders.h"
32 #import <WebCore/BlockExceptions.h>
33 #import <WebCore/GraphicsLayer.h>
34 #import <WebCore/PlatformCAAnimationMac.h>
35 #import <WebCore/PlatformCAFilters.h>
36 #import <WebCore/TimingFunction.h>
37 #import <wtf/CurrentTime.h>
38 #import <wtf/RetainPtr.h>
39 #import <QuartzCore/QuartzCore.h>
40
41 using namespace WTF;
42 using namespace WebCore;
43
44 static double mediaTimeToCurrentTime(CFTimeInterval t)
45 {
46     return monotonicallyIncreasingTime() + t - CACurrentMediaTime();
47 }
48
49 static NSString * const WKExplicitBeginTimeFlag = @"WKPlatformCAAnimationExplicitBeginTimeFlag";
50
51 @interface WKAnimationDelegate : NSObject {
52     GraphicsLayer::PlatformLayerID _layerID;
53     WebKit::RemoteLayerTreeHost* _layerTreeHost;
54 }
55
56 - (instancetype)initWithLayerID:(GraphicsLayer::PlatformLayerID)layerID layerTreeHost:(WebKit::RemoteLayerTreeHost*)layerTreeHost;
57 @end
58
59 @implementation WKAnimationDelegate
60
61 - (instancetype)initWithLayerID:(GraphicsLayer::PlatformLayerID)layerID layerTreeHost:(WebKit::RemoteLayerTreeHost*)layerTreeHost
62 {
63     if ((self = [super init])) {
64         _layerID = layerID;
65         _layerTreeHost = layerTreeHost;
66     }
67     return self;
68 }
69
70 - (void)animationDidStart:(CAAnimation *)animation
71 {
72     bool hasExplicitBeginTime = [[animation valueForKey:WKExplicitBeginTimeFlag] boolValue];
73     CFTimeInterval startTime;
74
75     if (hasExplicitBeginTime) {
76         // We don't know what time CA used to commit the animation, so just use the current time
77         // (even though this will be slightly off).
78         startTime = mediaTimeToCurrentTime(CACurrentMediaTime());
79     } else
80         startTime = mediaTimeToCurrentTime([animation beginTime]);
81
82     _layerTreeHost->animationDidStart(_layerID, animation, startTime);
83 }
84 @end
85
86 namespace WebKit {
87
88 void PlatformCAAnimationRemote::KeyframeValue::encode(IPC::ArgumentEncoder& encoder) const
89 {
90     encoder.encodeEnum(keyType);
91
92     switch (keyType) {
93     case NumberKeyType:
94         encoder << number;
95         break;
96     case ColorKeyType:
97         encoder << color;
98         break;
99     case PointKeyType:
100         encoder << point;
101         break;
102     case TransformKeyType:
103         encoder << transform;
104         break;
105     case FilterKeyType:
106         encoder << *filter.get();
107         break;
108     }
109 }
110
111 bool PlatformCAAnimationRemote::KeyframeValue::decode(IPC::ArgumentDecoder& decoder, PlatformCAAnimationRemote::KeyframeValue& value)
112 {
113     if (!decoder.decodeEnum(value.keyType))
114         return false;
115
116     switch (value.keyType) {
117     case NumberKeyType:
118         if (!decoder.decode(value.number))
119             return false;
120         break;
121     case ColorKeyType:
122         if (!decoder.decode(value.color))
123             return false;
124         break;
125     case PointKeyType:
126         if (!decoder.decode(value.point))
127             return false;
128         break;
129     case TransformKeyType:
130         if (!decoder.decode(value.transform))
131             return false;
132         break;
133     case FilterKeyType:
134         if (!decodeFilterOperation(decoder, value.filter))
135             return false;
136         break;
137     }
138
139     return true;
140 }
141
142 void PlatformCAAnimationRemote::Properties::encode(IPC::ArgumentEncoder& encoder) const
143 {
144     encoder << keyPath;
145     encoder.encodeEnum(animationType);
146
147     encoder << beginTime;
148     encoder << duration;
149     encoder << timeOffset;
150     encoder << repeatCount;
151     encoder << speed;
152
153     encoder.encodeEnum(fillMode);
154     encoder.encodeEnum(valueFunction);
155
156     encoder << autoReverses;
157     encoder << removedOnCompletion;
158     encoder << additive;
159     encoder << reverseTimingFunctions;
160     encoder << hasExplicitBeginTime;
161     
162     encoder << keyValues;
163     encoder << keyTimes;
164     
165     encoder << static_cast<uint64_t>(timingFunctions.size());
166     for (const auto& timingFunction : timingFunctions) {
167         switch (timingFunction->type()) {
168         case TimingFunction::LinearFunction:
169             encoder << *static_cast<LinearTimingFunction*>(timingFunction.get());
170             break;
171             
172         case TimingFunction::CubicBezierFunction:
173             encoder << *static_cast<CubicBezierTimingFunction*>(timingFunction.get());
174             break;
175         
176         case TimingFunction::StepsFunction:
177             encoder << *static_cast<StepsTimingFunction*>(timingFunction.get());
178             break;
179         }
180     }
181 }
182
183 bool PlatformCAAnimationRemote::Properties::decode(IPC::ArgumentDecoder& decoder, PlatformCAAnimationRemote::Properties& properties)
184 {
185     if (!decoder.decode(properties.keyPath))
186         return false;
187
188     if (!decoder.decodeEnum(properties.animationType))
189         return false;
190
191     if (!decoder.decode(properties.beginTime))
192         return false;
193
194     if (!decoder.decode(properties.duration))
195         return false;
196
197     if (!decoder.decode(properties.timeOffset))
198         return false;
199
200     if (!decoder.decode(properties.repeatCount))
201         return false;
202
203     if (!decoder.decode(properties.speed))
204         return false;
205
206     if (!decoder.decodeEnum(properties.fillMode))
207         return false;
208
209     if (!decoder.decodeEnum(properties.valueFunction))
210         return false;
211
212     if (!decoder.decode(properties.autoReverses))
213         return false;
214
215     if (!decoder.decode(properties.removedOnCompletion))
216         return false;
217
218     if (!decoder.decode(properties.additive))
219         return false;
220
221     if (!decoder.decode(properties.reverseTimingFunctions))
222         return false;
223
224     if (!decoder.decode(properties.hasExplicitBeginTime))
225         return false;
226
227     if (!decoder.decode(properties.keyValues))
228         return false;
229
230     if (!decoder.decode(properties.keyTimes))
231         return false;
232
233     uint64_t numTimingFunctions;
234     if (!decoder.decode(numTimingFunctions))
235         return false;
236     
237     if (numTimingFunctions) {
238         properties.timingFunctions.reserveInitialCapacity(numTimingFunctions);
239
240         for (size_t i = 0; i < numTimingFunctions; ++i) {
241         
242             TimingFunction::TimingFunctionType type;
243             if (!decoder.decodeEnum(type))
244                 return false;
245
246             RefPtr<TimingFunction> timingFunction;
247             switch (type) {
248             case TimingFunction::LinearFunction:
249                 timingFunction = LinearTimingFunction::create();
250                 if (!decoder.decode(*static_cast<LinearTimingFunction*>(timingFunction.get())))
251                     return false;
252                 break;
253                 
254             case TimingFunction::CubicBezierFunction:
255                 timingFunction = CubicBezierTimingFunction::create();
256                 if (!decoder.decode(*static_cast<CubicBezierTimingFunction*>(timingFunction.get())))
257                     return false;
258                 break;
259             
260             case TimingFunction::StepsFunction:
261                 timingFunction = StepsTimingFunction::create();
262                 if (!decoder.decode(*static_cast<StepsTimingFunction*>(timingFunction.get())))
263                     return false;
264                 break;
265             }
266             
267             properties.timingFunctions.uncheckedAppend(timingFunction.release());
268         }
269     }
270
271     return true;
272 }
273     
274 PassRefPtr<PlatformCAAnimation> PlatformCAAnimationRemote::create(PlatformCAAnimation::AnimationType type, const String& keyPath)
275 {
276     return adoptRef(new PlatformCAAnimationRemote(type, keyPath));
277 }
278
279 PassRefPtr<PlatformCAAnimation> PlatformCAAnimationRemote::copy() const
280 {
281     RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
282     
283     animation->setBeginTime(beginTime());
284     animation->setDuration(duration());
285     animation->setSpeed(speed());
286     animation->setTimeOffset(timeOffset());
287     animation->setRepeatCount(repeatCount());
288     animation->setAutoreverses(autoreverses());
289     animation->setFillMode(fillMode());
290     animation->setRemovedOnCompletion(isRemovedOnCompletion());
291     animation->setAdditive(isAdditive());
292     animation->copyTimingFunctionFrom(this);
293     animation->setValueFunction(valueFunction());
294
295     toPlatformCAAnimationRemote(animation.get())->setHasExplicitBeginTime(hasExplicitBeginTime());
296     
297     // Copy the specific Basic or Keyframe values.
298     if (animationType() == Keyframe) {
299         animation->copyValuesFrom(this);
300         animation->copyKeyTimesFrom(this);
301         animation->copyTimingFunctionsFrom(this);
302     } else {
303         animation->copyFromValueFrom(this);
304         animation->copyToValueFrom(this);
305     }
306     
307     return animation;
308 }
309
310 PlatformCAAnimationRemote::PlatformCAAnimationRemote(AnimationType type, const String& keyPath)
311     : PlatformCAAnimation(type)
312 {
313     m_properties.keyPath = keyPath;
314     m_properties.animationType = type;
315 }
316
317 String PlatformCAAnimationRemote::keyPath() const
318 {
319     return m_properties.keyPath;
320 }
321
322 CFTimeInterval PlatformCAAnimationRemote::beginTime() const
323 {
324     return m_properties.beginTime;
325 }
326
327 void PlatformCAAnimationRemote::setBeginTime(CFTimeInterval value)
328 {
329     m_properties.beginTime = value;
330     
331     // Also set a flag to tell us if we've passed in a 0 value. 
332     // The flag is needed because later beginTime will get changed
333     // to the time at which it fired and we need to know whether
334     // or not it was 0 to begin with.
335     if (value)
336         m_properties.hasExplicitBeginTime = value;
337 }
338
339 CFTimeInterval PlatformCAAnimationRemote::duration() const
340 {
341     return m_properties.duration;
342 }
343
344 void PlatformCAAnimationRemote::setDuration(CFTimeInterval value)
345 {
346     m_properties.duration = value;
347 }
348
349 float PlatformCAAnimationRemote::speed() const
350 {
351     return m_properties.speed;
352 }
353
354 void PlatformCAAnimationRemote::setSpeed(float value)
355 {
356     m_properties.speed = value;
357 }
358
359 CFTimeInterval PlatformCAAnimationRemote::timeOffset() const
360 {
361     return m_properties.timeOffset;
362 }
363
364 void PlatformCAAnimationRemote::setTimeOffset(CFTimeInterval value)
365 {
366     m_properties.timeOffset = value;
367 }
368
369 float PlatformCAAnimationRemote::repeatCount() const
370 {
371     return m_properties.repeatCount;
372 }
373
374 void PlatformCAAnimationRemote::setRepeatCount(float value)
375 {
376     m_properties.repeatCount = value;
377 }
378
379 bool PlatformCAAnimationRemote::autoreverses() const
380 {
381     return m_properties.autoReverses;
382 }
383
384 void PlatformCAAnimationRemote::setAutoreverses(bool value)
385 {
386     m_properties.autoReverses = value;
387 }
388
389 PlatformCAAnimation::FillModeType PlatformCAAnimationRemote::fillMode() const
390 {
391     return m_properties.fillMode;
392 }
393
394 void PlatformCAAnimationRemote::setFillMode(FillModeType value)
395 {
396     m_properties.fillMode = value;
397 }
398
399 void PlatformCAAnimationRemote::setTimingFunction(const TimingFunction* value, bool reverse)
400 {
401     Vector<RefPtr<TimingFunction>> timingFunctions;
402     timingFunctions.append(value->clone());
403
404     m_properties.timingFunctions = WTF::move(timingFunctions);
405     m_properties.reverseTimingFunctions = reverse;
406 }
407
408 void PlatformCAAnimationRemote::copyTimingFunctionFrom(const PlatformCAAnimation* value)
409 {
410     copyTimingFunctionsFrom(value);
411 }
412
413 bool PlatformCAAnimationRemote::isRemovedOnCompletion() const
414 {
415     return m_properties.removedOnCompletion;
416 }
417
418 void PlatformCAAnimationRemote::setRemovedOnCompletion(bool value)
419 {
420     m_properties.removedOnCompletion = value;
421 }
422
423 bool PlatformCAAnimationRemote::isAdditive() const
424 {
425     return m_properties.additive;
426 }
427
428 void PlatformCAAnimationRemote::setAdditive(bool value)
429 {
430     m_properties.additive = value;
431 }
432
433 PlatformCAAnimation::ValueFunctionType PlatformCAAnimationRemote::valueFunction() const
434 {
435     return m_properties.valueFunction;
436 }
437
438 void PlatformCAAnimationRemote::setValueFunction(ValueFunctionType value)
439 {
440     m_properties.valueFunction = value;
441 }
442
443 void PlatformCAAnimationRemote::setFromValue(float value)
444 {
445     if (animationType() != Basic)
446         return;
447
448     m_properties.keyValues.resize(2);
449     m_properties.keyValues[0] = KeyframeValue(value);
450 }
451
452 void PlatformCAAnimationRemote::setFromValue(const TransformationMatrix& value)
453 {
454     if (animationType() != Basic)
455         return;
456
457     m_properties.keyValues.resize(2);
458     m_properties.keyValues[0] = KeyframeValue(value);
459 }
460
461 void PlatformCAAnimationRemote::setFromValue(const FloatPoint3D& value)
462 {
463     if (animationType() != Basic)
464         return;
465
466     m_properties.keyValues.resize(2);
467     m_properties.keyValues[0] = KeyframeValue(value);
468 }
469
470 void PlatformCAAnimationRemote::setFromValue(const Color& value)
471 {
472     if (animationType() != Basic)
473         return;
474
475     m_properties.keyValues.resize(2);
476     m_properties.keyValues[0] = KeyframeValue(value);
477 }
478
479 #if ENABLE(CSS_FILTERS)
480 void PlatformCAAnimationRemote::setFromValue(const FilterOperation* operation, int internalFilterPropertyIndex)
481 {
482     if (animationType() != Basic)
483         return;
484
485     m_properties.keyValues.resize(2);
486     m_properties.keyValues[0] = KeyframeValue(operation->clone());
487 }
488 #endif
489
490 void PlatformCAAnimationRemote::copyFromValueFrom(const PlatformCAAnimation* value)
491 {
492     const PlatformCAAnimationRemote* other = toPlatformCAAnimationRemote(value);
493
494     if (other->m_properties.keyValues.isEmpty())
495         return;
496     
497     m_properties.keyValues.resize(2);
498     m_properties.keyValues[0] = other->m_properties.keyValues[0];
499 }
500
501 void PlatformCAAnimationRemote::setToValue(float value)
502 {
503     if (animationType() != Basic)
504         return;
505
506     m_properties.keyValues.resize(2);
507     m_properties.keyValues[1] = KeyframeValue(value);
508 }
509
510 void PlatformCAAnimationRemote::setToValue(const TransformationMatrix& value)
511 {
512     if (animationType() != Basic)
513         return;
514
515     m_properties.keyValues.resize(2);
516     m_properties.keyValues[1] = KeyframeValue(value);
517 }
518
519 void PlatformCAAnimationRemote::setToValue(const FloatPoint3D& value)
520 {
521     if (animationType() != Basic)
522         return;
523
524     m_properties.keyValues.resize(2);
525     m_properties.keyValues[1] = KeyframeValue(value);
526 }
527
528 void PlatformCAAnimationRemote::setToValue(const Color& value)
529 {
530     if (animationType() != Basic)
531         return;
532
533     m_properties.keyValues.resize(2);
534     m_properties.keyValues[1] = KeyframeValue(value);
535 }
536
537 #if ENABLE(CSS_FILTERS)
538 void PlatformCAAnimationRemote::setToValue(const FilterOperation* operation, int internalFilterPropertyIndex)
539 {
540     if (animationType() != Basic)
541         return;
542     
543     UNUSED_PARAM(internalFilterPropertyIndex);
544     ASSERT(operation);
545     m_properties.keyValues.resize(2);
546     m_properties.keyValues[1] = KeyframeValue(operation->clone());
547 }
548 #endif
549
550 void PlatformCAAnimationRemote::copyToValueFrom(const PlatformCAAnimation* value)
551 {
552     const PlatformCAAnimationRemote* other = toPlatformCAAnimationRemote(value);
553
554     if (other->m_properties.keyValues.size() < 2)
555         return;
556     m_properties.keyValues.resize(2);
557     m_properties.keyValues[1] = other->m_properties.keyValues[1];
558 }
559
560 // Keyframe-animation properties.
561 void PlatformCAAnimationRemote::setValues(const Vector<float>& values)
562 {
563     if (animationType() != Keyframe)
564         return;
565
566     Vector<KeyframeValue> keyframes;
567     keyframes.reserveInitialCapacity(values.size());
568     
569     for (size_t i = 0; i < values.size(); ++i)
570         keyframes.uncheckedAppend(KeyframeValue(values[i]));
571     
572     m_properties.keyValues = WTF::move(keyframes);
573 }
574
575 void PlatformCAAnimationRemote::setValues(const Vector<TransformationMatrix>& values)
576 {
577     if (animationType() != Keyframe)
578         return;
579         
580     Vector<KeyframeValue> keyframes;
581     keyframes.reserveInitialCapacity(values.size());
582     
583     for (size_t i = 0; i < values.size(); ++i)
584         keyframes.uncheckedAppend(KeyframeValue(values[i]));
585     
586     m_properties.keyValues = WTF::move(keyframes);
587 }
588
589 void PlatformCAAnimationRemote::setValues(const Vector<FloatPoint3D>& values)
590 {
591     if (animationType() != Keyframe)
592         return;
593         
594     Vector<KeyframeValue> keyframes;
595     keyframes.reserveInitialCapacity(values.size());
596     
597     for (size_t i = 0; i < values.size(); ++i)
598         keyframes.uncheckedAppend(KeyframeValue(values[i]));
599     
600     m_properties.keyValues = WTF::move(keyframes);
601 }
602
603 void PlatformCAAnimationRemote::setValues(const Vector<Color>& values)
604 {
605     if (animationType() != Keyframe)
606         return;
607         
608     Vector<KeyframeValue> keyframes;
609     keyframes.reserveInitialCapacity(values.size());
610     
611     for (size_t i = 0; i < values.size(); ++i)
612         keyframes.uncheckedAppend(KeyframeValue(values[i]));
613     
614     m_properties.keyValues = WTF::move(keyframes);
615 }
616
617 #if ENABLE(CSS_FILTERS)
618 void PlatformCAAnimationRemote::setValues(const Vector<RefPtr<FilterOperation>>& values, int internalFilterPropertyIndex)
619 {
620     UNUSED_PARAM(internalFilterPropertyIndex);
621     
622     if (animationType() != Keyframe)
623         return;
624         
625     Vector<KeyframeValue> keyframes;
626     keyframes.reserveInitialCapacity(values.size());
627     
628     for (size_t i = 0; i < values.size(); ++i)
629         keyframes.uncheckedAppend(KeyframeValue(values[i]));
630     
631     m_properties.keyValues = WTF::move(keyframes);
632 }
633 #endif
634
635 void PlatformCAAnimationRemote::copyValuesFrom(const PlatformCAAnimation* value)
636 {
637     const PlatformCAAnimationRemote* other = toPlatformCAAnimationRemote(value);
638     m_properties.keyValues = other->m_properties.keyValues;
639 }
640
641 void PlatformCAAnimationRemote::setKeyTimes(const Vector<float>& keyTimes)
642 {
643     m_properties.keyTimes = keyTimes;
644 }
645
646 void PlatformCAAnimationRemote::copyKeyTimesFrom(const PlatformCAAnimation* value)
647 {
648     const PlatformCAAnimationRemote* other = toPlatformCAAnimationRemote(value);
649     m_properties.keyTimes = other->m_properties.keyTimes;
650 }
651
652 void PlatformCAAnimationRemote::setTimingFunctions(const Vector<const TimingFunction*>& values, bool reverse)
653 {
654     Vector<RefPtr<WebCore::TimingFunction>> timingFunctions;
655     timingFunctions.reserveInitialCapacity(values.size());
656     
657     for (size_t i = 0; i < values.size(); ++i)
658         timingFunctions.uncheckedAppend(values[i]->clone());
659     
660     m_properties.timingFunctions = WTF::move(timingFunctions);
661     m_properties.reverseTimingFunctions = reverse;
662 }
663
664 void PlatformCAAnimationRemote::copyTimingFunctionsFrom(const PlatformCAAnimation* value)
665 {
666     const PlatformCAAnimationRemote* other = toPlatformCAAnimationRemote(value);
667
668     m_properties.timingFunctions = other->m_properties.timingFunctions;
669     m_properties.reverseTimingFunctions = other->m_properties.reverseTimingFunctions;
670 }
671
672 static NSObject* animationValueFromKeyframeValue(const PlatformCAAnimationRemote::KeyframeValue& keyframeValue)
673 {
674     switch (keyframeValue.keyframeType()) {
675     case PlatformCAAnimationRemote::KeyframeValue::NumberKeyType:
676         return @(keyframeValue.numberValue());
677             
678     case PlatformCAAnimationRemote::KeyframeValue::ColorKeyType: {
679         Color color = keyframeValue.colorValue();
680         return @[ @(color.red()), @(color.green()), @(color.blue()), @(color.alpha()) ];
681     }
682
683     case PlatformCAAnimationRemote::KeyframeValue::PointKeyType: {
684         FloatPoint3D point = keyframeValue.pointValue();
685         return @[ @(point.x()), @(point.y()), @(point.z()) ];
686     }
687     case PlatformCAAnimationRemote::KeyframeValue::TransformKeyType:
688         return [NSValue valueWithCATransform3D:keyframeValue.transformValue()];
689             
690     case PlatformCAAnimationRemote::KeyframeValue::FilterKeyType:
691         return PlatformCAFilters::filterValueForOperation(keyframeValue.filterValue(), 0 /* unused */).autorelease();
692     }
693 }
694
695 static void addAnimationToLayer(CALayer *layer, RemoteLayerTreeHost* layerTreeHost, const String& key, const PlatformCAAnimationRemote::Properties& properties)
696 {
697     RetainPtr<CAPropertyAnimation> caAnimation;
698     switch (properties.animationType) {
699     case PlatformCAAnimation::Basic: {
700         RetainPtr<CABasicAnimation> basicAnimation;
701         basicAnimation = [CABasicAnimation animationWithKeyPath:properties.keyPath];
702         
703         if (properties.keyValues.size() > 1) {
704             [basicAnimation setFromValue:animationValueFromKeyframeValue(properties.keyValues[0])];
705             [basicAnimation setToValue:animationValueFromKeyframeValue(properties.keyValues[1])];
706         }
707         
708         if (properties.timingFunctions.size())
709             [basicAnimation setTimingFunction:toCAMediaTimingFunction(properties.timingFunctions[0].get(), properties.reverseTimingFunctions)];
710         
711         caAnimation = basicAnimation;
712         break;
713     }
714     case PlatformCAAnimation::Keyframe: {
715         RetainPtr<CAKeyframeAnimation> keyframeAnimation;
716         keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:properties.keyPath];
717
718         if (properties.keyValues.size()) {
719             RetainPtr<NSMutableArray> keyframes = adoptNS([[NSMutableArray alloc] initWithCapacity:properties.keyValues.size()]);
720             for (const auto& value : properties.keyValues)
721                 [keyframes addObject:animationValueFromKeyframeValue(value)];
722             
723             [keyframeAnimation setValues:keyframes.get()];
724         }
725
726         if (properties.keyTimes.size()) {
727             RetainPtr<NSMutableArray> keyTimes = adoptNS([[NSMutableArray alloc] initWithCapacity:properties.keyTimes.size()]);
728             for (auto keyTime : properties.keyTimes)
729                 [keyTimes addObject:@(keyTime)];
730             
731             [keyframeAnimation setKeyTimes:keyTimes.get()];
732         }
733
734         if (properties.timingFunctions.size()) {
735             RetainPtr<NSMutableArray> timingFunctions = adoptNS([[NSMutableArray alloc] initWithCapacity:properties.timingFunctions.size()]);
736             for (const auto& timingFunction : properties.timingFunctions)
737                 [timingFunctions addObject:toCAMediaTimingFunction(timingFunction.get(), properties.reverseTimingFunctions)];
738             
739             [keyframeAnimation setTimingFunctions:timingFunctions.get()];
740         }
741         
742         caAnimation = keyframeAnimation;
743         break;
744     }
745     }
746     
747     [caAnimation setBeginTime:properties.beginTime];
748     [caAnimation setDuration:properties.duration];
749     [caAnimation setTimeOffset:properties.timeOffset];
750     [caAnimation setRepeatCount:properties.repeatCount];
751     [caAnimation setSpeed:properties.speed];
752     [caAnimation setAutoreverses:properties.autoReverses];
753     [caAnimation setRemovedOnCompletion:properties.removedOnCompletion];
754     [caAnimation setAdditive:properties.additive];
755     
756     if (properties.fillMode != PlatformCAAnimation::NoFillMode)
757         [caAnimation setFillMode:toCAFillModeType(properties.fillMode)];
758
759     if (properties.valueFunction != PlatformCAAnimation::NoValueFunction)
760         [caAnimation setValueFunction:[CAValueFunction functionWithName:toCAValueFunctionType(properties.valueFunction)]];
761     
762     if (properties.hasExplicitBeginTime)
763         [caAnimation setValue:@YES forKey:WKExplicitBeginTimeFlag];
764     
765     if (layerTreeHost) {
766         GraphicsLayer::PlatformLayerID layerID = RemoteLayerTreeHost::layerID(layer);
767     
768         RetainPtr<WKAnimationDelegate>& delegate = layerTreeHost->animationDelegates().add(layerID, nullptr).iterator->value;
769         if (!delegate)
770             delegate = adoptNS([[WKAnimationDelegate alloc] initWithLayerID:layerID layerTreeHost:layerTreeHost]);
771
772         [caAnimation setDelegate:delegate.get()];
773     }
774     
775     [layer addAnimation:caAnimation.get() forKey:key];
776 }
777
778 void PlatformCAAnimationRemote::updateLayerAnimations(CALayer *layer, RemoteLayerTreeHost* layerTreeHost, const AnimationsList& animationsToAdd, const HashSet<String>& animationsToRemove)
779 {
780     BEGIN_BLOCK_OBJC_EXCEPTIONS;
781
782     for (const auto& value : animationsToRemove)
783         [layer removeAnimationForKey:value];
784
785     for (const auto& keyAnimationPair : animationsToAdd)
786         addAnimationToLayer(layer, layerTreeHost, keyAnimationPair.first, keyAnimationPair.second);
787
788     END_BLOCK_OBJC_EXCEPTIONS;
789 }
790
791 } // namespace WebKit