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 "AffineTransform.h" 30 #include "FloatPoint.h" 31 #include "IntPoint.h" 32 #include <string.h> //for memcpy 33 #include <wtf/FastAllocBase.h> 34 35 #if PLATFORM(CG) 36 #include <CoreGraphics/CGAffineTransform.h> 37 #elif PLATFORM(CAIRO) 38 #include <cairo.h> 39 #elif PLATFORM(OPENVG) 40 #include "VGUtils.h" 41 #elif PLATFORM(QT) 42 #include <QTransform> 43 #elif PLATFORM(SKIA) 44 #include <SkMatrix.h> 45 #elif PLATFORM(WX) && USE(WXGC) 46 #include <wx/graphics.h> 47 #endif 48 49 #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS)) 50 #if COMPILER(MINGW) 51 typedef struct _XFORM XFORM; 52 #else 53 typedef struct tagXFORM XFORM; 54 #endif 55 #endif 56 57 namespace WebCore { 58 59 class AffineTransform; 60 class IntRect; 61 class FloatPoint3D; 62 class FloatRect; 63 class FloatQuad; 64 65 class TransformationMatrix : public FastAllocBase { 66 public: 67 typedef double Matrix4[4][4]; 68 TransformationMatrix()69 TransformationMatrix() { makeIdentity(); } TransformationMatrix(const TransformationMatrix & t)70 TransformationMatrix(const TransformationMatrix& t) { *this = t; } TransformationMatrix(double a,double b,double c,double d,double e,double f)71 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)72 TransformationMatrix(double m11, double m12, double m13, double m14, 73 double m21, double m22, double m23, double m24, 74 double m31, double m32, double m33, double m34, 75 double m41, double m42, double m43, double m44) 76 { 77 setMatrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44); 78 } 79 setMatrix(double a,double b,double c,double d,double e,double f)80 void setMatrix(double a, double b, double c, double d, double e, double f) 81 { 82 m_matrix[0][0] = a; m_matrix[0][1] = b; m_matrix[0][2] = 0; m_matrix[0][3] = 0; 83 m_matrix[1][0] = c; m_matrix[1][1] = d; m_matrix[1][2] = 0; m_matrix[1][3] = 0; 84 m_matrix[2][0] = 0; m_matrix[2][1] = 0; m_matrix[2][2] = 1; m_matrix[2][3] = 0; 85 m_matrix[3][0] = e; m_matrix[3][1] = f; m_matrix[3][2] = 0; m_matrix[3][3] = 1; 86 } 87 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)88 void setMatrix(double m11, double m12, double m13, double m14, 89 double m21, double m22, double m23, double m24, 90 double m31, double m32, double m33, double m34, 91 double m41, double m42, double m43, double m44) 92 { 93 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13; m_matrix[0][3] = m14; 94 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23; m_matrix[1][3] = m24; 95 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33; m_matrix[2][3] = m34; 96 m_matrix[3][0] = m41; m_matrix[3][1] = m42; m_matrix[3][2] = m43; m_matrix[3][3] = m44; 97 } 98 99 TransformationMatrix& operator =(const TransformationMatrix &t) 100 { 101 setMatrix(t.m_matrix); 102 return *this; 103 } 104 makeIdentity()105 TransformationMatrix& makeIdentity() 106 { 107 setMatrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); 108 return *this; 109 } 110 isIdentity()111 bool isIdentity() const 112 { 113 return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 && 114 m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 && 115 m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 && 116 m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0 && m_matrix[3][3] == 1; 117 } 118 119 // This form preserves the double math from input to output map(double x,double y,double & x2,double & y2)120 void map(double x, double y, double& x2, double& y2) const { multVecMatrix(x, y, x2, y2); } 121 122 // Map a 3D point through the transform, returning a 3D point. 123 FloatPoint3D mapPoint(const FloatPoint3D&) const; 124 125 // Map a 2D point through the transform, returning a 2D point. 126 // Note that this ignores the z component, effectively projecting the point into the z=0 plane. 127 FloatPoint mapPoint(const FloatPoint&) const; 128 129 // Like the version above, except that it rounds the mapped point to the nearest integer value. mapPoint(const IntPoint & p)130 IntPoint mapPoint(const IntPoint& p) const 131 { 132 return roundedIntPoint(mapPoint(FloatPoint(p))); 133 } 134 135 // If the matrix has 3D components, the z component of the result is 136 // dropped, effectively projecting the rect into the z=0 plane 137 FloatRect mapRect(const FloatRect&) const; 138 139 // Rounds the resulting mapped rectangle out. This is helpful for bounding 140 // box computations but may not be what is wanted in other contexts. 141 IntRect mapRect(const IntRect&) const; 142 143 // If the matrix has 3D components, the z component of the result is 144 // dropped, effectively projecting the quad into the z=0 plane 145 FloatQuad mapQuad(const FloatQuad&) const; 146 147 // Map a point on the z=0 plane into a point on 148 // the plane with with the transform applied, by extending 149 // a ray perpendicular to the source plane and computing 150 // the local x,y position of the point where that ray intersects 151 // with the destination plane. 152 FloatPoint projectPoint(const FloatPoint&) const; 153 // Projects the four corners of the quad 154 FloatQuad projectQuad(const FloatQuad&) const; 155 m11()156 double m11() const { return m_matrix[0][0]; } setM11(double f)157 void setM11(double f) { m_matrix[0][0] = f; } m12()158 double m12() const { return m_matrix[0][1]; } setM12(double f)159 void setM12(double f) { m_matrix[0][1] = f; } m13()160 double m13() const { return m_matrix[0][2]; } setM13(double f)161 void setM13(double f) { m_matrix[0][2] = f; } m14()162 double m14() const { return m_matrix[0][3]; } setM14(double f)163 void setM14(double f) { m_matrix[0][3] = f; } m21()164 double m21() const { return m_matrix[1][0]; } setM21(double f)165 void setM21(double f) { m_matrix[1][0] = f; } m22()166 double m22() const { return m_matrix[1][1]; } setM22(double f)167 void setM22(double f) { m_matrix[1][1] = f; } m23()168 double m23() const { return m_matrix[1][2]; } setM23(double f)169 void setM23(double f) { m_matrix[1][2] = f; } m24()170 double m24() const { return m_matrix[1][3]; } setM24(double f)171 void setM24(double f) { m_matrix[1][3] = f; } m31()172 double m31() const { return m_matrix[2][0]; } setM31(double f)173 void setM31(double f) { m_matrix[2][0] = f; } m32()174 double m32() const { return m_matrix[2][1]; } setM32(double f)175 void setM32(double f) { m_matrix[2][1] = f; } m33()176 double m33() const { return m_matrix[2][2]; } setM33(double f)177 void setM33(double f) { m_matrix[2][2] = f; } m34()178 double m34() const { return m_matrix[2][3]; } setM34(double f)179 void setM34(double f) { m_matrix[2][3] = f; } m41()180 double m41() const { return m_matrix[3][0]; } setM41(double f)181 void setM41(double f) { m_matrix[3][0] = f; } m42()182 double m42() const { return m_matrix[3][1]; } setM42(double f)183 void setM42(double f) { m_matrix[3][1] = f; } m43()184 double m43() const { return m_matrix[3][2]; } setM43(double f)185 void setM43(double f) { m_matrix[3][2] = f; } m44()186 double m44() const { return m_matrix[3][3]; } setM44(double f)187 void setM44(double f) { m_matrix[3][3] = f; } 188 a()189 double a() const { return m_matrix[0][0]; } setA(double a)190 void setA(double a) { m_matrix[0][0] = a; } 191 b()192 double b() const { return m_matrix[0][1]; } setB(double b)193 void setB(double b) { m_matrix[0][1] = b; } 194 c()195 double c() const { return m_matrix[1][0]; } setC(double c)196 void setC(double c) { m_matrix[1][0] = c; } 197 d()198 double d() const { return m_matrix[1][1]; } setD(double d)199 void setD(double d) { m_matrix[1][1] = d; } 200 e()201 double e() const { return m_matrix[3][0]; } setE(double e)202 void setE(double e) { m_matrix[3][0] = e; } 203 f()204 double f() const { return m_matrix[3][1]; } setF(double f)205 void setF(double f) { m_matrix[3][1] = f; } 206 207 // this = this * mat multiply(const TransformationMatrix & t)208 TransformationMatrix& multiply(const TransformationMatrix& t) { return *this *= t; } 209 210 // this = mat * this 211 TransformationMatrix& multLeft(const TransformationMatrix& mat); 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 (i.e., a multRight) 298 TransformationMatrix& operator*=(const TransformationMatrix& t) 299 { 300 *this = *this * t; 301 return *this; 302 } 303 304 // result = *this * t (i.e., a multRight) 305 TransformationMatrix operator*(const TransformationMatrix& t) const 306 { 307 TransformationMatrix result = t; 308 result.multLeft(*this); 309 return result; 310 } 311 312 #if PLATFORM(CG) 313 operator CGAffineTransform() const; 314 #elif PLATFORM(CAIRO) 315 operator cairo_matrix_t() const; 316 #elif PLATFORM(OPENVG) 317 operator VGMatrix() const; 318 #elif PLATFORM(QT) 319 operator QTransform() const; 320 #elif PLATFORM(SKIA) 321 operator SkMatrix() const; 322 #elif PLATFORM(WX) && USE(WXGC) 323 operator wxGraphicsMatrix() const; 324 #endif 325 326 #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS)) 327 operator XFORM() const; 328 #endif 329 isIdentityOrTranslation()330 bool isIdentityOrTranslation() const 331 { 332 return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 333 && m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 334 && m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 335 && m_matrix[3][3] == 1; 336 } 337 338 private: 339 // multiply passed 2D point by matrix (assume z=0) 340 void multVecMatrix(double x, double y, double& dstX, double& dstY) const; 341 342 // multiply passed 3D point by matrix 343 void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const; 344 setMatrix(const Matrix4 m)345 void setMatrix(const Matrix4 m) 346 { 347 if (m && m != m_matrix) 348 memcpy(m_matrix, m, sizeof(Matrix4)); 349 } 350 351 Matrix4 m_matrix; 352 }; 353 354 } // namespace WebCore 355 356 #endif // TransformationMatrix_h 357