/src/3rdparty/webkit/Source/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm

https://bitbucket.org/ultra_iter/qt-vtl · Objective C++ · 563 lines · 426 code · 106 blank · 31 comment · 68 complexity · ca9d5060d7ad51af2416c80d824119f0 MD5 · raw file

  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. #include "config.h"
  26. #if USE(ACCELERATED_COMPOSITING)
  27. #import "PlatformCAAnimation.h"
  28. #import "FloatConversion.h"
  29. #import "PlatformString.h"
  30. #import "TimingFunction.h"
  31. #import <QuartzCore/QuartzCore.h>
  32. #import <wtf/UnusedParam.h>
  33. #define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_LEOPARD))
  34. using namespace WebCore;
  35. // This value must be the same as in PlatformCALayerMac.mm
  36. static NSString * const WKNonZeroBeginTimeFlag = @"WKPlatformCAAnimationNonZeroBeginTimeFlag";
  37. static bool hasNonZeroBeginTimeFlag(const PlatformCAAnimation* animation)
  38. {
  39. return [[animation->platformAnimation() valueForKey:WKNonZeroBeginTimeFlag] boolValue];
  40. }
  41. static void setNonZeroBeginTimeFlag(PlatformCAAnimation* animation, bool value)
  42. {
  43. [animation->platformAnimation() setValue:[NSNumber numberWithBool:value] forKey:WKNonZeroBeginTimeFlag];
  44. }
  45. static NSString* toCAFillModeType(PlatformCAAnimation::FillModeType type)
  46. {
  47. switch (type) {
  48. case PlatformCAAnimation::NoFillMode:
  49. case PlatformCAAnimation::Forwards: return kCAFillModeForwards;
  50. case PlatformCAAnimation::Backwards: return kCAFillModeBackwards;
  51. case PlatformCAAnimation::Both: return kCAFillModeBoth;
  52. }
  53. return @"";
  54. }
  55. static PlatformCAAnimation::FillModeType fromCAFillModeType(NSString* string)
  56. {
  57. if ([string isEqualToString:kCAFillModeBackwards])
  58. return PlatformCAAnimation::Backwards;
  59. if ([string isEqualToString:kCAFillModeBoth])
  60. return PlatformCAAnimation::Both;
  61. return PlatformCAAnimation::Forwards;
  62. }
  63. #if HAVE_MODERN_QUARTZCORE
  64. static NSString* toCAValueFunctionType(PlatformCAAnimation::ValueFunctionType type)
  65. {
  66. switch (type) {
  67. case PlatformCAAnimation::NoValueFunction: return @"";
  68. case PlatformCAAnimation::RotateX: return kCAValueFunctionRotateX;
  69. case PlatformCAAnimation::RotateY: return kCAValueFunctionRotateY;
  70. case PlatformCAAnimation::RotateZ: return kCAValueFunctionRotateZ;
  71. case PlatformCAAnimation::ScaleX: return kCAValueFunctionScaleX;
  72. case PlatformCAAnimation::ScaleY: return kCAValueFunctionScaleY;
  73. case PlatformCAAnimation::ScaleZ: return kCAValueFunctionScaleZ;
  74. case PlatformCAAnimation::Scale: return kCAValueFunctionScale;
  75. case PlatformCAAnimation::TranslateX: return kCAValueFunctionTranslateX;
  76. case PlatformCAAnimation::TranslateY: return kCAValueFunctionTranslateY;
  77. case PlatformCAAnimation::TranslateZ: return kCAValueFunctionTranslateZ;
  78. case PlatformCAAnimation::Translate: return kCAValueFunctionTranslate;
  79. }
  80. return @"";
  81. }
  82. static PlatformCAAnimation::ValueFunctionType fromCAValueFunctionType(NSString* string)
  83. {
  84. if ([string isEqualToString:kCAValueFunctionRotateX])
  85. return PlatformCAAnimation::RotateX;
  86. if ([string isEqualToString:kCAValueFunctionRotateY])
  87. return PlatformCAAnimation::RotateY;
  88. if ([string isEqualToString:kCAValueFunctionRotateZ])
  89. return PlatformCAAnimation::RotateZ;
  90. if ([string isEqualToString:kCAValueFunctionScaleX])
  91. return PlatformCAAnimation::ScaleX;
  92. if ([string isEqualToString:kCAValueFunctionScaleY])
  93. return PlatformCAAnimation::ScaleY;
  94. if ([string isEqualToString:kCAValueFunctionScaleZ])
  95. return PlatformCAAnimation::ScaleZ;
  96. if ([string isEqualToString:kCAValueFunctionScale])
  97. return PlatformCAAnimation::Scale;
  98. if ([string isEqualToString:kCAValueFunctionTranslateX])
  99. return PlatformCAAnimation::TranslateX;
  100. if ([string isEqualToString:kCAValueFunctionTranslateY])
  101. return PlatformCAAnimation::TranslateY;
  102. if ([string isEqualToString:kCAValueFunctionTranslateZ])
  103. return PlatformCAAnimation::TranslateZ;
  104. if ([string isEqualToString:kCAValueFunctionTranslate])
  105. return PlatformCAAnimation::Translate;
  106. return PlatformCAAnimation::NoValueFunction;
  107. }
  108. #endif
  109. static CAMediaTimingFunction* toCAMediaTimingFunction(const TimingFunction* timingFunction)
  110. {
  111. ASSERT(timingFunction);
  112. if (timingFunction->isCubicBezierTimingFunction()) {
  113. const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
  114. return [CAMediaTimingFunction functionWithControlPoints:static_cast<float>(ctf->x1()) :static_cast<float>(ctf->y1())
  115. :static_cast<float>(ctf->x2()) :static_cast<float>(ctf->y2())];
  116. }
  117. return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
  118. }
  119. PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(AnimationType type, const String& keyPath)
  120. {
  121. return adoptRef(new PlatformCAAnimation(type, keyPath));
  122. }
  123. PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(PlatformAnimationRef animation)
  124. {
  125. return adoptRef(new PlatformCAAnimation(animation));
  126. }
  127. PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath)
  128. : m_type(type)
  129. {
  130. if (type == Basic)
  131. m_animation.adoptNS([[CABasicAnimation animationWithKeyPath:keyPath] retain]);
  132. else
  133. m_animation.adoptNS([[CAKeyframeAnimation animationWithKeyPath:keyPath] retain]);
  134. }
  135. PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation)
  136. {
  137. if ([static_cast<CAAnimation*>(animation) isKindOfClass:[CABasicAnimation class]])
  138. m_type = Basic;
  139. else if ([static_cast<CAAnimation*>(animation) isKindOfClass:[CAKeyframeAnimation class]])
  140. m_type = Keyframe;
  141. else {
  142. ASSERT(0);
  143. return;
  144. }
  145. m_animation = static_cast<CAPropertyAnimation*>(animation);
  146. }
  147. PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::copy() const
  148. {
  149. RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
  150. animation->setBeginTime(beginTime());
  151. animation->setDuration(duration());
  152. animation->setSpeed(speed());
  153. animation->setTimeOffset(timeOffset());
  154. animation->setRepeatCount(repeatCount());
  155. animation->setAutoreverses(autoreverses());
  156. animation->setFillMode(fillMode());
  157. animation->setRemovedOnCompletion(isRemovedOnCompletion());
  158. animation->setAdditive(isAdditive());
  159. animation->copyTimingFunctionFrom(this);
  160. animation->setValueFunction(valueFunction());
  161. setNonZeroBeginTimeFlag(animation.get(), hasNonZeroBeginTimeFlag(this));
  162. // Copy the specific Basic or Keyframe values
  163. if (animationType() == Keyframe) {
  164. animation->copyValuesFrom(this);
  165. animation->copyKeyTimesFrom(this);
  166. animation->copyTimingFunctionsFrom(this);
  167. } else {
  168. animation->copyFromValueFrom(this);
  169. animation->copyToValueFrom(this);
  170. }
  171. return animation;
  172. }
  173. PlatformCAAnimation::~PlatformCAAnimation()
  174. {
  175. }
  176. bool PlatformCAAnimation::supportsValueFunction()
  177. {
  178. static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
  179. return sHaveValueFunction;
  180. }
  181. PlatformAnimationRef PlatformCAAnimation::platformAnimation() const
  182. {
  183. return m_animation.get();
  184. }
  185. String PlatformCAAnimation::keyPath() const
  186. {
  187. return [m_animation.get() keyPath];
  188. }
  189. CFTimeInterval PlatformCAAnimation::beginTime() const
  190. {
  191. return [m_animation.get() beginTime];
  192. }
  193. void PlatformCAAnimation::setBeginTime(CFTimeInterval value)
  194. {
  195. [m_animation.get() setBeginTime:value];
  196. // Also set a flag to tell us if we've passed in a 0 value.
  197. // The flag is needed because later beginTime will get changed
  198. // to the time at which it fired and we need to know whether
  199. // or not it was 0 to begin with.
  200. if (value)
  201. setNonZeroBeginTimeFlag(this, true);
  202. }
  203. CFTimeInterval PlatformCAAnimation::duration() const
  204. {
  205. return [m_animation.get() duration];
  206. }
  207. void PlatformCAAnimation::setDuration(CFTimeInterval value)
  208. {
  209. [m_animation.get() setDuration:value];
  210. }
  211. float PlatformCAAnimation::speed() const
  212. {
  213. return [m_animation.get() speed];
  214. }
  215. void PlatformCAAnimation::setSpeed(float value)
  216. {
  217. [m_animation.get() setSpeed:value];
  218. }
  219. CFTimeInterval PlatformCAAnimation::timeOffset() const
  220. {
  221. return [m_animation.get() timeOffset];
  222. }
  223. void PlatformCAAnimation::setTimeOffset(CFTimeInterval value)
  224. {
  225. [m_animation.get() setTimeOffset:value];
  226. }
  227. float PlatformCAAnimation::repeatCount() const
  228. {
  229. return [m_animation.get() repeatCount];
  230. }
  231. void PlatformCAAnimation::setRepeatCount(float value)
  232. {
  233. [m_animation.get() setRepeatCount:value];
  234. }
  235. bool PlatformCAAnimation::autoreverses() const
  236. {
  237. return [m_animation.get() autoreverses];
  238. }
  239. void PlatformCAAnimation::setAutoreverses(bool value)
  240. {
  241. [m_animation.get() setAutoreverses:value];
  242. }
  243. PlatformCAAnimation::FillModeType PlatformCAAnimation::fillMode() const
  244. {
  245. return fromCAFillModeType([m_animation.get() fillMode]);
  246. }
  247. void PlatformCAAnimation::setFillMode(FillModeType value)
  248. {
  249. [m_animation.get() setFillMode:toCAFillModeType(value)];
  250. }
  251. void PlatformCAAnimation::setTimingFunction(const TimingFunction* value)
  252. {
  253. [m_animation.get() setTimingFunction:toCAMediaTimingFunction(value)];
  254. }
  255. void PlatformCAAnimation::copyTimingFunctionFrom(const PlatformCAAnimation* value)
  256. {
  257. [m_animation.get() setTimingFunction:[value->m_animation.get() timingFunction]];
  258. }
  259. bool PlatformCAAnimation::isRemovedOnCompletion() const
  260. {
  261. return [m_animation.get() isRemovedOnCompletion];
  262. }
  263. void PlatformCAAnimation::setRemovedOnCompletion(bool value)
  264. {
  265. [m_animation.get() setRemovedOnCompletion:value];
  266. }
  267. bool PlatformCAAnimation::isAdditive() const
  268. {
  269. return [m_animation.get() isAdditive];
  270. }
  271. void PlatformCAAnimation::setAdditive(bool value)
  272. {
  273. [m_animation.get() setAdditive:value];
  274. }
  275. PlatformCAAnimation::ValueFunctionType PlatformCAAnimation::valueFunction() const
  276. {
  277. #if HAVE_MODERN_QUARTZCORE
  278. CAValueFunction* vf = [m_animation.get() valueFunction];
  279. return fromCAValueFunctionType([vf name]);
  280. #else
  281. return NoValueFunction;
  282. #endif
  283. }
  284. void PlatformCAAnimation::setValueFunction(ValueFunctionType value)
  285. {
  286. #if HAVE_MODERN_QUARTZCORE
  287. [m_animation.get() setValueFunction:[CAValueFunction functionWithName:toCAValueFunctionType(value)]];
  288. #else
  289. UNUSED_PARAM(value);
  290. #endif
  291. }
  292. void PlatformCAAnimation::setFromValue(float value)
  293. {
  294. if (animationType() != Basic)
  295. return;
  296. [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[NSNumber numberWithDouble:value]];
  297. }
  298. void PlatformCAAnimation::setFromValue(const WebCore::TransformationMatrix& value)
  299. {
  300. if (animationType() != Basic)
  301. return;
  302. [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[NSValue valueWithCATransform3D:value]];
  303. }
  304. void PlatformCAAnimation::setFromValue(const FloatPoint3D& value)
  305. {
  306. if (animationType() != Basic)
  307. return;
  308. NSArray* array = [NSArray arrayWithObjects:
  309. [NSNumber numberWithDouble:value.x()],
  310. [NSNumber numberWithDouble:value.y()],
  311. [NSNumber numberWithDouble:value.z()],
  312. nil];
  313. [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:array];
  314. }
  315. void PlatformCAAnimation::setFromValue(const WebCore::Color& value)
  316. {
  317. if (animationType() != Basic)
  318. return;
  319. NSArray* array = [NSArray arrayWithObjects:
  320. [NSNumber numberWithDouble:value.red()],
  321. [NSNumber numberWithDouble:value.green()],
  322. [NSNumber numberWithDouble:value.blue()],
  323. [NSNumber numberWithDouble:value.alpha()],
  324. nil];
  325. [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:array];
  326. }
  327. void PlatformCAAnimation::copyFromValueFrom(const PlatformCAAnimation* value)
  328. {
  329. if (animationType() != Basic || value->animationType() != Basic)
  330. return;
  331. CABasicAnimation* otherAnimation = static_cast<CABasicAnimation*>(value->m_animation.get());
  332. [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[otherAnimation fromValue]];
  333. }
  334. void PlatformCAAnimation::setToValue(float value)
  335. {
  336. if (animationType() != Basic)
  337. return;
  338. [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[NSNumber numberWithDouble:value]];
  339. }
  340. void PlatformCAAnimation::setToValue(const WebCore::TransformationMatrix& value)
  341. {
  342. if (animationType() != Basic)
  343. return;
  344. [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[NSValue valueWithCATransform3D:value]];
  345. }
  346. void PlatformCAAnimation::setToValue(const FloatPoint3D& value)
  347. {
  348. if (animationType() != Basic)
  349. return;
  350. NSArray* array = [NSArray arrayWithObjects:
  351. [NSNumber numberWithDouble:value.x()],
  352. [NSNumber numberWithDouble:value.y()],
  353. [NSNumber numberWithDouble:value.z()],
  354. nil];
  355. [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:array];
  356. }
  357. void PlatformCAAnimation::setToValue(const WebCore::Color& value)
  358. {
  359. if (animationType() != Basic)
  360. return;
  361. NSArray* array = [NSArray arrayWithObjects:
  362. [NSNumber numberWithDouble:value.red()],
  363. [NSNumber numberWithDouble:value.green()],
  364. [NSNumber numberWithDouble:value.blue()],
  365. [NSNumber numberWithDouble:value.alpha()],
  366. nil];
  367. [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:array];
  368. }
  369. void PlatformCAAnimation::copyToValueFrom(const PlatformCAAnimation* value)
  370. {
  371. if (animationType() != Basic || value->animationType() != Basic)
  372. return;
  373. CABasicAnimation* otherAnimation = static_cast<CABasicAnimation*>(value->m_animation.get());
  374. [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[otherAnimation toValue]];
  375. }
  376. // Keyframe-animation properties.
  377. void PlatformCAAnimation::setValues(const Vector<float>& value)
  378. {
  379. if (animationType() != Keyframe)
  380. return;
  381. NSMutableArray* array = [NSMutableArray array];
  382. for (size_t i = 0; i < value.size(); ++i)
  383. [array addObject:[NSNumber numberWithDouble:value[i]]];
  384. [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
  385. }
  386. void PlatformCAAnimation::setValues(const Vector<WebCore::TransformationMatrix>& value)
  387. {
  388. if (animationType() != Keyframe)
  389. return;
  390. NSMutableArray* array = [NSMutableArray array];
  391. for (size_t i = 0; i < value.size(); ++i)
  392. [array addObject:[NSValue valueWithCATransform3D:value[i]]];
  393. [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
  394. }
  395. void PlatformCAAnimation::setValues(const Vector<FloatPoint3D>& value)
  396. {
  397. if (animationType() != Keyframe)
  398. return;
  399. NSMutableArray* array = [NSMutableArray array];
  400. for (size_t i = 0; i < value.size(); ++i) {
  401. NSArray* object = [NSArray arrayWithObjects:
  402. [NSNumber numberWithDouble:value[i].x()],
  403. [NSNumber numberWithDouble:value[i].y()],
  404. [NSNumber numberWithDouble:value[i].z()],
  405. nil];
  406. [array addObject:object];
  407. }
  408. [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
  409. }
  410. void PlatformCAAnimation::setValues(const Vector<WebCore::Color>& value)
  411. {
  412. if (animationType() != Keyframe)
  413. return;
  414. NSMutableArray* array = [NSMutableArray array];
  415. for (size_t i = 0; i < value.size(); ++i) {
  416. NSArray* object = [NSArray arrayWithObjects:
  417. [NSNumber numberWithDouble:value[i].red()],
  418. [NSNumber numberWithDouble:value[i].green()],
  419. [NSNumber numberWithDouble:value[i].blue()],
  420. [NSNumber numberWithDouble:value[i].alpha()],
  421. nil];
  422. [array addObject:object];
  423. }
  424. [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
  425. }
  426. void PlatformCAAnimation::copyValuesFrom(const PlatformCAAnimation* value)
  427. {
  428. if (animationType() != Keyframe || value->animationType() != Keyframe)
  429. return;
  430. CAKeyframeAnimation* otherAnimation = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
  431. [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:[otherAnimation values]];
  432. }
  433. void PlatformCAAnimation::setKeyTimes(const Vector<float>& value)
  434. {
  435. NSMutableArray* array = [NSMutableArray array];
  436. for (size_t i = 0; i < value.size(); ++i)
  437. [array addObject:[NSNumber numberWithFloat:value[i]]];
  438. [static_cast<CAKeyframeAnimation*>(m_animation.get()) setKeyTimes:array];
  439. }
  440. void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value)
  441. {
  442. CAKeyframeAnimation* other = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
  443. [static_cast<CAKeyframeAnimation*>(m_animation.get()) setKeyTimes:[other keyTimes]];
  444. }
  445. void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value)
  446. {
  447. NSMutableArray* array = [NSMutableArray array];
  448. for (size_t i = 0; i < value.size(); ++i)
  449. [array addObject:toCAMediaTimingFunction(value[i])];
  450. [static_cast<CAKeyframeAnimation*>(m_animation.get()) setTimingFunctions:array];
  451. }
  452. void PlatformCAAnimation::copyTimingFunctionsFrom(const PlatformCAAnimation* value)
  453. {
  454. CAKeyframeAnimation* other = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
  455. [static_cast<CAKeyframeAnimation*>(m_animation.get()) setTimingFunctions:[other timingFunctions]];
  456. }
  457. #endif // USE(ACCELERATED_COMPOSITING)