Bumping manifests a=b2g-bump
[gecko.git] / gfx / thebes / gfxMatrix.h
blob1af57ce20cb3bfd3344e602789126bf961b4b009
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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 GFX_MATRIX_H
7 #define GFX_MATRIX_H
9 #include "gfxPoint.h"
10 #include "gfxTypes.h"
11 #include "gfxRect.h"
13 // XX - I don't think this class should use gfxFloat at all,
14 // but should use 'double' and be called gfxDoubleMatrix;
15 // we can then typedef that to gfxMatrix where we typedef
16 // double to be gfxFloat.
18 /**
19 * A matrix that represents an affine transformation. Projective
20 * transformations are not supported. This matrix looks like:
22 * / a b 0 \
23 * | c d 0 |
24 * \ tx ty 1 /
26 * So, transforming a point (x, y) results in:
28 * / a b 0 \ / a * x + c * y + tx \ T
29 * (x y 1) * | c d 0 | = | b * x + d * y + ty |
30 * \ tx ty 1 / \ 1 /
33 class gfxMatrix {
34 public:
35 double _11; double _12;
36 double _21; double _22;
37 double _31; double _32;
39 /**
40 * Initializes this matrix as the identity matrix.
42 gfxMatrix() { Reset(); }
44 /**
45 * Initializes the matrix from individual components. See the class
46 * description for the layout of the matrix.
48 gfxMatrix(gfxFloat a, gfxFloat b, gfxFloat c, gfxFloat d, gfxFloat tx, gfxFloat ty) :
49 _11(a), _12(b),
50 _21(c), _22(d),
51 _31(tx), _32(ty) { }
53 friend std::ostream& operator<<(std::ostream& stream, const gfxMatrix& m) {
54 if (m.IsIdentity()) {
55 return stream << "[identity]";
58 return stream << "["
59 << m._11 << " " << m._12
60 << m._21 << " " << m._22
61 << m._31 << " " << m._32
62 << "]";
65 /**
66 * Post-multiplies m onto the matrix.
68 const gfxMatrix& operator *= (const gfxMatrix& m);
70 /**
71 * Multiplies *this with m and returns the result.
73 gfxMatrix operator * (const gfxMatrix& m) const {
74 return gfxMatrix(*this) *= m;
77 /* Returns true if the other matrix is fuzzy-equal to this matrix.
78 * Note that this isn't a cheap comparison!
80 bool operator==(const gfxMatrix& other) const
82 return FuzzyEqual(_11, other._11) && FuzzyEqual(_12, other._12) &&
83 FuzzyEqual(_21, other._21) && FuzzyEqual(_22, other._22) &&
84 FuzzyEqual(_31, other._31) && FuzzyEqual(_32, other._32);
87 bool operator!=(const gfxMatrix& other) const
89 return !(*this == other);
92 // matrix operations
93 /**
94 * Resets this matrix to the identity matrix.
96 const gfxMatrix& Reset();
98 bool IsIdentity() const {
99 return _11 == 1.0 && _12 == 0.0 &&
100 _21 == 0.0 && _22 == 1.0 &&
101 _31 == 0.0 && _32 == 0.0;
105 * Inverts this matrix, if possible. Otherwise, the matrix is left
106 * unchanged.
108 * XXX should this do something with the return value of
109 * cairo_matrix_invert?
111 bool Invert();
114 * Check if matrix is singular (no inverse exists).
116 bool IsSingular() const {
117 // if the determinant (ad - bc) is zero it's singular
118 return (_11 * _22) == (_12 * _21);
122 * Scales this matrix. The scale is pre-multiplied onto this matrix,
123 * i.e. the scaling takes place before the other transformations.
125 const gfxMatrix& Scale(gfxFloat x, gfxFloat y);
128 * Translates this matrix. The translation is pre-multiplied onto this matrix,
129 * i.e. the translation takes place before the other transformations.
131 const gfxMatrix& Translate(const gfxPoint& pt);
134 * Rotates this matrix. The rotation is pre-multiplied onto this matrix,
135 * i.e. the translation takes place after the other transformations.
137 * @param radians Angle in radians.
139 const gfxMatrix& Rotate(gfxFloat radians);
142 * Multiplies the current matrix with m.
143 * This is a pre-multiplication, i.e. the transformations of m are
144 * applied _before_ the existing transformations.
146 const gfxMatrix& PreMultiply(const gfxMatrix& m);
148 static gfxMatrix Translation(gfxFloat aX, gfxFloat aY)
150 return gfxMatrix(1.0, 0.0, 0.0, 1.0, aX, aY);
153 static gfxMatrix Translation(gfxPoint aPoint)
155 return Translation(aPoint.x, aPoint.y);
158 static gfxMatrix Rotation(gfxFloat aAngle);
160 static gfxMatrix Scaling(gfxFloat aX, gfxFloat aY)
162 return gfxMatrix(aX, 0.0, 0.0, aY, 0.0, 0.0);
166 * Transforms a point according to this matrix.
168 gfxPoint Transform(const gfxPoint& point) const;
172 * Transform a distance according to this matrix. This does not apply
173 * any translation components.
175 gfxSize Transform(const gfxSize& size) const;
178 * Transforms both the point and distance according to this matrix.
180 gfxRect Transform(const gfxRect& rect) const;
182 gfxRect TransformBounds(const gfxRect& rect) const;
185 * Returns the translation component of this matrix.
187 gfxPoint GetTranslation() const {
188 return gfxPoint(_31, _32);
192 * Returns true if the matrix is anything other than a straight
193 * translation by integers.
195 bool HasNonIntegerTranslation() const {
196 return HasNonTranslation() ||
197 !FuzzyEqual(_31, floor(_31 + 0.5)) ||
198 !FuzzyEqual(_32, floor(_32 + 0.5));
202 * Returns true if the matrix has any transform other
203 * than a straight translation
205 bool HasNonTranslation() const {
206 return !FuzzyEqual(_11, 1.0) || !FuzzyEqual(_22, 1.0) ||
207 !FuzzyEqual(_21, 0.0) || !FuzzyEqual(_12, 0.0);
211 * Returns true if the matrix only has an integer translation.
213 bool HasOnlyIntegerTranslation() const {
214 return !HasNonIntegerTranslation();
218 * Returns true if the matrix has any transform other
219 * than a translation or a -1 y scale (y axis flip)
221 bool HasNonTranslationOrFlip() const {
222 return !FuzzyEqual(_11, 1.0) ||
223 (!FuzzyEqual(_22, 1.0) && !FuzzyEqual(_22, -1.0)) ||
224 !FuzzyEqual(_21, 0.0) || !FuzzyEqual(_12, 0.0);
228 * Returns true if the matrix has any transform other
229 * than a translation or scale; this is, if there is
230 * no rotation.
232 bool HasNonAxisAlignedTransform() const {
233 return !FuzzyEqual(_21, 0.0) || !FuzzyEqual(_12, 0.0);
237 * Computes the determinant of this matrix.
239 double Determinant() const {
240 return _11*_22 - _12*_21;
243 /* Computes the scale factors of this matrix; that is,
244 * the amounts each basis vector is scaled by.
245 * The xMajor parameter indicates if the larger scale is
246 * to be assumed to be in the X direction or not.
248 gfxSize ScaleFactors(bool xMajor) const {
249 double det = Determinant();
251 if (det == 0.0)
252 return gfxSize(0.0, 0.0);
254 gfxSize sz = xMajor ? gfxSize(1.0, 0.0) : gfxSize(0.0, 1.0);
255 sz = Transform(sz);
257 double major = sqrt(sz.width * sz.width + sz.height * sz.height);
258 double minor = 0.0;
260 // ignore mirroring
261 if (det < 0.0)
262 det = - det;
264 if (major)
265 minor = det / major;
267 if (xMajor)
268 return gfxSize(major, minor);
270 return gfxSize(minor, major);
274 * Snap matrix components that are close to integers
275 * to integers. In particular, components that are integral when
276 * converted to single precision are set to those integers.
278 void NudgeToIntegers(void);
281 * Returns true if matrix is multiple of 90 degrees rotation with flipping,
282 * scaling and translation.
284 bool PreservesAxisAlignedRectangles() const {
285 return ((FuzzyEqual(_11, 0.0) && FuzzyEqual(_22, 0.0))
286 || (FuzzyEqual(_21, 0.0) && FuzzyEqual(_12, 0.0)));
289 private:
290 static bool FuzzyEqual(gfxFloat aV1, gfxFloat aV2) {
291 return fabs(aV2 - aV1) < 1e-6;
295 #endif /* GFX_MATRIX_H */