OSDN Git Service

Merge WebKit at r78450: Initial merge by git.
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / ca / mac / PlatformCAAnimationMac.mm
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #if USE(ACCELERATED_COMPOSITING)
29
30 #import "PlatformCAAnimation.h"
31
32 #import "FloatConversion.h"
33 #import "PlatformString.h"
34 #import "TimingFunction.h"
35 #import <QuartzCore/QuartzCore.h>
36 #import <wtf/UnusedParam.h>
37
38 #define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
39
40 using namespace WebCore;
41
42 // This value must be the same as in PlatformCALayerMac.mm
43 static NSString * const WKNonZeroBeginTimeFlag = @"WKPlatformCAAnimationNonZeroBeginTimeFlag";
44
45 static bool hasNonZeroBeginTimeFlag(const PlatformCAAnimation* animation)
46 {
47     return [[animation->platformAnimation() valueForKey:WKNonZeroBeginTimeFlag] boolValue];
48 }
49
50 static void setNonZeroBeginTimeFlag(PlatformCAAnimation* animation, bool value)
51 {
52     [animation->platformAnimation() setValue:[NSNumber numberWithBool:value] forKey:WKNonZeroBeginTimeFlag];
53 }
54     
55 static NSString* toCAFillModeType(PlatformCAAnimation::FillModeType type)
56 {
57     switch (type) {
58     case PlatformCAAnimation::NoFillMode:
59     case PlatformCAAnimation::Forwards: return kCAFillModeForwards;
60     case PlatformCAAnimation::Backwards: return kCAFillModeBackwards;
61     case PlatformCAAnimation::Both: return kCAFillModeBoth;
62     }
63     return @"";
64 }
65
66 static PlatformCAAnimation::FillModeType fromCAFillModeType(NSString* string)
67 {
68     if ([string isEqualToString:kCAFillModeBackwards])
69         return PlatformCAAnimation::Backwards;
70
71     if ([string isEqualToString:kCAFillModeBoth])
72         return PlatformCAAnimation::Both;
73
74     return PlatformCAAnimation::Forwards;
75 }
76
77 #if HAVE_MODERN_QUARTZCORE
78 static NSString* toCAValueFunctionType(PlatformCAAnimation::ValueFunctionType type)
79 {
80     switch (type) {
81     case PlatformCAAnimation::NoValueFunction: return @"";
82     case PlatformCAAnimation::RotateX: return kCAValueFunctionRotateX;
83     case PlatformCAAnimation::RotateY: return kCAValueFunctionRotateY;
84     case PlatformCAAnimation::RotateZ: return kCAValueFunctionRotateZ;
85     case PlatformCAAnimation::ScaleX: return kCAValueFunctionScaleX;
86     case PlatformCAAnimation::ScaleY: return kCAValueFunctionScaleY;
87     case PlatformCAAnimation::ScaleZ: return kCAValueFunctionScaleZ;
88     case PlatformCAAnimation::Scale: return kCAValueFunctionScale;
89     case PlatformCAAnimation::TranslateX: return kCAValueFunctionTranslateX;
90     case PlatformCAAnimation::TranslateY: return kCAValueFunctionTranslateY;
91     case PlatformCAAnimation::TranslateZ: return kCAValueFunctionTranslateZ;
92     case PlatformCAAnimation::Translate: return kCAValueFunctionTranslate;
93     }
94     return @"";
95 }
96
97 static PlatformCAAnimation::ValueFunctionType fromCAValueFunctionType(NSString* string)
98 {
99     if ([string isEqualToString:kCAValueFunctionRotateX])
100         return PlatformCAAnimation::RotateX;
101
102     if ([string isEqualToString:kCAValueFunctionRotateY])
103         return PlatformCAAnimation::RotateY;
104
105     if ([string isEqualToString:kCAValueFunctionRotateZ])
106         return PlatformCAAnimation::RotateZ;
107
108     if ([string isEqualToString:kCAValueFunctionScaleX])
109         return PlatformCAAnimation::ScaleX;
110
111     if ([string isEqualToString:kCAValueFunctionScaleY])
112         return PlatformCAAnimation::ScaleY;
113
114     if ([string isEqualToString:kCAValueFunctionScaleZ])
115         return PlatformCAAnimation::ScaleZ;
116
117     if ([string isEqualToString:kCAValueFunctionScale])
118         return PlatformCAAnimation::Scale;
119
120     if ([string isEqualToString:kCAValueFunctionTranslateX])
121         return PlatformCAAnimation::TranslateX;
122
123     if ([string isEqualToString:kCAValueFunctionTranslateY])
124         return PlatformCAAnimation::TranslateY;
125
126     if ([string isEqualToString:kCAValueFunctionTranslateZ])
127         return PlatformCAAnimation::TranslateZ;
128
129     if ([string isEqualToString:kCAValueFunctionTranslate])
130         return PlatformCAAnimation::Translate;
131
132     return PlatformCAAnimation::NoValueFunction;
133 }
134 #endif
135
136 static CAMediaTimingFunction* toCAMediaTimingFunction(const TimingFunction* timingFunction)
137 {
138     if (!timingFunction)
139         return [CAMediaTimingFunction functionWithControlPoints:0.25f :0.1f :0.25f :0.1f];
140             
141     if (timingFunction->isCubicBezierTimingFunction()) {
142         const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
143         return [CAMediaTimingFunction functionWithControlPoints:static_cast<float>(ctf->x1()) :static_cast<float>(ctf->y1())
144                                                                :static_cast<float>(ctf->x2()) :static_cast<float>(ctf->y2())];
145     }
146     
147     return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
148
149     return 0;
150 }
151
152 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(AnimationType type, const String& keyPath)
153 {
154     return adoptRef(new PlatformCAAnimation(type, keyPath));
155 }
156
157 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(PlatformAnimationRef animation)
158 {
159     return adoptRef(new PlatformCAAnimation(animation));
160 }
161
162 PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath)
163     : m_type(type)
164 {
165     if (type == Basic)
166         m_animation.adoptNS([[CABasicAnimation animationWithKeyPath:keyPath] retain]);
167     else
168         m_animation.adoptNS([[CAKeyframeAnimation animationWithKeyPath:keyPath] retain]);
169 }
170
171 PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation)
172 {
173     if ([static_cast<CAAnimation*>(animation) isKindOfClass:[CABasicAnimation class]])
174         m_type = Basic;
175     else if ([static_cast<CAAnimation*>(animation) isKindOfClass:[CAKeyframeAnimation class]])
176         m_type = Keyframe;
177     else {
178         ASSERT(0);
179         return;
180     }
181     
182     m_animation = static_cast<CAPropertyAnimation*>(animation);
183 }
184
185 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::copy() const
186 {
187     RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
188     
189     animation->setBeginTime(beginTime());
190     animation->setDuration(duration());
191     animation->setSpeed(speed());
192     animation->setTimeOffset(timeOffset());
193     animation->setRepeatCount(repeatCount());
194     animation->setAutoreverses(autoreverses());
195     animation->setFillMode(fillMode());
196     animation->setRemovedOnCompletion(isRemovedOnCompletion());
197     animation->setAdditive(isAdditive());
198     animation->copyTimingFunctionFrom(this);
199     animation->setValueFunction(valueFunction());
200
201     setNonZeroBeginTimeFlag(animation.get(), hasNonZeroBeginTimeFlag(this));
202     
203     // Copy the specific Basic or Keyframe values
204     if (animationType() == Keyframe) {
205         animation->copyValuesFrom(this);
206         animation->copyKeyTimesFrom(this);
207         animation->copyTimingFunctionsFrom(this);
208     } else {
209         animation->copyFromValueFrom(this);
210         animation->copyToValueFrom(this);
211     }
212     
213     return animation;
214 }
215 PlatformCAAnimation::~PlatformCAAnimation()
216 {
217 }
218
219 bool PlatformCAAnimation::supportsValueFunction()
220 {
221     static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
222     return sHaveValueFunction;
223 }
224
225 PlatformAnimationRef PlatformCAAnimation::platformAnimation() const
226 {
227     return m_animation.get();
228 }
229
230 String PlatformCAAnimation::keyPath() const
231 {
232     return [m_animation.get() keyPath];
233 }
234
235 CFTimeInterval PlatformCAAnimation::beginTime() const
236 {
237     return [m_animation.get() beginTime];
238 }
239
240 void PlatformCAAnimation::setBeginTime(CFTimeInterval value)
241 {
242     [m_animation.get() setBeginTime:value];
243     
244     // Also set a flag to tell us if we've passed in a 0 value. 
245     // The flag is needed because later beginTime will get changed
246     // to the time at which it fired and we need to know whether
247     // or not it was 0 to begin with.
248     if (value)
249         setNonZeroBeginTimeFlag(this, true);
250 }
251
252 CFTimeInterval PlatformCAAnimation::duration() const
253 {
254     return [m_animation.get() duration];
255 }
256
257 void PlatformCAAnimation::setDuration(CFTimeInterval value)
258 {
259     [m_animation.get() setDuration:value];
260 }
261
262 float PlatformCAAnimation::speed() const
263 {
264     return [m_animation.get() speed];
265 }
266
267 void PlatformCAAnimation::setSpeed(float value)
268 {
269     [m_animation.get() setSpeed:value];
270 }
271
272 CFTimeInterval PlatformCAAnimation::timeOffset() const
273 {
274     return [m_animation.get() timeOffset];
275 }
276
277 void PlatformCAAnimation::setTimeOffset(CFTimeInterval value)
278 {
279     [m_animation.get() setTimeOffset:value];
280 }
281
282 float PlatformCAAnimation::repeatCount() const
283 {
284     return [m_animation.get() repeatCount];
285 }
286
287 void PlatformCAAnimation::setRepeatCount(float value)
288 {
289     [m_animation.get() setRepeatCount:value];
290 }
291
292 bool PlatformCAAnimation::autoreverses() const
293 {
294     return [m_animation.get() autoreverses];
295 }
296
297 void PlatformCAAnimation::setAutoreverses(bool value)
298 {
299     [m_animation.get() setAutoreverses:value];
300 }
301
302 PlatformCAAnimation::FillModeType PlatformCAAnimation::fillMode() const
303 {
304     return fromCAFillModeType([m_animation.get() fillMode]);
305 }
306
307 void PlatformCAAnimation::setFillMode(FillModeType value)
308 {
309     [m_animation.get() setFillMode:toCAFillModeType(value)];
310 }
311
312 void PlatformCAAnimation::setTimingFunction(const TimingFunction* value)
313 {
314     [m_animation.get() setTimingFunction:toCAMediaTimingFunction(value)];
315 }
316
317 void PlatformCAAnimation::copyTimingFunctionFrom(const PlatformCAAnimation* value)
318 {
319     [m_animation.get() setTimingFunction:[value->m_animation.get() timingFunction]];
320 }
321
322 bool PlatformCAAnimation::isRemovedOnCompletion() const
323 {
324     return [m_animation.get() isRemovedOnCompletion];
325 }
326
327 void PlatformCAAnimation::setRemovedOnCompletion(bool value)
328 {
329     [m_animation.get() setRemovedOnCompletion:value];
330 }
331
332 bool PlatformCAAnimation::isAdditive() const
333 {
334     return [m_animation.get() isAdditive];
335 }
336
337 void PlatformCAAnimation::setAdditive(bool value)
338 {
339     [m_animation.get() setAdditive:value];
340 }
341
342 PlatformCAAnimation::ValueFunctionType PlatformCAAnimation::valueFunction() const
343 {
344 #if HAVE_MODERN_QUARTZCORE
345     CAValueFunction* vf = [m_animation.get() valueFunction];
346     return fromCAValueFunctionType([vf name]);
347 #else
348     return NoValueFunction;
349 #endif
350 }
351
352 void PlatformCAAnimation::setValueFunction(ValueFunctionType value)
353 {
354 #if HAVE_MODERN_QUARTZCORE
355     [m_animation.get() setValueFunction:[CAValueFunction functionWithName:toCAValueFunctionType(value)]];
356 #else
357     UNUSED_PARAM(value);
358 #endif
359 }
360
361 void PlatformCAAnimation::setFromValue(float value)
362 {
363     if (animationType() != Basic)
364         return;
365     [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[NSNumber numberWithDouble:value]];
366 }
367
368 void PlatformCAAnimation::setFromValue(const WebCore::TransformationMatrix& value)
369 {
370     if (animationType() != Basic)
371         return;
372         
373     [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[NSValue valueWithCATransform3D:value]];
374 }
375
376 void PlatformCAAnimation::setFromValue(const FloatPoint3D& value)
377 {
378     if (animationType() != Basic)
379         return;
380
381     NSArray* array = [NSArray arrayWithObjects:
382                         [NSNumber numberWithDouble:value.x()],
383                         [NSNumber numberWithDouble:value.y()],
384                         [NSNumber numberWithDouble:value.z()],
385                         nil];
386     [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:array];
387 }
388
389 void PlatformCAAnimation::setFromValue(const WebCore::Color& value)
390 {
391     if (animationType() != Basic)
392         return;
393
394     NSArray* array = [NSArray arrayWithObjects:
395                         [NSNumber numberWithDouble:value.red()],
396                         [NSNumber numberWithDouble:value.green()],
397                         [NSNumber numberWithDouble:value.blue()],
398                         [NSNumber numberWithDouble:value.alpha()],
399                         nil];
400     [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:array];
401 }
402
403 void PlatformCAAnimation::copyFromValueFrom(const PlatformCAAnimation* value)
404 {
405     if (animationType() != Basic || value->animationType() != Basic)
406         return;
407         
408     CABasicAnimation* otherAnimation = static_cast<CABasicAnimation*>(value->m_animation.get());
409     [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[otherAnimation fromValue]];
410 }
411
412 void PlatformCAAnimation::setToValue(float value)
413 {
414     if (animationType() != Basic)
415         return;
416     [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[NSNumber numberWithDouble:value]];
417 }
418
419 void PlatformCAAnimation::setToValue(const WebCore::TransformationMatrix& value)
420 {
421     if (animationType() != Basic)
422         return;
423
424     [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[NSValue valueWithCATransform3D:value]];
425 }
426
427 void PlatformCAAnimation::setToValue(const FloatPoint3D& value)
428 {
429     if (animationType() != Basic)
430         return;
431
432     NSArray* array = [NSArray arrayWithObjects:
433                         [NSNumber numberWithDouble:value.x()],
434                         [NSNumber numberWithDouble:value.y()],
435                         [NSNumber numberWithDouble:value.z()],
436                         nil];
437     [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:array];
438 }
439
440 void PlatformCAAnimation::setToValue(const WebCore::Color& value)
441 {
442     if (animationType() != Basic)
443         return;
444
445     NSArray* array = [NSArray arrayWithObjects:
446                         [NSNumber numberWithDouble:value.red()],
447                         [NSNumber numberWithDouble:value.green()],
448                         [NSNumber numberWithDouble:value.blue()],
449                         [NSNumber numberWithDouble:value.alpha()],
450                         nil];
451     [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:array];
452 }
453
454 void PlatformCAAnimation::copyToValueFrom(const PlatformCAAnimation* value)
455 {
456     if (animationType() != Basic || value->animationType() != Basic)
457         return;
458         
459     CABasicAnimation* otherAnimation = static_cast<CABasicAnimation*>(value->m_animation.get());
460     [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[otherAnimation toValue]];
461 }
462
463
464 // Keyframe-animation properties.
465 void PlatformCAAnimation::setValues(const Vector<float>& value)
466 {
467     if (animationType() != Keyframe)
468         return;
469         
470     NSMutableArray* array = [NSMutableArray array];
471     for (size_t i = 0; i < value.size(); ++i)
472         [array addObject:[NSNumber numberWithDouble:value[i]]];
473     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
474 }
475
476 void PlatformCAAnimation::setValues(const Vector<WebCore::TransformationMatrix>& value)
477 {
478     if (animationType() != Keyframe)
479         return;
480         
481     NSMutableArray* array = [NSMutableArray array];
482
483     for (size_t i = 0; i < value.size(); ++i)
484         [array addObject:[NSValue valueWithCATransform3D:value[i]]];
485         
486     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
487 }
488
489 void PlatformCAAnimation::setValues(const Vector<FloatPoint3D>& value)
490 {
491     if (animationType() != Keyframe)
492         return;
493         
494     NSMutableArray* array = [NSMutableArray array];
495
496     for (size_t i = 0; i < value.size(); ++i) {
497         NSArray* object = [NSArray arrayWithObjects:
498                         [NSNumber numberWithDouble:value[i].x()],
499                         [NSNumber numberWithDouble:value[i].y()],
500                         [NSNumber numberWithDouble:value[i].z()],
501                         nil];
502         [array addObject:object];
503     }
504     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
505 }
506
507 void PlatformCAAnimation::setValues(const Vector<WebCore::Color>& value)
508 {
509     if (animationType() != Keyframe)
510         return;
511         
512     NSMutableArray* array = [NSMutableArray array];
513
514     for (size_t i = 0; i < value.size(); ++i) {
515         NSArray* object = [NSArray arrayWithObjects:
516                         [NSNumber numberWithDouble:value[i].red()],
517                         [NSNumber numberWithDouble:value[i].green()],
518                         [NSNumber numberWithDouble:value[i].blue()],
519                         [NSNumber numberWithDouble:value[i].alpha()],
520                         nil];
521         [array addObject:object];
522     }
523     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
524 }
525
526 void PlatformCAAnimation::copyValuesFrom(const PlatformCAAnimation* value)
527 {
528     if (animationType() != Keyframe || value->animationType() != Keyframe)
529         return;
530         
531     CAKeyframeAnimation* otherAnimation = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
532     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:[otherAnimation values]];
533 }
534
535 void PlatformCAAnimation::setKeyTimes(const Vector<float>& value)
536 {
537     NSMutableArray* array = [NSMutableArray array];
538
539     for (size_t i = 0; i < value.size(); ++i)
540         [array addObject:[NSNumber numberWithFloat:value[i]]];
541     
542     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setKeyTimes:array];
543 }
544
545 void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value)
546 {
547     CAKeyframeAnimation* other = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
548     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setKeyTimes:[other keyTimes]];
549 }
550
551 void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value)
552 {
553     NSMutableArray* array = [NSMutableArray array];
554
555     for (size_t i = 0; i < value.size(); ++i)
556         [array addObject:toCAMediaTimingFunction(value[i])];
557     
558     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setTimingFunctions:array];
559 }
560
561 void PlatformCAAnimation::copyTimingFunctionsFrom(const PlatformCAAnimation* value)
562 {
563     CAKeyframeAnimation* other = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
564     [static_cast<CAKeyframeAnimation*>(m_animation.get()) setTimingFunctions:[other timingFunctions]];
565 }
566
567 #endif // USE(ACCELERATED_COMPOSITING)