1/*
2 * Copyright (C) 2005, 2006 Apple Inc.  All rights reserved.
3 *               2010 Dirk Schulze <krit@webkit.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#ifndef AffineTransform_h
28#define AffineTransform_h
29
30#include <array>
31#include <wtf/FastMalloc.h>
32
33#if USE(CG)
34typedef struct CGAffineTransform CGAffineTransform;
35#elif USE(CAIRO)
36#include <cairo.h>
37#endif
38
39namespace WebCore {
40
41class FloatPoint;
42class FloatQuad;
43class FloatRect;
44class FloatSize;
45class IntPoint;
46class IntSize;
47class IntRect;
48class TransformationMatrix;
49
50class AffineTransform {
51    WTF_MAKE_FAST_ALLOCATED;
52public:
53    AffineTransform();
54    AffineTransform(double a, double b, double c, double d, double e, double f);
55
56#if USE(CG)
57    AffineTransform(const CGAffineTransform&);
58#endif
59
60    void setMatrix(double a, double b, double c, double d, double e, double f);
61
62    void map(double x, double y, double& x2, double& y2) const;
63
64    // Rounds the mapped point to the nearest integer value.
65    IntPoint mapPoint(const IntPoint&) const;
66
67    FloatPoint mapPoint(const FloatPoint&) const;
68
69    IntSize mapSize(const IntSize&) const;
70
71    FloatSize mapSize(const FloatSize&) const;
72
73    // Rounds the resulting mapped rectangle out. This is helpful for bounding
74    // box computations but may not be what is wanted in other contexts.
75    IntRect mapRect(const IntRect&) const;
76
77    FloatRect mapRect(const FloatRect&) const;
78    FloatQuad mapQuad(const FloatQuad&) const;
79
80    bool isIdentity() const;
81
82    double a() const { return m_transform[0]; }
83    void setA(double a) { m_transform[0] = a; }
84    double b() const { return m_transform[1]; }
85    void setB(double b) { m_transform[1] = b; }
86    double c() const { return m_transform[2]; }
87    void setC(double c) { m_transform[2] = c; }
88    double d() const { return m_transform[3]; }
89    void setD(double d) { m_transform[3] = d; }
90    double e() const { return m_transform[4]; }
91    void setE(double e) { m_transform[4] = e; }
92    double f() const { return m_transform[5]; }
93    void setF(double f) { m_transform[5] = f; }
94
95    void makeIdentity();
96
97    AffineTransform& multiply(const AffineTransform& other);
98    AffineTransform& scale(double);
99    AffineTransform& scale(double sx, double sy);
100    AffineTransform& scaleNonUniform(double sx, double sy);
101    AffineTransform& rotate(double d);
102    AffineTransform& rotateFromVector(double x, double y);
103    AffineTransform& translate(double tx, double ty);
104    AffineTransform& shear(double sx, double sy);
105    AffineTransform& flipX();
106    AffineTransform& flipY();
107    AffineTransform& skew(double angleX, double angleY);
108    AffineTransform& skewX(double angle);
109    AffineTransform& skewY(double angle);
110
111    // These functions get the length of an axis-aligned unit vector
112    // once it has been mapped through the transform
113    double xScale() const;
114    double yScale() const;
115
116    double det() const;
117    bool isInvertible() const;
118    AffineTransform inverse() const;
119
120    void blend(const AffineTransform& from, double progress);
121
122    TransformationMatrix toTransformationMatrix() const;
123
124    bool isIdentityOrTranslation() const
125    {
126        return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && m_transform[3] == 1;
127    }
128
129    bool isIdentityOrTranslationOrFlipped() const
130    {
131        return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && (m_transform[3] == 1 || m_transform[3] == -1);
132    }
133
134    bool preservesAxisAlignment() const
135    {
136        return (m_transform[1] == 0 && m_transform[2] == 0) || (m_transform[0] == 0 && m_transform[3] == 0);
137    }
138
139    bool operator== (const AffineTransform& m2) const
140    {
141        return (m_transform[0] == m2.m_transform[0]
142             && m_transform[1] == m2.m_transform[1]
143             && m_transform[2] == m2.m_transform[2]
144             && m_transform[3] == m2.m_transform[3]
145             && m_transform[4] == m2.m_transform[4]
146             && m_transform[5] == m2.m_transform[5]);
147    }
148
149    bool operator!=(const AffineTransform& other) const { return !(*this == other); }
150
151    // *this = *this * t (i.e., a multRight)
152    AffineTransform& operator*=(const AffineTransform& t)
153    {
154        return multiply(t);
155    }
156
157    // result = *this * t (i.e., a multRight)
158    AffineTransform operator*(const AffineTransform& t) const
159    {
160        AffineTransform result = *this;
161        result *= t;
162        return result;
163    }
164
165#if USE(CG)
166    operator CGAffineTransform() const;
167#elif USE(CAIRO)
168    operator cairo_matrix_t() const;
169#endif
170
171    static AffineTransform translation(double x, double y)
172    {
173        return AffineTransform(1, 0, 0, 1, x, y);
174    }
175
176    // decompose the matrix into its component parts
177    typedef struct {
178        double scaleX, scaleY;
179        double angle;
180        double remainderA, remainderB, remainderC, remainderD;
181        double translateX, translateY;
182    } DecomposedType;
183
184    bool decompose(DecomposedType&) const;
185    void recompose(const DecomposedType&);
186
187private:
188    std::array<double, 6> m_transform;
189};
190
191AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest);
192
193}
194
195#endif
196