Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / ui / gfx / transform.h
blob55ab93867ca66e79c5138e9183ea6e9d2b5a8064
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_
8 #include <iosfwd>
9 #include <string>
11 #include "base/compiler_specific.h"
12 #include "third_party/skia/include/utils/SkMatrix44.h"
13 #include "ui/gfx/geometry/vector2d_f.h"
14 #include "ui/gfx/gfx_export.h"
16 namespace gfx {
18 class BoxF;
19 class RectF;
20 class Point;
21 class Point3F;
22 class Vector3dF;
24 // 4x4 transformation matrix. Transform is cheap and explicitly allows
25 // copy/assign.
26 class GFX_EXPORT Transform {
27 public:
29 enum SkipInitialization {
30 kSkipInitialization
33 Transform() : matrix_(SkMatrix44::kIdentity_Constructor) {}
35 // Skips initializing this matrix to avoid overhead, when we know it will be
36 // initialized before use.
37 Transform(SkipInitialization)
38 : matrix_(SkMatrix44::kUninitialized_Constructor) {}
39 Transform(const Transform& rhs) : matrix_(rhs.matrix_) {}
40 // Initialize with the concatenation of lhs * rhs.
41 Transform(const Transform& lhs, const Transform& rhs)
42 : matrix_(lhs.matrix_, rhs.matrix_) {}
43 // Constructs a transform from explicit 16 matrix elements. Elements
44 // should be given in row-major order.
45 Transform(SkMScalar col1row1,
46 SkMScalar col2row1,
47 SkMScalar col3row1,
48 SkMScalar col4row1,
49 SkMScalar col1row2,
50 SkMScalar col2row2,
51 SkMScalar col3row2,
52 SkMScalar col4row2,
53 SkMScalar col1row3,
54 SkMScalar col2row3,
55 SkMScalar col3row3,
56 SkMScalar col4row3,
57 SkMScalar col1row4,
58 SkMScalar col2row4,
59 SkMScalar col3row4,
60 SkMScalar col4row4);
61 // Constructs a transform from explicit 2d elements. All other matrix
62 // elements remain the same as the corresponding elements of an identity
63 // matrix.
64 Transform(SkMScalar col1row1,
65 SkMScalar col2row1,
66 SkMScalar col1row2,
67 SkMScalar col2row2,
68 SkMScalar x_translation,
69 SkMScalar y_translation);
70 ~Transform() {}
72 bool operator==(const Transform& rhs) const { return matrix_ == rhs.matrix_; }
73 bool operator!=(const Transform& rhs) const { return matrix_ != rhs.matrix_; }
75 // Resets this transform to the identity transform.
76 void MakeIdentity() { matrix_.setIdentity(); }
78 // Applies the current transformation on a 2d rotation and assigns the result
79 // to |this|.
80 void Rotate(double degrees) { RotateAboutZAxis(degrees); }
82 // Applies the current transformation on an axis-angle rotation and assigns
83 // the result to |this|.
84 void RotateAboutXAxis(double degrees);
85 void RotateAboutYAxis(double degrees);
86 void RotateAboutZAxis(double degrees);
87 void RotateAbout(const Vector3dF& axis, double degrees);
89 // Applies the current transformation on a scaling and assigns the result
90 // to |this|.
91 void Scale(SkMScalar x, SkMScalar y);
92 void Scale3d(SkMScalar x, SkMScalar y, SkMScalar z);
93 gfx::Vector2dF Scale2d() const {
94 return gfx::Vector2dF(matrix_.get(0, 0), matrix_.get(1, 1));
97 // Applies the current transformation on a translation and assigns the result
98 // to |this|.
99 void Translate(SkMScalar x, SkMScalar y);
100 void Translate3d(SkMScalar x, SkMScalar y, SkMScalar z);
102 // Applies the current transformation on a skew and assigns the result
103 // to |this|.
104 void SkewX(double angle_x);
105 void SkewY(double angle_y);
107 // Applies the current transformation on a perspective transform and assigns
108 // the result to |this|.
109 void ApplyPerspectiveDepth(SkMScalar depth);
111 // Applies a transformation on the current transformation
112 // (i.e. 'this = this * transform;').
113 void PreconcatTransform(const Transform& transform);
115 // Applies a transformation on the current transformation
116 // (i.e. 'this = transform * this;').
117 void ConcatTransform(const Transform& transform);
119 // Returns true if this is the identity matrix.
120 bool IsIdentity() const { return matrix_.isIdentity(); }
122 // Returns true if the matrix is either identity or pure translation.
123 bool IsIdentityOrTranslation() const { return matrix_.isTranslate(); }
125 // Returns true if the matrix is either the identity or a 2d translation.
126 bool IsIdentityOr2DTranslation() const {
127 return matrix_.isTranslate() && matrix_.get(2, 3) == 0;
130 // Returns true if the matrix is either identity or pure translation,
131 // allowing for an amount of inaccuracy as specified by the parameter.
132 bool IsApproximatelyIdentityOrTranslation(SkMScalar tolerance) const;
134 // Returns true if the matrix is either a positive scale and/or a translation.
135 bool IsPositiveScaleOrTranslation() const {
136 if (!IsScaleOrTranslation())
137 return false;
138 return matrix_.get(0, 0) > 0.0 && matrix_.get(1, 1) > 0.0 &&
139 matrix_.get(2, 2) > 0.0;
142 // Returns true if the matrix is either identity or pure, non-fractional
143 // translation.
144 bool IsIdentityOrIntegerTranslation() const;
146 // Returns true if the matrix had only scaling components.
147 bool IsScale2d() const { return matrix_.isScale(); }
149 // Returns true if the matrix is has only scaling and translation components.
150 bool IsScaleOrTranslation() const { return matrix_.isScaleTranslate(); }
152 // Returns true if axis-aligned 2d rects will remain axis-aligned after being
153 // transformed by this matrix.
154 bool Preserves2dAxisAlignment() const;
156 // Returns true if the matrix has any perspective component that would
157 // change the w-component of a homogeneous point.
158 bool HasPerspective() const { return matrix_.hasPerspective(); }
160 // Returns true if this transform is non-singular.
161 bool IsInvertible() const { return matrix_.invert(NULL); }
163 // Returns true if a layer with a forward-facing normal of (0, 0, 1) would
164 // have its back side facing frontwards after applying the transform.
165 bool IsBackFaceVisible() const;
167 // Inverts the transform which is passed in. Returns true if successful.
168 bool GetInverse(Transform* transform) const WARN_UNUSED_RESULT;
170 // Transposes this transform in place.
171 void Transpose();
173 // Set 3rd row and 3rd colum to (0, 0, 1, 0). Note that this flattening
174 // operation is not quite the same as an orthographic projection and is
175 // technically not a linear operation.
177 // One useful interpretation of doing this operation:
178 // - For x and y values, the new transform behaves effectively like an
179 // orthographic projection was added to the matrix sequence.
180 // - For z values, the new transform overrides any effect that the transform
181 // had on z, and instead it preserves the z value for any points that are
182 // transformed.
183 // - Because of linearity of transforms, this flattened transform also
184 // preserves the effect that any subsequent (multiplied from the right)
185 // transforms would have on z values.
187 void FlattenTo2d();
189 // Returns true if the 3rd row and 3rd column are both (0, 0, 1, 0).
190 bool IsFlat() const;
192 // Returns the x and y translation components of the matrix.
193 Vector2dF To2dTranslation() const;
195 // Applies the transformation to the point.
196 void TransformPoint(Point3F* point) const;
198 // Applies the transformation to the point.
199 void TransformPoint(Point* point) const;
201 // Applies the reverse transformation on the point. Returns true if the
202 // transformation can be inverted.
203 bool TransformPointReverse(Point3F* point) const;
205 // Applies the reverse transformation on the point. Returns true if the
206 // transformation can be inverted. Rounds the result to the nearest point.
207 bool TransformPointReverse(Point* point) const;
209 // Applies transformation on the given rect. After the function completes,
210 // |rect| will be the smallest axis aligned bounding rect containing the
211 // transformed rect.
212 void TransformRect(RectF* rect) const;
214 // Applies the reverse transformation on the given rect. After the function
215 // completes, |rect| will be the smallest axis aligned bounding rect
216 // containing the transformed rect. Returns false if the matrix cannot be
217 // inverted.
218 bool TransformRectReverse(RectF* rect) const;
220 // Applies transformation on the given box. After the function completes,
221 // |box| will be the smallest axis aligned bounding box containing the
222 // transformed box.
223 void TransformBox(BoxF* box) const;
225 // Applies the reverse transformation on the given box. After the function
226 // completes, |box| will be the smallest axis aligned bounding box
227 // containing the transformed box. Returns false if the matrix cannot be
228 // inverted.
229 bool TransformBoxReverse(BoxF* box) const;
231 // Decomposes |this| and |from|, interpolates the decomposed values, and
232 // sets |this| to the reconstituted result. Returns false if either matrix
233 // can't be decomposed. Uses routines described in this spec:
234 // http://www.w3.org/TR/css3-3d-transforms/.
236 // Note: this call is expensive since we need to decompose the transform. If
237 // you're going to be calling this rapidly (e.g., in an animation) you should
238 // decompose once using gfx::DecomposeTransforms and reuse your
239 // DecomposedTransform.
240 bool Blend(const Transform& from, double progress);
242 void RoundTranslationComponents();
244 // Returns |this| * |other|.
245 Transform operator*(const Transform& other) const {
246 return Transform(*this, other);
249 // Sets |this| = |this| * |other|
250 Transform& operator*=(const Transform& other) {
251 PreconcatTransform(other);
252 return *this;
255 // Returns the underlying matrix.
256 const SkMatrix44& matrix() const { return matrix_; }
257 SkMatrix44& matrix() { return matrix_; }
259 std::string ToString() const;
261 private:
262 void TransformPointInternal(const SkMatrix44& xform,
263 Point* point) const;
265 void TransformPointInternal(const SkMatrix44& xform,
266 Point3F* point) const;
268 SkMatrix44 matrix_;
270 // copy/assign are allowed.
273 // This is declared here for use in gtest-based unit tests but is defined in
274 // the gfx_test_support target. Depend on that to use this in your unit test.
275 // This should not be used in production code - call ToString() instead.
276 void PrintTo(const Transform& transform, ::std::ostream* os);
278 } // namespace gfx
280 #endif // UI_GFX_TRANSFORM_H_