/*
 Copyright (C) 2007 Eric Seidel <eric@webkit.org>
 
 This file is part of the WebKit project
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
 License as published by the Free Software Foundation; either
 version 2 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Library General Public License for more details.
 
 You should have received a copy of the GNU Library General Public License
 along with this library; see the file COPYING.LIB.  If not, write to
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.
 */

#include "config.h"
#if ENABLE(SVG)
#include "SVGTransformDistance.h"

#include "FloatConversion.h"
#include "FloatPoint.h"
#include "FloatSize.h"
#include "SVGTransform.h"

#include <math.h>

namespace WebCore {
    
SVGTransformDistance::SVGTransformDistance()
    : m_type(SVGTransform::SVG_TRANSFORM_UNKNOWN)
    , m_angle(0)
{
}

SVGTransformDistance::SVGTransformDistance(SVGTransform::SVGTransformType type, double angle, double cx, double cy, const AffineTransform& transform)
    : m_type(type)
    , m_angle(angle)
    , m_cx(cx)
    , m_cy(cy)
    , m_transform(transform)
{
}

SVGTransformDistance::SVGTransformDistance(const SVGTransform& fromSVGTransform, const SVGTransform& toSVGTransform)
    : m_type(fromSVGTransform.type())
    , m_angle(0)
    , m_cx(0)
    , m_cy(0)
{
    ASSERT(m_type == toSVGTransform.type());
    
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return;
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        // FIXME: need to be able to subtract to matrices
        return;
    case SVGTransform::SVG_TRANSFORM_ROTATE:
    {
        FloatSize centerDistance = toSVGTransform.rotationCenter() - fromSVGTransform.rotationCenter();
        m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
        m_cx = centerDistance.width();
        m_cy = centerDistance.height();
        return;
    }
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        FloatSize translationDistance = toSVGTransform.translate() - fromSVGTransform.translate();
        m_transform.translate(translationDistance.width(), translationDistance.height());
        return;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        float scaleX = fromSVGTransform.scale().width() != 0 ? toSVGTransform.scale().width() / fromSVGTransform.scale().width() : toSVGTransform.scale().width() / 0.00001f;
        float scaleY = fromSVGTransform.scale().height() != 0 ? toSVGTransform.scale().height() / fromSVGTransform.scale().height() : toSVGTransform.scale().height() / 0.00001f;
        m_transform.scale(scaleX, scaleY);
        return;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
        return;
    }
}

SVGTransformDistance SVGTransformDistance::scaledDistance(float scaleFactor) const
{
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return SVGTransformDistance();
    case SVGTransform::SVG_TRANSFORM_ROTATE:
        return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform());
    case SVGTransform::SVG_TRANSFORM_SCALE:
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform(m_transform).scale(scaleFactor));
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        AffineTransform newTransform(m_transform);
        newTransform.setE(m_transform.e() * scaleFactor);
        newTransform.setF(m_transform.f() * scaleFactor);
        return SVGTransformDistance(m_type, 0, 0, 0, newTransform);
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform());
    }
    
    ASSERT_NOT_REACHED();
    return SVGTransformDistance();
}

SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform& first, const SVGTransform& second)
{
    ASSERT(first.type() == second.type());
    
    SVGTransform transform;
    
    switch (first.type()) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return SVGTransform();
    case SVGTransform::SVG_TRANSFORM_ROTATE:
    {
        transform.setRotate(first.angle() + second.angle(), first.rotationCenter().x() + second.rotationCenter().x(),
                            first.rotationCenter().y() + second.rotationCenter().y());
        return transform;
    }
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        transform.setMatrix(first.matrix() * second.matrix());
        return transform;
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        float dx = first.translate().x() + second.translate().x();
        float dy = first.translate().y() + second.translate().y();
        transform.setTranslate(dx, dy);
        return transform;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        FloatSize scale = first.scale() + second.scale();
        transform.setScale(scale.width(), scale.height());
        return transform;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
        transform.setSkewX(first.angle() + second.angle());
        return transform;
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        transform.setSkewY(first.angle() + second.angle());
        return transform;
    }
    
    ASSERT_NOT_REACHED();
    return SVGTransform();
}

