Home | History | Annotate | Download | only in transforms
      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 
     69     TransformationMatrix() { makeIdentity(); }
     70     TransformationMatrix(const TransformationMatrix& t) { *this = t; }
     71     TransformationMatrix(double a, double b, double c, double d, double e, double f) { setMatrix(a, b, c, d, e, f); }
     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 
     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 
     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 
    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 
    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
    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.
    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 
    156     double m11() const { return m_matrix[0][0]; }
    157     void setM11(double f) { m_matrix[0][0] = f; }
    158     double m12() const { return m_matrix[0][1]; }
    159     void setM12(double f) { m_matrix[0][1] = f; }
    160     double m13() const { return m_matrix[0][2]; }
    161     void setM13(double f) { m_matrix[0][2] = f; }
    162     double m14() const { return m_matrix[0][3]; }
    163     void setM14(double f) { m_matrix[0][3] = f; }
    164     double m21() const { return m_matrix[1][0]; }
    165     void setM21(double f) { m_matrix[1][0] = f; }
    166     double m22() const { return m_matrix[1][1]; }
    167     void setM22(double f) { m_matrix[1][1] = f; }
    168     double m23() const { return m_matrix[1][2]; }
    169     void setM23(double f) { m_matrix[1][2] = f; }
    170     double m24() const { return m_matrix[1][3]; }
    171     void setM24(double f) { m_matrix[1][3] = f; }
    172     double m31() const { return m_matrix[2][0]; }
    173     void setM31(double f) { m_matrix[2][0] = f; }
    174     double m32() const { return m_matrix[2][1]; }
    175     void setM32(double f) { m_matrix[2][1] = f; }
    176     double m33() const { return m_matrix[2][2]; }
    177     void setM33(double f) { m_matrix[2][2] = f; }
    178     double m34() const { return m_matrix[2][3]; }
    179     void setM34(double f) { m_matrix[2][3] = f; }
    180     double m41() const { return m_matrix[3][0]; }
    181     void setM41(double f) { m_matrix[3][0] = f; }
    182     double m42() const { return m_matrix[3][1]; }
    183     void setM42(double f) { m_matrix[3][1] = f; }
    184     double m43() const { return m_matrix[3][2]; }
    185     void setM43(double f) { m_matrix[3][2] = f; }
    186     double m44() const { return m_matrix[3][3]; }
    187     void setM44(double f) { m_matrix[3][3] = f; }
    188 
    189     double a() const { return m_matrix[0][0]; }
    190     void setA(double a) { m_matrix[0][0] = a; }
    191 
    192     double b() const { return m_matrix[0][1]; }
    193     void setB(double b) { m_matrix[0][1] = b; }
    194 
    195     double c() const { return m_matrix[1][0]; }
    196     void setC(double c) { m_matrix[1][0] = c; }
    197 
    198     double d() const { return m_matrix[1][1]; }
    199     void setD(double d) { m_matrix[1][1] = d; }
    200 
    201     double e() const { return m_matrix[3][0]; }
    202     void setE(double e) { m_matrix[3][0] = e; }
    203 
    204     double f() const { return m_matrix[3][1]; }
    205     void setF(double f) { m_matrix[3][1] = f; }
    206 
    207     // this = this * mat
    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 
    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);
    235     TransformationMatrix& skewX(double angle) { return skew(angle, 0); }
    236     TransformationMatrix& skewY(double angle) { return skew(0, angle); }
    237 
    238     TransformationMatrix& applyPerspective(double p);
    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 
    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 
    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 
    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