Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2011 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 #include "PlatformCAAnimation.h"
     31 
     32 #include "FloatConversion.h"
     33 #include "PlatformString.h"
     34 #include "TimingFunction.h"
     35 #include <QuartzCore/CACFAnimation.h>
     36 #include <QuartzCore/CACFTiming.h>
     37 #include <QuartzCore/CACFTimingFunction.h>
     38 #include <QuartzCore/CACFValueFunction.h>
     39 #include <QuartzCore/CACFVector.h>
     40 #include <wtf/UnusedParam.h>
     41 
     42 using namespace WebCore;
     43 
     44 static CFStringRef toCACFFillModeType(PlatformCAAnimation::FillModeType type)
     45 {
     46     switch (type) {
     47     case PlatformCAAnimation::NoFillMode:
     48     case PlatformCAAnimation::Forwards: return kCACFFillModeForwards;
     49     case PlatformCAAnimation::Backwards: return kCACFFillModeBackwards;
     50     case PlatformCAAnimation::Both: return kCACFFillModeBoth;
     51     }
     52     ASSERT_NOT_REACHED();
     53     return 0;
     54 }
     55 
     56 static PlatformCAAnimation::FillModeType fromCACFFillModeType(CFStringRef string)
     57 {
     58     if (string == kCACFFillModeBackwards)
     59         return PlatformCAAnimation::Backwards;
     60 
     61     if (string == kCACFFillModeBoth)
     62         return PlatformCAAnimation::Both;
     63 
     64     return PlatformCAAnimation::Forwards;
     65 }
     66 
     67 static CFStringRef toCACFValueFunctionType(PlatformCAAnimation::ValueFunctionType type)
     68 {
     69     switch (type) {
     70     case PlatformCAAnimation::NoValueFunction: return 0;
     71     case PlatformCAAnimation::RotateX: return kCACFValueFunctionRotateX;
     72     case PlatformCAAnimation::RotateY: return kCACFValueFunctionRotateY;
     73     case PlatformCAAnimation::RotateZ: return kCACFValueFunctionRotateZ;
     74     case PlatformCAAnimation::ScaleX: return kCACFValueFunctionScaleX;
     75     case PlatformCAAnimation::ScaleY: return kCACFValueFunctionScaleY;
     76     case PlatformCAAnimation::ScaleZ: return kCACFValueFunctionScaleZ;
     77     case PlatformCAAnimation::Scale: return kCACFValueFunctionScale;
     78     case PlatformCAAnimation::TranslateX: return kCACFValueFunctionTranslateX;
     79     case PlatformCAAnimation::TranslateY: return kCACFValueFunctionTranslateY;
     80     case PlatformCAAnimation::TranslateZ: return kCACFValueFunctionTranslateZ;
     81     case PlatformCAAnimation::Translate: return kCACFValueFunctionTranslate;
     82     }
     83     ASSERT_NOT_REACHED();
     84     return 0;
     85 }
     86 
     87 static PlatformCAAnimation::ValueFunctionType fromCACFValueFunctionType(CFStringRef string)
     88 {
     89     if (string == kCACFValueFunctionRotateX)
     90         return PlatformCAAnimation::RotateX;
     91 
     92     if (string == kCACFValueFunctionRotateY)
     93         return PlatformCAAnimation::RotateY;
     94 
     95     if (string == kCACFValueFunctionRotateZ)
     96         return PlatformCAAnimation::RotateZ;
     97 
     98     if (string == kCACFValueFunctionScaleX)
     99         return PlatformCAAnimation::ScaleX;
    100 
    101     if (string == kCACFValueFunctionScaleY)
    102         return PlatformCAAnimation::ScaleY;
    103 
    104     if (string == kCACFValueFunctionScaleZ)
    105         return PlatformCAAnimation::ScaleZ;
    106 
    107     if (string == kCACFValueFunctionScale)
    108         return PlatformCAAnimation::Scale;
    109 
    110     if (string == kCACFValueFunctionTranslateX)
    111         return PlatformCAAnimation::TranslateX;
    112 
    113     if (string == kCACFValueFunctionTranslateY)
    114         return PlatformCAAnimation::TranslateY;
    115 
    116     if (string == kCACFValueFunctionTranslateZ)
    117         return PlatformCAAnimation::TranslateZ;
    118 
    119     if (string == kCACFValueFunctionTranslate)
    120         return PlatformCAAnimation::Translate;
    121 
    122     return PlatformCAAnimation::NoValueFunction;
    123 }
    124 
    125 static RetainPtr<CACFTimingFunctionRef> toCACFTimingFunction(const TimingFunction* timingFunction)
    126 {
    127     ASSERT(timingFunction);
    128     if (timingFunction->isCubicBezierTimingFunction()) {
    129         const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
    130         return RetainPtr<CACFTimingFunctionRef>(AdoptCF, CACFTimingFunctionCreate(static_cast<float>(ctf->x1()), static_cast<float>(ctf->y1()), static_cast<float>(ctf->x2()), static_cast<float>(ctf->y2())));
    131     }
    132 
    133     return CACFTimingFunctionGetFunctionWithName(kCACFTimingFunctionLinear);
    134 }
    135 
    136 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(AnimationType type, const String& keyPath)
    137 {
    138     return adoptRef(new PlatformCAAnimation(type, keyPath));
    139 }
    140 
    141 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(PlatformAnimationRef animation)
    142 {
    143     return adoptRef(new PlatformCAAnimation(animation));
    144 }
    145 
    146 PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath)
    147     : m_type(type)
    148 {
    149     if (type == Basic)
    150         m_animation.adoptCF(CACFAnimationCreate(kCACFBasicAnimation));
    151     else
    152         m_animation.adoptCF(CACFAnimationCreate(kCACFKeyframeAnimation));
    153 
    154     RetainPtr<CFStringRef> s(AdoptCF, keyPath.createCFString());
    155     CACFAnimationSetKeyPath(m_animation.get(), s.get());
    156 }
    157 
    158 PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation)
    159 {
    160     if (CACFAnimationGetClass(animation) == kCACFBasicAnimation)
    161         m_type = Basic;
    162     else if (CACFAnimationGetClass(animation) == kCACFKeyframeAnimation)
    163         m_type = Keyframe;
    164     else {
    165         ASSERT_NOT_REACHED();
    166         return;
    167     }
    168 
    169     m_animation = animation;
    170 }
    171 
    172 PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::copy() const
    173 {
    174     RefPtr<PlatformCAAnimation> animation = create(animationType(), keyPath());
    175 
    176     animation->setBeginTime(beginTime());
    177     animation->setDuration(duration());
    178     animation->setSpeed(speed());
    179     animation->setTimeOffset(timeOffset());
    180     animation->setRepeatCount(repeatCount());
    181     animation->setAutoreverses(autoreverses());
    182     animation->setFillMode(fillMode());
    183     animation->setRemovedOnCompletion(isRemovedOnCompletion());
    184     animation->setAdditive(isAdditive());
    185     animation->copyTimingFunctionFrom(this);
    186     animation->setValueFunction(valueFunction());
    187 
    188     // Copy the specific Basic or Keyframe values
    189     if (animationType() == Keyframe) {
    190         animation->copyValuesFrom(this);
    191         animation->copyKeyTimesFrom(this);
    192         animation->copyTimingFunctionsFrom(this);
    193     } else {
    194         animation->copyFromValueFrom(this);
    195         animation->copyToValueFrom(this);
    196     }
    197 
    198     return animation;
    199 }
    200 
    201 PlatformCAAnimation::~PlatformCAAnimation()
    202 {
    203 }
    204 
    205 bool PlatformCAAnimation::supportsValueFunction()
    206 {
    207     return true;
    208 }
    209 
    210 PlatformAnimationRef PlatformCAAnimation::platformAnimation() const
    211 {
    212     return m_animation.get();
    213 }
    214 
    215 String PlatformCAAnimation::keyPath() const
    216 {
    217     return CACFAnimationGetKeyPath(m_animation.get());
    218 }
    219 
    220 CFTimeInterval PlatformCAAnimation::beginTime() const
    221 {
    222     return CACFAnimationGetBeginTime(m_animation.get());
    223 }
    224 
    225 void PlatformCAAnimation::setBeginTime(CFTimeInterval value)
    226 {
    227     CACFAnimationSetBeginTime(m_animation.get(), value);
    228 }
    229 
    230 CFTimeInterval PlatformCAAnimation::duration() const
    231 {
    232     return CACFAnimationGetDuration(m_animation.get());
    233 }
    234 
    235 void PlatformCAAnimation::setDuration(CFTimeInterval value)
    236 {
    237     CACFAnimationSetDuration(m_animation.get(), value);
    238 }
    239 
    240 float PlatformCAAnimation::speed() const
    241 {
    242     return CACFAnimationGetSpeed(m_animation.get());
    243 }
    244 
    245 void PlatformCAAnimation::setSpeed(float value)
    246 {
    247     CACFAnimationSetSpeed(m_animation.get(), value);
    248 }
    249 
    250 CFTimeInterval PlatformCAAnimation::timeOffset() const
    251 {
    252     return CACFAnimationGetTimeOffset(m_animation.get());
    253 }
    254 
    255 void PlatformCAAnimation::setTimeOffset(CFTimeInterval value)
    256 {
    257     CACFAnimationSetTimeOffset(m_animation.get(), value);
    258 }
    259 
    260 float PlatformCAAnimation::repeatCount() const
    261 {
    262     return CACFAnimationGetRepeatCount(m_animation.get());
    263 }
    264 
    265 void PlatformCAAnimation::setRepeatCount(float value)
    266 {
    267     CACFAnimationSetRepeatCount(m_animation.get(), value);
    268 }
    269 
    270 bool PlatformCAAnimation::autoreverses() const
    271 {
    272     return CACFAnimationGetAutoreverses(m_animation.get());
    273 }
    274 
    275 void PlatformCAAnimation::setAutoreverses(bool value)
    276 {
    277     CACFAnimationSetAutoreverses(m_animation.get(), value);
    278 }
    279 
    280 PlatformCAAnimation::FillModeType PlatformCAAnimation::fillMode() const
    281 {
    282     return fromCACFFillModeType(CACFAnimationGetFillMode(m_animation.get()));
    283 }
    284 
    285 void PlatformCAAnimation::setFillMode(FillModeType value)
    286 {
    287     CACFAnimationSetFillMode(m_animation.get(), toCACFFillModeType(value));
    288 }
    289 
    290 void PlatformCAAnimation::setTimingFunction(const TimingFunction* value)
    291 {
    292     CACFAnimationSetTimingFunction(m_animation.get(), toCACFTimingFunction(value).get());
    293 }
    294 
    295 void PlatformCAAnimation::copyTimingFunctionFrom(const PlatformCAAnimation* value)
    296 {
    297     CACFAnimationSetTimingFunction(m_animation.get(), CACFAnimationGetTimingFunction(value->m_animation.get()));
    298 }
    299 
    300 bool PlatformCAAnimation::isRemovedOnCompletion() const
    301 {
    302     return CACFAnimationIsRemovedOnCompletion(m_animation.get());
    303 }
    304 
    305 void PlatformCAAnimation::setRemovedOnCompletion(bool value)
    306 {
    307     CACFAnimationSetRemovedOnCompletion(m_animation.get(), value);
    308 }
    309 
    310 bool PlatformCAAnimation::isAdditive() const
    311 {
    312     return CACFAnimationIsAdditive(m_animation.get());
    313 }
    314 
    315 void PlatformCAAnimation::setAdditive(bool value)
    316 {
    317     CACFAnimationSetAdditive(m_animation.get(), value);
    318 }
    319 
    320 PlatformCAAnimation::ValueFunctionType PlatformCAAnimation::valueFunction() const
    321 {
    322     return fromCACFValueFunctionType(CACFValueFunctionGetName(CACFAnimationGetValueFunction(m_animation.get())));
    323 }
    324 
    325 void PlatformCAAnimation::setValueFunction(ValueFunctionType value)
    326 {
    327     CACFAnimationSetValueFunction(m_animation.get(), CACFValueFunctionGetFunctionWithName(toCACFValueFunctionType(value)));
    328 }
    329 
    330 void PlatformCAAnimation::setFromValue(float value)
    331 {
    332     if (animationType() != Basic)
    333         return;
    334 
    335     RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value));
    336     CACFAnimationSetFromValue(m_animation.get(), v.get());
    337 }
    338 
    339 void PlatformCAAnimation::setFromValue(const WebCore::TransformationMatrix& value)
    340 {
    341     if (animationType() != Basic)
    342         return;
    343 
    344     RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreateTransform(value));
    345     CACFAnimationSetFromValue(m_animation.get(), v.get());
    346 }
    347 
    348 void PlatformCAAnimation::setFromValue(const FloatPoint3D& value)
    349 {
    350     if (animationType() != Basic)
    351         return;
    352 
    353     float a[3] = { value.x(), value.y(), value.z() };
    354     RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(3, a));
    355     CACFAnimationSetFromValue(m_animation.get(), v.get());
    356 }
    357 
    358 void PlatformCAAnimation::setFromValue(const WebCore::Color& value)
    359 {
    360     if (animationType() != Basic)
    361         return;
    362 
    363     float a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
    364     RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(4, a));
    365     CACFAnimationSetFromValue(m_animation.get(), v.get());
    366 }
    367 
    368 void PlatformCAAnimation::copyFromValueFrom(const PlatformCAAnimation* value)
    369 {
    370     if (animationType() != Basic || value->animationType() != Basic)
    371         return;
    372 
    373     CACFAnimationSetFromValue(m_animation.get(), CACFAnimationGetFromValue(value->platformAnimation()));
    374 }
    375 
    376 void PlatformCAAnimation::setToValue(float value)
    377 {
    378     if (animationType() != Basic)
    379         return;
    380 
    381     RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value));
    382     CACFAnimationSetToValue(m_animation.get(), v.get());
    383 }
    384 
    385 void PlatformCAAnimation::setToValue(const WebCore::TransformationMatrix& value)
    386 {
    387     if (animationType() != Basic)
    388         return;
    389 
    390     RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreateTransform(value));
    391     CACFAnimationSetToValue(m_animation.get(), v.get());
    392 }
    393 
    394 void PlatformCAAnimation::setToValue(const FloatPoint3D& value)
    395 {
    396     if (animationType() != Basic)
    397         return;
    398 
    399     float a[3] = { value.x(), value.y(), value.z() };
    400     RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(3, a));
    401     CACFAnimationSetToValue(m_animation.get(), v.get());
    402 }
    403 
    404 void PlatformCAAnimation::setToValue(const WebCore::Color& value)
    405 {
    406     if (animationType() != Basic)
    407         return;
    408 
    409     float a[4] = { value.red(), value.green(), value.blue(), value.alpha() };
    410     RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(4, a));
    411     CACFAnimationSetToValue(m_animation.get(), v.get());
    412 }
    413 
    414 void PlatformCAAnimation::copyToValueFrom(const PlatformCAAnimation* value)
    415 {
    416     if (animationType() != Basic || value->animationType() != Basic)
    417         return;
    418 
    419     CACFAnimationSetToValue(m_animation.get(), CACFAnimationGetToValue(value->platformAnimation()));
    420 }
    421 
    422 
    423 // Keyframe-animation properties.
    424 void PlatformCAAnimation::setValues(const Vector<float>& value)
    425 {
    426     if (animationType() != Keyframe)
    427         return;
    428 
    429     RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
    430     for (size_t i = 0; i < value.size(); ++i) {
    431         RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i]));
    432         CFArrayAppendValue(array.get(), v.get());
    433     }
    434 
    435     CACFAnimationSetValues(m_animation.get(), array.get());
    436 }
    437 
    438 void PlatformCAAnimation::setValues(const Vector<WebCore::TransformationMatrix>& value)
    439 {
    440     if (animationType() != Keyframe)
    441         return;
    442 
    443     RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
    444     for (size_t i = 0; i < value.size(); ++i) {
    445         RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreateTransform(value[i]));
    446         CFArrayAppendValue(array.get(), v.get());
    447     }
    448 
    449     CACFAnimationSetValues(m_animation.get(), array.get());
    450 }
    451 
    452 void PlatformCAAnimation::setValues(const Vector<FloatPoint3D>& value)
    453 {
    454     if (animationType() != Keyframe)
    455         return;
    456 
    457     RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
    458     for (size_t i = 0; i < value.size(); ++i) {
    459         float a[3] = { value[i].x(), value[i].y(), value[i].z() };
    460         RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(3, a));
    461         CFArrayAppendValue(array.get(), v.get());
    462     }
    463 
    464     CACFAnimationSetValues(m_animation.get(), array.get());
    465 }
    466 
    467 void PlatformCAAnimation::setValues(const Vector<WebCore::Color>& value)
    468 {
    469     if (animationType() != Keyframe)
    470         return;
    471 
    472     RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
    473     for (size_t i = 0; i < value.size(); ++i) {
    474         float a[4] = { value[i].red(), value[i].green(), value[i].blue(), value[i].alpha() };
    475         RetainPtr<CACFVectorRef> v(AdoptCF, CACFVectorCreate(4, a));
    476         CFArrayAppendValue(array.get(), v.get());
    477     }
    478 
    479     CACFAnimationSetValues(m_animation.get(), array.get());
    480 }
    481 
    482 void PlatformCAAnimation::copyValuesFrom(const PlatformCAAnimation* value)
    483 {
    484     if (animationType() != Keyframe || value->animationType() != Keyframe)
    485         return;
    486 
    487     CACFAnimationSetValues(m_animation.get(), CACFAnimationGetValues(value->platformAnimation()));
    488 }
    489 
    490 void PlatformCAAnimation::setKeyTimes(const Vector<float>& value)
    491 {
    492     if (animationType() != Keyframe)
    493         return;
    494 
    495     RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
    496     for (size_t i = 0; i < value.size(); ++i) {
    497         RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i]));
    498         CFArrayAppendValue(array.get(), v.get());
    499     }
    500 
    501     CACFAnimationSetKeyTimes(m_animation.get(), array.get());
    502 }
    503 
    504 void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value)
    505 {
    506     if (animationType() != Keyframe)
    507         return;
    508 
    509     CACFAnimationSetKeyTimes(m_animation.get(), CACFAnimationGetKeyTimes(value->platformAnimation()));
    510 }
    511 
    512 void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value)
    513 {
    514     if (animationType() != Keyframe)
    515         return;
    516 
    517     RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks));
    518     for (size_t i = 0; i < value.size(); ++i) {
    519         RetainPtr<CFNumberRef> v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i]));
    520         CFArrayAppendValue(array.get(), toCACFTimingFunction(value[i]).get());
    521     }
    522 
    523     CACFAnimationSetTimingFunctions(m_animation.get(), array.get());
    524 }
    525 
    526 void PlatformCAAnimation::copyTimingFunctionsFrom(const PlatformCAAnimation* value)
    527 {
    528     CACFAnimationSetTimingFunctions(m_animation.get(), CACFAnimationGetTimingFunctions(value->platformAnimation()));
    529 }
    530 
    531 #endif // USE(ACCELERATED_COMPOSITING)
    532