This source file includes following definitions.
- makeIdentity
- setMatrix
- isIdentity
- xScale
- yScale
- det
- isInvertible
- inverse
- multiply
- rotate
- rotateRadians
- scale
- scale
- translate
- scaleNonUniform
- rotateFromVector
- flipX
- flipY
- shear
- skew
- skewX
- skewY
- makeMapBetweenRects
- map
- mapPoint
- mapPoint
- mapSize
- mapSize
- mapRect
- mapRect
- mapQuad
- blend
- toTransformationMatrix
- decompose
- recompose
#include "config.h"
#include "platform/transforms/AffineTransform.h"
#include "platform/FloatConversion.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/FloatRect.h"
#include "platform/geometry/IntRect.h"
#include "wtf/MathExtras.h"
namespace WebCore {
AffineTransform::AffineTransform()
{
setMatrix(1, 0, 0, 1, 0, 0);
}
AffineTransform::AffineTransform(double a, double b, double c, double d, double e, double f)
{
setMatrix(a, b, c, d, e, f);
}
void AffineTransform::makeIdentity()
{
setMatrix(1, 0, 0, 1, 0, 0);
}
void AffineTransform::setMatrix(double a, double b, double c, double d, double e, double f)
{
m_transform[0] = a;
m_transform[1] = b;
m_transform[2] = c;
m_transform[3] = d;
m_transform[4] = e;
m_transform[5] = f;
}
bool AffineTransform::isIdentity() const
{
return (m_transform[0] == 1 && m_transform[1] == 0
&& m_transform[2] == 0 && m_transform[3] == 1
&& m_transform[4] == 0 && m_transform[5] == 0);
}
double AffineTransform::xScale() const
{
return sqrt(m_transform[0] * m_transform[0] + m_transform[1] * m_transform[1]);
}
double AffineTransform::yScale() const
{
return sqrt(m_transform[2] * m_transform[2] + m_transform[3] * m_transform[3]);
}
double AffineTransform::det() const
{
return m_transform[0] * m_transform[3] - m_transform[1] * m_transform[2];
}
bool AffineTransform::isInvertible() const
{
return det() != 0.0;
}
AffineTransform AffineTransform::inverse() const
{
double determinant = det();
if (determinant == 0.0)
return AffineTransform();
AffineTransform result;
if (isIdentityOrTranslation()) {
result.m_transform[4] = -m_transform[4];
result.m_transform[5] = -m_transform[5];
return result;
}
result.m_transform[0] = m_transform[3] / determinant;
result.m_transform[1] = -m_transform[1] / determinant;
result.m_transform[2] = -m_transform[2] / determinant;
result.m_transform[3] = m_transform[0] / determinant;
result.m_transform[4] = (m_transform[2] * m_transform[5]
- m_transform[3] * m_transform[4]) / determinant;
result.m_transform[5] = (m_transform[1] * m_transform[4]
- m_transform[0] * m_transform[5]) / determinant;
return result;
}
AffineTransform& AffineTransform::multiply(const AffineTransform& other)
{
AffineTransform trans;
trans.m_transform[0] = other.m_transform[0] * m_transform[0] + other.m_transform[1] * m_transform[2];
trans.m_transform[1] = other.m_transform[0] * m_transform[1] + other.m_transform[1] * m_transform[3];
trans.m_transform[2] = other.m_transform[2] * m_transform[0] + other.m_transform[3] * m_transform[2];
trans.m_transform[3] = other.m_transform[2] * m_transform[1] + other.m_transform[3] * m_transform[3];
trans.m_transform[4] = other.m_transform[4] * m_transform[0] + other.m_transform[5] * m_transform[2] + m_transform[4];
trans.m_transform[5] = other.m_transform[4] * m_transform[1] + other.m_transform[5] * m_transform[3] + m_transform[5];
setMatrix(trans.m_transform);
return *this;
}
AffineTransform& AffineTransform::rotate(double a)
{
return rotateRadians(deg2rad(a));
}
AffineTransform& AffineTransform::rotateRadians(double a)
{
double cosAngle = cos(a);
double sinAngle = sin(a);
AffineTransform rot(cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0);
multiply(rot);
return *this;
}
AffineTransform& AffineTransform::scale(double s)
{
return scale(s, s);
}
AffineTransform& AffineTransform::scale(double sx, double sy)
{
m_transform[0] *= sx;
m_transform[1] *= sx;
m_transform[2] *= sy;
m_transform[3] *= sy;
return *this;
}
AffineTransform& AffineTransform::translate(double tx, double ty)
{
if (isIdentityOrTranslation()) {
m_transform[4] += tx;
m_transform[5] += ty;
return *this;
}
m_transform[4] += tx * m_transform[0] + ty * m_transform[2];
m_transform[5] += tx * m_transform[1] + ty * m_transform[3];
return *this;
}
AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
{
return scale(sx, sy);
}
AffineTransform& AffineTransform::rotateFromVector(double x, double y)
{
return rotateRadians(atan2(y, x));
}
AffineTransform& AffineTransform::flipX()
{
return scale(-1, 1);
}
AffineTransform& AffineTransform::flipY()
{
return scale(1, -1);
}
AffineTransform& AffineTransform::shear(double sx, double sy)
{
double a = m_transform[0];
double b = m_transform[1];
m_transform[0] += sy * m_transform[2];
m_transform[1] += sy * m_transform[3];
m_transform[2] += sx * a;
m_transform[3] += sx * b;
return *this;
}
AffineTransform& AffineTransform::skew(double angleX, double angleY)
{
return shear(tan(deg2rad(angleX)), tan(deg2rad(angleY)));
}
AffineTransform& AffineTransform::skewX(double angle)
{
return shear(tan(deg2rad(angle)), 0);
}
AffineTransform& AffineTransform::skewY(double angle)
{
return shear(0, tan(deg2rad(angle)));
}
AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest)
{
AffineTransform transform;
transform.translate(dest.x() - source.x(), dest.y() - source.y());
transform.scale(dest.width() / source.width(), dest.height() / source.height());
return transform;
}
void AffineTransform::map(double x, double y, double& x2, double& y2) const
{
x2 = (m_transform[0] * x + m_transform[2] * y + m_transform[4]);
y2 = (m_transform[1] * x + m_transform[3] * y + m_transform[5]);
}
IntPoint AffineTransform::mapPoint(const IntPoint& point) const
{
double x2, y2;
map(point.x(), point.y(), x2, y2);
return IntPoint(lround(x2), lround(y2));
}
FloatPoint AffineTransform::mapPoint(const FloatPoint& point) const
{
double x2, y2;
map(point.x(), point.y(), x2, y2);
return FloatPoint(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2));
}
IntSize AffineTransform::mapSize(const IntSize& size) const
{
double width2 = size.width() * xScale();
double height2 = size.height() * yScale();
return IntSize(lround(width2), lround(height2));
}
FloatSize AffineTransform::mapSize(const FloatSize& size) const
{
double width2 = size.width() * xScale();
double height2 = size.height() * yScale();
return FloatSize(narrowPrecisionToFloat(width2), narrowPrecisionToFloat(height2));
}
IntRect AffineTransform::mapRect(const IntRect &rect) const
{
return enclosingIntRect(mapRect(FloatRect(rect)));
}
FloatRect AffineTransform::mapRect(const FloatRect& rect) const
{
if (isIdentityOrTranslation()) {
if (!m_transform[4] && !m_transform[5])
return rect;
FloatRect mappedRect(rect);
mappedRect.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5]));
return mappedRect;
}
FloatQuad result;
result.setP1(mapPoint(rect.location()));
result.setP2(mapPoint(FloatPoint(rect.maxX(), rect.y())));
result.setP3(mapPoint(FloatPoint(rect.maxX(), rect.maxY())));
result.setP4(mapPoint(FloatPoint(rect.x(), rect.maxY())));
return result.boundingBox();
}
FloatQuad AffineTransform::mapQuad(const FloatQuad& q) const
{
if (isIdentityOrTranslation()) {
FloatQuad mappedQuad(q);
mappedQuad.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5]));
return mappedQuad;
}
FloatQuad result;
result.setP1(mapPoint(q.p1()));
result.setP2(mapPoint(q.p2()));
result.setP3(mapPoint(q.p3()));
result.setP4(mapPoint(q.p4()));
return result;
}
void AffineTransform::blend(const AffineTransform& from, double progress)
{
DecomposedType srA, srB;
from.decompose(srA);
this->decompose(srB);
if ((srA.scaleX < 0 && srB.scaleY < 0) || (srA.scaleY < 0 && srB.scaleX < 0)) {
srA.scaleX = -srA.scaleX;
srA.scaleY = -srA.scaleY;
srA.angle += srA.angle < 0 ? piDouble : -piDouble;
}
srA.angle = fmod(srA.angle, twoPiDouble);
srB.angle = fmod(srB.angle, twoPiDouble);
if (fabs(srA.angle - srB.angle) > piDouble) {
if (srA.angle > srB.angle)
srA.angle -= twoPiDouble;
else
srB.angle -= twoPiDouble;
}
srA.scaleX += progress * (srB.scaleX - srA.scaleX);
srA.scaleY += progress * (srB.scaleY - srA.scaleY);
srA.angle += progress * (srB.angle - srA.angle);
srA.remainderA += progress * (srB.remainderA - srA.remainderA);
srA.remainderB += progress * (srB.remainderB - srA.remainderB);
srA.remainderC += progress * (srB.remainderC - srA.remainderC);
srA.remainderD += progress * (srB.remainderD - srA.remainderD);
srA.translateX += progress * (srB.translateX - srA.translateX);
srA.translateY += progress * (srB.translateY - srA.translateY);
this->recompose(srA);
}
TransformationMatrix AffineTransform::toTransformationMatrix() const
{
return TransformationMatrix(m_transform[0], m_transform[1], m_transform[2],
m_transform[3], m_transform[4], m_transform[5]);
}
bool AffineTransform::decompose(DecomposedType& decomp) const
{
AffineTransform m(*this);
double sx = xScale();
double sy = yScale();
if (m.a() * m.d() - m.c() * m.b() < 0) {
if (m.a() < m.d())
sx = -sx;
else
sy = -sy;
}
m.scale(1 / sx, 1 / sy);
double angle = atan2(m.b(), m.a());
m.rotateRadians(-angle);
decomp.scaleX = sx;
decomp.scaleY = sy;
decomp.angle = angle;
decomp.remainderA = m.a();
decomp.remainderB = m.b();
decomp.remainderC = m.c();
decomp.remainderD = m.d();
decomp.translateX = m.e();
decomp.translateY = m.f();
return true;
}
void AffineTransform::recompose(const DecomposedType& decomp)
{
this->setA(decomp.remainderA);
this->setB(decomp.remainderB);
this->setC(decomp.remainderC);
this->setD(decomp.remainderD);
this->setE(decomp.translateX);
this->setF(decomp.translateY);
this->rotateRadians(decomp.angle);
this->scale(decomp.scaleX, decomp.scaleY);
}
}