gfx/2d/Matrix.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef MOZILLA_GFX_MATRIX_H_
     7 #define MOZILLA_GFX_MATRIX_H_
     9 #include "Types.h"
    10 #include "Rect.h"
    11 #include "Point.h"
    12 #include <math.h>
    14 namespace mozilla {
    15 namespace gfx {
    17 class Matrix
    18 {
    19 public:
    20   Matrix()
    21     : _11(1.0f), _12(0)
    22     , _21(0), _22(1.0f)
    23     , _31(0), _32(0)
    24   {}
    25   Matrix(Float a11, Float a12, Float a21, Float a22, Float a31, Float a32)
    26     : _11(a11), _12(a12)
    27     , _21(a21), _22(a22)
    28     , _31(a31), _32(a32)
    29   {}
    30   Float _11, _12;
    31   Float _21, _22;
    32   Float _31, _32;
    34   Point operator *(const Point &aPoint) const
    35   {
    36     Point retPoint;
    38     retPoint.x = aPoint.x * _11 + aPoint.y * _21 + _31;
    39     retPoint.y = aPoint.x * _12 + aPoint.y * _22 + _32;
    41     return retPoint;
    42   }
    44   Size operator *(const Size &aSize) const
    45   {
    46     Size retSize;
    48     retSize.width = aSize.width * _11 + aSize.height * _21;
    49     retSize.height = aSize.width * _12 + aSize.height * _22;
    51     return retSize;
    52   }
    54   GFX2D_API Rect TransformBounds(const Rect& rect) const;
    56   // Apply a scale to this matrix. This scale will be applied -before- the
    57   // existing transformation of the matrix.
    58   Matrix &Scale(Float aX, Float aY)
    59   {
    60     _11 *= aX;
    61     _12 *= aX;
    62     _21 *= aY;
    63     _22 *= aY;
    65     return *this;
    66   }
    68   Matrix &Translate(Float aX, Float aY)
    69   {
    70     _31 += _11 * aX + _21 * aY;
    71     _32 += _12 * aX + _22 * aY;
    73     return *this;
    74   }
    76   Matrix &PostTranslate(Float aX, Float aY)
    77   {
    78     _31 += aX;
    79     _32 += aY;
    80     return *this;
    81   }
    83   Matrix &Rotate(Float aAngle)
    84   {
    85     return *this = Matrix::Rotation(aAngle) * *this;
    86   }
    88   bool Invert()
    89   {
    90     // Compute co-factors.
    91     Float A = _22;
    92     Float B = -_21;
    93     Float C = _21 * _32 - _22 * _31;
    94     Float D = -_12;
    95     Float E = _11;
    96     Float F = _31 * _12 - _11 * _32;
    98     Float det = Determinant();
   100     if (!det) {
   101       return false;
   102     }
   104     Float inv_det = 1 / det;
   106     _11 = inv_det * A;
   107     _12 = inv_det * D;
   108     _21 = inv_det * B;
   109     _22 = inv_det * E;
   110     _31 = inv_det * C;
   111     _32 = inv_det * F;
   113     return true;
   114   }
   116   Float Determinant() const
   117   {
   118     return _11 * _22 - _12 * _21;
   119   }
   121   static Matrix Translation(Float aX, Float aY)
   122   {
   123     return Matrix(1.0f, 0.0f, 0.0f, 1.0f, aX, aY);
   124   }
   126   static Matrix Translation(Point aPoint)
   127   {
   128     return Translation(aPoint.x, aPoint.y);
   129   }
   131   GFX2D_API static Matrix Rotation(Float aAngle);
   133   static Matrix Scaling(Float aX, Float aY)
   134   {
   135     return Matrix(aX, 0.0f, 0.0f, aY, 0.0f, 0.0f);
   136   }
   138   Matrix operator*(const Matrix &aMatrix) const
   139   {
   140     Matrix resultMatrix;
   142     resultMatrix._11 = this->_11 * aMatrix._11 + this->_12 * aMatrix._21;
   143     resultMatrix._12 = this->_11 * aMatrix._12 + this->_12 * aMatrix._22;
   144     resultMatrix._21 = this->_21 * aMatrix._11 + this->_22 * aMatrix._21;
   145     resultMatrix._22 = this->_21 * aMatrix._12 + this->_22 * aMatrix._22;
   146     resultMatrix._31 = this->_31 * aMatrix._11 + this->_32 * aMatrix._21 + aMatrix._31;
   147     resultMatrix._32 = this->_31 * aMatrix._12 + this->_32 * aMatrix._22 + aMatrix._32;
   149     return resultMatrix;
   150   }
   152   Matrix& operator*=(const Matrix &aMatrix)
   153   {
   154     Matrix resultMatrix = *this * aMatrix;
   155     return *this = resultMatrix;
   156   }
   158   /* Returns true if the other matrix is fuzzy-equal to this matrix.
   159    * Note that this isn't a cheap comparison!
   160    */
   161   bool operator==(const Matrix& other) const
   162   {
   163     return FuzzyEqual(_11, other._11) && FuzzyEqual(_12, other._12) &&
   164            FuzzyEqual(_21, other._21) && FuzzyEqual(_22, other._22) &&
   165            FuzzyEqual(_31, other._31) && FuzzyEqual(_32, other._32);
   166   }
   168   bool operator!=(const Matrix& other) const
   169   {
   170     return !(*this == other);
   171   }
   173   /* Returns true if the matrix is a rectilinear transformation (i.e.
   174    * grid-aligned rectangles are transformed to grid-aligned rectangles)
   175    */
   176   bool IsRectilinear() const {
   177     if (FuzzyEqual(_12, 0) && FuzzyEqual(_21, 0)) {
   178       return true;
   179     } else if (FuzzyEqual(_22, 0) && FuzzyEqual(_11, 0)) {
   180       return true;
   181     }
   183     return false;
   184   }
   186   /**
   187    * Returns true if the matrix is anything other than a straight
   188    * translation by integers.
   189   */
   190   bool HasNonIntegerTranslation() const {
   191     return HasNonTranslation() ||
   192       !FuzzyEqual(_31, floor(_31 + 0.5)) ||
   193       !FuzzyEqual(_32, floor(_32 + 0.5));
   194   }
   196   /**
   197    * Returns true if the matrix has any transform other
   198    * than a straight translation.
   199    */
   200   bool HasNonTranslation() const {
   201     return !FuzzyEqual(_11, 1.0) || !FuzzyEqual(_22, 1.0) ||
   202            !FuzzyEqual(_12, 0.0) || !FuzzyEqual(_21, 0.0);
   203   }
   205   /* Returns true if the matrix is an identity matrix.
   206    */
   207   bool IsIdentity() const
   208   {
   209     return _11 == 1.0f && _12 == 0.0f &&
   210            _21 == 0.0f && _22 == 1.0f &&
   211            _31 == 0.0f && _32 == 0.0f;
   212   }
   214   /* Returns true if the matrix is singular.
   215    */
   216   bool IsSingular() const
   217   {
   218     return Determinant() == 0;
   219   }
   221   GFX2D_API void NudgeToIntegers();
   223   bool IsTranslation() const
   224   {
   225     return FuzzyEqual(_11, 1.0f) && FuzzyEqual(_12, 0.0f) &&
   226            FuzzyEqual(_21, 0.0f) && FuzzyEqual(_22, 1.0f);
   227   }
   229   bool IsIntegerTranslation() const
   230   {
   231     return IsTranslation() &&
   232            FuzzyEqual(_31, floorf(_31 + 0.5f)) &&
   233            FuzzyEqual(_32, floorf(_32 + 0.5f));
   234   }
   236   Point GetTranslation() const {
   237     return Point(_31, _32);
   238   }
   240   /**
   241    * Returns true if matrix is multiple of 90 degrees rotation with flipping,
   242    * scaling and translation.
   243    */
   244   bool PreservesAxisAlignedRectangles() const {
   245       return ((FuzzyEqual(_11, 0.0) && FuzzyEqual(_22, 0.0))
   246           || (FuzzyEqual(_12, 0.0) && FuzzyEqual(_21, 0.0)));
   247   }
   249   /**
   250    * Returns true if the matrix has any transform other
   251    * than a translation or scale; this is, if there is
   252    * no rotation.
   253    */
   254   bool HasNonAxisAlignedTransform() const {
   255       return !FuzzyEqual(_21, 0.0) || !FuzzyEqual(_12, 0.0);
   256   }
   258   /**
   259    * Returns true if the matrix has non-integer scale
   260    */
   261   bool HasNonIntegerScale() const {
   262       return !FuzzyEqual(_11, floor(_11 + 0.5)) ||
   263              !FuzzyEqual(_22, floor(_22 + 0.5));
   264   }
   266 private:
   267   static bool FuzzyEqual(Float aV1, Float aV2) {
   268     // XXX - Check if fabs does the smart thing and just negates the sign bit.
   269     return fabs(aV2 - aV1) < 1e-6;
   270   }
   271 };
   273 class Matrix4x4
   274 {
   275 public:
   276   Matrix4x4()
   277     : _11(1.0f), _12(0.0f), _13(0.0f), _14(0.0f)
   278     , _21(0.0f), _22(1.0f), _23(0.0f), _24(0.0f)
   279     , _31(0.0f), _32(0.0f), _33(1.0f), _34(0.0f)
   280     , _41(0.0f), _42(0.0f), _43(0.0f), _44(1.0f)
   281   {}
   283   Float _11, _12, _13, _14;
   284   Float _21, _22, _23, _24;
   285   Float _31, _32, _33, _34;
   286   Float _41, _42, _43, _44;
   288   /**
   289    * Returns true if the matrix is isomorphic to a 2D affine transformation.
   290    */
   291   bool Is2D() const
   292   {
   293     if (_13 != 0.0f || _14 != 0.0f ||
   294         _23 != 0.0f || _24 != 0.0f ||
   295         _31 != 0.0f || _32 != 0.0f || _33 != 1.0f || _34 != 0.0f ||
   296         _43 != 0.0f || _44 != 1.0f) {
   297       return false;
   298     }
   299     return true;
   300   }
   302   bool Is2D(Matrix* aMatrix) const {
   303     if (!Is2D()) {
   304       return false;
   305     }
   306     if (aMatrix) {
   307       aMatrix->_11 = _11;
   308       aMatrix->_12 = _12;
   309       aMatrix->_21 = _21;
   310       aMatrix->_22 = _22;
   311       aMatrix->_31 = _41;
   312       aMatrix->_32 = _42;
   313     }
   314     return true;
   315   }
   317   Matrix As2D() const
   318   {
   319     MOZ_ASSERT(Is2D(), "Matrix is not a 2D affine transform");
   321     return Matrix(_11, _12, _21, _22, _41, _42);
   322   }
   324   bool CanDraw2D(Matrix* aMatrix = nullptr) const {
   325     if (_14 != 0.0f ||
   326         _24 != 0.0f ||
   327         _44 != 1.0f) {
   328       return false;
   329     }
   330     if (aMatrix) {
   331       aMatrix->_11 = _11;
   332       aMatrix->_12 = _12;
   333       aMatrix->_21 = _21;
   334       aMatrix->_22 = _22;
   335       aMatrix->_31 = _41;
   336       aMatrix->_32 = _42;
   337     }
   338     return true;
   339   }
   341   Matrix4x4& ProjectTo2D() {
   342     _31 = 0.0f;
   343     _32 = 0.0f;
   344     _13 = 0.0f;
   345     _23 = 0.0f;
   346     _33 = 1.0f;
   347     _43 = 0.0f;
   348     _34 = 0.0f;
   349     return *this;
   350   }
   352   static Matrix4x4 From2D(const Matrix &aMatrix) {
   353     Matrix4x4 matrix;
   354     matrix._11 = aMatrix._11;
   355     matrix._12 = aMatrix._12;
   356     matrix._21 = aMatrix._21;
   357     matrix._22 = aMatrix._22;
   358     matrix._41 = aMatrix._31;
   359     matrix._42 = aMatrix._32;
   360     return matrix;
   361   }
   363   bool Is2DIntegerTranslation() const
   364   {
   365     return Is2D() && As2D().IsIntegerTranslation();
   366   }
   368   Point4D operator *(const Point4D& aPoint) const
   369   {
   370     Point4D retPoint;
   372     retPoint.x = aPoint.x * _11 + aPoint.y * _21 + aPoint.z * _31 + _41;
   373     retPoint.y = aPoint.x * _12 + aPoint.y * _22 + aPoint.z * _32 + _42;
   374     retPoint.z = aPoint.x * _13 + aPoint.y * _23 + aPoint.z * _33 + _43;
   375     retPoint.w = aPoint.x * _14 + aPoint.y * _24 + aPoint.z * _34 + _44;
   377     return retPoint;
   378   }
   380   Point3D operator *(const Point3D& aPoint) const
   381   {
   382     Point4D temp(aPoint.x, aPoint.y, aPoint.z, 1);
   384     temp = *this * temp;
   385     temp /= temp.w;
   387     return Point3D(temp.x, temp.y, temp.z);
   388   }
   390   Point operator *(const Point &aPoint) const
   391   {
   392     Point4D temp(aPoint.x, aPoint.y, 0, 1);
   394     temp = *this * temp;
   395     temp /= temp.w;
   397     return Point(temp.x, temp.y);
   398   }
   400   GFX2D_API Rect TransformBounds(const Rect& rect) const;
   402   // Apply a scale to this matrix. This scale will be applied -before- the
   403   // existing transformation of the matrix.
   404   Matrix4x4 &Scale(Float aX, Float aY, Float aZ)
   405   {
   406     _11 *= aX;
   407     _12 *= aX;
   408     _13 *= aX;
   409     _21 *= aY;
   410     _22 *= aY;
   411     _23 *= aY;
   412     _31 *= aZ;
   413     _32 *= aZ;
   414     _33 *= aZ;
   416     return *this;
   417   }
   419   Matrix4x4 &Translate(Float aX, Float aY, Float aZ)
   420   {
   421     _41 += aX * _11 + aY * _21 + aZ * _31;
   422     _42 += aX * _12 + aY * _22 + aZ * _32;
   423     _43 += aX * _13 + aY * _23 + aZ * _33;
   424     _44 += aX * _14 + aY * _24 + aZ * _34;
   426     return *this;
   427   }
   429   bool operator==(const Matrix4x4& o) const
   430   {
   431     // XXX would be nice to memcmp here, but that breaks IEEE 754 semantics
   432     return _11 == o._11 && _12 == o._12 && _13 == o._13 && _14 == o._14 &&
   433            _21 == o._21 && _22 == o._22 && _23 == o._23 && _24 == o._24 &&
   434            _31 == o._31 && _32 == o._32 && _33 == o._33 && _34 == o._34 &&
   435            _41 == o._41 && _42 == o._42 && _43 == o._43 && _44 == o._44;
   436   }
   438   bool operator!=(const Matrix4x4& o) const
   439   {
   440     return !((*this) == o);
   441   }
   443   Matrix4x4 operator*(const Matrix4x4 &aMatrix) const
   444   {
   445     Matrix4x4 matrix;
   447     matrix._11 = _11 * aMatrix._11 + _12 * aMatrix._21 + _13 * aMatrix._31 + _14 * aMatrix._41;
   448     matrix._21 = _21 * aMatrix._11 + _22 * aMatrix._21 + _23 * aMatrix._31 + _24 * aMatrix._41;
   449     matrix._31 = _31 * aMatrix._11 + _32 * aMatrix._21 + _33 * aMatrix._31 + _34 * aMatrix._41;
   450     matrix._41 = _41 * aMatrix._11 + _42 * aMatrix._21 + _43 * aMatrix._31 + _44 * aMatrix._41;
   451     matrix._12 = _11 * aMatrix._12 + _12 * aMatrix._22 + _13 * aMatrix._32 + _14 * aMatrix._42;
   452     matrix._22 = _21 * aMatrix._12 + _22 * aMatrix._22 + _23 * aMatrix._32 + _24 * aMatrix._42;
   453     matrix._32 = _31 * aMatrix._12 + _32 * aMatrix._22 + _33 * aMatrix._32 + _34 * aMatrix._42;
   454     matrix._42 = _41 * aMatrix._12 + _42 * aMatrix._22 + _43 * aMatrix._32 + _44 * aMatrix._42;
   455     matrix._13 = _11 * aMatrix._13 + _12 * aMatrix._23 + _13 * aMatrix._33 + _14 * aMatrix._43;
   456     matrix._23 = _21 * aMatrix._13 + _22 * aMatrix._23 + _23 * aMatrix._33 + _24 * aMatrix._43;
   457     matrix._33 = _31 * aMatrix._13 + _32 * aMatrix._23 + _33 * aMatrix._33 + _34 * aMatrix._43;
   458     matrix._43 = _41 * aMatrix._13 + _42 * aMatrix._23 + _43 * aMatrix._33 + _44 * aMatrix._43;
   459     matrix._14 = _11 * aMatrix._14 + _12 * aMatrix._24 + _13 * aMatrix._34 + _14 * aMatrix._44;
   460     matrix._24 = _21 * aMatrix._14 + _22 * aMatrix._24 + _23 * aMatrix._34 + _24 * aMatrix._44;
   461     matrix._34 = _31 * aMatrix._14 + _32 * aMatrix._24 + _33 * aMatrix._34 + _34 * aMatrix._44;
   462     matrix._44 = _41 * aMatrix._14 + _42 * aMatrix._24 + _43 * aMatrix._34 + _44 * aMatrix._44;
   464     return matrix;
   465   }
   468   /* Returns true if the matrix is an identity matrix.
   469    */
   470   bool IsIdentity() const
   471   {
   472     return _11 == 1.0f && _12 == 0.0f && _13 == 0.0f && _14 == 0.0f &&
   473            _21 == 0.0f && _22 == 1.0f && _23 == 0.0f && _24 == 0.0f &&
   474            _31 == 0.0f && _32 == 0.0f && _33 == 1.0f && _34 == 0.0f &&
   475            _41 == 0.0f && _42 == 0.0f && _43 == 0.0f && _44 == 1.0f;
   476   }
   478   bool IsSingular() const
   479   {
   480     return Determinant() == 0.0;
   481   }
   483   Float Determinant() const
   484   {
   485     return _14 * _23 * _32 * _41
   486          - _13 * _24 * _32 * _41
   487          - _14 * _22 * _33 * _41
   488          + _12 * _24 * _33 * _41
   489          + _13 * _22 * _34 * _41
   490          - _12 * _23 * _34 * _41
   491          - _14 * _23 * _31 * _42
   492          + _13 * _24 * _31 * _42
   493          + _14 * _21 * _33 * _42
   494          - _11 * _24 * _33 * _42
   495          - _13 * _21 * _34 * _42
   496          + _11 * _23 * _34 * _42
   497          + _14 * _22 * _31 * _43
   498          - _12 * _24 * _31 * _43
   499          - _14 * _21 * _32 * _43
   500          + _11 * _24 * _32 * _43
   501          + _12 * _21 * _34 * _43
   502          - _11 * _22 * _34 * _43
   503          - _13 * _22 * _31 * _44
   504          + _12 * _23 * _31 * _44
   505          + _13 * _21 * _32 * _44
   506          - _11 * _23 * _32 * _44
   507          - _12 * _21 * _33 * _44
   508          + _11 * _22 * _33 * _44;
   509   }
   511 };
   513 class Matrix5x4
   514 {
   515 public:
   516   Matrix5x4()
   517     : _11(1.0f), _12(0), _13(0), _14(0)
   518     , _21(0), _22(1.0f), _23(0), _24(0)
   519     , _31(0), _32(0), _33(1.0f), _34(0)
   520     , _41(0), _42(0), _43(0), _44(1.0f)
   521     , _51(0), _52(0), _53(0), _54(0)
   522   {}
   523   Matrix5x4(Float a11, Float a12, Float a13, Float a14,
   524          Float a21, Float a22, Float a23, Float a24,
   525          Float a31, Float a32, Float a33, Float a34,
   526          Float a41, Float a42, Float a43, Float a44,
   527          Float a51, Float a52, Float a53, Float a54)
   528     : _11(a11), _12(a12), _13(a13), _14(a14)
   529     , _21(a21), _22(a22), _23(a23), _24(a24)
   530     , _31(a31), _32(a32), _33(a33), _34(a34)
   531     , _41(a41), _42(a42), _43(a43), _44(a44)
   532     , _51(a51), _52(a52), _53(a53), _54(a54)
   533   {}
   534   Float _11, _12, _13, _14;
   535   Float _21, _22, _23, _24;
   536   Float _31, _32, _33, _34;
   537   Float _41, _42, _43, _44;
   538   Float _51, _52, _53, _54;
   539 };
   541 }
   542 }
   544 #endif /* MOZILLA_GFX_MATRIX_H_ */

mercurial