/* * Copyright (C) 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #if USE(ACCELERATED_COMPOSITING) #include "PlatformCAAnimation.h" #include "FloatConversion.h" #include "PlatformString.h" #include "TimingFunction.h" #include #include #include #include #include #include using namespace WebCore; static String toCACFFillModeType(PlatformCAAnimation::FillModeType type) { switch (type) { case PlatformCAAnimation::NoFillMode: case PlatformCAAnimation::Forwards: return kCACFFillModeForwards; case PlatformCAAnimation::Backwards: return kCACFFillModeBackwards; case PlatformCAAnimation::Both: return kCACFFillModeBoth; } return ""; } static PlatformCAAnimation::FillModeType fromCACFFillModeType(const String& string) { if (string == kCACFFillModeBackwards) return PlatformCAAnimation::Backwards; if (string == kCACFFillModeBoth) return PlatformCAAnimation::Both; return PlatformCAAnimation::Forwards; } static String toCACFValueFunctionType(PlatformCAAnimation::ValueFunctionType type) { switch (type) { case PlatformCAAnimation::NoValueFunction: return ""; case PlatformCAAnimation::RotateX: return kCACFValueFunctionRotateX; case PlatformCAAnimation::RotateY: return kCACFValueFunctionRotateY; case PlatformCAAnimation::RotateZ: return kCACFValueFunctionRotateZ; case PlatformCAAnimation::ScaleX: return kCACFValueFunctionScaleX; case PlatformCAAnimation::ScaleY: return kCACFValueFunctionScaleY; case PlatformCAAnimation::ScaleZ: return kCACFValueFunctionScaleZ; case PlatformCAAnimation::Scale: return kCACFValueFunctionScale; case PlatformCAAnimation::TranslateX: return kCACFValueFunctionTranslateX; case PlatformCAAnimation::TranslateY: return kCACFValueFunctionTranslateY; case PlatformCAAnimation::TranslateZ: return kCACFValueFunctionTranslateZ; case PlatformCAAnimation::Translate: return kCACFValueFunctionTranslate; } return ""; } static PlatformCAAnimation::ValueFunctionType fromCACFValueFunctionType(const String string) { if (string == kCACFValueFunctionRotateX) return PlatformCAAnimation::RotateX; if (string == kCACFValueFunctionRotateY) return PlatformCAAnimation::RotateY; if (string == kCACFValueFunctionRotateZ) return PlatformCAAnimation::RotateZ; if (string == kCACFValueFunctionScaleX) return PlatformCAAnimation::ScaleX; if (string == kCACFValueFunctionScaleY) return PlatformCAAnimation::ScaleY; if (string == kCACFValueFunctionScaleZ) return PlatformCAAnimation::ScaleZ; if (string == kCACFValueFunctionScale) return PlatformCAAnimation::Scale; if (string == kCACFValueFunctionTranslateX) return PlatformCAAnimation::TranslateX; if (string == kCACFValueFunctionTranslateY) return PlatformCAAnimation::TranslateY; if (string == kCACFValueFunctionTranslateZ) return PlatformCAAnimation::TranslateZ; if (string == kCACFValueFunctionTranslate) return PlatformCAAnimation::Translate; return PlatformCAAnimation::NoValueFunction; } static CACFTimingFunctionRef toCACFTimingFunction(const TimingFunction* timingFunction) { if (!timingFunction) return CACFTimingFunctionCreate(0.25f, 0.1f, 0.25f, 0.1f); if (timingFunction->isCubicBezierTimingFunction()) { const CubicBezierTimingFunction* ctf = static_cast(timingFunction); return CACFTimingFunctionCreate(static_cast(ctf->x1()), static_cast(ctf->y1()), static_cast(ctf->x2()), static_cast(ctf->y2())); } return CACFTimingFunctionGetFunctionWithName(kCACFTimingFunctionLinear); } PassRefPtr PlatformCAAnimation::create(AnimationType type, const String& keyPath) { return adoptRef(new PlatformCAAnimation(type, keyPath)); } PassRefPtr PlatformCAAnimation::create(PlatformAnimationRef animation) { return adoptRef(new PlatformCAAnimation(animation)); } PassRefPtr PlatformCAAnimation::create(const PlatformCAAnimation* animation) { return adoptRef(new PlatformCAAnimation(animation)); } PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath) : m_type(type) { if (type == Basic) m_animation.adoptCF(CACFAnimationCreate(kCACFBasicAnimation)); else m_animation.adoptCF(CACFAnimationCreate(kCACFKeyframeAnimation)); RetainPtr s(AdoptCF, keyPath.createCFString()); CACFAnimationSetKeyPath(m_animation.get(), s.get()); } PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation) { if (String(CACFAnimationGetClass(animation)) == kCACFBasicAnimation) m_type = Basic; else if (String(CACFAnimationGetClass(animation)) == kCACFKeyframeAnimation) m_type = Keyframe; else { ASSERT(0); return; } m_animation = animation; } PlatformCAAnimation::PlatformCAAnimation(const PlatformCAAnimation* animation) { m_animation.adoptCF(CACFAnimationCreate((animation->animationType() == Basic) ? kCACFBasicAnimation : kCACFKeyframeAnimation)); RetainPtr keyPath(AdoptCF, animation->keyPath().createCFString()); CACFAnimationSetKeyPath(m_animation.get(), keyPath.get()); setBeginTime(animation->beginTime()); setDuration(animation->duration()); setSpeed(animation->speed()); setTimeOffset(animation->timeOffset()); setRepeatCount(animation->repeatCount()); setAutoreverses(animation->autoreverses()); setFillMode(animation->fillMode()); setRemovedOnCompletion(animation->isRemovedOnCompletion()); setAdditive(animation->isAdditive()); copyTimingFunctionFrom(animation); setValueFunction(animation->valueFunction()); // Copy the specific Basic or Keyframe values if (animation->animationType() == Keyframe) { copyValuesFrom(animation); copyKeyTimesFrom(animation); copyTimingFunctionsFrom(animation); } else { copyFromValueFrom(animation); copyToValueFrom(animation); } } PlatformCAAnimation::~PlatformCAAnimation() { } bool PlatformCAAnimation::supportsValueFunction() { return true; } PlatformAnimationRef PlatformCAAnimation::platformAnimation() const { return m_animation.get(); } String PlatformCAAnimation::keyPath() const { return CACFAnimationGetKeyPath(m_animation.get()); } CFTimeInterval PlatformCAAnimation::beginTime() const { return CACFAnimationGetBeginTime(m_animation.get()); } void PlatformCAAnimation::setBeginTime(CFTimeInterval value) { CACFAnimationSetBeginTime(m_animation.get(), value); } CFTimeInterval PlatformCAAnimation::duration() const { return CACFAnimationGetDuration(m_animation.get()); } void PlatformCAAnimation::setDuration(CFTimeInterval value) { CACFAnimationSetDuration(m_animation.get(), value); } float PlatformCAAnimation::speed() const { return CACFAnimationGetSpeed(m_animation.get()); } void PlatformCAAnimation::setSpeed(float value) { CACFAnimationSetSpeed(m_animation.get(), value); } CFTimeInterval PlatformCAAnimation::timeOffset() const { return CACFAnimationGetTimeOffset(m_animation.get()); } void PlatformCAAnimation::setTimeOffset(CFTimeInterval value) { CACFAnimationSetTimeOffset(m_animation.get(), value); } float PlatformCAAnimation::repeatCount() const { return CACFAnimationGetRepeatCount(m_animation.get()); } void PlatformCAAnimation::setRepeatCount(float value) { CACFAnimationSetRepeatCount(m_animation.get(), value); } bool PlatformCAAnimation::autoreverses() const { return CACFAnimationGetAutoreverses(m_animation.get()); } void PlatformCAAnimation::setAutoreverses(bool value) { CACFAnimationSetAutoreverses(m_animation.get(), value); } PlatformCAAnimation::FillModeType PlatformCAAnimation::fillMode() const { return fromCACFFillModeType(CACFAnimationGetFillMode(m_animation.get())); } void PlatformCAAnimation::setFillMode(FillModeType value) { RetainPtr keyPath(AdoptCF, toCACFFillModeType(value).createCFString()); CACFAnimationSetFillMode(m_animation.get(), keyPath.get()); } void PlatformCAAnimation::setTimingFunction(const TimingFunction* value) { CACFAnimationSetTimingFunction(m_animation.get(), toCACFTimingFunction(value)); } void PlatformCAAnimation::copyTimingFunctionFrom(const PlatformCAAnimation* value) { CACFAnimationSetTimingFunction(m_animation.get(), CACFAnimationGetTimingFunction(value->m_animation.get())); } bool PlatformCAAnimation::isRemovedOnCompletion() const { return CACFAnimationIsRemovedOnCompletion(m_animation.get()); } void PlatformCAAnimation::setRemovedOnCompletion(bool value) { CACFAnimationSetRemovedOnCompletion(m_animation.get(), value); } bool PlatformCAAnimation::isAdditive() const { return CACFAnimationIsAdditive(m_animation.get()); } void PlatformCAAnimation::setAdditive(bool value) { CACFAnimationSetAdditive(m_animation.get(), value); } PlatformCAAnimation::ValueFunctionType PlatformCAAnimation::valueFunction() const { return fromCACFValueFunctionType(CACFValueFunctionGetName(CACFAnimationGetValueFunction(m_animation.get()))); } void PlatformCAAnimation::setValueFunction(ValueFunctionType value) { RetainPtr keyPath(AdoptCF, toCACFValueFunctionType(value).createCFString()); CACFAnimationSetValueFunction(m_animation.get(), CACFValueFunctionGetFunctionWithName(keyPath.get())); } void PlatformCAAnimation::setFromValue(float value) { if (animationType() != Basic) return; RetainPtr v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value)); CACFAnimationSetFromValue(m_animation.get(), v.get()); } void PlatformCAAnimation::setFromValue(const WebCore::TransformationMatrix& value) { if (animationType() != Basic) return; RetainPtr v(AdoptCF, CACFVectorCreateTransform(value)); CACFAnimationSetFromValue(m_animation.get(), v.get()); } void PlatformCAAnimation::setFromValue(const FloatPoint3D& value) { if (animationType() != Basic) return; float a[3] = { value.x(), value.y(), value.z() }; RetainPtr v(AdoptCF, CACFVectorCreate(3, a)); CACFAnimationSetFromValue(m_animation.get(), v.get()); } void PlatformCAAnimation::setFromValue(const WebCore::Color& value) { if (animationType() != Basic) return; float a[4] = { value.red(), value.green(), value.blue(), value.alpha() }; RetainPtr v(AdoptCF, CACFVectorCreate(4, a)); CACFAnimationSetFromValue(m_animation.get(), v.get()); } void PlatformCAAnimation::copyFromValueFrom(const PlatformCAAnimation* value) { if (animationType() != Basic || value->animationType() != Basic) return; CACFAnimationSetFromValue(m_animation.get(), CACFAnimationGetFromValue(value->platformAnimation())); } void PlatformCAAnimation::setToValue(float value) { if (animationType() != Basic) return; RetainPtr v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value)); CACFAnimationSetToValue(m_animation.get(), v.get()); } void PlatformCAAnimation::setToValue(const WebCore::TransformationMatrix& value) { if (animationType() != Basic) return; RetainPtr v(AdoptCF, CACFVectorCreateTransform(value)); CACFAnimationSetToValue(m_animation.get(), v.get()); } void PlatformCAAnimation::setToValue(const FloatPoint3D& value) { if (animationType() != Basic) return; float a[3] = { value.x(), value.y(), value.z() }; RetainPtr v(AdoptCF, CACFVectorCreate(3, a)); CACFAnimationSetToValue(m_animation.get(), v.get()); } void PlatformCAAnimation::setToValue(const WebCore::Color& value) { if (animationType() != Basic) return; float a[4] = { value.red(), value.green(), value.blue(), value.alpha() }; RetainPtr v(AdoptCF, CACFVectorCreate(4, a)); CACFAnimationSetToValue(m_animation.get(), v.get()); } void PlatformCAAnimation::copyToValueFrom(const PlatformCAAnimation* value) { if (animationType() != Basic || value->animationType() != Basic) return; CACFAnimationSetToValue(m_animation.get(), CACFAnimationGetToValue(value->platformAnimation())); } // Keyframe-animation properties. void PlatformCAAnimation::setValues(const Vector& value) { if (animationType() != Keyframe) return; RetainPtr array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks)); for (size_t i = 0; i < value.size(); ++i) { RetainPtr v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i])); CFArrayAppendValue(array.get(), v.get()); } CACFAnimationSetValues(m_animation.get(), array.get()); } void PlatformCAAnimation::setValues(const Vector& value) { if (animationType() != Keyframe) return; RetainPtr array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks)); for (size_t i = 0; i < value.size(); ++i) { RetainPtr v(AdoptCF, CACFVectorCreateTransform(value[i])); CFArrayAppendValue(array.get(), v.get()); } CACFAnimationSetValues(m_animation.get(), array.get()); } void PlatformCAAnimation::setValues(const Vector& value) { if (animationType() != Keyframe) return; RetainPtr array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks)); for (size_t i = 0; i < value.size(); ++i) { float a[3] = { value[i].x(), value[i].y(), value[i].z() }; RetainPtr v(AdoptCF, CACFVectorCreate(3, a)); CFArrayAppendValue(array.get(), v.get()); } CACFAnimationSetValues(m_animation.get(), array.get()); } void PlatformCAAnimation::setValues(const Vector& value) { if (animationType() != Keyframe) return; RetainPtr array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks)); for (size_t i = 0; i < value.size(); ++i) { float a[4] = { value[i].red(), value[i].green(), value[i].blue(), value[i].alpha() }; RetainPtr v(AdoptCF, CACFVectorCreate(4, a)); CFArrayAppendValue(array.get(), v.get()); } CACFAnimationSetValues(m_animation.get(), array.get()); } void PlatformCAAnimation::copyValuesFrom(const PlatformCAAnimation* value) { if (animationType() != Keyframe || value->animationType() != Keyframe) return; CACFAnimationSetValues(m_animation.get(), CACFAnimationGetValues(value->platformAnimation())); } void PlatformCAAnimation::setKeyTimes(const Vector& value) { if (animationType() != Keyframe) return; RetainPtr array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks)); for (size_t i = 0; i < value.size(); ++i) { RetainPtr v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i])); CFArrayAppendValue(array.get(), v.get()); } CACFAnimationSetKeyTimes(m_animation.get(), array.get()); } void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value) { if (animationType() != Keyframe) return; CACFAnimationSetKeyTimes(m_animation.get(), CACFAnimationGetKeyTimes(value->platformAnimation())); } void PlatformCAAnimation::setTimingFunctions(const Vector& value) { if (animationType() != Keyframe) return; RetainPtr array(AdoptCF, CFArrayCreateMutable(0, value.size(), &kCFTypeArrayCallBacks)); for (size_t i = 0; i < value.size(); ++i) { RetainPtr v(AdoptCF, CFNumberCreate(0, kCFNumberFloatType, &value[i])); CFArrayAppendValue(array.get(), toCACFTimingFunction(value[i])); } CACFAnimationSetTimingFunctions(m_animation.get(), array.get()); } void PlatformCAAnimation::copyTimingFunctionsFrom(const PlatformCAAnimation* value) { CACFAnimationSetTimingFunctions(m_animation.get(), CACFAnimationGetTimingFunctions(value->platformAnimation())); } #endif // USE(ACCELERATED_COMPOSITING)