Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / platform / transforms / AffineTransform.cpp
blob953923d0e3f597f8c2534982bc9bf23aaae5a5b5
1 /*
2 * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved.
3 * 2010 Dirk Schulze <krit@webkit.org>
4 * Copyright (C) 2013 Google Inc. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "config.h"
29 #include "platform/transforms/AffineTransform.h"
31 #include "platform/FloatConversion.h"
32 #include "platform/geometry/FloatQuad.h"
33 #include "platform/geometry/FloatRect.h"
34 #include "platform/geometry/IntRect.h"
35 #include "wtf/MathExtras.h"
37 namespace blink {
39 AffineTransform::AffineTransform()
41 setMatrix(1, 0, 0, 1, 0, 0);
44 AffineTransform::AffineTransform(double a, double b, double c, double d, double e, double f)
46 setMatrix(a, b, c, d, e, f);
49 void AffineTransform::makeIdentity()
51 setMatrix(1, 0, 0, 1, 0, 0);
54 void AffineTransform::setMatrix(double a, double b, double c, double d, double e, double f)
56 m_transform[0] = a;
57 m_transform[1] = b;
58 m_transform[2] = c;
59 m_transform[3] = d;
60 m_transform[4] = e;
61 m_transform[5] = f;
64 bool AffineTransform::isIdentity() const
66 return (m_transform[0] == 1 && m_transform[1] == 0
67 && m_transform[2] == 0 && m_transform[3] == 1
68 && m_transform[4] == 0 && m_transform[5] == 0);
71 double AffineTransform::xScale() const
73 return sqrt(m_transform[0] * m_transform[0] + m_transform[1] * m_transform[1]);
76 double AffineTransform::yScale() const
78 return sqrt(m_transform[2] * m_transform[2] + m_transform[3] * m_transform[3]);
81 double AffineTransform::det() const
83 return m_transform[0] * m_transform[3] - m_transform[1] * m_transform[2];
86 bool AffineTransform::isInvertible() const
88 return det() != 0.0;
91 AffineTransform AffineTransform::inverse() const
93 double determinant = det();
94 if (determinant == 0.0)
95 return AffineTransform();
97 AffineTransform result;
98 if (isIdentityOrTranslation()) {
99 result.m_transform[4] = -m_transform[4];
100 result.m_transform[5] = -m_transform[5];
101 return result;
104 result.m_transform[0] = m_transform[3] / determinant;
105 result.m_transform[1] = -m_transform[1] / determinant;
106 result.m_transform[2] = -m_transform[2] / determinant;
107 result.m_transform[3] = m_transform[0] / determinant;
108 result.m_transform[4] = (m_transform[2] * m_transform[5]
109 - m_transform[3] * m_transform[4]) / determinant;
110 result.m_transform[5] = (m_transform[1] * m_transform[4]
111 - m_transform[0] * m_transform[5]) / determinant;
113 return result;
116 namespace {
118 // res = t1 * t2
119 inline void doMultiply(const AffineTransform& t1, const AffineTransform& t2, AffineTransform* res)
121 res->setA(t1.a() * t2.a() + t1.c() * t2.b());
122 res->setB(t1.b() * t2.a() + t1.d() * t2.b());
123 res->setC(t1.a() * t2.c() + t1.c() * t2.d());
124 res->setD(t1.b() * t2.c() + t1.d() * t2.d());
125 res->setE(t1.a() * t2.e() + t1.c() * t2.f() + t1.e());
126 res->setF(t1.b() * t2.e() + t1.d() * t2.f() + t1.f());
129 } // anonymous namespace
131 AffineTransform& AffineTransform::multiply(const AffineTransform& other)
133 if (other.isIdentityOrTranslation()) {
134 if (other.m_transform[4] || other.m_transform[5])
135 translate(other.m_transform[4], other.m_transform[5]);
136 return *this;
139 AffineTransform trans;
140 doMultiply(*this, other, &trans);
141 setMatrix(trans.m_transform);
143 return *this;
146 AffineTransform& AffineTransform::preMultiply(const AffineTransform& other)
148 if (other.isIdentityOrTranslation()) {
149 if (other.m_transform[4] || other.m_transform[5]) {
150 m_transform[4] += other.m_transform[4];
151 m_transform[5] += other.m_transform[5];
153 return *this;
156 AffineTransform trans;
157 doMultiply(other, *this, &trans);
158 setMatrix(trans.m_transform);
160 return *this;
163 AffineTransform& AffineTransform::rotate(double a)
165 // angle is in degree. Switch to radian
166 return rotateRadians(deg2rad(a));
169 AffineTransform& AffineTransform::rotateRadians(double a)
171 double cosAngle = cos(a);
172 double sinAngle = sin(a);
173 AffineTransform rot(cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0);
175 multiply(rot);
176 return *this;
179 AffineTransform& AffineTransform::scale(double s)
181 return scale(s, s);
184 AffineTransform& AffineTransform::scale(double sx, double sy)
186 m_transform[0] *= sx;
187 m_transform[1] *= sx;
188 m_transform[2] *= sy;
189 m_transform[3] *= sy;
190 return *this;
193 // *this = *this * translation
194 AffineTransform& AffineTransform::translate(double tx, double ty)
196 if (isIdentityOrTranslation()) {
197 m_transform[4] += tx;
198 m_transform[5] += ty;
199 return *this;
202 m_transform[4] += tx * m_transform[0] + ty * m_transform[2];
203 m_transform[5] += tx * m_transform[1] + ty * m_transform[3];
204 return *this;
207 AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
209 return scale(sx, sy);
212 AffineTransform& AffineTransform::rotateFromVector(double x, double y)
214 return rotateRadians(atan2(y, x));
217 AffineTransform& AffineTransform::flipX()
219 return scale(-1, 1);
222 AffineTransform& AffineTransform::flipY()
224 return scale(1, -1);
227 AffineTransform& AffineTransform::shear(double sx, double sy)
229 double a = m_transform[0];
230 double b = m_transform[1];
232 m_transform[0] += sy * m_transform[2];
233 m_transform[1] += sy * m_transform[3];
234 m_transform[2] += sx * a;
235 m_transform[3] += sx * b;
237 return *this;
240 AffineTransform& AffineTransform::skew(double angleX, double angleY)
242 return shear(tan(deg2rad(angleX)), tan(deg2rad(angleY)));
245 AffineTransform& AffineTransform::skewX(double angle)
247 return shear(tan(deg2rad(angle)), 0);
250 AffineTransform& AffineTransform::skewY(double angle)
252 return shear(0, tan(deg2rad(angle)));
255 void AffineTransform::map(double x, double y, double& x2, double& y2) const
257 x2 = (m_transform[0] * x + m_transform[2] * y + m_transform[4]);
258 y2 = (m_transform[1] * x + m_transform[3] * y + m_transform[5]);
261 IntPoint AffineTransform::mapPoint(const IntPoint& point) const
263 double x2, y2;
264 map(point.x(), point.y(), x2, y2);
266 // Round the point.
267 return IntPoint(lround(x2), lround(y2));
270 FloatPoint AffineTransform::mapPoint(const FloatPoint& point) const
272 double x2, y2;
273 map(point.x(), point.y(), x2, y2);
275 return FloatPoint(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2));
278 IntSize AffineTransform::mapSize(const IntSize& size) const
280 double width2 = size.width() * xScale();
281 double height2 = size.height() * yScale();
283 return IntSize(lround(width2), lround(height2));
286 FloatSize AffineTransform::mapSize(const FloatSize& size) const
288 double width2 = size.width() * xScale();
289 double height2 = size.height() * yScale();
291 return FloatSize(narrowPrecisionToFloat(width2), narrowPrecisionToFloat(height2));
294 IntRect AffineTransform::mapRect(const IntRect &rect) const
296 return enclosingIntRect(mapRect(FloatRect(rect)));
299 FloatRect AffineTransform::mapRect(const FloatRect& rect) const
301 if (isIdentityOrTranslation()) {
302 if (!m_transform[4] && !m_transform[5])
303 return rect;
305 FloatRect mappedRect(rect);
306 mappedRect.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5]));
307 return mappedRect;
310 FloatQuad result;
311 result.setP1(mapPoint(rect.location()));
312 result.setP2(mapPoint(FloatPoint(rect.maxX(), rect.y())));
313 result.setP3(mapPoint(FloatPoint(rect.maxX(), rect.maxY())));
314 result.setP4(mapPoint(FloatPoint(rect.x(), rect.maxY())));
315 return result.boundingBox();
318 FloatQuad AffineTransform::mapQuad(const FloatQuad& q) const
320 if (isIdentityOrTranslation()) {
321 FloatQuad mappedQuad(q);
322 mappedQuad.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5]));
323 return mappedQuad;
326 FloatQuad result;
327 result.setP1(mapPoint(q.p1()));
328 result.setP2(mapPoint(q.p2()));
329 result.setP3(mapPoint(q.p3()));
330 result.setP4(mapPoint(q.p4()));
331 return result;
334 TransformationMatrix AffineTransform::toTransformationMatrix() const
336 return TransformationMatrix(m_transform[0], m_transform[1], m_transform[2],
337 m_transform[3], m_transform[4], m_transform[5]);
340 bool AffineTransform::decompose(DecomposedType& decomp) const
342 AffineTransform m(*this);
344 // Compute scaling factors
345 double sx = xScale();
346 double sy = yScale();
348 // Compute cross product of transformed unit vectors. If negative,
349 // one axis was flipped.
350 if (m.a() * m.d() - m.c() * m.b() < 0) {
351 // Flip axis with minimum unit vector dot product
352 if (m.a() < m.d())
353 sx = -sx;
354 else
355 sy = -sy;
358 // Remove scale from matrix
359 m.scale(1 / sx, 1 / sy);
361 // Compute rotation
362 double angle = atan2(m.b(), m.a());
364 // Remove rotation from matrix
365 m.rotateRadians(-angle);
367 // Return results
368 decomp.scaleX = sx;
369 decomp.scaleY = sy;
370 decomp.angle = angle;
371 decomp.remainderA = m.a();
372 decomp.remainderB = m.b();
373 decomp.remainderC = m.c();
374 decomp.remainderD = m.d();
375 decomp.translateX = m.e();
376 decomp.translateY = m.f();
378 return true;
381 void AffineTransform::recompose(const DecomposedType& decomp)
383 this->setA(decomp.remainderA);
384 this->setB(decomp.remainderB);
385 this->setC(decomp.remainderC);
386 this->setD(decomp.remainderD);
387 this->setE(decomp.translateX);
388 this->setF(decomp.translateY);
389 this->rotateRadians(decomp.angle);
390 this->scale(decomp.scaleX, decomp.scaleY);