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 "FloatPoint.h"
     30 #include "IntPoint.h"
     31 #include <string.h> //for memcpy
     32 #include <wtf/FastAllocBase.h>
     33 
     34 #if USE(CA)
     35 typedef struct CATransform3D CATransform3D;
     36 #endif
     37 #if USE(CG)
     38 typedef struct CGAffineTransform CGAffineTransform;
     39 #elif USE(CAIRO)
     40 #include <cairo.h>
     41 #elif PLATFORM(OPENVG)
     42 #include "VGUtils.h"
     43 #elif PLATFORM(QT)
     44 #include <QTransform>
     45 #elif USE(SKIA)
     46 #include <SkMatrix.h>
     47 #elif PLATFORM(WX) && USE(WXGC)
     48 #include <wx/graphics.h>
     49 #endif
     50 
     51 #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS))
     52 #if COMPILER(MINGW) && !COMPILER(MINGW64)
     53 typedef struct _XFORM XFORM;
     54 #else
     55 typedef struct tagXFORM XFORM;
     56 #endif
     57 #endif
     58 
     59 namespace WebCore {
     60 
     61 class AffineTransform;
     62 class IntRect;
     63 class FloatPoint3D;
     64 class FloatRect;
     65 class FloatQuad;
     66 
     67 class TransformationMatrix {
     68     WTF_MAKE_FAST_ALLOCATED;
     69 public:
     70     typedef double Matrix4[4][4];
     71 
     72     TransformationMatrix() { makeIdentity(); }
     73     TransformationMatrix(const TransformationMatrix& t) { *this = t; }
     74     TransformationMatrix(double a, double b, double c, double d, double e, double f) { setMatrix(a, b, c, d, e, f); }
     75     TransformationMatrix(double m11, double m12, double m13, double m14,
     76                          double m21, double m22, double m23, double m24,
     77                          double m31, double m32, double m33, double m34,
     78                          double m41, double m42, double m43, double m44)
     79     {
     80         setMatrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
     81     }
     82 
     83     void setMatrix(double a, double b, double c, double d, double e, double f)
     84     {
     85         m_matrix[0][0] = a; m_matrix[0][1] = b; m_matrix[0][2] = 0; m_matrix[0][3] = 0;
     86         m_matrix[1][0] = c; m_matrix[1][1] = d; m_matrix[1][2] = 0; m_matrix[1][3] = 0;
     87         m_matrix[2][0] = 0; m_matrix[2][1] = 0; m_matrix[2][2] = 1; m_matrix[2][3] = 0;
     88         m_matrix[3][0] = e; m_matrix[3][1] = f; m_matrix[3][2] = 0; m_matrix[3][3] = 1;
     89     }
     90 
     91     void setMatrix(double m11, double m12, double m13, double m14,
     92                    double m21, double m22, double m23, double m24,
     93                    double m31, double m32, double m33, double m34,
     94                    double m41, double m42, double m43, double m44)
     95     {
     96         m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13; m_matrix[0][3] = m14;
     97         m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23; m_matrix[1][3] = m24;
     98         m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33; m_matrix[2][3] = m34;
     99         m_matrix[3][0] = m41; m_matrix[3][1] = m42; m_matrix[3][2] = m43; m_matrix[3][3] = m44;
    100     }
    101 
    102     TransformationMatrix& operator =(const TransformationMatrix &t)
    103     {
    104         setMatrix(t.m_matrix);
    105         return *this;
    106     }
    107 
    108     TransformationMatrix& makeIdentity()
    109     {
    110         setMatrix(1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1);
    111         return *this;
    112     }
    113 
    114     bool isIdentity() const
    115     {
    116         return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 &&
    117                m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 &&
    118                m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 &&
    119                m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0 && m_matrix[3][3] == 1;
    120     }
    121 
    122     // This form preserves the double math from input to output
    123     void map(double x, double y, double& x2, double& y2) const { multVecMatrix(x, y, x2, y2); }
    124 
    125     // Map a 3D point through the transform, returning a 3D point.
    126     FloatPoint3D mapPoint(const FloatPoint3D&) const;
    127 
    128     // Map a 2D point through the transform, returning a 2D point.
    129     // Note that this ignores the z component, effectively projecting the point into the z=0 plane.
    130     FloatPoint mapPoint(const FloatPoint&) const;
    131 
    132     // Like the version above, except that it rounds the mapped point to the nearest integer value.
    133     IntPoint mapPoint(const IntPoint& p) const
    134     {
    135         return roundedIntPoint(mapPoint(FloatPoint(p)));
    136     }
    137 
    138     // If the matrix has 3D components, the z component of the result is
    139     // dropped, effectively projecting the rect into the z=0 plane
    140     FloatRect mapRect(const FloatRect&) const;
    141 
    142     // Rounds the resulting mapped rectangle out. This is helpful for bounding
    143     // box computations but may not be what is wanted in other contexts.
    144     IntRect mapRect(const IntRect&) const;
    145 
    146     // If the matrix has 3D components, the z component of the result is
    147     // dropped, effectively projecting the quad into the z=0 plane
    148     FloatQuad mapQuad(const FloatQuad&) const;
    149 
    150     // Map a point on the z=0 plane into a point on
    151     // the plane with with the transform applied, by extending
    152     // a ray perpendicular to the source plane and computing
    153     // the local x,y position of the point where that ray intersects
    154     // with the destination plane.
    155     FloatPoint projectPoint(const FloatPoint&) const;
    156     // Projects the four corners of the quad
    157     FloatQuad projectQuad(const FloatQuad&) const;
    158 
    159     double m11() const { return m_matrix[0][0]; }
    160     void setM11(double f) { m_matrix[0][0] = f; }
    161     double m12() const { return m_matrix[0][1]; }
    162     void setM12(double f) { m_matrix[0][1] = f; }
    163     double m13() const { return m_matrix[0][2]; }
    164     void setM13(double f) { m_matrix[0][2] = f; }
    165     double m14() const { return m_matrix[0][3]; }
    166     void setM14(double f) { m_matrix[0][3] = f; }
    167     double m21() const { return m_matrix[1][0]; }
    168     void setM21(double f) { m_matrix[1][0] = f; }
    169     double m22() const { return m_matrix[1][1]; }
    170     void setM22(double f) { m_matrix[1][1] = f; }
    171     double m23() const { return m_matrix[1][2]; }
    172     void setM23(double f) { m_matrix[1][2] = f; }
    173     double m24() const { return m_matrix[1][3]; }
    174     void setM24(double f) { m_matrix[1][3] = f; }
    175     double m31() const { return m_matrix[2][0]; }
    176     void setM31(double f) { m_matrix[2][0] = f; }
    177     double m32() const { return m_matrix[2][1]; }
    178     void setM32(double f) { m_matrix[2][1] = f; }
    179     double m33() const { return m_matrix[2][2]; }
    180     void setM33(double f) { m_matrix[2][2] = f; }
    181     double m34() const { return m_matrix[2][3]; }
    182     void setM34(double f) { m_matrix[2][3] = f; }
    183     double m41() const { return m_matrix[3][0]; }
    184     void setM41(double f) { m_matrix[3][0] = f; }
    185     double m42() const { return m_matrix[3][1]; }
    186     void setM42(double f) { m_matrix[3][1] = f; }
    187     double m43() const { return m_matrix[3][2]; }
    188     void setM43(double f) { m_matrix[3][2] = f; }
    189     double m44() const { return m_matrix[3][3]; }
    190     void setM44(double f) { m_matrix[3][3] = f; }
    191 
    192     double a() const { return m_matrix[0][0]; }
    193     void setA(double a) { m_matrix[0][0] = a; }
    194 
    195     double b() const { return m_matrix[0][1]; }
    196     void setB(double b) { m_matrix[0][1] = b; }
    197 
    198     double c() const { return m_matrix[1][0]; }
    199     void setC(double c) { m_matrix[1][0] = c; }
    200 
    201     double d() const { return m_matrix[1][1]; }
    202     void setD(double d) { m_matrix[1][1] = d; }
    203 
    204     double e() const { return m_matrix[3][0]; }
    205     void setE(double e) { m_matrix[3][0] = e; }
    206 
    207     double f() const { return m_matrix[3][1]; }
    208     void setF(double f) { m_matrix[3][1] = f; }
    209 
    210     // this = this * mat
    211     TransformationMatrix& multiply(const TransformationMatrix&);
    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
    298     TransformationMatrix& operator*=(const TransformationMatrix& t)
    299     {
    300         return multiply(t);
    301     }
    302 
    303     // result = *this * t
    304     TransformationMatrix operator*(const TransformationMatrix& t) const
    305     {
    306         TransformationMatrix result = *this;
    307         result.multiply(t);
    308         return result;
    309     }
    310 
    311 #if USE(CA)
    312     TransformationMatrix(const CATransform3D&);
    313     operator CATransform3D() const;
    314 #endif
    315 #if USE(CG)
    316     TransformationMatrix(const CGAffineTransform&);
    317     operator CGAffineTransform() const;
    318 #elif USE(CAIRO)
    319     operator cairo_matrix_t() const;
    320 #elif PLATFORM(OPENVG)
    321     operator VGMatrix() const;
    322 #elif PLATFORM(QT)
    323     operator QTransform() const;
    324 #elif USE(SKIA)
    325     operator SkMatrix() const;
    326 #elif PLATFORM(WX) && USE(WXGC)
    327     operator wxGraphicsMatrix() const;
    328 #endif
    329 
    330 #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS))
    331     operator XFORM() const;
    332 #endif
    333 
    334     bool isIdentityOrTranslation() const
    335     {
    336         return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0
    337             && m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0
    338             && m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0
    339             && m_matrix[3][3] == 1;
    340     }
    341 
    342 private:
    343     // multiply passed 2D point by matrix (assume z=0)
    344     void multVecMatrix(double x, double y, double& dstX, double& dstY) const;
    345 
    346     // multiply passed 3D point by matrix
    347     void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const;
    348 
    349     void setMatrix(const Matrix4 m)
    350     {
    351         if (m && m != m_matrix)
    352             memcpy(m_matrix, m, sizeof(Matrix4));
    353     }
    354 
    355     Matrix4 m_matrix;
    356 };
    357 
    358 } // namespace WebCore
    359 
    360 #endif // TransformationMatrix_h
    361