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