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