]> git.saurik.com Git - iphone-api.git/blob - WebCore/TransformationMatrix.h
Adding the WebCore headers (for Cydget).
[iphone-api.git] / WebCore / TransformationMatrix.h
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 #endif
36
37 namespace WebCore {
38
39 class IntRect;
40 class FloatPoint3D;
41 class FloatRect;
42 class FloatQuad;
43
44 class TransformationMatrix {
45 public:
46 typedef double Matrix4[4][4];
47
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)
55 {
56 setMatrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
57 }
58
59 void setMatrix(double a, double b, double c, double d, double e, double f)
60 {
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;
65 }
66
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)
71 {
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;
76 }
77
78 TransformationMatrix& operator =(const TransformationMatrix &t)
79 {
80 setMatrix(t.m_matrix);
81 return *this;
82 }
83
84 TransformationMatrix& makeIdentity()
85 {
86 setMatrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
87 return *this;
88 }
89
90 bool isIdentity() const
91 {
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;
96 }
97
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); }
100
101 // Map a 3D point through the transform, returning a 3D point.
102 FloatPoint3D mapPoint(const FloatPoint3D&) const;
103
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;
107
108 // Like the version above, except that it rounds the mapped point to the nearest integer value.
109 IntPoint mapPoint(const IntPoint& p) const
110 {
111 return roundedIntPoint(mapPoint(p));
112 }
113
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;
117
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;
121
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;
125
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;
134
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; }
167
168 double a() const { return m_matrix[0][0]; }
169 void setA(double a) { m_matrix[0][0] = a; }
170
171 double b() const { return m_matrix[0][1]; }
172 void setB(double b) { m_matrix[0][1] = b; }
173
174 double c() const { return m_matrix[1][0]; }
175 void setC(double c) { m_matrix[1][0] = c; }
176
177 double d() const { return m_matrix[1][1]; }
178 void setD(double d) { m_matrix[1][1] = d; }
179
180 double e() const { return m_matrix[3][0]; }
181 void setE(double e) { m_matrix[3][0] = e; }
182
183 double f() const { return m_matrix[3][1]; }
184 void setF(double f) { m_matrix[3][1] = f; }
185
186 // this = this * mat
187 TransformationMatrix& multiply(const TransformationMatrix& t) { return *this *= t; }
188
189 // this = mat * this
190 TransformationMatrix& multLeft(const TransformationMatrix& mat);
191
192 TransformationMatrix& scale(double);
193 TransformationMatrix& scaleNonUniform(double sx, double sy);
194 TransformationMatrix& scale3d(double sx, double sy, double sz);
195
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);
199
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);
203
204 TransformationMatrix& translate(double tx, double ty);
205 TransformationMatrix& translate3d(double tx, double ty, double tz);
206
207 // translation added with a post-multiply
208 TransformationMatrix& translateRight(double tx, double ty);
209 TransformationMatrix& translateRight3d(double tx, double ty, double tz);
210
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); }
216
217 TransformationMatrix& applyPerspective(double p);
218 bool hasPerspective() const { return m_matrix[2][3] != 0.0f; }
219
220 bool isInvertible() const;
221
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;
225
226 // decompose the matrix into its component parts
227 typedef struct {
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;
233 } DecomposedType;
234
235 bool decompose(DecomposedType& decomp) const;
236 void recompose(const DecomposedType& decomp);
237
238 void blend(const TransformationMatrix& from, double progress);
239
240 bool isAffine() const
241 {
242 return (m13() == 0 && m14() == 0 && m23() == 0 && m24() == 0 &&
243 m31() == 0 && m32() == 0 && m33() == 1 && m34() == 0 && m43() == 0 && m44() == 1);
244 }
245
246 // Throw away the non-affine parts of the matrix (lossy!)
247 void makeAffine();
248
249 bool operator==(const TransformationMatrix& m2) const
250 {
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]);
267 }
268
269 bool operator!=(const TransformationMatrix& other) const { return !(*this == other); }
270
271 // *this = *this * t (i.e., a multRight)
272 TransformationMatrix& operator*=(const TransformationMatrix& t)
273 {
274 *this = *this * t;
275 return *this;
276 }
277
278 // result = *this * t (i.e., a multRight)
279 TransformationMatrix operator*(const TransformationMatrix& t)
280 {
281 TransformationMatrix result = t;
282 result.multLeft(*this);
283 return result;
284 }
285
286 #if PLATFORM(CG)
287 operator CGAffineTransform() const;
288 #endif
289
290 private:
291 TransformationMatrix makeMapBetweenRects(const FloatRect& source, const FloatRect& dest);
292
293 // multiply passed 2D point by matrix (assume z=0)
294 void multVecMatrix(double x, double y, double& dstX, double& dstY) const;
295
296 // multiply passed 3D point by matrix
297 void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const;
298
299 void setMatrix(const Matrix4 m)
300 {
301 if (m && m != m_matrix)
302 memcpy(m_matrix, m, sizeof(Matrix4));
303 }
304
305 bool isIdentityOrTranslation() const
306 {
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 &&
310 m_matrix[3][3] == 1;
311 }
312
313 Matrix4 m_matrix;
314 };
315
316 } // namespace WebCore
317
318 #endif // TransformationMatrix_h