• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
33 #if PLATFORM(CG)
34 #include <CoreGraphics/CGAffineTransform.h>
35 #elif PLATFORM(CAIRO)
36 #include <cairo.h>
37 #elif PLATFORM(QT)
38 #include <QTransform>
39 #elif PLATFORM(SKIA) || PLATFORM(SGL)
40 #include <SkMatrix.h>
41 #elif PLATFORM(WX) && USE(WXGC)
42 #include <wx/graphics.h>
43 #endif
44 
45 namespace WebCore {
46 
47 class IntRect;
48 class FloatPoint3D;
49 class FloatRect;
50 class FloatQuad;
51 
52 class TransformationMatrix {
53 public:
54     typedef double Matrix4[4][4];
55 
TransformationMatrix()56     TransformationMatrix() { makeIdentity(); }
TransformationMatrix(const TransformationMatrix & t)57     TransformationMatrix(const TransformationMatrix& t) { *this = t; }
TransformationMatrix(double a,double b,double c,double d,double e,double f)58     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)59     TransformationMatrix(double m11, double m12, double m13, double m14,
60                          double m21, double m22, double m23, double m24,
61                          double m31, double m32, double m33, double m34,
62                          double m41, double m42, double m43, double m44)
63     {
64         setMatrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
65     }
66 
setMatrix(double a,double b,double c,double d,double e,double f)67     void setMatrix(double a, double b, double c, double d, double e, double f)
68     {
69         m_matrix[0][0] = a; m_matrix[0][1] = b; m_matrix[0][2] = 0; m_matrix[0][3] = 0;
70         m_matrix[1][0] = c; m_matrix[1][1] = d; m_matrix[1][2] = 0; m_matrix[1][3] = 0;
71         m_matrix[2][0] = 0; m_matrix[2][1] = 0; m_matrix[2][2] = 1; m_matrix[2][3] = 0;
72         m_matrix[3][0] = e; m_matrix[3][1] = f; m_matrix[3][2] = 0; m_matrix[3][3] = 1;
73     }
74 
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)75     void setMatrix(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         m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13; m_matrix[0][3] = m14;
81         m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23; m_matrix[1][3] = m24;
82         m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33; m_matrix[2][3] = m34;
83         m_matrix[3][0] = m41; m_matrix[3][1] = m42; m_matrix[3][2] = m43; m_matrix[3][3] = m44;
84     }
85 
86     TransformationMatrix& operator =(const TransformationMatrix &t)
87     {
88         setMatrix(t.m_matrix);
89         return *this;
90     }
91 
makeIdentity()92     TransformationMatrix& makeIdentity()
93     {
94         setMatrix(1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1);
95         return *this;
96     }
97 
isIdentity()98     bool isIdentity() const
99     {
100         return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 &&
101                m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 &&
102                m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 &&
103                m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0 && m_matrix[3][3] == 1;
104     }
105 
106     // This form preserves the double math from input to output
map(double x,double y,double & x2,double & y2)107     void map(double x, double y, double& x2, double& y2) const { multVecMatrix(x, y, x2, y2); }
108 
109     // Map a 3D point through the transform, returning a 3D point.
110     FloatPoint3D mapPoint(const FloatPoint3D&) const;
111 
112     // Map a 2D point through the transform, returning a 2D point.
113     // Note that this ignores the z component, effectively projecting the point into the z=0 plane.
114     FloatPoint mapPoint(const FloatPoint&) const;
115 
116     // Like the version above, except that it rounds the mapped point to the nearest integer value.
mapPoint(const IntPoint & p)117     IntPoint mapPoint(const IntPoint& p) const
118     {
119         return roundedIntPoint(mapPoint(FloatPoint(p)));
120     }
121 
122     // If the matrix has 3D components, the z component of the result is
123     // dropped, effectively projecting the rect into the z=0 plane
124     FloatRect mapRect(const FloatRect&) const;
125 
126     // Rounds the resulting mapped rectangle out. This is helpful for bounding
127     // box computations but may not be what is wanted in other contexts.
128     IntRect mapRect(const IntRect&) const;
129 
130     // If the matrix has 3D components, the z component of the result is
131     // dropped, effectively projecting the quad into the z=0 plane
132     FloatQuad mapQuad(const FloatQuad&) const;
133 
134     // Map a point on the z=0 plane into a point on
135     // the plane with with the transform applied, by extending
136     // a ray perpendicular to the source plane and computing
137     // the local x,y position of the point where that ray intersects
138     // with the destination plane.
139     FloatPoint projectPoint(const FloatPoint&) const;
140     // Projects the four corners of the quad
141     FloatQuad projectQuad(const FloatQuad&) const;
142 
m11()143     double m11() const { return m_matrix[0][0]; }
setM11(double f)144     void setM11(double f) { m_matrix[0][0] = f; }
m12()145     double m12() const { return m_matrix[0][1]; }
setM12(double f)146     void setM12(double f) { m_matrix[0][1] = f; }
m13()147     double m13() const { return m_matrix[0][2]; }
setM13(double f)148     void setM13(double f) { m_matrix[0][2] = f; }
m14()149     double m14() const { return m_matrix[0][3]; }
setM14(double f)150     void setM14(double f) { m_matrix[0][3] = f; }
m21()151     double m21() const { return m_matrix[1][0]; }
setM21(double f)152     void setM21(double f) { m_matrix[1][0] = f; }
m22()153     double m22() const { return m_matrix[1][1]; }
setM22(double f)154     void setM22(double f) { m_matrix[1][1] = f; }
m23()155     double m23() const { return m_matrix[1][2]; }
setM23(double f)156     void setM23(double f) { m_matrix[1][2] = f; }
m24()157     double m24() const { return m_matrix[1][3]; }
setM24(double f)158     void setM24(double f) { m_matrix[1][3] = f; }
m31()159     double m31() const { return m_matrix[2][0]; }
setM31(double f)160     void setM31(double f) { m_matrix[2][0] = f; }
m32()161     double m32() const { return m_matrix[2][1]; }
setM32(double f)162     void setM32(double f) { m_matrix[2][1] = f; }
m33()163     double m33() const { return m_matrix[2][2]; }
setM33(double f)164     void setM33(double f) { m_matrix[2][2] = f; }
m34()165     double m34() const { return m_matrix[2][3]; }
setM34(double f)166     void setM34(double f) { m_matrix[2][3] = f; }
m41()167     double m41() const { return m_matrix[3][0]; }
setM41(double f)168     void setM41(double f) { m_matrix[3][0] = f; }
m42()169     double m42() const { return m_matrix[3][1]; }
setM42(double f)170     void setM42(double f) { m_matrix[3][1] = f; }
m43()171     double m43() const { return m_matrix[3][2]; }
setM43(double f)172     void setM43(double f) { m_matrix[3][2] = f; }
m44()173     double m44() const { return m_matrix[3][3]; }
setM44(double f)174     void setM44(double f) { m_matrix[3][3] = f; }
175 
a()176     double a() const { return m_matrix[0][0]; }
setA(double a)177     void setA(double a) { m_matrix[0][0] = a; }
178 
b()179     double b() const { return m_matrix[0][1]; }
setB(double b)180     void setB(double b) { m_matrix[0][1] = b; }
181 
c()182     double c() const { return m_matrix[1][0]; }
setC(double c)183     void setC(double c) { m_matrix[1][0] = c; }
184 
d()185     double d() const { return m_matrix[1][1]; }
setD(double d)186     void setD(double d) { m_matrix[1][1] = d; }
187 
e()188     double e() const { return m_matrix[3][0]; }
setE(double e)189     void setE(double e) { m_matrix[3][0] = e; }
190 
f()191     double f() const { return m_matrix[3][1]; }
setF(double f)192     void setF(double f) { m_matrix[3][1] = f; }
193 
194     // this = this * mat
multiply(const TransformationMatrix & t)195     TransformationMatrix& multiply(const TransformationMatrix& t) { return *this *= t; }
196 
197     // this = mat * this
198     TransformationMatrix& multLeft(const TransformationMatrix& mat);
199 
200     TransformationMatrix& scale(double);
201     TransformationMatrix& scaleNonUniform(double sx, double sy);
202     TransformationMatrix& scale3d(double sx, double sy, double sz);
203 
rotate(double d)204     TransformationMatrix& rotate(double d) { return rotate3d(0, 0, d); }
205     TransformationMatrix& rotateFromVector(double x, double y);
206     TransformationMatrix& rotate3d(double rx, double ry, double rz);
207 
208     // The vector (x,y,z) is normalized if it's not already. A vector of
209     // (0,0,0) uses a vector of (0,0,1).
210     TransformationMatrix& rotate3d(double x, double y, double z, double angle);
211 
212     TransformationMatrix& translate(double tx, double ty);
213     TransformationMatrix& translate3d(double tx, double ty, double tz);
214 
215     // translation added with a post-multiply
216     TransformationMatrix& translateRight(double tx, double ty);
217     TransformationMatrix& translateRight3d(double tx, double ty, double tz);
218 
219     TransformationMatrix& flipX();
220     TransformationMatrix& flipY();
221     TransformationMatrix& skew(double angleX, double angleY);
skewX(double angle)222     TransformationMatrix& skewX(double angle) { return skew(angle, 0); }
skewY(double angle)223     TransformationMatrix& skewY(double angle) { return skew(0, angle); }
224 
225     TransformationMatrix& applyPerspective(double p);
hasPerspective()226     bool hasPerspective() const { return m_matrix[2][3] != 0.0f; }
227 
228     // returns a transformation that maps a rect to a rect
229     static TransformationMatrix rectToRect(const FloatRect&, const FloatRect&);
230 
231     bool isInvertible() const;
232 
233     // This method returns the identity matrix if it is not invertible.
234     // Use isInvertible() before calling this if you need to know.
235     TransformationMatrix inverse() const;
236 
237     // decompose the matrix into its component parts
238     typedef struct {
239         double scaleX, scaleY, scaleZ;
240         double skewXY, skewXZ, skewYZ;
241         double quaternionX, quaternionY, quaternionZ, quaternionW;
242         double translateX, translateY, translateZ;
243         double perspectiveX, perspectiveY, perspectiveZ, perspectiveW;
244     } DecomposedType;
245 
246     bool decompose(DecomposedType& decomp) const;
247     void recompose(const DecomposedType& decomp);
248 
249     void blend(const TransformationMatrix& from, double progress);
250 
isAffine()251     bool isAffine() const
252     {
253         return (m13() == 0 && m14() == 0 && m23() == 0 && m24() == 0 &&
254                 m31() == 0 && m32() == 0 && m33() == 1 && m34() == 0 && m43() == 0 && m44() == 1);
255     }
256 
257     // Throw away the non-affine parts of the matrix (lossy!)
258     void makeAffine();
259 
260     bool operator==(const TransformationMatrix& m2) const
261     {
262         return (m_matrix[0][0] == m2.m_matrix[0][0] &&
263                 m_matrix[0][1] == m2.m_matrix[0][1] &&
264                 m_matrix[0][2] == m2.m_matrix[0][2] &&
265                 m_matrix[0][3] == m2.m_matrix[0][3] &&
266                 m_matrix[1][0] == m2.m_matrix[1][0] &&
267                 m_matrix[1][1] == m2.m_matrix[1][1] &&
268                 m_matrix[1][2] == m2.m_matrix[1][2] &&
269                 m_matrix[1][3] == m2.m_matrix[1][3] &&
270                 m_matrix[2][0] == m2.m_matrix[2][0] &&
271                 m_matrix[2][1] == m2.m_matrix[2][1] &&
272                 m_matrix[2][2] == m2.m_matrix[2][2] &&
273                 m_matrix[2][3] == m2.m_matrix[2][3] &&
274                 m_matrix[3][0] == m2.m_matrix[3][0] &&
275                 m_matrix[3][1] == m2.m_matrix[3][1] &&
276                 m_matrix[3][2] == m2.m_matrix[3][2] &&
277                 m_matrix[3][3] == m2.m_matrix[3][3]);
278     }
279 
280     bool operator!=(const TransformationMatrix& other) const { return !(*this == other); }
281 
282     // *this = *this * t (i.e., a multRight)
283     TransformationMatrix& operator*=(const TransformationMatrix& t)
284     {
285         *this = *this * t;
286         return *this;
287     }
288 
289     // result = *this * t (i.e., a multRight)
290     TransformationMatrix operator*(const TransformationMatrix& t) const
291     {
292         TransformationMatrix result = t;
293         result.multLeft(*this);
294         return result;
295     }
296 
297 #if PLATFORM(CG)
298     operator CGAffineTransform() const;
299 #elif PLATFORM(CAIRO)
300     operator cairo_matrix_t() const;
301 #elif PLATFORM(QT)
302     operator QTransform() const;
303 #elif PLATFORM(SKIA) || PLATFORM(SGL)
304     operator SkMatrix() const;
305 #elif PLATFORM(WX) && USE(WXGC)
306     operator wxGraphicsMatrix() const;
307 #endif
308 
309 #if PLATFORM(WIN)
310     operator XFORM() const;
311 #endif
312 
313 private:
314     // multiply passed 2D point by matrix (assume z=0)
315     void multVecMatrix(double x, double y, double& dstX, double& dstY) const;
316 
317     // multiply passed 3D point by matrix
318     void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const;
319 
setMatrix(const Matrix4 m)320     void setMatrix(const Matrix4 m)
321     {
322         if (m && m != m_matrix)
323             memcpy(m_matrix, m, sizeof(Matrix4));
324     }
325 
isIdentityOrTranslation()326     bool isIdentityOrTranslation() const
327     {
328         return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 &&
329                m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 &&
330                m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 &&
331                m_matrix[3][3] == 1;
332     }
333 
334     Matrix4 m_matrix;
335 };
336 
337 } // namespace WebCore
338 
339 #endif // TransformationMatrix_h
340