1 /*
2  * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef TransformationMatrix_h
27 #define TransformationMatrix_h
28 
29 #include "FloatPoint.h"
30 #include "IntPoint.h"
31 #include <string.h> //for memcpy
32 #include <wtf/FastAllocBase.h>
33 
34 #if USE(CA)
35 typedef struct CATransform3D CATransform3D;
36 #endif
37 #if USE(CG)
38 typedef struct CGAffineTransform CGAffineTransform;
39 #elif USE(CAIRO)
40 #include <cairo.h>
41 #elif PLATFORM(OPENVG)
42 #include "VGUtils.h"
43 #elif PLATFORM(QT)
44 #include <QTransform>
45 #elif USE(SKIA)
46 #include <SkMatrix.h>
47 #elif PLATFORM(WX) && USE(WXGC)
48 #include <wx/graphics.h>
49 #endif
50 
51 #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS))
52 #if COMPILER(MINGW) && !COMPILER(MINGW64)
53 typedef struct _XFORM XFORM;
54 #else
55 typedef struct tagXFORM XFORM;
56 #endif
57 #endif
58 
59 namespace WebCore {
60 
61 class AffineTransform;
62 class IntRect;
63 class FloatPoint3D;
64 class FloatRect;
65 class FloatQuad;
66 
67 class TransformationMatrix {
68     WTF_MAKE_FAST_ALLOCATED;
69 public:
70     typedef double Matrix4[4][4];
71 
TransformationMatrix()72     TransformationMatrix() { makeIdentity(); }
TransformationMatrix(const TransformationMatrix & t)73     TransformationMatrix(const TransformationMatrix& t) { *this = t; }
TransformationMatrix(double a,double b,double c,double d,double e,double f)74     TransformationMatrix(double a, double b, double c, double d, double e, double f) { setMatrix(a, b, c, d, e, f); }
TransformationMatrix(double m11,double m12,double m13,double m14,double m21,double m22,double m23,double m24,double m31,double m32,double m33,double m34,double m41,double m42,double m43,double m44)75     TransformationMatrix(double m11, double m12, double m13, double m14,
76                          double m21, double m22, double m23, double m24,
77                          double m31, double m32, double m33, double m34,
78                          double m41, double m42, double m43, double m44)
79     {
80         setMatrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
81     }
82 
setMatrix(double a,double b,double c,double d,double e,double f)83     void setMatrix(double a, double b, double c, double d, double e, double f)
84     {
85         m_matrix[0][0] = a; m_matrix[0][1] = b; m_matrix[0][2] = 0; m_matrix[0][3] = 0;
86         m_matrix[1][0] = c; m_matrix[1][1] = d; m_matrix[1][2] = 0; m_matrix[1][3] = 0;
87         m_matrix[2][0] = 0; m_matrix[2][1] = 0; m_matrix[2][2] = 1; m_matrix[2][3] = 0;
88         m_matrix[3][0] = e; m_matrix[3][1] = f; m_matrix[3][2] = 0; m_matrix[3][3] = 1;
89     }
90 
setMatrix(double m11,double m12,double m13,double m14,double m21,double m22,double m23,double m24,double m31,double m32,double m33,double m34,double m41,double m42,double m43,double m44)91     void setMatrix(double m11, double m12, double m13, double m14,
92                    double m21, double m22, double m23, double m24,
93                    double m31, double m32, double m33, double m34,
94                    double m41, double m42, double m43, double m44)
95     {
96         m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13; m_matrix[0][3] = m14;
97         m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23; m_matrix[1][3] = m24;
98         m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33; m_matrix[2][3] = m34;
99         m_matrix[3][0] = m41; m_matrix[3][1] = m42; m_matrix[3][2] = m43; m_matrix[3][3] = m44;
100     }
101 
102     TransformationMatrix& operator =(const TransformationMatrix &t)
103     {
104         setMatrix(t.m_matrix);
105         return *this;
106     }
107 
makeIdentity()108     TransformationMatrix& makeIdentity()
109     {
110         setMatrix(1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1);
111         return *this;
112     }
113 
isIdentity()114     bool isIdentity() const
115     {
116         return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 &&
117                m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 &&
118                m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 &&
119                m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0 && m_matrix[3][3] == 1;
120     }
121 
122     // This form preserves the double math from input to output
map(double x,double y,double & x2,double & y2)123     void map(double x, double y, double& x2, double& y2) const { multVecMatrix(x, y, x2, y2); }
124 
125     // Map a 3D point through the transform, returning a 3D point.
126     FloatPoint3D mapPoint(const FloatPoint3D&) const;
127 
128     // Map a 2D point through the transform, returning a 2D point.
129     // Note that this ignores the z component, effectively projecting the point into the z=0 plane.
130     FloatPoint mapPoint(const FloatPoint&) const;
131 
132     // Like the version above, except that it rounds the mapped point to the nearest integer value.
mapPoint(const IntPoint & p)133     IntPoint mapPoint(const IntPoint& p) const
134     {
135         return roundedIntPoint(mapPoint(FloatPoint(p)));
136     }
137 
138     // If the matrix has 3D components, the z component of the result is
139     // dropped, effectively projecting the rect into the z=0 plane
140     FloatRect mapRect(const FloatRect&) const;
141 
142     // Rounds the resulting mapped rectangle out. This is helpful for bounding
143     // box computations but may not be what is wanted in other contexts.
144     IntRect mapRect(const IntRect&) const;
145 
146     // If the matrix has 3D components, the z component of the result is
147     // dropped, effectively projecting the quad into the z=0 plane
148     FloatQuad mapQuad(const FloatQuad&) const;
149 
150     // Map a point on the z=0 plane into a point on
151     // the plane with with the transform applied, by extending
152     // a ray perpendicular to the source plane and computing
153     // the local x,y position of the point where that ray intersects
154     // with the destination plane.
155     FloatPoint projectPoint(const FloatPoint&) const;
156     // Projects the four corners of the quad
157     FloatQuad projectQuad(const FloatQuad&) const;
158 
m11()159     double m11() const { return m_matrix[0][0]; }
setM11(double f)160     void setM11(double f) { m_matrix[0][0] = f; }
m12()161     double m12() const { return m_matrix[0][1]; }
setM12(double f)162     void setM12(double f) { m_matrix[0][1] = f; }
m13()163     double m13() const { return m_matrix[0][2]; }
setM13(double f)164     void setM13(double f) { m_matrix[0][2] = f; }
m14()165     double m14() const { return m_matrix[0][3]; }
setM14(double f)166     void setM14(double f) { m_matrix[0][3] = f; }
m21()167     double m21() const { return m_matrix[1][0]; }
setM21(double f)168     void setM21(double f) { m_matrix[1][0] = f; }
m22()169     double m22() const { return m_matrix[1][1]; }
setM22(double f)170     void setM22(double f) { m_matrix[1][1] = f; }
m23()171     double m23() const { return m_matrix[1][2]; }
setM23(double f)172     void setM23(double f) { m_matrix[1][2] = f; }
m24()173     double m24() const { return m_matrix[1][3]; }
setM24(double f)174     void setM24(double f) { m_matrix[1][3] = f; }
m31()175     double m31() const { return m_matrix[2][0]; }
setM31(double f)176     void setM31(double f) { m_matrix[2][0] = f; }
m32()177     double m32() const { return m_matrix[2][1]; }
setM32(double f)178     void setM32(double f) { m_matrix[2][1] = f; }
m33()179     double m33() const { return m_matrix[2][2]; }
setM33(double f)180     void setM33(double f) { m_matrix[2][2] = f; }
m34()181     double m34() const { return m_matrix[2][3]; }
setM34(double f)182     void setM34(double f) { m_matrix[2][3] = f; }
m41()183     double m41() const { return m_matrix[3][0]; }
setM41(double f)184     void setM41(double f) { m_matrix[3][0] = f; }
m42()185     double m42() const { return m_matrix[3][1]; }
setM42(double f)186     void setM42(double f) { m_matrix[3][1] = f; }
m43()187     double m43() const { return m_matrix[3][2]; }
setM43(double f)188     void setM43(double f) { m_matrix[3][2] = f; }
m44()189     double m44() const { return m_matrix[3][3]; }
setM44(double f)190     void setM44(double f) { m_matrix[3][3] = f; }
191 
a()192     double a() const { return m_matrix[0][0]; }
setA(double a)193     void setA(double a) { m_matrix[0][0] = a; }
194 
b()195     double b() const { return m_matrix[0][1]; }
setB(double b)196     void setB(double b) { m_matrix[0][1] = b; }
197 
c()198     double c() const { return m_matrix[1][0]; }
setC(double c)199     void setC(double c) { m_matrix[1][0] = c; }
200 
d()201     double d() const { return m_matrix[1][1]; }
setD(double d)202     void setD(double d) { m_matrix[1][1] = d; }
203 
e()204     double e() const { return m_matrix[3][0]; }
setE(double e)205     void setE(double e) { m_matrix[3][0] = e; }
206 
f()207     double f() const { return m_matrix[3][1]; }
setF(double f)208     void setF(double f) { m_matrix[3][1] = f; }
209 
210     // this = this * mat
211     TransformationMatrix& multiply(const TransformationMatrix&);
212 
213     TransformationMatrix& scale(double);
214     TransformationMatrix& scaleNonUniform(double sx, double sy);
215     TransformationMatrix& scale3d(double sx, double sy, double sz);
216 
rotate(double d)217     TransformationMatrix& rotate(double d) { return rotate3d(0, 0, d); }
218     TransformationMatrix& rotateFromVector(double x, double y);
219     TransformationMatrix& rotate3d(double rx, double ry, double rz);
220 
221     // The vector (x,y,z) is normalized if it's not already. A vector of
222     // (0,0,0) uses a vector of (0,0,1).
223     TransformationMatrix& rotate3d(double x, double y, double z, double angle);
224 
225     TransformationMatrix& translate(double tx, double ty);
226     TransformationMatrix& translate3d(double tx, double ty, double tz);
227 
228     // translation added with a post-multiply
229     TransformationMatrix& translateRight(double tx, double ty);
230     TransformationMatrix& translateRight3d(double tx, double ty, double tz);
231 
232     TransformationMatrix& flipX();
233     TransformationMatrix& flipY();
234     TransformationMatrix& skew(double angleX, double angleY);
skewX(double angle)235     TransformationMatrix& skewX(double angle) { return skew(angle, 0); }
skewY(double angle)236     TransformationMatrix& skewY(double angle) { return skew(0, angle); }
237 
238     TransformationMatrix& applyPerspective(double p);
hasPerspective()239     bool hasPerspective() const { return m_matrix[2][3] != 0.0f; }
240 
241     // returns a transformation that maps a rect to a rect
242     static TransformationMatrix rectToRect(const FloatRect&, const FloatRect&);
243 
244     bool isInvertible() const;
245 
246     // This method returns the identity matrix if it is not invertible.
247     // Use isInvertible() before calling this if you need to know.
248     TransformationMatrix inverse() const;
249 
250     // decompose the matrix into its component parts
251     typedef struct {
252         double scaleX, scaleY, scaleZ;
253         double skewXY, skewXZ, skewYZ;
254         double quaternionX, quaternionY, quaternionZ, quaternionW;
255         double translateX, translateY, translateZ;
256         double perspectiveX, perspectiveY, perspectiveZ, perspectiveW;
257     } DecomposedType;
258 
259     bool decompose(DecomposedType& decomp) const;
260     void recompose(const DecomposedType& decomp);
261 
262     void blend(const TransformationMatrix& from, double progress);
263 
isAffine()264     bool isAffine() const
265     {
266         return (m13() == 0 && m14() == 0 && m23() == 0 && m24() == 0 &&
267                 m31() == 0 && m32() == 0 && m33() == 1 && m34() == 0 && m43() == 0 && m44() == 1);
268     }
269 
270     // Throw away the non-affine parts of the matrix (lossy!)
271     void makeAffine();
272 
273     AffineTransform toAffineTransform() const;
274 
275     bool operator==(const TransformationMatrix& m2) const
276     {
277         return (m_matrix[0][0] == m2.m_matrix[0][0] &&
278                 m_matrix[0][1] == m2.m_matrix[0][1] &&
279                 m_matrix[0][2] == m2.m_matrix[0][2] &&
280                 m_matrix[0][3] == m2.m_matrix[0][3] &&
281                 m_matrix[1][0] == m2.m_matrix[1][0] &&
282                 m_matrix[1][1] == m2.m_matrix[1][1] &&
283                 m_matrix[1][2] == m2.m_matrix[1][2] &&
284                 m_matrix[1][3] == m2.m_matrix[1][3] &&
285                 m_matrix[2][0] == m2.m_matrix[2][0] &&
286                 m_matrix[2][1] == m2.m_matrix[2][1] &&
287                 m_matrix[2][2] == m2.m_matrix[2][2] &&
288                 m_matrix[2][3] == m2.m_matrix[2][3] &&
289                 m_matrix[3][0] == m2.m_matrix[3][0] &&
290                 m_matrix[3][1] == m2.m_matrix[3][1] &&
291                 m_matrix[3][2] == m2.m_matrix[3][2] &&
292                 m_matrix[3][3] == m2.m_matrix[3][3]);
293     }
294 
295     bool operator!=(const TransformationMatrix& other) const { return !(*this == other); }
296 
297     // *this = *this * t
298     TransformationMatrix& operator*=(const TransformationMatrix& t)
299     {
300         return multiply(t);
301     }
302 
303     // result = *this * t
304     TransformationMatrix operator*(const TransformationMatrix& t) const
305     {
306         TransformationMatrix result = *this;
307         result.multiply(t);
308         return result;
309     }
310 
311 #if USE(CA)
312     TransformationMatrix(const CATransform3D&);
313     operator CATransform3D() const;
314 #endif
315 #if USE(CG)
316     TransformationMatrix(const CGAffineTransform&);
317     operator CGAffineTransform() const;
318 #elif USE(CAIRO)
319     operator cairo_matrix_t() const;
320 #elif PLATFORM(OPENVG)
321     operator VGMatrix() const;
322 #elif PLATFORM(QT)
323     operator QTransform() const;
324 #elif USE(SKIA)
325     operator SkMatrix() const;
326 #elif PLATFORM(WX) && USE(WXGC)
327     operator wxGraphicsMatrix() const;
328 #endif
329 
330 #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS))
331     operator XFORM() const;
332 #endif
333 
isIdentityOrTranslation()334     bool isIdentityOrTranslation() const
335     {
336         return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0
337             && m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0
338             && m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0
339             && m_matrix[3][3] == 1;
340     }
341 
342 private:
343     // multiply passed 2D point by matrix (assume z=0)
344     void multVecMatrix(double x, double y, double& dstX, double& dstY) const;
345 
346     // multiply passed 3D point by matrix
347     void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const;
348 
setMatrix(const Matrix4 m)349     void setMatrix(const Matrix4 m)
350     {
351         if (m && m != m_matrix)
352             memcpy(m_matrix, m, sizeof(Matrix4));
353     }
354 
355     Matrix4 m_matrix;
356 };
357 
358 } // namespace WebCore
359 
360 #endif // TransformationMatrix_h
361