Home | History | Annotate | Download | only in transforms
      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 = sqrt(m.a() * m.a() + m.b() * m.b());
     45     double sy = sqrt(m.c() * m.c() + m.d() * m.d());
     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::det() const
    123 {
    124     return m_transform[0] * m_transform[3] - m_transform[1] * m_transform[2];
    125 }
    126 
    127 bool AffineTransform::isInvertible() const
    128 {
    129     return det() != 0.0;
    130 }
    131 
    132 AffineTransform AffineTransform::inverse() const
    133 {
    134     double determinant = det();
    135     if (determinant == 0.0)
    136         return AffineTransform();
    137 
    138     AffineTransform result;
    139     if (isIdentityOrTranslation()) {
    140         result.m_transform[4] = -m_transform[4];
    141         result.m_transform[5] = -m_transform[5];
    142         return result;
    143     }
    144 
    145     result.m_transform[0] = m_transform[3] / determinant;
    146     result.m_transform[1] = -m_transform[1] / determinant;
    147     result.m_transform[2] = -m_transform[2] / determinant;
    148     result.m_transform[3] = m_transform[0] / determinant;
    149     result.m_transform[4] = (m_transform[2] * m_transform[5]
    150                            - m_transform[3] * m_transform[4]) / determinant;
    151     result.m_transform[5] = (m_transform[1] * m_transform[4]
    152                            - m_transform[0] * m_transform[5]) / determinant;
    153 
    154     return result;
    155 }
    156 
    157 AffineTransform& AffineTransform::multiply(const AffineTransform& other)
    158 {
    159     return (*this) *= other;
    160 }
    161 
    162 AffineTransform& AffineTransform::multLeft(const AffineTransform& other)
    163 {
    164     AffineTransform trans;
    165 
    166     trans.m_transform[0] = other.m_transform[0] * m_transform[0] + other.m_transform[1] * m_transform[2];
    167     trans.m_transform[1] = other.m_transform[0] * m_transform[1] + other.m_transform[1] * m_transform[3];
    168     trans.m_transform[2] = other.m_transform[2] * m_transform[0] + other.m_transform[3] * m_transform[2];
    169     trans.m_transform[3] = other.m_transform[2] * m_transform[1] + other.m_transform[3] * m_transform[3];
    170     trans.m_transform[4] = other.m_transform[4] * m_transform[0] + other.m_transform[5] * m_transform[2] + m_transform[4];
    171     trans.m_transform[5] = other.m_transform[4] * m_transform[1] + other.m_transform[5] * m_transform[3] + m_transform[5];
    172 
    173     setMatrix(trans.m_transform);
    174     return *this;
    175 }
    176 
    177 AffineTransform& AffineTransform::rotate(double a)
    178 {
    179     // angle is in degree. Switch to radian
    180     a = deg2rad(a);
    181     double cosAngle = cos(a);
    182     double sinAngle = sin(a);
    183     AffineTransform rot(cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0);
    184 
    185     multLeft(rot);
    186     return *this;
    187 }
    188 
    189 AffineTransform& AffineTransform::scale(double s)
    190 {
    191     return scale(s, s);
    192 }
    193 
    194 AffineTransform& AffineTransform::scale(double sx, double sy)
    195 {
    196     m_transform[0] *= sx;
    197     m_transform[1] *= sx;
    198     m_transform[2] *= sy;
    199     m_transform[3] *= sy;
    200     return *this;
    201 }
    202 
    203 // *this = *this * translation
    204 AffineTransform& AffineTransform::translate(double tx, double ty)
    205 {
    206     if (isIdentityOrTranslation()) {
    207         m_transform[4] += tx;
    208         m_transform[5] += ty;
    209         return *this;
    210     }
    211 
    212     m_transform[4] += tx * m_transform[0] + ty * m_transform[2];
    213     m_transform[5] += tx * m_transform[1] + ty * m_transform[3];
    214     return *this;
    215 }
    216 
    217 // *this = translation * *this
    218 AffineTransform& AffineTransform::translateRight(double tx, double ty)
    219 {
    220     m_transform[4] += tx;
    221     m_transform[5] += ty;
    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 q(rect);
    318 
    319     FloatQuad result;
    320     result.setP1(mapPoint(q.p1()));
    321     result.setP2(mapPoint(q.p2()));
    322     result.setP3(mapPoint(q.p3()));
    323     result.setP4(mapPoint(q.p4()));
    324     return result.boundingBox();
    325 }
    326 
    327 void AffineTransform::blend(const AffineTransform& from, double progress)
    328 {
    329     double srA[9], srB[9];
    330 
    331     affineTransformDecompose(from, srA);
    332     affineTransformDecompose(*this, srB);
    333 
    334     // If x-axis of one is flipped, and y-axis of the other, convert to an unflipped rotation.
    335     if ((srA[0] < 0 && srB[1] < 0) || (srA[1] < 0 &&  srB[0] < 0)) {
    336         srA[0] = -srA[0];
    337         srA[1] = -srA[1];
    338         srA[2] += srA[2] < 0 ? piDouble : -piDouble;
    339     }
    340 
    341     // Don't rotate the long way around.
    342     srA[2] = fmod(srA[2], 2.0 * piDouble);
    343     srB[2] = fmod(srB[2], 2.0 * piDouble);
    344 
    345     if (fabs(srA[2] - srB[2]) > piDouble) {
    346         if (srA[2] > srB[2])
    347             srA[2] -= piDouble * 2.0;
    348         else
    349             srB[2] -= piDouble * 2.0;
    350     }
    351 
    352     for (int i = 0; i < 9; i++)
    353         srA[i] = srA[i] + progress * (srB[i] - srA[i]);
    354 
    355     affineTransformCompose(*this, srA);
    356 }
    357 
    358 TransformationMatrix AffineTransform::toTransformationMatrix() const
    359 {
    360     return TransformationMatrix(m_transform[0], m_transform[1], m_transform[2],
    361                                 m_transform[3], m_transform[4], m_transform[5]);
    362 }
    363 
    364 }
    365