1 /* 2 * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. 3 * 2010 Dirk Schulze <krit (at) webkit.org> 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "AffineTransform.h" 29 30 #include "FloatConversion.h" 31 #include "FloatQuad.h" 32 #include "FloatRect.h" 33 #include "IntRect.h" 34 35 #include <wtf/MathExtras.h> 36 37 namespace WebCore { 38 39 static void affineTransformDecompose(const AffineTransform& matrix, double sr[9]) 40 { 41 AffineTransform m(matrix); 42 43 // Compute scaling factors 44 double sx = matrix.xScale(); 45 double sy = matrix.yScale(); 46 47 // Compute cross product of transformed unit vectors. If negative, 48 // one axis was flipped. 49 if (m.a() * m.d() - m.c() * m.b() < 0.0) { 50 // Flip axis with minimum unit vector dot product 51 if (m.a() < m.d()) 52 sx = -sx; 53 else 54 sy = -sy; 55 } 56 57 // Remove scale from matrix 58 m.scale(1.0 / sx, 1.0 / sy); 59 60 // Compute rotation 61 double angle = atan2(m.b(), m.a()); 62 63 // Remove rotation from matrix 64 m.rotate(rad2deg(-angle)); 65 66 // Return results 67 sr[0] = sx; 68 sr[1] = sy; 69 sr[2] = angle; 70 sr[3] = m.a(); 71 sr[4] = m.b(); 72 sr[5] = m.c(); 73 sr[6] = m.d(); 74 sr[7] = m.e(); 75 sr[8] = m.f(); 76 } 77 78 static void affineTransformCompose(AffineTransform& m, const double sr[9]) 79 { 80 m.setA(sr[3]); 81 m.setB(sr[4]); 82 m.setC(sr[5]); 83 m.setD(sr[6]); 84 m.setE(sr[7]); 85 m.setF(sr[8]); 86 m.rotate(rad2deg(sr[2])); 87 m.scale(sr[0], sr[1]); 88 } 89 90 AffineTransform::AffineTransform() 91 { 92 setMatrix(1, 0, 0, 1, 0, 0); 93 } 94 95 AffineTransform::AffineTransform(double a, double b, double c, double d, double e, double f) 96 { 97 setMatrix(a, b, c, d, e, f); 98 } 99 100 void AffineTransform::makeIdentity() 101 { 102 setMatrix(1, 0, 0, 1, 0, 0); 103 } 104 105 void AffineTransform::setMatrix(double a, double b, double c, double d, double e, double f) 106 { 107 m_transform[0] = a; 108 m_transform[1] = b; 109 m_transform[2] = c; 110 m_transform[3] = d; 111 m_transform[4] = e; 112 m_transform[5] = f; 113 } 114 115 bool AffineTransform::isIdentity() const 116 { 117 return (m_transform[0] == 1 && m_transform[1] == 0 118 && m_transform[2] == 0 && m_transform[3] == 1 119 && m_transform[4] == 0 && m_transform[5] == 0); 120 } 121 122 double AffineTransform::xScale() const 123 { 124 return sqrt(m_transform[0] * m_transform[0] + m_transform[1] * m_transform[1]); 125 } 126 127 double AffineTransform::yScale() const 128 { 129 return sqrt(m_transform[2] * m_transform[2] + m_transform[3] * m_transform[3]); 130 } 131 132 double AffineTransform::det() const 133 { 134 return m_transform[0] * m_transform[3] - m_transform[1] * m_transform[2]; 135 } 136 137 bool AffineTransform::isInvertible() const 138 { 139 return det() != 0.0; 140 } 141 142 AffineTransform AffineTransform::inverse() const 143 { 144 double determinant = det(); 145 if (determinant == 0.0) 146 return AffineTransform(); 147 148 AffineTransform result; 149 if (isIdentityOrTranslation()) { 150 result.m_transform[4] = -m_transform[4]; 151 result.m_transform[5] = -m_transform[5]; 152 return result; 153 } 154 155 result.m_transform[0] = m_transform[3] / determinant; 156 result.m_transform[1] = -m_transform[1] / determinant; 157 result.m_transform[2] = -m_transform[2] / determinant; 158 result.m_transform[3] = m_transform[0] / determinant; 159 result.m_transform[4] = (m_transform[2] * m_transform[5] 160 - m_transform[3] * m_transform[4]) / determinant; 161 result.m_transform[5] = (m_transform[1] * m_transform[4] 162 - m_transform[0] * m_transform[5]) / determinant; 163 164 return result; 165 } 166 167 168 // Multiplies this AffineTransform by the provided AffineTransform - i.e. 169 // this = this * other; 170 AffineTransform& AffineTransform::multiply(const AffineTransform& other) 171 { 172 AffineTransform trans; 173 174 trans.m_transform[0] = other.m_transform[0] * m_transform[0] + other.m_transform[1] * m_transform[2]; 175 trans.m_transform[1] = other.m_transform[0] * m_transform[1] + other.m_transform[1] * m_transform[3]; 176 trans.m_transform[2] = other.m_transform[2] * m_transform[0] + other.m_transform[3] * m_transform[2]; 177 trans.m_transform[3] = other.m_transform[2] * m_transform[1] + other.m_transform[3] * m_transform[3]; 178 trans.m_transform[4] = other.m_transform[4] * m_transform[0] + other.m_transform[5] * m_transform[2] + m_transform[4]; 179 trans.m_transform[5] = other.m_transform[4] * m_transform[1] + other.m_transform[5] * m_transform[3] + m_transform[5]; 180 181 setMatrix(trans.m_transform); 182 return *this; 183 } 184 185 AffineTransform& AffineTransform::rotate(double a) 186 { 187 // angle is in degree. Switch to radian 188 a = deg2rad(a); 189 double cosAngle = cos(a); 190 double sinAngle = sin(a); 191 AffineTransform rot(cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0); 192 193 multiply(rot); 194 return *this; 195 } 196 197 AffineTransform& AffineTransform::scale(double s) 198 { 199 return scale(s, s); 200 } 201 202 AffineTransform& AffineTransform::scale(double sx, double sy) 203 { 204 m_transform[0] *= sx; 205 m_transform[1] *= sx; 206 m_transform[2] *= sy; 207 m_transform[3] *= sy; 208 return *this; 209 } 210 211 // *this = *this * translation 212 AffineTransform& AffineTransform::translate(double tx, double ty) 213 { 214 if (isIdentityOrTranslation()) { 215 m_transform[4] += tx; 216 m_transform[5] += ty; 217 return *this; 218 } 219 220 m_transform[4] += tx * m_transform[0] + ty * m_transform[2]; 221 m_transform[5] += tx * m_transform[1] + ty * m_transform[3]; 222 return *this; 223 } 224 225 AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy) 226 { 227 return scale(sx, sy); 228 } 229 230 AffineTransform& AffineTransform::rotateFromVector(double x, double y) 231 { 232 return rotate(rad2deg(atan2(y, x))); 233 } 234 235 AffineTransform& AffineTransform::flipX() 236 { 237 return scale(-1, 1); 238 } 239 240 AffineTransform& AffineTransform::flipY() 241 { 242 return scale(1, -1); 243 } 244 245 AffineTransform& AffineTransform::shear(double sx, double sy) 246 { 247 double a = m_transform[0]; 248 double b = m_transform[1]; 249 250 m_transform[0] += sy * m_transform[2]; 251 m_transform[1] += sy * m_transform[3]; 252 m_transform[2] += sx * a; 253 m_transform[3] += sx * b; 254 255 return *this; 256 } 257 258 AffineTransform& AffineTransform::skew(double angleX, double angleY) 259 { 260 return shear(tan(deg2rad(angleX)), tan(deg2rad(angleY))); 261 } 262 263 AffineTransform& AffineTransform::skewX(double angle) 264 { 265 return shear(tan(deg2rad(angle)), 0); 266 } 267 268 AffineTransform& AffineTransform::skewY(double angle) 269 { 270 return shear(0, tan(deg2rad(angle))); 271 } 272 273 AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest) 274 { 275 AffineTransform transform; 276 transform.translate(dest.x() - source.x(), dest.y() - source.y()); 277 transform.scale(dest.width() / source.width(), dest.height() / source.height()); 278 return transform; 279 } 280 281 void AffineTransform::map(double x, double y, double& x2, double& y2) const 282 { 283 x2 = (m_transform[0] * x + m_transform[2] * y + m_transform[4]); 284 y2 = (m_transform[1] * x + m_transform[3] * y + m_transform[5]); 285 } 286 287 IntPoint AffineTransform::mapPoint(const IntPoint& point) const 288 { 289 double x2, y2; 290 map(point.x(), point.y(), x2, y2); 291 292 // Round the point. 293 return IntPoint(lround(x2), lround(y2)); 294 } 295 296 FloatPoint AffineTransform::mapPoint(const FloatPoint& point) const 297 { 298 double x2, y2; 299 map(point.x(), point.y(), x2, y2); 300 301 return FloatPoint(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2)); 302 } 303 304 IntRect AffineTransform::mapRect(const IntRect &rect) const 305 { 306 return enclosingIntRect(mapRect(FloatRect(rect))); 307 } 308 309 FloatRect AffineTransform::mapRect(const FloatRect& rect) const 310 { 311 if (isIdentityOrTranslation()) { 312 FloatRect mappedRect(rect); 313 mappedRect.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5])); 314 return mappedRect; 315 } 316 317 FloatQuad result; 318 result.setP1(mapPoint(rect.location())); 319 result.setP2(mapPoint(FloatPoint(rect.maxX(), rect.y()))); 320 result.setP3(mapPoint(FloatPoint(rect.maxX(), rect.maxY()))); 321 result.setP4(mapPoint(FloatPoint(rect.x(), rect.maxY()))); 322 return result.boundingBox(); 323 } 324 325 FloatQuad AffineTransform::mapQuad(const FloatQuad& q) const 326 { 327 if (isIdentityOrTranslation()) { 328 FloatQuad mappedQuad(q); 329 mappedQuad.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5])); 330 return mappedQuad; 331 } 332 333 FloatQuad result; 334 result.setP1(mapPoint(q.p1())); 335 result.setP2(mapPoint(q.p2())); 336 result.setP3(mapPoint(q.p3())); 337 result.setP4(mapPoint(q.p4())); 338 return result; 339 } 340 341 void AffineTransform::blend(const AffineTransform& from, double progress) 342 { 343 double srA[9], srB[9]; 344 345 affineTransformDecompose(from, srA); 346 affineTransformDecompose(*this, srB); 347 348 // If x-axis of one is flipped, and y-axis of the other, convert to an unflipped rotation. 349 if ((srA[0] < 0 && srB[1] < 0) || (srA[1] < 0 && srB[0] < 0)) { 350 srA[0] = -srA[0]; 351 srA[1] = -srA[1]; 352 srA[2] += srA[2] < 0 ? piDouble : -piDouble; 353 } 354 355 // Don't rotate the long way around. 356 srA[2] = fmod(srA[2], 2.0 * piDouble); 357 srB[2] = fmod(srB[2], 2.0 * piDouble); 358 359 if (fabs(srA[2] - srB[2]) > piDouble) { 360 if (srA[2] > srB[2]) 361 srA[2] -= piDouble * 2.0; 362 else 363 srB[2] -= piDouble * 2.0; 364 } 365 366 for (int i = 0; i < 9; i++) 367 srA[i] = srA[i] + progress * (srB[i] - srA[i]); 368 369 affineTransformCompose(*this, srA); 370 } 371 372 TransformationMatrix AffineTransform::toTransformationMatrix() const 373 { 374 return TransformationMatrix(m_transform[0], m_transform[1], m_transform[2], 375 m_transform[3], m_transform[4], m_transform[5]); 376 } 377 378 } 379