Add support for the frames() timing function
[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::FramesFunction:
202             encoder << *static_cast<FramesTimingFunction*>(timingFunction.get());
203             break;
204
205         case TimingFunction::SpringFunction:
206             encoder << *static_cast<SpringTimingFunction*>(timingFunction.get());
207             break;
208         }
209     }
210 }
211
212 std::optional<PlatformCAAnimationRemote::Properties> PlatformCAAnimationRemote::Properties::decode(IPC::Decoder& decoder)
213 {
214     PlatformCAAnimationRemote::Properties properties;
215     if (!decoder.decode(properties.keyPath))
216         return std::nullopt;
217
218     if (!decoder.decodeEnum(properties.animationType))
219         return std::nullopt;
220
221     if (!decoder.decode(properties.beginTime))
222         return std::nullopt;
223
224     if (!decoder.decode(properties.duration))
225         return std::nullopt;
226
227     if (!decoder.decode(properties.timeOffset))
228         return std::nullopt;
229
230     if (!decoder.decode(properties.repeatCount))
231         return std::nullopt;
232
233     if (!decoder.decode(properties.speed))
234         return std::nullopt;
235
236     if (!decoder.decodeEnum(properties.fillMode))
237         return std::nullopt;
238
239     if (!decoder.decodeEnum(properties.valueFunction))
240         return std::nullopt;
241
242     if (!decoder.decode(properties.autoReverses))
243         return std::nullopt;
244
245     if (!decoder.decode(properties.removedOnCompletion))
246         return std::nullopt;
247
248     if (!decoder.decode(properties.additive))
249         return std::nullopt;
250
251     if (!decoder.decode(properties.reverseTimingFunctions))
252         return std::nullopt;
253
254     if (!decoder.decode(properties.hasExplicitBeginTime))
255         return std::nullopt;
256
257     if (!decoder.decode(properties.keyValues))
258         return std::nullopt;
259
260     if (!decoder.decode(properties.keyTimes))
261         return std::nullopt;
262
263     uint64_t numTimingFunctions;
264     if (!decoder.decode(numTimingFunctions))
265         return std::nullopt;
266     
267     if (numTimingFunctions) {
268         properties.timingFunctions.reserveInitialCapacity(numTimingFunctions);
269
270         for (size_t i = 0; i < numTimingFunctions; ++i) {
271         
272             TimingFunction::TimingFunctionType type;
273             if (!decoder.decodeEnum(type))
274                 return std::nullopt;
275
276             RefPtr<TimingFunction> timingFunction;
277             switch (type) {
278             case TimingFunction::LinearFunction:
279                 timingFunction = LinearTimingFunction::create();
280                 if (!decoder.decode(*static_cast<LinearTimingFunction*>(timingFunction.get())))
281                     return std::nullopt;
282                 break;
283                 
284             case TimingFunction::CubicBezierFunction:
285                 timingFunction = CubicBezierTimingFunction::create();
286                 if (!decoder.decode(*static_cast<CubicBezierTimingFunction*>(timingFunction.get())))
287                     return std::nullopt;
288                 break;
289             
290             case TimingFunction::StepsFunction:
291                 timingFunction = StepsTimingFunction::create();
292                 if (!decoder.decode(*static_cast<StepsTimingFunction*>(timingFunction.get())))
293                     return std::nullopt;
294                 break;
295
296             case TimingFunction::FramesFunction:
297                 timingFunction = FramesTimingFunction::create();
298                 if (!decoder.decode(*static_cast<FramesTimingFunction*>(timingFunction.get())))
299                     return std::nullopt;
300                 break;
301
302             case TimingFunction::SpringFunction:
303                 timingFunction = SpringTimingFunction::create();
304                 if (!decoder.decode(*static_cast<SpringTimingFunction*>(timingFunction.get())))
305                     return std::nullopt;
306                 break;
307             }
308             
309             properties.timingFunctions.uncheckedAppend(WTFMove(timingFunction));
310         }
311     }
312
313     return WTFMove(properties);
314 }
315     
316 Ref<PlatformCAAnimation> PlatformCAAnimationRemote::create(PlatformCAAnimation::AnimationType type, const String& keyPath)
317 {
318     return adoptRef(*new PlatformCAAnimationRemote(type, keyPath));
319 }
320
321 Ref<PlatformCAAnimation> PlatformCAAnimationRemote::copy() const
322 {
323     auto animation = create(animationType(), keyPath());
324     
325     animation->setBeginTime(beginTime());
326     animation->setDuration(duration());
327     animation->setSpeed(speed());
328     animation->setTimeOffset(timeOffset());
329     animation->setRepeatCount(repeatCount());
330     animation->setAutoreverses(autoreverses());
331     animation->setFillMode(fillMode());
332     animation->setRemovedOnCompletion(isRemovedOnCompletion());
333     animation->setAdditive(isAdditive());
334     animation->copyTimingFunctionFrom(*this);
335     animation->setValueFunction(valueFunction());
336
337     downcast<PlatformCAAnimationRemote>(animation.get()).setHasExplicitBeginTime(hasExplicitBeginTime());
338     
339     // Copy the specific Basic or Keyframe values.
340     if (animationType() == Keyframe) {
341         animation->copyValuesFrom(*this);
342         animation->copyKeyTimesFrom(*this);
343         animation->copyTimingFunctionsFrom(*this);
344     } else {
345         animation->copyFromValueFrom(*this);
346         animation->copyToValueFrom(*this);
347     }
348     
349     return animation;
350 }
351
352 PlatformCAAnimationRemote::PlatformCAAnimationRemote(AnimationType type, const String& keyPath)
353     : PlatformCAAnimation(type)
354 {
355     m_properties.keyPath = keyPath;
356     m_properties.animationType = type;
357 }
358
359 String PlatformCAAnimationRemote::keyPath() const
360 {
361     return m_properties.keyPath;
362 }
363
364 CFTimeInterval PlatformCAAnimationRemote::beginTime() const
365 {
366     return m_properties.beginTime;
367 }
368
369 void PlatformCAAnimationRemote::setBeginTime(CFTimeInterval value)
370 {
371     m_properties.beginTime = value;
372     
373     // Also set a flag to tell us if we've passed in a 0 value. 
374     // The flag is needed because later beginTime will get changed
375     // to the time at which it fired and we need to know whether
376     // or not it was 0 to begin with.
377     if (value)
378         m_properties.hasExplicitBeginTime = value;
379 }
380
381 CFTimeInterval PlatformCAAnimationRemote::duration() const
382 {
383     return m_properties.duration;
384 }
385
386 void PlatformCAAnimationRemote::setDuration(CFTimeInterval value)
387 {
388     m_properties.duration = value;
389 }
390
391 float PlatformCAAnimationRemote::speed() const
392 {
393     return m_properties.speed;
394 }
395
396 void PlatformCAAnimationRemote::setSpeed(float value)
397 {
398     m_properties.speed = value;
399 }
400
401 CFTimeInterval PlatformCAAnimationRemote::timeOffset() const
402 {
403     return m_properties.timeOffset;
404 }
405
406 void PlatformCAAnimationRemote::setTimeOffset(CFTimeInterval value)
407 {
408     m_properties.timeOffset = value;
409 }
410
411 float PlatformCAAnimationRemote::repeatCount() const
412 {
413     return m_properties.repeatCount;
414 }
415
416 void PlatformCAAnimationRemote::setRepeatCount(float value)
417 {
418     m_properties.repeatCount = value;
419 }
420
421 bool PlatformCAAnimationRemote::autoreverses() const
422 {
423     return m_properties.autoReverses;
424 }
425
426 void PlatformCAAnimationRemote::setAutoreverses(bool value)
427 {
428     m_properties.autoReverses = value;
429 }
430
431 PlatformCAAnimation::FillModeType PlatformCAAnimationRemote::fillMode() const
432 {
433     return m_properties.fillMode;
434 }
435
436 void PlatformCAAnimationRemote::setFillMode(FillModeType value)
437 {
438     m_properties.fillMode = value;
439 }
440
441 void PlatformCAAnimationRemote::setTimingFunction(const TimingFunction* value, bool reverse)
442 {
443     Vector<RefPtr<TimingFunction>> timingFunctions;
444     timingFunctions.append(value->clone());
445
446     m_properties.timingFunctions = WTFMove(timingFunctions);
447     m_properties.reverseTimingFunctions = reverse;
448 }
449
450 void PlatformCAAnimationRemote::copyTimingFunctionFrom(const PlatformCAAnimation& value)
451 {
452     copyTimingFunctionsFrom(value);
453 }
454
455 bool PlatformCAAnimationRemote::isRemovedOnCompletion() const
456 {
457     return m_properties.removedOnCompletion;
458 }
459
460 void PlatformCAAnimationRemote::setRemovedOnCompletion(bool value)
461 {
462     m_properties.removedOnCompletion = value;
463 }
464
465 bool PlatformCAAnimationRemote::isAdditive() const
466 {
467     return m_properties.additive;
468 }
469
470 void PlatformCAAnimationRemote::setAdditive(bool value)
471 {
472     m_properties.additive = value;
473 }
474
475 PlatformCAAnimation::ValueFunctionType PlatformCAAnimationRemote::valueFunction() const
476 {
477     return m_properties.valueFunction;
478 }
479
480 void PlatformCAAnimationRemote::setValueFunction(ValueFunctionType value)
481 {
482     m_properties.valueFunction = value;
483 }
484
485 void PlatformCAAnimationRemote::setFromValue(float value)
486 {
487     if (animationType() != Basic)
488         return;
489
490     m_properties.keyValues.resize(2);
491     m_properties.keyValues[0] = KeyframeValue(value);
492 }
493
494 void PlatformCAAnimationRemote::setFromValue(const TransformationMatrix& value)
495 {
496     if (animationType() != Basic)
497         return;
498
499     m_properties.keyValues.resize(2);
500     m_properties.keyValues[0] = KeyframeValue(value);
501 }
502
503 void PlatformCAAnimationRemote::setFromValue(const FloatPoint3D& value)
504 {
505     if (animationType() != Basic)
506         return;
507
508     m_properties.keyValues.resize(2);
509     m_properties.keyValues[0] = KeyframeValue(value);
510 }
511
512 void PlatformCAAnimationRemote::setFromValue(const Color& value)
513 {
514     if (animationType() != Basic)
515         return;
516
517     m_properties.keyValues.resize(2);
518     m_properties.keyValues[0] = KeyframeValue(value);
519 }
520
521 void PlatformCAAnimationRemote::setFromValue(const FilterOperation* operation, int internalFilterPropertyIndex)
522 {
523     if (animationType() != Basic)
524         return;
525
526     m_properties.keyValues.resize(2);
527     m_properties.keyValues[0] = KeyframeValue(operation->clone());
528 }
529
530 void PlatformCAAnimationRemote::copyFromValueFrom(const PlatformCAAnimation& value)
531 {
532     const PlatformCAAnimationRemote& other = downcast<PlatformCAAnimationRemote>(value);
533
534     if (other.m_properties.keyValues.isEmpty())
535         return;
536     
537     m_properties.keyValues.resize(2);
538     m_properties.keyValues[0] = other.m_properties.keyValues[0];
539 }
540
541 void PlatformCAAnimationRemote::setToValue(float value)
542 {
543     if (animationType() != Basic)
544         return;
545
546     m_properties.keyValues.resize(2);
547     m_properties.keyValues[1] = KeyframeValue(value);
548 }
549
550 void PlatformCAAnimationRemote::setToValue(const TransformationMatrix& value)
551 {
552     if (animationType() != Basic)
553         return;
554
555     m_properties.keyValues.resize(2);
556     m_properties.keyValues[1] = KeyframeValue(value);
557 }
558
559 void PlatformCAAnimationRemote::setToValue(const FloatPoint3D& value)
560 {
561     if (animationType() != Basic)
562         return;
563
564     m_properties.keyValues.resize(2);
565     m_properties.keyValues[1] = KeyframeValue(value);
566 }
567
568 void PlatformCAAnimationRemote::setToValue(const Color& value)
569 {
570     if (animationType() != Basic)
571         return;
572
573     m_properties.keyValues.resize(2);
574     m_properties.keyValues[1] = KeyframeValue(value);
575 }
576
577 void PlatformCAAnimationRemote::setToValue(const FilterOperation* operation, int internalFilterPropertyIndex)
578 {
579     if (animationType() != Basic)
580         return;
581     
582     UNUSED_PARAM(internalFilterPropertyIndex);
583     ASSERT(operation);
584     m_properties.keyValues.resize(2);
585     m_properties.keyValues[1] = KeyframeValue(operation->clone());
586 }
587
588 void PlatformCAAnimationRemote::copyToValueFrom(const PlatformCAAnimation& value)
589 {
590     const PlatformCAAnimationRemote& other = downcast<PlatformCAAnimationRemote>(value);
591
592     if (other.m_properties.keyValues.size() < 2)
593         return;
594     m_properties.keyValues.resize(2);
595     m_properties.keyValues[1] = other.m_properties.keyValues[1];
596 }
597
598 // Keyframe-animation properties.
599 void PlatformCAAnimationRemote::setValues(const Vector<float>& values)
600 {
601     if (animationType() != Keyframe)
602         return;
603
604     Vector<KeyframeValue> keyframes;
605     keyframes.reserveInitialCapacity(values.size());
606     
607     for (size_t i = 0; i < values.size(); ++i)
608         keyframes.uncheckedAppend(KeyframeValue(values[i]));
609     
610     m_properties.keyValues = WTFMove(keyframes);
611 }
612
613 void PlatformCAAnimationRemote::setValues(const Vector<TransformationMatrix>& values)
614 {
615     if (animationType() != Keyframe)
616         return;
617
618     Vector<KeyframeValue> keyframes;
619     keyframes.reserveInitialCapacity(values.size());
620     
621     for (size_t i = 0; i < values.size(); ++i)
622         keyframes.uncheckedAppend(KeyframeValue(values[i]));
623     
624     m_properties.keyValues = WTFMove(keyframes);
625 }
626
627 void PlatformCAAnimationRemote::setValues(const Vector<FloatPoint3D>& values)
628 {
629     if (animationType() != Keyframe)
630         return;
631
632     Vector<KeyframeValue> keyframes;
633     keyframes.reserveInitialCapacity(values.size());
634     
635     for (size_t i = 0; i < values.size(); ++i)
636         keyframes.uncheckedAppend(KeyframeValue(values[i]));
637     
638     m_properties.keyValues = WTFMove(keyframes);
639 }
640
641 void PlatformCAAnimationRemote::setValues(const Vector<Color>& values)
642 {
643     if (animationType() != Keyframe)
644         return;
645
646     Vector<KeyframeValue> keyframes;
647     keyframes.reserveInitialCapacity(values.size());
648     
649     for (size_t i = 0; i < values.size(); ++i)
650         keyframes.uncheckedAppend(KeyframeValue(values[i]));
651     
652     m_properties.keyValues = WTFMove(keyframes);
653 }
654
655 void PlatformCAAnimationRemote::setValues(const Vector<RefPtr<FilterOperation>>& values, int internalFilterPropertyIndex)
656 {
657     UNUSED_PARAM(internalFilterPropertyIndex);
658     
659     if (animationType() != Keyframe)
660         return;
661
662     Vector<KeyframeValue> keyframes;
663     keyframes.reserveInitialCapacity(values.size());
664     
665     for (auto& value : values)
666         keyframes.uncheckedAppend(KeyframeValue { value.copyRef() });
667     
668     m_properties.keyValues = WTFMove(keyframes);
669 }
670
671 void PlatformCAAnimationRemote::copyValuesFrom(const PlatformCAAnimation& value)
672 {
673     m_properties.keyValues = downcast<PlatformCAAnimationRemote>(value).m_properties.keyValues;
674 }
675
676 void PlatformCAAnimationRemote::setKeyTimes(const Vector<float>& keyTimes)
677 {
678     m_properties.keyTimes = keyTimes;
679 }
680
681 void PlatformCAAnimationRemote::copyKeyTimesFrom(const PlatformCAAnimation& value)
682 {
683     m_properties.keyTimes = downcast<PlatformCAAnimationRemote>(value).m_properties.keyTimes;
684 }
685
686 void PlatformCAAnimationRemote::setTimingFunctions(const Vector<const TimingFunction*>& values, bool reverse)
687 {
688     Vector<RefPtr<WebCore::TimingFunction>> timingFunctions;
689     timingFunctions.reserveInitialCapacity(values.size());
690     
691     for (size_t i = 0; i < values.size(); ++i)
692         timingFunctions.uncheckedAppend(values[i]->clone());
693     
694     m_properties.timingFunctions = WTFMove(timingFunctions);
695     m_properties.reverseTimingFunctions = reverse;
696 }
697
698 void PlatformCAAnimationRemote::copyTimingFunctionsFrom(const PlatformCAAnimation& value)
699 {
700     const PlatformCAAnimationRemote& other = downcast<PlatformCAAnimationRemote>(value);
701
702     m_properties.timingFunctions = other.m_properties.timingFunctions;
703     m_properties.reverseTimingFunctions = other.m_properties.reverseTimingFunctions;
704 }
705
706 static NSObject* animationValueFromKeyframeValue(const PlatformCAAnimationRemote::KeyframeValue& keyframeValue)
707 {
708     switch (keyframeValue.keyframeType()) {
709     case PlatformCAAnimationRemote::KeyframeValue::NumberKeyType:
710         return @(keyframeValue.numberValue());
711             
712     case PlatformCAAnimationRemote::KeyframeValue::ColorKeyType: {
713         Color color = keyframeValue.colorValue();
714         return @[ @(color.red()), @(color.green()), @(color.blue()), @(color.alpha()) ];
715     }
716
717     case PlatformCAAnimationRemote::KeyframeValue::PointKeyType: {
718         FloatPoint3D point = keyframeValue.pointValue();
719         return @[ @(point.x()), @(point.y()), @(point.z()) ];
720     }
721     case PlatformCAAnimationRemote::KeyframeValue::TransformKeyType:
722         return [NSValue valueWithCATransform3D:keyframeValue.transformValue()];
723             
724     case PlatformCAAnimationRemote::KeyframeValue::FilterKeyType:
725         return PlatformCAFilters::filterValueForOperation(keyframeValue.filterValue(), 0 /* unused */).autorelease();
726     }
727 }
728
729 static void addAnimationToLayer(CALayer *layer, RemoteLayerTreeHost* layerTreeHost, const String& key, const PlatformCAAnimationRemote::Properties& properties)
730 {
731     RetainPtr<CAPropertyAnimation> caAnimation;
732     switch (properties.animationType) {
733     case PlatformCAAnimation::Basic: {
734         RetainPtr<CABasicAnimation> basicAnimation;
735         basicAnimation = [CABasicAnimation animationWithKeyPath:properties.keyPath];
736         
737         if (properties.keyValues.size() > 1) {
738             [basicAnimation setFromValue:animationValueFromKeyframeValue(properties.keyValues[0])];
739             [basicAnimation setToValue:animationValueFromKeyframeValue(properties.keyValues[1])];
740         }
741         
742         if (properties.timingFunctions.size())
743             [basicAnimation setTimingFunction:toCAMediaTimingFunction(properties.timingFunctions[0].get(), properties.reverseTimingFunctions)];
744         
745         caAnimation = basicAnimation;
746         break;
747     }
748     case PlatformCAAnimation::Keyframe: {
749         RetainPtr<CAKeyframeAnimation> keyframeAnimation;
750         keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:properties.keyPath];
751
752         if (properties.keyValues.size()) {
753             RetainPtr<NSMutableArray> keyframes = adoptNS([[NSMutableArray alloc] initWithCapacity:properties.keyValues.size()]);
754             for (const auto& value : properties.keyValues)
755                 [keyframes addObject:animationValueFromKeyframeValue(value)];
756             
757             [keyframeAnimation setValues:keyframes.get()];
758         }
759
760         if (properties.keyTimes.size()) {
761             RetainPtr<NSMutableArray> keyTimes = adoptNS([[NSMutableArray alloc] initWithCapacity:properties.keyTimes.size()]);
762             for (auto keyTime : properties.keyTimes)
763                 [keyTimes addObject:@(keyTime)];
764             
765             [keyframeAnimation setKeyTimes:keyTimes.get()];
766         }
767
768         if (properties.timingFunctions.size()) {
769             RetainPtr<NSMutableArray> timingFunctions = adoptNS([[NSMutableArray alloc] initWithCapacity:properties.timingFunctions.size()]);
770             for (const auto& timingFunction : properties.timingFunctions)
771                 [timingFunctions addObject:toCAMediaTimingFunction(timingFunction.get(), properties.reverseTimingFunctions)];
772             
773             [keyframeAnimation setTimingFunctions:timingFunctions.get()];
774         }
775         
776         caAnimation = keyframeAnimation;
777         break;
778     }
779     case PlatformCAAnimation::Spring: {
780         RetainPtr<CASpringAnimation> springAnimation;
781         springAnimation = [CASpringAnimation animationWithKeyPath:properties.keyPath];
782         
783         if (properties.keyValues.size() > 1) {
784             [springAnimation setFromValue:animationValueFromKeyframeValue(properties.keyValues[0])];
785             [springAnimation setToValue:animationValueFromKeyframeValue(properties.keyValues[1])];
786         }
787         
788         if (properties.timingFunctions.size()) {
789             auto& timingFunction = properties.timingFunctions[0];
790             if (timingFunction->isSpringTimingFunction()) {
791                 auto& function = *static_cast<const SpringTimingFunction*>(timingFunction.get());
792                 [springAnimation setMass:function.mass()];
793                 [springAnimation setStiffness:function.stiffness()];
794                 [springAnimation setDamping:function.damping()];
795                 [springAnimation setInitialVelocity:function.initialVelocity()];
796             }
797         }
798         caAnimation = springAnimation;
799         break;
800     }
801     }
802     
803     [caAnimation setBeginTime:properties.beginTime];
804     [caAnimation setDuration:properties.duration];
805     [caAnimation setTimeOffset:properties.timeOffset];
806     [caAnimation setRepeatCount:properties.repeatCount];
807     [caAnimation setSpeed:properties.speed];
808     [caAnimation setAutoreverses:properties.autoReverses];
809     [caAnimation setRemovedOnCompletion:properties.removedOnCompletion];
810     [caAnimation setAdditive:properties.additive];
811     
812     if (properties.fillMode != PlatformCAAnimation::NoFillMode)
813         [caAnimation setFillMode:toCAFillModeType(properties.fillMode)];
814
815     if (properties.valueFunction != PlatformCAAnimation::NoValueFunction)
816         [caAnimation setValueFunction:[CAValueFunction functionWithName:toCAValueFunctionType(properties.valueFunction)]];
817     
818     if (properties.hasExplicitBeginTime)
819         [caAnimation setValue:@YES forKey:WKExplicitBeginTimeFlag];
820     
821     if (layerTreeHost) {
822         GraphicsLayer::PlatformLayerID layerID = RemoteLayerTreeHost::layerID(layer);
823     
824         RetainPtr<WKAnimationDelegate>& delegate = layerTreeHost->animationDelegates().add(layerID, nullptr).iterator->value;
825         if (!delegate)
826             delegate = adoptNS([[WKAnimationDelegate alloc] initWithLayerID:layerID layerTreeHost:layerTreeHost]);
827
828         [caAnimation setDelegate:delegate.get()];
829     }
830     
831     [layer addAnimation:caAnimation.get() forKey:key];
832 }
833
834 void PlatformCAAnimationRemote::updateLayerAnimations(CALayer *layer, RemoteLayerTreeHost* layerTreeHost, const AnimationsList& animationsToAdd, const HashSet<String>& animationsToRemove)
835 {
836     BEGIN_BLOCK_OBJC_EXCEPTIONS;
837
838     for (const auto& value : animationsToRemove)
839         [layer removeAnimationForKey:value];
840
841     for (const auto& keyAnimationPair : animationsToAdd)
842         addAnimationToLayer(layer, layerTreeHost, keyAnimationPair.first, keyAnimationPair.second);
843
844     END_BLOCK_OBJC_EXCEPTIONS;
845 }
846
847 TextStream& operator<<(TextStream&ts, const PlatformCAAnimationRemote::KeyframeValue& value)
848 {
849     switch (value.keyframeType()) {
850     case PlatformCAAnimationRemote::KeyframeValue::NumberKeyType:
851         ts << "number=" << value.numberValue();
852         break;
853     case PlatformCAAnimationRemote::KeyframeValue::ColorKeyType:
854         ts << "color=";
855         ts << value.colorValue();
856         break;
857     case PlatformCAAnimationRemote::KeyframeValue::PointKeyType:
858         ts << "point=";
859         ts << value.pointValue();
860         break;
861     case PlatformCAAnimationRemote::KeyframeValue::TransformKeyType:
862         ts << "transform=";
863         ts << value.transformValue();
864         break;
865     case PlatformCAAnimationRemote::KeyframeValue::FilterKeyType:
866         ts << "filter=";
867         if (value.filterValue())
868             ts << *value.filterValue();
869         else
870             ts << "null";
871         break;
872     }
873     return ts;
874 }
875
876 TextStream& operator<<(TextStream& ts, const PlatformCAAnimationRemote::Properties& animation)
877 {
878     ts << "type=";
879     ts << animation.animationType;
880     ts << " keyPath=";
881     ts << animation.keyPath;
882
883     if (animation.beginTime)
884         ts.dumpProperty("beginTime", animation.beginTime);
885
886     if (animation.duration)
887         ts.dumpProperty("duration", animation.duration);
888
889     if (animation.timeOffset)
890         ts.dumpProperty("timeOffset", animation.timeOffset);
891
892     ts.dumpProperty("repeatCount", animation.repeatCount);
893
894     if (animation.speed != 1)
895         ts.dumpProperty("speed", animation.speed);
896
897     ts.dumpProperty("fillMode", animation.fillMode);
898     ts.dumpProperty("valueFunction", animation.valueFunction);
899
900     if (animation.autoReverses)
901         ts.dumpProperty("autoReverses", animation.autoReverses);
902
903     if (!animation.removedOnCompletion)
904         ts.dumpProperty("removedOnCompletion", animation.removedOnCompletion);
905
906     if (animation.additive)
907         ts.dumpProperty("additive", animation.additive);
908
909     if (animation.reverseTimingFunctions)
910         ts.dumpProperty("reverseTimingFunctions", animation.reverseTimingFunctions);
911
912     if (animation.hasExplicitBeginTime)
913         ts.dumpProperty("hasExplicitBeginTime", animation.hasExplicitBeginTime);
914
915     ts << "\n";
916     ts.increaseIndent();
917     ts.writeIndent();
918     ts << "(" << "keyframes";
919     ts.increaseIndent();
920
921     size_t maxFrames = std::max(animation.keyValues.size(), animation.keyTimes.size());
922     maxFrames = std::max(maxFrames, animation.timingFunctions.size());
923
924     for (size_t i = 0; i < maxFrames; ++i) {
925         ts << "\n";
926         ts.writeIndent();
927         ts << "(keyframe " << unsigned(i);
928         if (i < animation.keyTimes.size())
929             ts.dumpProperty("time", animation.keyTimes[i]);
930
931         if (i < animation.timingFunctions.size() && animation.timingFunctions[i])
932             ts.dumpProperty<const TimingFunction&>("timing function", *animation.timingFunctions[i]);
933
934         if (i < animation.keyValues.size())
935             ts.dumpProperty("value", animation.keyValues[i]);
936
937         ts << ")";
938     }
939
940     ts.decreaseIndent();
941     ts.decreaseIndent();
942
943     return ts;
944 }
945
946 } // namespace WebKit