bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
{
    ASSERT(!keyframesName.isEmpty());

    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity))
        return false;

    if (valueList.property() == AnimatedPropertyFilter) {
        int listIndex = validateFilterOperations(valueList);
        if (listIndex < 0)
            return false;

        const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
        if (!filtersCanBeComposited(filters))
            return false;
    }

    bool listsMatch = false;
    bool hasBigRotation;

    if (valueList.property() == AnimatedPropertyTransform)
        listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;

    const double currentTime = monotonicallyIncreasingTime();
    m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, *anim, listsMatch, currentTime - timeOffset, 0, TextureMapperAnimation::AnimationState::Playing));
    // m_animationStartTime is the time of the first real frame of animation, now or delayed by a negative offset.
    if (timeOffset > 0)
        m_animationStartTime = currentTime;
    else
        m_animationStartTime = currentTime - timeOffset;
    notifyChange(AnimationChange);
    notifyChange(AnimationStarted);
    return true;
}
Esempio n. 2
0
bool GraphicsLayerBlackBerry::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& animationName, double timeOffset)
{
    // This is what GraphicsLayerCA checks for.
    if (!animation || animation->isEmptyOrZeroDuration() || values.size() < 2)
        return false;

    // We only support these two kinds of properties at the moment.
    if (values.property() != AnimatedPropertyWebkitTransform && values.property() != AnimatedPropertyOpacity)
        return false;

    // Remove any running animation for the same property.
    // FIXME: Maybe this is superstition, I got the idea from GraphicsLayerQt
    // WebCore might be adding an animation with the same name, but for a different property
    removeAnimationByIdAndProperty(LayerAnimation::idFromAnimation(animation), values.property(), m_runningAnimations);
    removeAnimationByIdAndProperty(LayerAnimation::idFromAnimation(animation), values.property(), m_suspendedAnimations);

    RefPtr<LayerAnimation> layerAnimation = LayerAnimation::create(values, boxSize, animation, animationName, timeOffset);

#if DEBUG_LAYER_ANIMATION
    fprintf(stderr, "LayerAnimation 0x%08x: Adding animation %s for property %d\n", layerAnimation.get(), animationName.latin1().data(), values.property());
#endif

    m_runningAnimations.append(layerAnimation);

    updateAnimations();

    return true;
}
Esempio n. 3
0
bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
                                        const IntSize& boxSize,
                                        const Animation* anim,
                                        const String& keyframesName,
                                        double beginTime)
{
    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
        return false;

    bool createdAnimations = false;
    if (valueList.property() == AnimatedPropertyWebkitTransform) {
        createdAnimations = createTransformAnimationsFromKeyframes(valueList,
                                                                   anim,
                                                                   keyframesName,
                                                                   beginTime,
                                                                   boxSize);
    } else {
        createdAnimations = createAnimationFromKeyframes(valueList,
                                                         anim,
                                                         keyframesName,
                                                         beginTime);
    }
    if (createdAnimations)
        askForSync();
    return createdAnimations;
}
Esempio n. 4
0
int GraphicsLayer::validateFilterOperations(const KeyframeValueList& valueList)
{
    ASSERT(valueList.property() == AnimatedPropertyWebkitFilter);

    if (valueList.size() < 2)
        return -1;

    // Empty filters match anything, so find the first non-empty entry as the reference
    size_t firstIndex = 0;
    for ( ; firstIndex < valueList.size(); ++firstIndex) {
        if (filterOperationsAt(valueList, firstIndex)->operations().size() > 0)
            break;
    }

    if (firstIndex >= valueList.size())
        return -1;

    const FilterOperations* firstVal = filterOperationsAt(valueList, firstIndex);
    
    for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
        const FilterOperations* val = filterOperationsAt(valueList, i);
        
        // An emtpy filter list matches anything.
        if (val->operations().isEmpty())
            continue;
        
        if (!firstVal->operationsMatch(*val))
            return -1;
    }
    
    return firstIndex;
}
Esempio n. 5
0
bool CCLayerAnimationController::addAnimation(const KeyframeValueList& valueList, const IntSize&, const Animation* animation, int animationId, int groupId, double timeOffset)
{
    if (!animation)
        return false;

    OwnPtr<CCActiveAnimation> toAdd;
    if (valueList.property() == AnimatedPropertyWebkitTransform)
        toAdd = createActiveAnimation<TransformAnimationValue, CCTransformKeyframe, CCKeyframedTransformAnimationCurve>(valueList, animation, animationId, groupId, timeOffset, CCActiveAnimation::Transform);
    else if (valueList.property() == AnimatedPropertyOpacity)
        toAdd = createActiveAnimation<FloatAnimationValue, CCFloatKeyframe, CCKeyframedFloatAnimationCurve>(valueList, animation, animationId, groupId, timeOffset, CCActiveAnimation::Opacity);

    if (toAdd.get()) {
        // Remove any existing animations with the same animation id and target property.
        for (size_t i = 0; i < m_activeAnimations.size();) {
            if (m_activeAnimations[i]->id() == animationId && m_activeAnimations[i]->targetProperty() == toAdd->targetProperty())
                m_activeAnimations.remove(i);
            else
                i++;
        }
        m_activeAnimations.append(toAdd.release());
        return true;
    }

    return false;
}
Esempio n. 6
0
PassOwnPtr<WebKit::WebAnimation> createWebAnimation(const KeyframeValueList& values, const Animation* animation, int animationId, double timeOffset, const FloatSize& boxSize)
{
    if (values.property() == AnimatedPropertyWebkitTransform)
        return createWebAnimation<TransformAnimationValue, WebTransformKeyframe, WebTransformAnimationCurve>(values, animation, animationId, timeOffset, WebKit::WebAnimation::TargetPropertyTransform, FloatSize(boxSize));

    if (values.property() == AnimatedPropertyOpacity)
        return createWebAnimation<FloatAnimationValue, WebFloatKeyframe, WebFloatAnimationCurve>(values, animation, animationId, timeOffset, WebKit::WebAnimation::TargetPropertyOpacity, FloatSize());

    return nullptr;
}
PassOwnPtr<WebKit::WebAnimation> createWebAnimation(const KeyframeValueList& values, const CSSAnimationData* animation, int animationId, double timeOffset, const FloatSize& boxSize)
{


    if (values.property() == AnimatedPropertyWebkitTransform) {
        OwnPtr<WebTransformAnimationCurve> curve = adoptPtr(Platform::current()->compositorSupport()->createTransformAnimationCurve());
        return createWebAnimation<TransformAnimationValue, WebTransformKeyframe, WebTransformAnimationCurve>(values, animation, animationId, timeOffset, curve.get(), WebKit::WebAnimation::TargetPropertyTransform, FloatSize(boxSize));
    }

    if (values.property() == AnimatedPropertyOpacity) {
        OwnPtr<WebFloatAnimationCurve> curve = adoptPtr(Platform::current()->compositorSupport()->createFloatAnimationCurve());
        return createWebAnimation<FloatAnimationValue, WebFloatKeyframe, WebFloatAnimationCurve>(values, animation, animationId, timeOffset, curve.get(), WebKit::WebAnimation::TargetPropertyOpacity, FloatSize());
    }

    return nullptr;
}
Esempio n. 8
0
bool WebGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
{
    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
        return false;

    WebLayerAnimation webAnimation(valueList);
    webAnimation.name = keyframesName;
    webAnimation.operation = WebLayerAnimation::AddAnimation;
    webAnimation.boxSize = boxSize;
    webAnimation.animation = Animation::create(anim);
    webAnimation.startTime = timeOffset;
    m_layerInfo.animations.append(webAnimation);

    m_hasPendingAnimations = true;
    notifyChange();

    return true;
}
Esempio n. 9
0
bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
{
    ASSERT(!keyframesName.isEmpty());

    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
        return false;

    bool listsMatch = false;
    bool hasBigRotation;

    if (valueList.property() == AnimatedPropertyWebkitTransform)
        listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;

    m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, WTF::currentTime() - timeOffset, listsMatch));
    notifyChange(TextureMapperLayer::AnimationChange);
    m_animationStartedTimer.startOneShot(0);
    return true;
}
Esempio n. 10
0
bool CCLayerAnimationController::addAnimation(const KeyframeValueList& valueList, const IntSize&, const Animation* animation, int animationId, int groupId, double timeOffset)
{
    if (!animation)
        return false;

    OwnPtr<CCActiveAnimation> toAdd;
    if (valueList.property() == AnimatedPropertyWebkitTransform)
        toAdd = createActiveAnimation<TransformAnimationValue, CCTransformKeyframe, CCKeyframedTransformAnimationCurve>(valueList, animation, animationId, groupId, timeOffset, CCActiveAnimation::Transform);
    else if (valueList.property() == AnimatedPropertyOpacity)
        toAdd = createActiveAnimation<FloatAnimationValue, CCFloatKeyframe, CCKeyframedFloatAnimationCurve>(valueList, animation, animationId, groupId, timeOffset, CCActiveAnimation::Opacity);

    if (toAdd.get()) {
        m_activeAnimations.append(toAdd.release());
        return true;
    }

    return false;
}
bool CoordinatedGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double delayAsNegativeTimeOffset)
{
    ASSERT(!keyframesName.isEmpty());

    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity && valueList.property() != AnimatedPropertyWebkitFilter))
        return false;

    bool listsMatch = false;
    bool ignoredHasBigRotation;

    if (valueList.property() == AnimatedPropertyWebkitTransform)
        listsMatch = validateTransformOperations(valueList, ignoredHasBigRotation) >= 0;

    m_lastAnimationStartTime = monotonicallyIncreasingTime() - delayAsNegativeTimeOffset;
    m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, m_lastAnimationStartTime, listsMatch));
    m_animationStartedTimer.startOneShot(0);
    didChangeAnimations();
    return true;
}
bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
{
    ASSERT(!keyframesName.isEmpty());

    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
        return false;

    for (size_t i = 0; i < m_animations.size(); ++i) {
        // The same animation name can be used for two animations with different properties.
        if (m_animations[i]->name != keyframesName || m_animations[i]->keyframes.property() != valueList.property())
            continue;

        // We already have a copy of this animation, that means that we're resuming it rather than adding it.
        RefPtr<TextureMapperAnimation>& animation = m_animations[i];
        animation->animation = Animation::create(anim);
        animation->paused = false;
        animation->startTime = WTF::currentTime() - timeOffset;
        notifyChange(TextureMapperNode::AnimationChange);
        m_animationStartedTimer.startOneShot(0);
        return true;
    }

    RefPtr<TextureMapperAnimation> animation = TextureMapperAnimation::create(valueList);
    animation->boxSize = boxSize;
    animation->name = keyframesName;
    animation->animation = Animation::create(anim);
    animation->paused = false;
    animation->startTime = WTF::currentTime() - timeOffset;

    if (valueList.property() == AnimatedPropertyWebkitTransform) {
        bool hasBigRotation; // Not used, but required as a pointer parameter for the function.
        fetchTransformOperationList(valueList, animation->functionList, animation->listsMatch, hasBigRotation);
    }

    m_animations.append(animation);
    notifyChange(TextureMapperNode::AnimationChange);
    m_animationStartedTimer.startOneShot(0);

    return true;
}
Esempio n. 13
0
bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList,
                                                                  const Animation* animation,
                                                                  const String& keyframesName,
                                                                  double beginTime,
                                                                  const IntSize& boxSize)
{
    ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
    TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
        keyframesName.latin1().data(), beginTime);

    KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
    for (unsigned int i = 0; i < valueList.size(); i++) {
        TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i);
        PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
        TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(),
                                                                     originalValue->value(),
                                                                     timingFunction);
        operationsList->insert(value);
    }

    RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation,
                                                                               operationsList,
                                                                               beginTime);

    if (keyframesName.isEmpty())
        anim->setName(propertyIdToString(valueList.property()));
    else
        anim->setName(keyframesName);


    m_contentLayer->addAnimation(anim.release());

    needsNotifyClient();
    return true;
}
bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
{
    ASSERT(!keyframesName.isEmpty());

    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
        return false;

    bool listsMatch = false;
    bool hasBigRotation;

    if (valueList.property() == AnimatedPropertyWebkitTransform)
        listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;

    const double currentTime = WTF::currentTime();
    m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, currentTime - timeOffset, listsMatch));
    // m_animationStartTime is the time of the first real frame of animation, now or delayed by a negative offset.
    if (timeOffset > 0)
        m_animationStartTime = currentTime;
    else
        m_animationStartTime = currentTime - timeOffset;
    notifyChange(AnimationChange);
    notifyChange(AnimationStarted);
    return true;
}
Esempio n. 15
0
bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& valueList,
     const Animation* animation, const String& keyframesName, double beginTime)
{
    bool isKeyframe = valueList.size() > 2;
    TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
        isKeyframe, keyframesName.latin1().data(), beginTime);

    switch (valueList.property()) {
    case AnimatedPropertyInvalid: break;
    case AnimatedPropertyWebkitTransform: break;
    case AnimatedPropertyBackgroundColor: break;
    case AnimatedPropertyOpacity: {
        MLOG("ANIMATEDPROPERTYOPACITY");

        KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity);
        for (unsigned int i = 0; i < valueList.size(); i++) {
            FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i);
            PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
            FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(),
                                                                 originalValue->value(),
                                                                 timingFunction);
            operationsList->insert(value);
        }

        RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation,
                                                                               operationsList,
                                                                               beginTime);
        if (keyframesName.isEmpty())
            anim->setName(propertyIdToString(valueList.property()));
        else
            anim->setName(keyframesName);

        m_contentLayer->addAnimation(anim.release());
        needsNotifyClient();
        return true;
    } break;
    }
    return false;
}
Esempio n. 16
0
int GraphicsLayer::validateFilterOperations(const KeyframeValueList& valueList)
{
#if ENABLE(FILTERS_LEVEL_2)
    ASSERT(valueList.property() == AnimatedPropertyFilter || valueList.property() == AnimatedPropertyWebkitBackdropFilter);
#else
    ASSERT(valueList.property() == AnimatedPropertyFilter);
#endif

    if (valueList.size() < 2)
        return -1;

    // Empty filters match anything, so find the first non-empty entry as the reference
    size_t firstIndex = 0;
    for ( ; firstIndex < valueList.size(); ++firstIndex) {
        if (!filterOperationsAt(valueList, firstIndex).operations().isEmpty())
            break;
    }

    if (firstIndex >= valueList.size())
        return -1;

    const FilterOperations& firstVal = filterOperationsAt(valueList, firstIndex);
    
    for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
        const FilterOperations& val = filterOperationsAt(valueList, i);
        
        // An emtpy filter list matches anything.
        if (val.operations().isEmpty())
            continue;
        
        if (!firstVal.operationsMatch(val))
            return -1;
    }
    
    return firstIndex;
}
Esempio n. 17
0
void GraphicsLayer::fetchTransformOperationList(const KeyframeValueList& valueList, TransformOperationList& list, bool& isValid, bool& hasBigRotation)
{
    ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);

    list.clear();
    isValid = false;
    hasBigRotation = false;
    
    if (valueList.size() < 2)
        return;
    
    // Empty transforms match anything, so find the first non-empty entry as the reference.
    size_t firstIndex = 0;
    for ( ; firstIndex < valueList.size(); ++firstIndex) {
        if (operationsAt(valueList, firstIndex)->operations().size() > 0)
            break;
    }
    
    if (firstIndex >= valueList.size())
        return;
        
    const TransformOperations* firstVal = operationsAt(valueList, firstIndex);
    
    // See if the keyframes are valid.
    for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
        const TransformOperations* val = operationsAt(valueList, i);
        
        // a null transform matches anything
        if (val->operations().isEmpty())
            continue;
            
        if (firstVal->operations().size() != val->operations().size())
            return;
            
        for (size_t j = 0; j < firstVal->operations().size(); ++j) {
            if (!firstVal->operations().at(j)->isSameType(*val->operations().at(j)))
                return;
        }
    }

    // Keyframes are valid, fill in the list.
    isValid = true;
    
    double lastRotAngle = 0.0;
    double maxRotAngle = -1.0;
        
    list.resize(firstVal->operations().size());
    for (size_t j = 0; j < firstVal->operations().size(); ++j) {
        TransformOperation::OperationType type = firstVal->operations().at(j)->getOperationType();
        list[j] = type;
        
        // if this is a rotation entry, we need to see if any angle differences are >= 180 deg
        if (type == TransformOperation::ROTATE_X ||
            type == TransformOperation::ROTATE_Y ||
            type == TransformOperation::ROTATE_Z ||
            type == TransformOperation::ROTATE_3D) {
            lastRotAngle = static_cast<RotateTransformOperation*>(firstVal->operations().at(j).get())->angle();
            
            if (maxRotAngle < 0)
                maxRotAngle = fabs(lastRotAngle);
            
            for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
                const TransformOperations* val = operationsAt(valueList, i);
                double rotAngle = val->operations().isEmpty() ? 0 : (static_cast<RotateTransformOperation*>(val->operations().at(j).get())->angle());
                double diffAngle = fabs(rotAngle - lastRotAngle);
                if (diffAngle > maxRotAngle)
                    maxRotAngle = diffAngle;
                lastRotAngle = rotAngle;
            }
        }
    }
    
    hasBigRotation = maxRotAngle >= 180.0;
}
PassOwnPtr<WebKit::WebAnimation> createWebAnimation(const KeyframeValueList& valueList, const CSSAnimationData* animation, int animationId, double timeOffset, Curve* curve, WebKit::WebAnimation::TargetProperty targetProperty, const FloatSize& boxSize)
{
    bool alternate = false;
    bool reverse = false;
    if (animation && animation->isDirectionSet()) {
        CSSAnimationData::AnimationDirection direction = animation->direction();
        if (direction == CSSAnimationData::AnimationDirectionAlternate || direction == CSSAnimationData::AnimationDirectionAlternateReverse)
            alternate = true;
        if (direction == CSSAnimationData::AnimationDirectionReverse || direction == CSSAnimationData::AnimationDirectionAlternateReverse)
            reverse = true;
    }

    for (size_t i = 0; i < valueList.size(); i++) {
        size_t index = reverse ? valueList.size() - i - 1 : i;
        const Value* originalValue = static_cast<const Value*>(valueList.at(index));
        const Value* lastOriginalValue = 0;
        if (valueList.size() > 1 && ((reverse && index + 1 < valueList.size()) || (!reverse && index > 0)))
            lastOriginalValue = static_cast<const Value*>(valueList.at(reverse ? index + 1 : index - 1));

        const TimingFunction* originalTimingFunction = originalValue->timingFunction();

        // If there hasn't been a timing function associated with this keyframe, use the
        // animation's timing function, if we have one.
        if (!originalTimingFunction && animation->isTimingFunctionSet())
            originalTimingFunction = animation->timingFunction().get();

        // Ease is the default timing function.
        WebKit::WebAnimationCurve::TimingFunctionType timingFunctionType = WebKit::WebAnimationCurve::TimingFunctionTypeEase;

        bool isUsingCustomBezierTimingFunction = false;
        double x1 = 0;
        double y1 = 0;
        double x2 = 1;
        double y2 = 1;

        if (originalTimingFunction) {
            switch (originalTimingFunction->type()) {
            case TimingFunction::StepsFunction:
                // FIXME: add support for steps timing function.
                return nullptr;
            case TimingFunction::LinearFunction:
                timingFunctionType = WebKit::WebAnimationCurve::TimingFunctionTypeLinear;
                break;
            case TimingFunction::CubicBezierFunction:
                const CubicBezierTimingFunction* originalBezierTimingFunction = static_cast<const CubicBezierTimingFunction*>(originalTimingFunction);
                isUsingCustomBezierTimingFunction = true;
                x1 = originalBezierTimingFunction->x1();
                y1 = originalBezierTimingFunction->y1();
                x2 = originalBezierTimingFunction->x2();
                y2 = originalBezierTimingFunction->y2();
                break;
            } // switch
        }

        double duration = (animation && animation->isDurationSet()) ? animation->duration() : 1;
        double keyTime = originalValue->keyTime() * duration;

        if (reverse)
            keyTime = duration - keyTime;

        bool addedKeyframe = false;
        if (isUsingCustomBezierTimingFunction)
            addedKeyframe = appendKeyframeWithCustomBezierTimingFunction<Value, Keyframe, Curve>(curve, keyTime, originalValue, lastOriginalValue, x1, y1, x2, y2, boxSize);
        else
            addedKeyframe = appendKeyframeWithStandardTimingFunction<Value, Keyframe, Curve>(curve, keyTime, originalValue, lastOriginalValue, timingFunctionType, boxSize);
        if (!addedKeyframe)
            return nullptr;
    }

    OwnPtr<WebKit::WebAnimation> webAnimation = adoptPtr(Platform::current()->compositorSupport()->createAnimation(*curve, targetProperty, animationId));

    int iterations = (animation && animation->isIterationCountSet()) ? animation->iterationCount() : 1;
    webAnimation->setIterations(iterations);
    webAnimation->setAlternatesDirection(alternate);

    // If timeOffset > 0, then the animation has started in the past.
    webAnimation->setTimeOffset(timeOffset);

    return webAnimation.release();
}
Esempio n. 19
0
int GraphicsLayer::validateTransformOperations(const KeyframeValueList& valueList, bool& hasBigRotation)
{
    ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);

    hasBigRotation = false;
    
    if (valueList.size() < 2)
        return -1;
    
    // Empty transforms match anything, so find the first non-empty entry as the reference.
    size_t firstIndex = 0;
    for ( ; firstIndex < valueList.size(); ++firstIndex) {
        if (operationsAt(valueList, firstIndex)->operations().size() > 0)
            break;
    }
    
    if (firstIndex >= valueList.size())
        return -1;
        
    const TransformOperations* firstVal = operationsAt(valueList, firstIndex);
    
    // See if the keyframes are valid.
    for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
        const TransformOperations* val = operationsAt(valueList, i);
        
        // An emtpy transform list matches anything.
        if (val->operations().isEmpty())
            continue;
            
        if (!firstVal->operationsMatch(*val))
            return -1;
    }

    // Keyframes are valid, check for big rotations.    
    double lastRotAngle = 0.0;
    double maxRotAngle = -1.0;
        
    for (size_t j = 0; j < firstVal->operations().size(); ++j) {
        TransformOperation::OperationType type = firstVal->operations().at(j)->getOperationType();
        
        // if this is a rotation entry, we need to see if any angle differences are >= 180 deg
        if (type == TransformOperation::ROTATE_X ||
            type == TransformOperation::ROTATE_Y ||
            type == TransformOperation::ROTATE_Z ||
            type == TransformOperation::ROTATE_3D) {
            lastRotAngle = static_cast<RotateTransformOperation*>(firstVal->operations().at(j).get())->angle();
            
            if (maxRotAngle < 0)
                maxRotAngle = fabs(lastRotAngle);
            
            for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
                const TransformOperations* val = operationsAt(valueList, i);
                double rotAngle = val->operations().isEmpty() ? 0 : (static_cast<RotateTransformOperation*>(val->operations().at(j).get())->angle());
                double diffAngle = fabs(rotAngle - lastRotAngle);
                if (diffAngle > maxRotAngle)
                    maxRotAngle = diffAngle;
                lastRotAngle = rotAngle;
            }
        }
    }
    
    hasBigRotation = maxRotAngle >= 180.0;
    
    return firstIndex;
}