2 * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef TransformationMatrix_h
27 #define TransformationMatrix_h
29 #include "FloatPoint.h"
31 #include <string.h> //for memcpy
34 #include <CoreGraphics/CGAffineTransform.h>
44 class TransformationMatrix
{
46 typedef double Matrix4
[4][4];
48 TransformationMatrix() { makeIdentity(); }
49 TransformationMatrix(const TransformationMatrix
& t
) { *this = t
; }
50 TransformationMatrix(double a
, double b
, double c
, double d
, double e
, double f
) { setMatrix(a
, b
, c
, d
, e
, f
); }
51 TransformationMatrix(double m11
, double m12
, double m13
, double m14
,
52 double m21
, double m22
, double m23
, double m24
,
53 double m31
, double m32
, double m33
, double m34
,
54 double m41
, double m42
, double m43
, double m44
)
56 setMatrix(m11
, m12
, m13
, m14
, m21
, m22
, m23
, m24
, m31
, m32
, m33
, m34
, m41
, m42
, m43
, m44
);
59 void setMatrix(double a
, double b
, double c
, double d
, double e
, double f
)
61 m_matrix
[0][0] = a
; m_matrix
[0][1] = b
; m_matrix
[0][2] = 0; m_matrix
[0][3] = 0;
62 m_matrix
[1][0] = c
; m_matrix
[1][1] = d
; m_matrix
[1][2] = 0; m_matrix
[1][3] = 0;
63 m_matrix
[2][0] = 0; m_matrix
[2][1] = 0; m_matrix
[2][2] = 1; m_matrix
[2][3] = 0;
64 m_matrix
[3][0] = e
; m_matrix
[3][1] = f
; m_matrix
[3][2] = 0; m_matrix
[3][3] = 1;
67 void setMatrix(double m11
, double m12
, double m13
, double m14
,
68 double m21
, double m22
, double m23
, double m24
,
69 double m31
, double m32
, double m33
, double m34
,
70 double m41
, double m42
, double m43
, double m44
)
72 m_matrix
[0][0] = m11
; m_matrix
[0][1] = m12
; m_matrix
[0][2] = m13
; m_matrix
[0][3] = m14
;
73 m_matrix
[1][0] = m21
; m_matrix
[1][1] = m22
; m_matrix
[1][2] = m23
; m_matrix
[1][3] = m24
;
74 m_matrix
[2][0] = m31
; m_matrix
[2][1] = m32
; m_matrix
[2][2] = m33
; m_matrix
[2][3] = m34
;
75 m_matrix
[3][0] = m41
; m_matrix
[3][1] = m42
; m_matrix
[3][2] = m43
; m_matrix
[3][3] = m44
;
78 TransformationMatrix
& operator =(const TransformationMatrix
&t
)
80 setMatrix(t
.m_matrix
);
84 TransformationMatrix
& makeIdentity()
86 setMatrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
90 bool isIdentity() const
92 return m_matrix
[0][0] == 1 && m_matrix
[0][1] == 0 && m_matrix
[0][2] == 0 && m_matrix
[0][3] == 0 &&
93 m_matrix
[1][0] == 0 && m_matrix
[1][1] == 1 && m_matrix
[1][2] == 0 && m_matrix
[1][3] == 0 &&
94 m_matrix
[2][0] == 0 && m_matrix
[2][1] == 0 && m_matrix
[2][2] == 1 && m_matrix
[2][3] == 0 &&
95 m_matrix
[3][0] == 0 && m_matrix
[3][1] == 0 && m_matrix
[3][2] == 0 && m_matrix
[3][3] == 1;
98 // This form preserves the double math from input to output
99 void map(double x
, double y
, double& x2
, double& y2
) const { multVecMatrix(x
, y
, x2
, y2
); }
101 // Map a 3D point through the transform, returning a 3D point.
102 FloatPoint3D
mapPoint(const FloatPoint3D
&) const;
104 // Map a 2D point through the transform, returning a 2D point.
105 // Note that this ignores the z component, effectively projecting the point into the z=0 plane.
106 FloatPoint
mapPoint(const FloatPoint
&) const;
108 // Like the version above, except that it rounds the mapped point to the nearest integer value.
109 IntPoint
mapPoint(const IntPoint
& p
) const
111 return roundedIntPoint(mapPoint(p
));
114 // If the matrix has 3D components, the z component of the result is
115 // dropped, effectively projecting the rect into the z=0 plane
116 FloatRect
mapRect(const FloatRect
&) const;
118 // Rounds the resulting mapped rectangle out. This is helpful for bounding
119 // box computations but may not be what is wanted in other contexts.
120 IntRect
mapRect(const IntRect
&) const;
122 // If the matrix has 3D components, the z component of the result is
123 // dropped, effectively projecting the quad into the z=0 plane
124 FloatQuad
mapQuad(const FloatQuad
&) const;
126 // Map a point on the z=0 plane into a point on
127 // the plane with with the transform applied, by extending
128 // a ray perpendicular to the source plane and computing
129 // the local x,y position of the point where that ray intersects
130 // with the destination plane.
131 FloatPoint
projectPoint(const FloatPoint
&) const;
132 // Projects the four corners of the quad
133 FloatQuad
projectQuad(const FloatQuad
&) const;
135 double m11() const { return m_matrix
[0][0]; }
136 void setM11(double f
) { m_matrix
[0][0] = f
; }
137 double m12() const { return m_matrix
[0][1]; }
138 void setM12(double f
) { m_matrix
[0][1] = f
; }
139 double m13() const { return m_matrix
[0][2]; }
140 void setM13(double f
) { m_matrix
[0][2] = f
; }
141 double m14() const { return m_matrix
[0][3]; }
142 void setM14(double f
) { m_matrix
[0][3] = f
; }
143 double m21() const { return m_matrix
[1][0]; }
144 void setM21(double f
) { m_matrix
[1][0] = f
; }
145 double m22() const { return m_matrix
[1][1]; }
146 void setM22(double f
) { m_matrix
[1][1] = f
; }
147 double m23() const { return m_matrix
[1][2]; }
148 void setM23(double f
) { m_matrix
[1][2] = f
; }
149 double m24() const { return m_matrix
[1][3]; }
150 void setM24(double f
) { m_matrix
[1][3] = f
; }
151 double m31() const { return m_matrix
[2][0]; }
152 void setM31(double f
) { m_matrix
[2][0] = f
; }
153 double m32() const { return m_matrix
[2][1]; }
154 void setM32(double f
) { m_matrix
[2][1] = f
; }
155 double m33() const { return m_matrix
[2][2]; }
156 void setM33(double f
) { m_matrix
[2][2] = f
; }
157 double m34() const { return m_matrix
[2][3]; }
158 void setM34(double f
) { m_matrix
[2][3] = f
; }
159 double m41() const { return m_matrix
[3][0]; }
160 void setM41(double f
) { m_matrix
[3][0] = f
; }
161 double m42() const { return m_matrix
[3][1]; }
162 void setM42(double f
) { m_matrix
[3][1] = f
; }
163 double m43() const { return m_matrix
[3][2]; }
164 void setM43(double f
) { m_matrix
[3][2] = f
; }
165 double m44() const { return m_matrix
[3][3]; }
166 void setM44(double f
) { m_matrix
[3][3] = f
; }
168 double a() const { return m_matrix
[0][0]; }
169 void setA(double a
) { m_matrix
[0][0] = a
; }
171 double b() const { return m_matrix
[0][1]; }
172 void setB(double b
) { m_matrix
[0][1] = b
; }
174 double c() const { return m_matrix
[1][0]; }
175 void setC(double c
) { m_matrix
[1][0] = c
; }
177 double d() const { return m_matrix
[1][1]; }
178 void setD(double d
) { m_matrix
[1][1] = d
; }
180 double e() const { return m_matrix
[3][0]; }
181 void setE(double e
) { m_matrix
[3][0] = e
; }
183 double f() const { return m_matrix
[3][1]; }
184 void setF(double f
) { m_matrix
[3][1] = f
; }
187 TransformationMatrix
& multiply(const TransformationMatrix
& t
) { return *this *= t
; }
190 TransformationMatrix
& multLeft(const TransformationMatrix
& mat
);
192 TransformationMatrix
& scale(double);
193 TransformationMatrix
& scaleNonUniform(double sx
, double sy
);
194 TransformationMatrix
& scale3d(double sx
, double sy
, double sz
);
196 TransformationMatrix
& rotate(double d
) { return rotate3d(0, 0, d
); }
197 TransformationMatrix
& rotateFromVector(double x
, double y
);
198 TransformationMatrix
& rotate3d(double rx
, double ry
, double rz
);
200 // The vector (x,y,z) is normalized if it's not already. A vector of
201 // (0,0,0) uses a vector of (0,0,1).
202 TransformationMatrix
& rotate3d(double x
, double y
, double z
, double angle
);
204 TransformationMatrix
& translate(double tx
, double ty
);
205 TransformationMatrix
& translate3d(double tx
, double ty
, double tz
);
207 // translation added with a post-multiply
208 TransformationMatrix
& translateRight(double tx
, double ty
);
209 TransformationMatrix
& translateRight3d(double tx
, double ty
, double tz
);
211 TransformationMatrix
& flipX();
212 TransformationMatrix
& flipY();
213 TransformationMatrix
& skew(double angleX
, double angleY
);
214 TransformationMatrix
& skewX(double angle
) { return skew(angle
, 0); }
215 TransformationMatrix
& skewY(double angle
) { return skew(0, angle
); }
217 TransformationMatrix
& applyPerspective(double p
);
218 bool hasPerspective() const { return m_matrix
[2][3] != 0.0f
; }
220 bool isInvertible() const;
222 // This method returns the identity matrix if it is not invertible.
223 // Use isInvertible() before calling this if you need to know.
224 TransformationMatrix
inverse() const;
226 // decompose the matrix into its component parts
228 double scaleX
, scaleY
, scaleZ
;
229 double skewXY
, skewXZ
, skewYZ
;
230 double quaternionX
, quaternionY
, quaternionZ
, quaternionW
;
231 double translateX
, translateY
, translateZ
;
232 double perspectiveX
, perspectiveY
, perspectiveZ
, perspectiveW
;
235 bool decompose(DecomposedType
& decomp
) const;
236 void recompose(const DecomposedType
& decomp
);
238 void blend(const TransformationMatrix
& from
, double progress
);
240 bool isAffine() const
242 return (m13() == 0 && m14() == 0 && m23() == 0 && m24() == 0 &&
243 m31() == 0 && m32() == 0 && m33() == 1 && m34() == 0 && m43() == 0 && m44() == 1);
246 // Throw away the non-affine parts of the matrix (lossy!)
249 bool operator==(const TransformationMatrix
& m2
) const
251 return (m_matrix
[0][0] == m2
.m_matrix
[0][0] &&
252 m_matrix
[0][1] == m2
.m_matrix
[0][1] &&
253 m_matrix
[0][2] == m2
.m_matrix
[0][2] &&
254 m_matrix
[0][3] == m2
.m_matrix
[0][3] &&
255 m_matrix
[1][0] == m2
.m_matrix
[1][0] &&
256 m_matrix
[1][1] == m2
.m_matrix
[1][1] &&
257 m_matrix
[1][2] == m2
.m_matrix
[1][2] &&
258 m_matrix
[1][3] == m2
.m_matrix
[1][3] &&
259 m_matrix
[2][0] == m2
.m_matrix
[2][0] &&
260 m_matrix
[2][1] == m2
.m_matrix
[2][1] &&
261 m_matrix
[2][2] == m2
.m_matrix
[2][2] &&
262 m_matrix
[2][3] == m2
.m_matrix
[2][3] &&
263 m_matrix
[3][0] == m2
.m_matrix
[3][0] &&
264 m_matrix
[3][1] == m2
.m_matrix
[3][1] &&
265 m_matrix
[3][2] == m2
.m_matrix
[3][2] &&
266 m_matrix
[3][3] == m2
.m_matrix
[3][3]);
269 bool operator!=(const TransformationMatrix
& other
) const { return !(*this == other
); }
271 // *this = *this * t (i.e., a multRight)
272 TransformationMatrix
& operator*=(const TransformationMatrix
& t
)
278 // result = *this * t (i.e., a multRight)
279 TransformationMatrix
operator*(const TransformationMatrix
& t
)
281 TransformationMatrix result
= t
;
282 result
.multLeft(*this);
287 operator CGAffineTransform() const;
291 TransformationMatrix
makeMapBetweenRects(const FloatRect
& source
, const FloatRect
& dest
);
293 // multiply passed 2D point by matrix (assume z=0)
294 void multVecMatrix(double x
, double y
, double& dstX
, double& dstY
) const;
296 // multiply passed 3D point by matrix
297 void multVecMatrix(double x
, double y
, double z
, double& dstX
, double& dstY
, double& dstZ
) const;
299 void setMatrix(const Matrix4 m
)
301 if (m
&& m
!= m_matrix
)
302 memcpy(m_matrix
, m
, sizeof(Matrix4
));
305 bool isIdentityOrTranslation() const
307 return m_matrix
[0][0] == 1 && m_matrix
[0][1] == 0 && m_matrix
[0][2] == 0 && m_matrix
[0][3] == 0 &&
308 m_matrix
[1][0] == 0 && m_matrix
[1][1] == 1 && m_matrix
[1][2] == 0 && m_matrix
[1][3] == 0 &&
309 m_matrix
[2][0] == 0 && m_matrix
[2][1] == 0 && m_matrix
[2][2] == 1 && m_matrix
[2][3] == 0 &&
316 } // namespace WebCore
318 #endif // TransformationMatrix_h