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