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