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