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.
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_ */