void SVGTransformDistance::addSVGTransform(const SVGTransform& transform, bool absoluteValue)
{
    // If this is the first add, set the type for this SVGTransformDistance
    if (m_type == SVGTransform::SVG_TRANSFORM_UNKNOWN)
        m_type = transform.type();
    
    ASSERT(m_type == transform.type());
    
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return;
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        m_transform *= transform.matrix(); // FIXME: what does 'distance' between two transforms mean?  how should we respect 'absoluteValue' here?
        return;
    case SVGTransform::SVG_TRANSFORM_ROTATE:
        m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle();
        m_cx += absoluteValue ? fabsf(transform.rotationCenter().x()) : transform.rotationCenter().x();
        m_cy += absoluteValue ? fabsf(transform.rotationCenter().y()) : transform.rotationCenter().y();
        // fall through
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        float dx = absoluteValue ? fabsf(transform.translate().x()) : transform.translate().x();
        float dy = absoluteValue ? fabsf(transform.translate().y()) : transform.translate().y();
        m_transform.translate(dx, dy);
        return;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        float scaleX = absoluteValue ? fabsf(transform.scale().width()) : transform.scale().width();
        float scaleY = absoluteValue ? fabsf(transform.scale().height()) : transform.scale().height();
        m_transform.scale(scaleX, scaleY);
        return;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle();
        return;
    }
    
    ASSERT_NOT_REACHED();
    return;
}

SVGTransform SVGTransformDistance::addToSVGTransform(const SVGTransform& transform) const
{
    ASSERT(m_type == transform.type() || transform == SVGTransform());
    
    SVGTransform newTransform(transform);
    
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return SVGTransform();
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        return SVGTransform(transform.matrix() * m_transform);
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        FloatPoint translation = transform.translate();
        translation += FloatSize::narrowPrecision(m_transform.e(), m_transform.f());
        newTransform.setTranslate(translation.x(), translation.y());
        return newTransform;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        FloatSize scale = transform.scale();
        scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d());
        newTransform.setScale(scale.width(), scale.height());
        return newTransform;
    }
    case SVGTransform::SVG_TRANSFORM_ROTATE:
    {
        // FIXME: I'm not certain the translation is calculated correctly here
        FloatPoint center = transform.rotationCenter();
        newTransform.setRotate(narrowPrecisionToFloat(transform.angle() + m_angle),
                               narrowPrecisionToFloat(center.x() + m_cx),
                               narrowPrecisionToFloat(center.y() + m_cy));
        return newTransform;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
        newTransform.setSkewX(narrowPrecisionToFloat(transform.angle() + m_angle));
        return newTransform;
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        newTransform.setSkewY(narrowPrecisionToFloat(transform.angle() + m_angle));
        return newTransform;
    }
    
    ASSERT_NOT_REACHED();
    return SVGTransform();
}

bool SVGTransformDistance::isZero() const
{
    return (m_transform == AffineTransform() && m_angle == 0);
}

float SVGTransformDistance::distance() const
{
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return 0.0f;
    case SVGTransform::SVG_TRANSFORM_ROTATE:
        return narrowPrecisionToFloat(sqrt(m_angle * m_angle + m_cx * m_cx + m_cy * m_cy));
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        return 0.0f; // I'm not quite sure yet what distance between two matrices means.
    case SVGTransform::SVG_TRANSFORM_SCALE:
        return narrowPrecisionToFloat(sqrt(m_transform.a() * m_transform.a() + m_transform.d() * m_transform.d()));
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
        return narrowPrecisionToFloat(sqrt(m_transform.e() * m_transform.e() + m_transform.f() * m_transform.f()));
    case SVGTransform::SVG_TRANSFORM_SKEWX:
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        return narrowPrecisionToFloat(m_angle);
    }
    ASSERT_NOT_REACHED();
    return 0.0f;
}

}

#endif
