/*
 * Copyright (C) 2005-2016 Apple Inc.  All rights reserved.
 *               2010 Dirk Schulze <krit@webkit.org>
 *
 * 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 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. 
 */

#ifndef AffineTransform_h
#define AffineTransform_h

#include <array>
#include <wtf/FastMalloc.h>
#include <wtf/Forward.h>

#if USE(CG)
typedef struct CGAffineTransform CGAffineTransform;
#endif

#if PLATFORM(WIN)
struct D2D_MATRIX_3X2_F;
typedef D2D_MATRIX_3X2_F D2D1_MATRIX_3X2_F;
#endif

namespace WTF {
class TextStream;
}

namespace WebCore {

class FloatPoint;
class FloatQuad;
class FloatRect;
class FloatSize;
class IntPoint;
class IntSize;
class IntRect;
class Region;
class TransformationMatrix;

class AffineTransform {
    WTF_MAKE_FAST_ALLOCATED;
public:
    WEBCORE_EXPORT AffineTransform();
    WEBCORE_EXPORT AffineTransform(double a, double b, double c, double d, double e, double f);

#if USE(CG)
    WEBCORE_EXPORT AffineTransform(const CGAffineTransform&);
#endif

#if PLATFORM(WIN)
    AffineTransform(const D2D1_MATRIX_3X2_F&);
#endif

    void setMatrix(double a, double b, double c, double d, double e, double f);

    void map(double x, double y, double& x2, double& y2) const;

    // Rounds the mapped point to the nearest integer value.
    WEBCORE_EXPORT IntPoint mapPoint(const IntPoint&) const;

    WEBCORE_EXPORT FloatPoint mapPoint(const FloatPoint&) const;

    WEBCORE_EXPORT IntSize mapSize(const IntSize&) const;

    WEBCORE_EXPORT FloatSize mapSize(const FloatSize&) const;

    // Rounds the resulting mapped rectangle out. This is helpful for bounding
    // box computations but may not be what is wanted in other contexts.
    WEBCORE_EXPORT IntRect mapRect(const IntRect&) const;

    WEBCORE_EXPORT FloatRect mapRect(const FloatRect&) const;
    WEBCORE_EXPORT FloatQuad mapQuad(const FloatQuad&) const;

    WEBCORE_EXPORT Region mapRegion(const Region&) const;

    WEBCORE_EXPORT bool isIdentity() const;

    double a() const { return m_transform[0]; }
    void setA(double a) { m_transform[0] = a; }
    double b() const { return m_transform[1]; }
    void setB(double b) { m_transform[1] = b; }
    double c() const { return m_transform[2]; }
    void setC(double c) { m_transform[2] = c; }
    double d() const { return m_transform[3]; }
    void setD(double d) { m_transform[3] = d; }
    double e() const { return m_transform[4]; }
    void setE(double e) { m_transform[4] = e; }
    double f() const { return m_transform[5]; }
    void setF(double f) { m_transform[5] = f; }

    WEBCORE_EXPORT void makeIdentity();

    WEBCORE_EXPORT AffineTransform& multiply(const AffineTransform& other);
    WEBCORE_EXPORT AffineTransform& scale(double);
    AffineTransform& scale(double sx, double sy); 
    WEBCORE_EXPORT AffineTransform& scaleNonUniform(double sx, double sy); // Same as scale(sx, sy).
    WEBCORE_EXPORT AffineTransform& scale(const FloatSize&);
    WEBCORE_EXPORT AffineTransform& rotate(double);
    AffineTransform& rotateFromVector(double x, double y);
    WEBCORE_EXPORT AffineTransform& translate(double tx, double ty);
    WEBCORE_EXPORT AffineTransform& translate(const FloatPoint&);
    WEBCORE_EXPORT AffineTransform& translate(const FloatSize&);
    WEBCORE_EXPORT AffineTransform& shear(double sx, double sy);
    WEBCORE_EXPORT AffineTransform& flipX();
    WEBCORE_EXPORT AffineTransform& flipY();
    WEBCORE_EXPORT AffineTransform& skew(double angleX, double angleY);
    AffineTransform& skewX(double angle);
    AffineTransform& skewY(double angle);

    // These functions get the length of an axis-aligned unit vector
    // once it has been mapped through the transform
    WEBCORE_EXPORT double xScale() const;
    WEBCORE_EXPORT double yScale() const;

    bool isInvertible() const; // If you call this this, you're probably doing it wrong.
    WEBCORE_EXPORT Optional<AffineTransform> inverse() const;

    WEBCORE_EXPORT void blend(const AffineTransform& from, double progress);

    WEBCORE_EXPORT TransformationMatrix toTransformationMatrix() const;

    bool isIdentityOrTranslation() const
    {
        return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && m_transform[3] == 1;
    }
    
    bool isIdentityOrTranslationOrFlipped() const
    {
        return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && (m_transform[3] == 1 || m_transform[3] == -1);
    }

    bool preservesAxisAlignment() const
    {
        return (m_transform[1] == 0 && m_transform[2] == 0) || (m_transform[0] == 0 && m_transform[3] == 0);
    }

    bool operator== (const AffineTransform& m2) const
    {
        return (m_transform[0] == m2.m_transform[0]
             && m_transform[1] == m2.m_transform[1]
             && m_transform[2] == m2.m_transform[2]
             && m_transform[3] == m2.m_transform[3]
             && m_transform[4] == m2.m_transform[4]
             && m_transform[5] == m2.m_transform[5]);
    }

    bool operator!=(const AffineTransform& other) const { return !(*this == other); }

    // *this = *this * t (i.e., a multRight)
    AffineTransform& operator*=(const AffineTransform& t)
    {
        return multiply(t);
    }
    
    // result = *this * t (i.e., a multRight)
    AffineTransform operator*(const AffineTransform& t) const
    {
        AffineTransform result = *this;
        result *= t;
        return result;
    }

#if USE(CG)
    WEBCORE_EXPORT operator CGAffineTransform() const;
#endif

#if PLATFORM(WIN)
    operator D2D1_MATRIX_3X2_F() const;
#endif

    static AffineTransform translation(double x, double y)
    {
        return AffineTransform(1, 0, 0, 1, x, y);
    }

    // decompose the matrix into its component parts
    typedef struct {
        double scaleX, scaleY;
        double angle;
        double remainderA, remainderB, remainderC, remainderD;
        double translateX, translateY;
    } DecomposedType;
    
    bool decompose(DecomposedType&) const;
    void recompose(const DecomposedType&);

private:
    std::array<double, 6> m_transform;
};

WEBCORE_EXPORT AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest);

WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const AffineTransform&);

}

#endif
