• 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 "AffineTransform.h"
30 #include "FloatPoint.h"
31 #include "IntPoint.h"
32 #include <string.h> //for memcpy
33 #include <wtf/FastAllocBase.h>
34 
35 #if PLATFORM(CG)
36 #include <CoreGraphics/CGAffineTransform.h>
37 #elif PLATFORM(CAIRO)
38 #include <cairo.h>
39 #elif PLATFORM(OPENVG)
40 #include "VGUtils.h"
41 #elif PLATFORM(QT)
42 #include <QTransform>
43 #elif PLATFORM(SKIA)
44 #include <SkMatrix.h>
45 #elif PLATFORM(WX) && USE(WXGC)
46 #include <wx/graphics.h>
47 #endif
48 
49 #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS))
50 #if COMPILER(MINGW)
51 typedef struct _XFORM XFORM;
52 #else
53 typedef struct tagXFORM XFORM;
54 #endif
55 #endif
56 
57 namespace WebCore {
58 
59 class AffineTransform;
60 class IntRect;
61 class FloatPoint3D;
62 class FloatRect;
63 class FloatQuad;
64 
65 class TransformationMatrix : public FastAllocBase {
66 public:
67     typedef double Matrix4[4][4];
68 
TransformationMatrix()69     TransformationMatrix() { makeIdentity(); }
TransformationMatrix(const TransformationMatrix & t)70     TransformationMatrix(const TransformationMatrix& t) { *this = t; }
TransformationMatrix(double a,double b,double c,double d,double e,double f)71     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)72     TransformationMatrix(double m11, double m12, double m13, double m14,
73                          double m21, double m22, double m23, double m24,
74                          double m31, double m32, double m33, double m34,
75                          double m41, double m42, double m43, double m44)
76     {
77         setMatrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
78     }
79 
setMatrix(double a,double b,double c,double d,double e,double f)80     void setMatrix(double a, double b, double c, double d, double e, double f)
81     {
82         m_matrix[0][0] = a; m_matrix[0][1] = b; m_matrix[0][2] = 0; m_matrix[0][3] = 0;
83         m_matrix[1][0] = c; m_matrix[1][1] = d; m_matrix[1][2] = 0; m_matrix[1][3] = 0;
84         m_matrix[2][0] = 0; m_matrix[2][1] = 0; m_matrix[2][2] = 1; m_matrix[2][3] = 0;
85         m_matrix[3][0] = e; m_matrix[3][1] = f; m_matrix[3][2] = 0; m_matrix[3][3] = 1;
86     }
87 
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)88     void setMatrix(double m11, double m12, double m13, double m14,
89                    double m21, double m22, double m23, double m24,
90                    double m31, double m32, double m33, double m34,
91                    double m41, double m42, double m43, double m44)
92     {
93         m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13; m_matrix[0][3] = m14;
94         m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23; m_matrix[1][3] = m24;
95         m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33; m_matrix[2][3] = m34;
96         m_matrix[3][0] = m41; m_matrix[3][1] = m42; m_matrix[3][2] = m43; m_matrix[3][3] = m44;
97     }
98 
99     TransformationMatrix& operator =(const TransformationMatrix &t)
100     {
101         setMatrix(t.m_matrix);
102         return *this;
103     }
104 
makeIdentity()105     TransformationMatrix& makeIdentity()
106     {
107         setMatrix(1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1);
108         return *this;
109     }
110 
isIdentity()111     bool isIdentity() const
112     {
113         return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 &&
114                m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 &&
115                m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 &&
116                m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0 && m_matrix[3][3] == 1;
117     }
118 
119     // This form preserves the double math from input to output
map(double x,double y,double & x2,double & y2)120     void map(double x, double y, double& x2, double& y2) const { multVecMatrix(x, y, x2, y2); }
121 
122     // Map a 3D point through the transform, returning a 3D point.
123     FloatPoint3D mapPoint(const FloatPoint3D&) const;
124 
125     // Map a 2D point through the transform, returning a 2D point.
126     // Note that this ignores the z component, effectively projecting the point into the z=0 plane.
127     FloatPoint mapPoint(const FloatPoint&) const;
128 
129     // Like the version above, except that it rounds the mapped point to the nearest integer value.
mapPoint(const IntPoint & p)130     IntPoint mapPoint(const IntPoint& p) const
131     {
132         return roundedIntPoint(mapPoint(FloatPoint(p)));
133     }
134 
135     // If the matrix has 3D components, the z component of the result is
136     // dropped, effectively projecting the rect into the z=0 plane
137     FloatRect mapRect(const FloatRect&) const;
138 
139     // Rounds the resulting mapped rectangle out. This is helpful for bounding
140     // box computations but may not be what is wanted in other contexts.
141     IntRect mapRect(const IntRect&) const;
142 
143     // If the matrix has 3D components, the z component of the result is
144     // dropped, effectively projecting the quad into the z=0 plane
145     FloatQuad mapQuad(const FloatQuad&) const;
146 
147     // Map a point on the z=0 plane into a point on
148     // the plane with with the transform applied, by extending
149     // a ray perpendicular to the source plane and computing
150     // the local x,y position of the point where that ray intersects
151     // with the destination plane.
152     FloatPoint projectPoint(const FloatPoint&) const;
153     // Projects the four corners of the quad
154     FloatQuad projectQuad(const FloatQuad&) const;
155 
m11()156     double m11() const { return m_matrix[0][0]; }
setM11(double f)157     void setM11(double f) { m_matrix[0][0] = f; }
m12()158     double m12() const { return m_matrix[0][1]; }
setM12(double f)159     void setM12(double f) { m_matrix[0][1] = f; }
m13()160     double m13() const { return m_matrix[0][2]; }
setM13(double f)161     void setM13(double f) { m_matrix[0][2] = f; }
m14()162     double m14() const { return m_matrix[0][3]; }
setM14(double f)163     void setM14(double f) { m_matrix[0][3] = f; }
m21()164     double m21() const { return m_matrix[1][0]; }
setM21(double f)165     void setM21(double f) { m_matrix[1][0] = f; }
m22()166     double m22() const { return m_matrix[1][1]; }
setM22(double f)167     void setM22(double f) { m_matrix[1][1] = f; }
m23()168     double m23() const { return m_matrix[1][2]; }
setM23(double f)169     void setM23(double f) { m_matrix[1][2] = f; }
m24()170     double m24() const { return m_matrix[1][3]; }
setM24(double f)171     void setM24(double f) { m_matrix[1][3] = f; }
m31()172     double m31() const { return m_matrix[2][0]; }
setM31(double f)173     void setM31(double f) { m_matrix[2][0] = f; }
m32()174     double m32() const { return m_matrix[2][1]; }
setM32(double f)175     void setM32(double f) { m_matrix[2][1] = f; }
m33()176     double m33() const { return m_matrix[2][2]; }
setM33(double f)177     void setM33(double f) { m_matrix[2][2] = f; }
m34()178     double m34() const { return m_matrix[2][3]; }
setM34(double f)179     void setM34(double f) { m_matrix[2][3] = f; }
m41()180     double m41() const { return m_matrix[3][0]; }
setM41(double f)181     void setM41(double f) { m_matrix[3][0] = f; }
m42()182     double m42() const { return m_matrix[3][1]; }
setM42(double f)183     void setM42(double f) { m_matrix[3][1] = f; }
m43()184     double m43() const { return m_matrix[3][2]; }
setM43(double f)185     void setM43(double f) { m_matrix[3][2] = f; }
m44()186     double m44() const { return m_matrix[3][3]; }
setM44(double f)187     void setM44(double f) { m_matrix[3][3] = f; }
188 
a()189     double a() const { return m_matrix[0][0]; }
setA(double a)190     void setA(double a) { m_matrix[0][0] = a; }
191 
b()192     double b() const { return m_matrix[0][1]; }
setB(double b)193     void setB(double b) { m_matrix[0][1] = b; }
194 
c()195     double c() const { return m_matrix[1][0]; }
setC(double c)196     void setC(double c) { m_matrix[1][0] = c; }
197 
d()198     double d() const { return m_matrix[1][1]; }
setD(double d)199     void setD(double d) { m_matrix[1][1] = d; }
200 
e()201     double e() const { return m_matrix[3][0]; }
setE(double e)202     void setE(double e) { m_matrix[3][0] = e; }
203 
f()204     double f() const { return m_matrix[3][1]; }
setF(double f)205     void setF(double f) { m_matrix[3][1] = f; }
206 
207     // this = this * mat
multiply(const TransformationMatrix & t)208     TransformationMatrix& multiply(const TransformationMatrix& t) { return *this *= t; }
209 
210     // this = mat * this
211     TransformationMatrix& multLeft(const TransformationMatrix& mat);
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 (i.e., a multRight)
298     TransformationMatrix& operator*=(const TransformationMatrix& t)
299     {
300         *this = *this * t;
301         return *this;
302     }
303 
304     // result = *this * t (i.e., a multRight)
305     TransformationMatrix operator*(const TransformationMatrix& t) const
306     {
307         TransformationMatrix result = t;
308         result.multLeft(*this);
309         return result;
310     }
311 
312 #if PLATFORM(CG)
313     operator CGAffineTransform() const;
314 #elif PLATFORM(CAIRO)
315     operator cairo_matrix_t() const;
316 #elif PLATFORM(OPENVG)
317     operator VGMatrix() const;
318 #elif PLATFORM(QT)
319     operator QTransform() const;
320 #elif PLATFORM(SKIA)
321     operator SkMatrix() const;
322 #elif PLATFORM(WX) && USE(WXGC)
323     operator wxGraphicsMatrix() const;
324 #endif
325 
326 #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS))
327     operator XFORM() const;
328 #endif
329 
isIdentityOrTranslation()330     bool isIdentityOrTranslation() const
331     {
332         return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0
333             && m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0
334             && m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0
335             && m_matrix[3][3] == 1;
336     }
337 
338 private:
339     // multiply passed 2D point by matrix (assume z=0)
340     void multVecMatrix(double x, double y, double& dstX, double& dstY) const;
341 
342     // multiply passed 3D point by matrix
343     void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const;
344 
setMatrix(const Matrix4 m)345     void setMatrix(const Matrix4 m)
346     {
347         if (m && m != m_matrix)
348             memcpy(m_matrix, m, sizeof(Matrix4));
349     }
350 
351     Matrix4 m_matrix;
352 };
353 
354 } // namespace WebCore
355 
356 #endif // TransformationMatrix_h
357