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/. */
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.
19 * A matrix that represents an affine transformation. Projective
20 * transformations are not supported. This matrix looks like:
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 |
35 double _11
; double _12
;
36 double _21
; double _22
;
37 double _31
; double _32
;
40 * Initializes this matrix as the identity matrix.
42 gfxMatrix() { Reset(); }
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
) :
53 friend std::ostream
& operator<<(std::ostream
& stream
, const gfxMatrix
& m
) {
55 return stream
<< "[identity]";
59 << m
._11
<< " " << m
._12
60 << m
._21
<< " " << m
._22
61 << m
._31
<< " " << m
._32
66 * Post-multiplies m onto the matrix.
68 const gfxMatrix
& operator *= (const gfxMatrix
& m
);
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
);
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
108 * XXX should this do something with the return value of
109 * cairo_matrix_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
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();
252 return gfxSize(0.0, 0.0);
254 gfxSize sz
= xMajor
? gfxSize(1.0, 0.0) : gfxSize(0.0, 1.0);
257 double major
= sqrt(sz
.width
* sz
.width
+ sz
.height
* sz
.height
);
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)));
290 static bool FuzzyEqual(gfxFloat aV1
, gfxFloat aV2
) {
291 return fabs(aV2
- aV1
) < 1e-6;
295 #endif /* GFX_MATRIX_H */