/*
 * Copyright (C) 2013 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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"
#include "core/animation/AnimatableColor.h"

#include "core/platform/animation/AnimationUtilities.h"
#include "wtf/MathExtras.h"

namespace WebCore {

AnimatableColorImpl::AnimatableColorImpl(float red, float green, float blue, float alpha)
    : m_alpha(clampTo(alpha, 0.0f, 1.0f))
    , m_red(clampTo(red, 0.0f, 1.0f))
    , m_green(clampTo(green, 0.0f, 1.0f))
    , m_blue(clampTo(blue, 0.0f, 1.0f))
{
}

AnimatableColorImpl::AnimatableColorImpl(Color color)
    : m_alpha(color.alpha() / 255.0f)
    , m_red(color.red() / 255.0f * m_alpha)
    , m_green(color.green() / 255.0f * m_alpha)
    , m_blue(color.blue() / 255.0f * m_alpha)
{
}

Color AnimatableColorImpl::toColor() const
{
    if (!m_alpha)
        return Color();
    return Color(m_red / m_alpha, m_green / m_alpha, m_blue / m_alpha, m_alpha);
}

AnimatableColorImpl AnimatableColorImpl::interpolateTo(const AnimatableColorImpl& to, double fraction) const
{
    return AnimatableColorImpl(blend(m_red, to.m_red, fraction),
        blend(m_green, to.m_green, fraction),
        blend(m_blue, to.m_blue, fraction),
        blend(m_alpha, to.m_alpha, fraction));
}

AnimatableColorImpl AnimatableColorImpl::addWith(const AnimatableColorImpl& addend) const
{
    return AnimatableColorImpl(m_red + addend.m_red,
        m_green + addend.m_green,
        m_blue + addend.m_blue,
        m_alpha + addend.m_alpha);
}

PassRefPtr<AnimatableColor> AnimatableColor::create(const AnimatableColorImpl& color, const AnimatableColorImpl& visitedLinkColor)
{
    return adoptRef(new AnimatableColor(color, visitedLinkColor));
}

PassRefPtr<AnimatableValue> AnimatableColor::interpolateTo(const AnimatableValue* value, double fraction) const
{
    const AnimatableColor* color = toAnimatableColor(value);
    return create(m_color.interpolateTo(color->m_color, fraction),
        m_visitedLinkColor.interpolateTo(color->m_visitedLinkColor, fraction));
}

PassRefPtr<AnimatableValue> AnimatableColor::addWith(const AnimatableValue* value) const
{
    const AnimatableColor* color = toAnimatableColor(value);
    return create(m_color.addWith(color->m_color),
        m_visitedLinkColor.addWith(color->m_visitedLinkColor));
}

} // namespace WebCore
