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