1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef UI_GFX_TRANSFORM_H_
6 #define UI_GFX_TRANSFORM_H_
10 #include "base/compiler_specific.h"
11 #include "third_party/skia/include/utils/SkMatrix44.h"
12 #include "ui/base/ui_export.h"
21 // 4x4 transformation matrix. Transform is cheap and explicitly allows
23 class UI_EXPORT Transform
{
26 enum SkipInitialization
{
30 Transform() : matrix_(SkMatrix44::kIdentity_Constructor
) {}
32 // Skips initializing this matrix to avoid overhead, when we know it will be
33 // initialized before use.
34 Transform(SkipInitialization
)
35 : matrix_(SkMatrix44::kUninitialized_Constructor
) {}
36 Transform(const Transform
& rhs
) : matrix_(rhs
.matrix_
) {}
37 // Initialize with the concatenation of lhs * rhs.
38 Transform(const Transform
& lhs
, const Transform
& rhs
)
39 : matrix_(lhs
.matrix_
, rhs
.matrix_
) {}
40 // Constructs a transform from explicit 16 matrix elements. Elements
41 // should be given in row-major order.
42 Transform(double col1row1
, double col2row1
, double col3row1
, double col4row1
,
43 double col1row2
, double col2row2
, double col3row2
, double col4row2
,
44 double col1row3
, double col2row3
, double col3row3
, double col4row3
,
45 double col1row4
, double col2row4
, double col3row4
, double col4row4
);
46 // Constructs a transform from explicit 2d elements. All other matrix
47 // elements remain the same as the corresponding elements of an identity
49 Transform(double col1row1
, double col2row1
,
50 double col1row2
, double col2row2
,
51 double x_translation
, double y_translation
);
54 bool operator==(const Transform
& rhs
) const { return matrix_
== rhs
.matrix_
; }
55 bool operator!=(const Transform
& rhs
) const { return matrix_
!= rhs
.matrix_
; }
57 // Resets this transform to the identity transform.
58 void MakeIdentity() { matrix_
.setIdentity(); }
60 // Applies the current transformation on a 2d rotation and assigns the result
62 void Rotate(double degrees
) { RotateAboutZAxis(degrees
); }
64 // Applies the current transformation on an axis-angle rotation and assigns
65 // the result to |this|.
66 void RotateAboutXAxis(double degrees
);
67 void RotateAboutYAxis(double degrees
);
68 void RotateAboutZAxis(double degrees
);
69 void RotateAbout(const Vector3dF
& axis
, double degrees
);
71 // Applies the current transformation on a scaling and assigns the result
73 void Scale(double x
, double y
);
74 void Scale3d(double x
, double y
, double z
);
76 // Applies the current transformation on a translation and assigns the result
78 void Translate(double x
, double y
);
79 void Translate3d(double x
, double y
, double z
);
81 // Applies the current transformation on a skew and assigns the result
83 void SkewX(double angle_x
);
84 void SkewY(double angle_y
);
86 // Applies the current transformation on a perspective transform and assigns
87 // the result to |this|.
88 void ApplyPerspectiveDepth(double depth
);
90 // Applies a transformation on the current transformation
91 // (i.e. 'this = this * transform;').
92 void PreconcatTransform(const Transform
& transform
);
94 // Applies a transformation on the current transformation
95 // (i.e. 'this = transform * this;').
96 void ConcatTransform(const Transform
& transform
);
98 // Returns true if this is the identity matrix.
99 bool IsIdentity() const { return matrix_
.isIdentity(); }
101 // Returns true if the matrix is either identity or pure translation.
102 bool IsIdentityOrTranslation() const {
103 return !(matrix_
.getType() & ~SkMatrix44::kTranslate_Mask
);
106 // Returns true if the matrix is either a positive scale and/or a translation.
107 bool IsPositiveScaleOrTranslation() const {
108 if (!IsScaleOrTranslation())
110 return matrix_
.getDouble(0, 0) > 0.0 &&
111 matrix_
.getDouble(1, 1) > 0.0 &&
112 matrix_
.getDouble(2, 2) > 0.0;
115 // Returns true if the matrix is either identity or pure, non-fractional
117 bool IsIdentityOrIntegerTranslation() const;
119 // Returns true if the matrix is has only scaling and translation components.
120 bool IsScaleOrTranslation() const {
121 int mask
= SkMatrix44::kScale_Mask
| SkMatrix44::kTranslate_Mask
;
122 return (matrix_
.getType() & ~mask
) == 0;
125 // Returns true if the matrix has any perspective component that would
126 // change the w-component of a homogeneous point.
127 bool HasPerspective() const {
128 return (matrix_
.getType() & SkMatrix44::kPerspective_Mask
) != 0;
131 // Returns true if this transform is non-singular.
132 bool IsInvertible() const { return matrix_
.invert(NULL
); }
134 // Returns true if a layer with a forward-facing normal of (0, 0, 1) would
135 // have its back side facing frontwards after applying the transform.
136 bool IsBackFaceVisible() const;
138 // Inverts the transform which is passed in. Returns true if successful.
139 bool GetInverse(Transform
* transform
) const WARN_UNUSED_RESULT
;
141 // Transposes this transform in place.
144 // Set 3rd row and 3rd colum to (0, 0, 1, 0). Note that this flattening
145 // operation is not quite the same as an orthographic projection and is
146 // technically not a linear operation.
148 // One useful interpretation of doing this operation:
149 // - For x and y values, the new transform behaves effectively like an
150 // orthographic projection was added to the matrix sequence.
151 // - For z values, the new transform overrides any effect that the transform
152 // had on z, and instead it preserves the z value for any points that are
154 // - Because of linearity of transforms, this flattened transform also
155 // preserves the effect that any subsequent (multiplied from the right)
156 // transforms would have on z values.
160 // Applies the transformation on the point. Returns true if the point is
161 // transformed successfully.
162 void TransformPoint(Point3F
& point
) const;
164 // Applies the transformation on the point. Returns true if the point is
165 // transformed successfully. Rounds the result to the nearest point.
166 void TransformPoint(Point
& point
) const;
168 // Applies the reverse transformation on the point. Returns true if the
169 // transformation can be inverted.
170 bool TransformPointReverse(Point3F
& point
) const;
172 // Applies the reverse transformation on the point. Returns true if the
173 // transformation can be inverted. Rounds the result to the nearest point.
174 bool TransformPointReverse(Point
& point
) const;
176 // Applies transformation on the rectangle. Returns true if the transformed
177 // rectangle was axis aligned. If it returns false, rect will be the
178 // smallest axis aligned bounding box containing the transformed rect.
179 void TransformRect(RectF
* rect
) const;
181 // Applies the reverse transformation on the rectangle. Returns true if
182 // the transformed rectangle was axis aligned. If it returns false,
183 // rect will be the smallest axis aligned bounding box containing the
185 bool TransformRectReverse(RectF
* rect
) const;
187 // Decomposes |this| and |from|, interpolates the decomposed values, and
188 // sets |this| to the reconstituted result. Returns false if either matrix
189 // can't be decomposed. Uses routines described in this spec:
190 // http://www.w3.org/TR/css3-3d-transforms/.
192 // Note: this call is expensive since we need to decompose the transform. If
193 // you're going to be calling this rapidly (e.g., in an animation) you should
194 // decompose once using gfx::DecomposeTransforms and reuse your
195 // DecomposedTransform.
196 bool Blend(const Transform
& from
, double progress
);
198 // Returns |this| * |other|.
199 Transform
operator*(const Transform
& other
) const {
200 return Transform(*this, other
);
203 // Sets |this| = |this| * |other|
204 Transform
& operator*=(const Transform
& other
) {
205 PreconcatTransform(other
);
209 // Returns the underlying matrix.
210 const SkMatrix44
& matrix() const { return matrix_
; }
211 SkMatrix44
& matrix() { return matrix_
; }
213 std::string
ToString() const;
216 void TransformPointInternal(const SkMatrix44
& xform
,
219 void TransformPointInternal(const SkMatrix44
& xform
,
220 Point3F
& point
) const;
224 // copy/assign are allowed.
229 #endif // UI_GFX_TRANSFORM_H_