18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef TransformationMatrix_h
27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#define TransformationMatrix_h
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "FloatPoint.h"
305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "IntPoint.h"
315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include <string.h> //for memcpy
32643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <wtf/FastAllocBase.h>
335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CA)
3581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochtypedef struct CATransform3D CATransform3D;
36f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CG)
3881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochtypedef struct CGAffineTransform CGAffineTransform;
392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#elif USE(CAIRO)
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <cairo.h>
41d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif PLATFORM(OPENVG)
42d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "VGUtils.h"
438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#elif PLATFORM(QT)
448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <QTransform>
4581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#elif USE(SKIA)
468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <SkMatrix.h>
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#elif PLATFORM(WX) && USE(WXGC)
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wx/graphics.h>
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
51d0825bca7fe65beaee391d30da42e937db621564Steve Block#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS))
5221939df44de1705786c545cd1bf519d47250322dBen Murdoch#if COMPILER(MINGW) && !COMPILER(MINGW64)
53d0825bca7fe65beaee391d30da42e937db621564Steve Blocktypedef struct _XFORM XFORM;
54d0825bca7fe65beaee391d30da42e937db621564Steve Block#else
55d0825bca7fe65beaee391d30da42e937db621564Steve Blocktypedef struct tagXFORM XFORM;
56d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif
57d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif
58d0825bca7fe65beaee391d30da42e937db621564Steve Block
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
618a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Blockclass AffineTransform;
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectclass IntRect;
638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianclass FloatPoint3D;
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectclass FloatRect;
65635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectclass FloatQuad;
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
67ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochclass TransformationMatrix {
68ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WTF_MAKE_FAST_ALLOCATED;
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic:
708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    typedef double Matrix4[4][4];
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix() { makeIdentity(); }
738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix(const TransformationMatrix& t) { *this = t; }
748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix(double a, double b, double c, double d, double e, double f) { setMatrix(a, b, c, d, e, f); }
758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix(double m11, double m12, double m13, double m14,
768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                         double m21, double m22, double m23, double m24,
778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                         double m31, double m32, double m33, double m34,
788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                         double m41, double m42, double m43, double m44)
798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        setMatrix(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setMatrix(double a, double b, double c, double d, double e, double f)
848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[0][0] = a; m_matrix[0][1] = b; m_matrix[0][2] = 0; m_matrix[0][3] = 0;
868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[1][0] = c; m_matrix[1][1] = d; m_matrix[1][2] = 0; m_matrix[1][3] = 0;
878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[2][0] = 0; m_matrix[2][1] = 0; m_matrix[2][2] = 1; m_matrix[2][3] = 0;
888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[3][0] = e; m_matrix[3][1] = f; m_matrix[3][2] = 0; m_matrix[3][3] = 1;
898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setMatrix(double m11, double m12, double m13, double m14,
928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                   double m21, double m22, double m23, double m24,
938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                   double m31, double m32, double m33, double m34,
948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                   double m41, double m42, double m43, double m44)
958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13; m_matrix[0][3] = m14;
978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23; m_matrix[1][3] = m24;
988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33; m_matrix[2][3] = m34;
998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[3][0] = m41; m_matrix[3][1] = m42; m_matrix[3][2] = m43; m_matrix[3][3] = m44;
1008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& operator =(const TransformationMatrix &t)
1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        setMatrix(t.m_matrix);
1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return *this;
1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& makeIdentity()
1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        setMatrix(1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1);
1118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return *this;
1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool isIdentity() const
1158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
1168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 &&
1178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 &&
1188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 &&
1198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0 && m_matrix[3][3] == 1;
1208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // This form preserves the double math from input to output
1238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void map(double x, double y, double& x2, double& y2) const { multVecMatrix(x, y, x2, y2); }
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Map a 3D point through the transform, returning a 3D point.
1268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    FloatPoint3D mapPoint(const FloatPoint3D&) const;
1278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Map a 2D point through the transform, returning a 2D point.
1298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Note that this ignores the z component, effectively projecting the point into the z=0 plane.
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FloatPoint mapPoint(const FloatPoint&) const;
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Like the version above, except that it rounds the mapped point to the nearest integer value.
1335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    IntPoint mapPoint(const IntPoint& p) const
1345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return roundedIntPoint(mapPoint(FloatPoint(p)));
1365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // If the matrix has 3D components, the z component of the result is
1398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // dropped, effectively projecting the rect into the z=0 plane
1408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    FloatRect mapRect(const FloatRect&) const;
1418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Rounds the resulting mapped rectangle out. This is helpful for bounding
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // box computations but may not be what is wanted in other contexts.
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntRect mapRect(const IntRect&) const;
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // If the matrix has 3D components, the z component of the result is
1478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // dropped, effectively projecting the quad into the z=0 plane
148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    FloatQuad mapQuad(const FloatQuad&) const;
149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Map a point on the z=0 plane into a point on
1518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // the plane with with the transform applied, by extending
1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // a ray perpendicular to the source plane and computing
1538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // the local x,y position of the point where that ray intersects
1548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // with the destination plane.
1558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    FloatPoint projectPoint(const FloatPoint&) const;
1568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Projects the four corners of the quad
1578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    FloatQuad projectQuad(const FloatQuad&) const;
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m11() const { return m_matrix[0][0]; }
1608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM11(double f) { m_matrix[0][0] = f; }
1618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m12() const { return m_matrix[0][1]; }
1628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM12(double f) { m_matrix[0][1] = f; }
1638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m13() const { return m_matrix[0][2]; }
1648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM13(double f) { m_matrix[0][2] = f; }
1658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m14() const { return m_matrix[0][3]; }
1668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM14(double f) { m_matrix[0][3] = f; }
1678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m21() const { return m_matrix[1][0]; }
1688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM21(double f) { m_matrix[1][0] = f; }
1698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m22() const { return m_matrix[1][1]; }
1708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM22(double f) { m_matrix[1][1] = f; }
1718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m23() const { return m_matrix[1][2]; }
1728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM23(double f) { m_matrix[1][2] = f; }
1738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m24() const { return m_matrix[1][3]; }
1748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM24(double f) { m_matrix[1][3] = f; }
1758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m31() const { return m_matrix[2][0]; }
1768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM31(double f) { m_matrix[2][0] = f; }
1778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m32() const { return m_matrix[2][1]; }
1788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM32(double f) { m_matrix[2][1] = f; }
1798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m33() const { return m_matrix[2][2]; }
1808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM33(double f) { m_matrix[2][2] = f; }
1818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m34() const { return m_matrix[2][3]; }
1828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM34(double f) { m_matrix[2][3] = f; }
1838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m41() const { return m_matrix[3][0]; }
1848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM41(double f) { m_matrix[3][0] = f; }
1858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m42() const { return m_matrix[3][1]; }
1868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM42(double f) { m_matrix[3][1] = f; }
1878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m43() const { return m_matrix[3][2]; }
1888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM43(double f) { m_matrix[3][2] = f; }
1898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double m44() const { return m_matrix[3][3]; }
1908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setM44(double f) { m_matrix[3][3] = f; }
1918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double a() const { return m_matrix[0][0]; }
1938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setA(double a) { m_matrix[0][0] = a; }
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double b() const { return m_matrix[0][1]; }
1968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setB(double b) { m_matrix[0][1] = b; }
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double c() const { return m_matrix[1][0]; }
1998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setC(double c) { m_matrix[1][0] = c; }
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double d() const { return m_matrix[1][1]; }
2028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setD(double d) { m_matrix[1][1] = d; }
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double e() const { return m_matrix[3][0]; }
2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setE(double e) { m_matrix[3][0] = e; }
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double f() const { return m_matrix[3][1]; }
2088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setF(double f) { m_matrix[3][1] = f; }
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // this = this * mat
2112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    TransformationMatrix& multiply(const TransformationMatrix&);
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
213635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    TransformationMatrix& scale(double);
214635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    TransformationMatrix& scaleNonUniform(double sx, double sy);
2158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& scale3d(double sx, double sy, double sz);
2168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& rotate(double d) { return rotate3d(0, 0, d); }
218635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    TransformationMatrix& rotateFromVector(double x, double y);
2198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& rotate3d(double rx, double ry, double rz);
2208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // The vector (x,y,z) is normalized if it's not already. A vector of
2228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // (0,0,0) uses a vector of (0,0,1).
2238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& rotate3d(double x, double y, double z, double angle);
2248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
225635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    TransformationMatrix& translate(double tx, double ty);
2268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& translate3d(double tx, double ty, double tz);
2278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // translation added with a post-multiply
2298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& translateRight(double tx, double ty);
2308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& translateRight3d(double tx, double ty, double tz);
2318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
232635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    TransformationMatrix& flipX();
233635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    TransformationMatrix& flipY();
234635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    TransformationMatrix& skew(double angleX, double angleY);
2358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& skewX(double angle) { return skew(angle, 0); }
2368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& skewY(double angle) { return skew(0, angle); }
2378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& applyPerspective(double p);
2398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool hasPerspective() const { return m_matrix[2][3] != 0.0f; }
240635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // returns a transformation that maps a rect to a rect
2420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static TransformationMatrix rectToRect(const FloatRect&, const FloatRect&);
2430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool isInvertible() const;
2458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // This method returns the identity matrix if it is not invertible.
2478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Use isInvertible() before calling this if you need to know.
248635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    TransformationMatrix inverse() const;
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // decompose the matrix into its component parts
2518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    typedef struct {
2528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double scaleX, scaleY, scaleZ;
2538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double skewXY, skewXZ, skewYZ;
2548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double quaternionX, quaternionY, quaternionZ, quaternionW;
2558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double translateX, translateY, translateZ;
2568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double perspectiveX, perspectiveY, perspectiveZ, perspectiveW;
2578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } DecomposedType;
2588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool decompose(DecomposedType& decomp) const;
2608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void recompose(const DecomposedType& decomp);
2618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
262635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    void blend(const TransformationMatrix& from, double progress);
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool isAffine() const
2658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return (m13() == 0 && m14() == 0 && m23() == 0 && m24() == 0 &&
2678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m31() == 0 && m32() == 0 && m33() == 1 && m34() == 0 && m43() == 0 && m44() == 1);
2688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
2698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Throw away the non-affine parts of the matrix (lossy!)
2718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void makeAffine();
2728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2738a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    AffineTransform toAffineTransform() const;
2748a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
2758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool operator==(const TransformationMatrix& m2) const
2768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
2778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return (m_matrix[0][0] == m2.m_matrix[0][0] &&
2788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[0][1] == m2.m_matrix[0][1] &&
2798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[0][2] == m2.m_matrix[0][2] &&
2808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[0][3] == m2.m_matrix[0][3] &&
2818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[1][0] == m2.m_matrix[1][0] &&
2828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[1][1] == m2.m_matrix[1][1] &&
2838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[1][2] == m2.m_matrix[1][2] &&
2848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[1][3] == m2.m_matrix[1][3] &&
2858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[2][0] == m2.m_matrix[2][0] &&
2868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[2][1] == m2.m_matrix[2][1] &&
2878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[2][2] == m2.m_matrix[2][2] &&
2888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[2][3] == m2.m_matrix[2][3] &&
2898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[3][0] == m2.m_matrix[3][0] &&
2908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[3][1] == m2.m_matrix[3][1] &&
2918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[3][2] == m2.m_matrix[3][2] &&
2928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_matrix[3][3] == m2.m_matrix[3][3]);
2938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
295635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    bool operator!=(const TransformationMatrix& other) const { return !(*this == other); }
2962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // *this = *this * t
2988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix& operator*=(const TransformationMatrix& t)
2998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
3002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return multiply(t);
3018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
3028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // result = *this * t
3040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    TransformationMatrix operator*(const TransformationMatrix& t) const
3058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
3062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        TransformationMatrix result = *this;
3072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        result.multiply(t);
3088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return result;
3098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
310635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CA)
312f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    TransformationMatrix(const CATransform3D&);
313f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    operator CATransform3D() const;
314f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
3152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CG)
316f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    TransformationMatrix(const CGAffineTransform&);
3178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    operator CGAffineTransform() const;
3182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#elif USE(CAIRO)
3198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    operator cairo_matrix_t() const;
320d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif PLATFORM(OPENVG)
321d0825bca7fe65beaee391d30da42e937db621564Steve Block    operator VGMatrix() const;
3228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#elif PLATFORM(QT)
3238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    operator QTransform() const;
32481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#elif USE(SKIA)
3258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    operator SkMatrix() const;
3268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#elif PLATFORM(WX) && USE(WXGC)
3278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    operator wxGraphicsMatrix() const;
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
330d0825bca7fe65beaee391d30da42e937db621564Steve Block#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS))
3310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    operator XFORM() const;
3320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
3330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
334d0825bca7fe65beaee391d30da42e937db621564Steve Block    bool isIdentityOrTranslation() const
335d0825bca7fe65beaee391d30da42e937db621564Steve Block    {
336d0825bca7fe65beaee391d30da42e937db621564Steve Block        return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0
337d0825bca7fe65beaee391d30da42e937db621564Steve Block            && m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0
338d0825bca7fe65beaee391d30da42e937db621564Steve Block            && m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0
339d0825bca7fe65beaee391d30da42e937db621564Steve Block            && m_matrix[3][3] == 1;
340d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
341d0825bca7fe65beaee391d30da42e937db621564Steve Block
3428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianprivate:
3438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // multiply passed 2D point by matrix (assume z=0)
3448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void multVecMatrix(double x, double y, double& dstX, double& dstY) const;
345d0825bca7fe65beaee391d30da42e937db621564Steve Block
3468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // multiply passed 3D point by matrix
3478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const;
348d0825bca7fe65beaee391d30da42e937db621564Steve Block
3498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void setMatrix(const Matrix4 m)
3508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    {
3518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (m && m != m_matrix)
3528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            memcpy(m_matrix, m, sizeof(Matrix4));
3538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
354d0825bca7fe65beaee391d30da42e937db621564Steve Block
3558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Matrix4 m_matrix;
3568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian};
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
360635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif // TransformationMatrix_h
361