blob: f9819f3cdebd0bc640db3d9b2439ffb38790e7d8 [file] [log] [blame]
[email protected]3c2196b22012-03-17 03:42:251// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]36df22b2011-02-24 21:47:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef UI_GFX_TRANSFORM_H_
6#define UI_GFX_TRANSFORM_H_
[email protected]36df22b2011-02-24 21:47:567
[email protected]6ab42d92012-12-20 20:36:538#include <string>
9
[email protected]45127922012-11-17 12:24:4910#include "base/compiler_specific.h"
[email protected]80248e32011-07-08 15:31:1111#include "third_party/skia/include/utils/SkMatrix44.h"
[email protected]d34e4072013-09-05 20:28:3012#include "ui/gfx/gfx_export.h"
[email protected]bea4c872013-08-14 18:10:0013#include "ui/gfx/vector2d_f.h"
[email protected]b9b1e7a42011-05-17 15:29:5114
[email protected]36df22b2011-02-24 21:47:5615namespace gfx {
[email protected]0f0453e2012-10-14 18:15:3516
[email protected]79fbdab02012-11-14 07:28:1117class RectF;
[email protected]80248e32011-07-08 15:31:1118class Point;
[email protected]2771b1c2012-10-31 05:15:4319class Point3F;
[email protected]f7c321eb2012-11-26 20:13:0820class Vector3dF;
[email protected]36df22b2011-02-24 21:47:5621
[email protected]80248e32011-07-08 15:31:1122// 4x4 transformation matrix. Transform is cheap and explicitly allows
[email protected]b9b1e7a42011-05-17 15:29:5123// copy/assign.
[email protected]507bad52011-08-06 04:51:0724class UI_EXPORT Transform {
[email protected]36df22b2011-02-24 21:47:5625 public:
[email protected]bda41962013-01-07 18:46:1726
27 enum SkipInitialization {
28 kSkipInitialization
29 };
30
[email protected]0db13222012-12-13 21:27:5431 Transform() : matrix_(SkMatrix44::kIdentity_Constructor) {}
[email protected]bda41962013-01-07 18:46:1732
33 // Skips initializing this matrix to avoid overhead, when we know it will be
34 // initialized before use.
35 Transform(SkipInitialization)
36 : matrix_(SkMatrix44::kUninitialized_Constructor) {}
[email protected]0db13222012-12-13 21:27:5437 Transform(const Transform& rhs) : matrix_(rhs.matrix_) {}
[email protected]d9a6f3302012-12-07 19:17:5438 // Initialize with the concatenation of lhs * rhs.
[email protected]0db13222012-12-13 21:27:5439 Transform(const Transform& lhs, const Transform& rhs)
40 : matrix_(lhs.matrix_, rhs.matrix_) {}
[email protected]78634b0c2013-01-15 07:49:4041 // Constructs a transform from explicit 16 matrix elements. Elements
42 // should be given in row-major order.
[email protected]803f6b52013-09-12 00:51:2643 Transform(SkMScalar col1row1,
44 SkMScalar col2row1,
45 SkMScalar col3row1,
46 SkMScalar col4row1,
47 SkMScalar col1row2,
48 SkMScalar col2row2,
49 SkMScalar col3row2,
50 SkMScalar col4row2,
51 SkMScalar col1row3,
52 SkMScalar col2row3,
53 SkMScalar col3row3,
54 SkMScalar col4row3,
55 SkMScalar col1row4,
56 SkMScalar col2row4,
57 SkMScalar col3row4,
58 SkMScalar col4row4);
[email protected]78634b0c2013-01-15 07:49:4059 // Constructs a transform from explicit 2d elements. All other matrix
60 // elements remain the same as the corresponding elements of an identity
61 // matrix.
[email protected]803f6b52013-09-12 00:51:2662 Transform(SkMScalar col1row1,
63 SkMScalar col2row1,
64 SkMScalar col1row2,
65 SkMScalar col2row2,
66 SkMScalar x_translation,
67 SkMScalar y_translation);
[email protected]0db13222012-12-13 21:27:5468 ~Transform() {}
[email protected]36df22b2011-02-24 21:47:5669
[email protected]0db13222012-12-13 21:27:5470 bool operator==(const Transform& rhs) const { return matrix_ == rhs.matrix_; }
71 bool operator!=(const Transform& rhs) const { return matrix_ != rhs.matrix_; }
[email protected]80248e32011-07-08 15:31:1172
[email protected]f7c321eb2012-11-26 20:13:0873 // Resets this transform to the identity transform.
[email protected]0db13222012-12-13 21:27:5474 void MakeIdentity() { matrix_.setIdentity(); }
[email protected]2fcafa02012-11-15 01:12:5575
[email protected]2c7cd6d2012-11-28 23:49:2676 // Applies the current transformation on a 2d rotation and assigns the result
[email protected]2fcafa02012-11-15 01:12:5577 // to |this|.
[email protected]2c7cd6d2012-11-28 23:49:2678 void Rotate(double degrees) { RotateAboutZAxis(degrees); }
[email protected]2fcafa02012-11-15 01:12:5579
80 // Applies the current transformation on an axis-angle rotation and assigns
81 // the result to |this|.
[email protected]2c7cd6d2012-11-28 23:49:2682 void RotateAboutXAxis(double degrees);
83 void RotateAboutYAxis(double degrees);
84 void RotateAboutZAxis(double degrees);
85 void RotateAbout(const Vector3dF& axis, double degrees);
[email protected]2fcafa02012-11-15 01:12:5586
87 // Applies the current transformation on a scaling and assigns the result
88 // to |this|.
[email protected]803f6b52013-09-12 00:51:2689 void Scale(SkMScalar x, SkMScalar y);
90 void Scale3d(SkMScalar x, SkMScalar y, SkMScalar z);
[email protected]2fcafa02012-11-15 01:12:5591
92 // Applies the current transformation on a translation and assigns the result
93 // to |this|.
[email protected]803f6b52013-09-12 00:51:2694 void Translate(SkMScalar x, SkMScalar y);
95 void Translate3d(SkMScalar x, SkMScalar y, SkMScalar z);
[email protected]2fcafa02012-11-15 01:12:5596
97 // Applies the current transformation on a skew and assigns the result
98 // to |this|.
[email protected]803f6b52013-09-12 00:51:2699 void SkewX(SkMScalar angle_x);
100 void SkewY(SkMScalar angle_y);
[email protected]2fcafa02012-11-15 01:12:55101
102 // Applies the current transformation on a perspective transform and assigns
103 // the result to |this|.
[email protected]803f6b52013-09-12 00:51:26104 void ApplyPerspectiveDepth(SkMScalar depth);
[email protected]2fcafa02012-11-15 01:12:55105
[email protected]b9b1e7a42011-05-17 15:29:51106 // Applies a transformation on the current transformation
[email protected]80248e32011-07-08 15:31:11107 // (i.e. 'this = this * transform;').
108 void PreconcatTransform(const Transform& transform);
[email protected]36df22b2011-02-24 21:47:56109
[email protected]598080082011-04-14 19:36:33110 // Applies a transformation on the current transformation
[email protected]80248e32011-07-08 15:31:11111 // (i.e. 'this = transform * this;').
112 void ConcatTransform(const Transform& transform);
[email protected]36df22b2011-02-24 21:47:56113
[email protected]45127922012-11-17 12:24:49114 // Returns true if this is the identity matrix.
[email protected]d9a6f3302012-12-07 19:17:54115 bool IsIdentity() const { return matrix_.isIdentity(); }
[email protected]45127922012-11-17 12:24:49116
[email protected]2c7cd6d2012-11-28 23:49:26117 // Returns true if the matrix is either identity or pure translation.
[email protected]d9a6f3302012-12-07 19:17:54118 bool IsIdentityOrTranslation() const {
119 return !(matrix_.getType() & ~SkMatrix44::kTranslate_Mask);
120 }
[email protected]2c7cd6d2012-11-28 23:49:26121
[email protected]aedf4e52013-01-09 23:24:44122 // Returns true if the matrix is either a positive scale and/or a translation.
123 bool IsPositiveScaleOrTranslation() const {
124 if (!IsScaleOrTranslation())
125 return false;
[email protected]803f6b52013-09-12 00:51:26126 return matrix_.get(0, 0) > 0.0 && matrix_.get(1, 1) > 0.0 &&
127 matrix_.get(2, 2) > 0.0;
[email protected]aedf4e52013-01-09 23:24:44128 }
129
[email protected]d1a56f02012-12-04 12:18:30130 // Returns true if the matrix is either identity or pure, non-fractional
131 // translation.
132 bool IsIdentityOrIntegerTranslation() const;
133
[email protected]2c7cd6d2012-11-28 23:49:26134 // Returns true if the matrix is has only scaling and translation components.
[email protected]0db13222012-12-13 21:27:54135 bool IsScaleOrTranslation() const {
136 int mask = SkMatrix44::kScale_Mask | SkMatrix44::kTranslate_Mask;
137 return (matrix_.getType() & ~mask) == 0;
138 }
[email protected]2c7cd6d2012-11-28 23:49:26139
[email protected]3a9a92d2013-07-11 04:37:00140 // Returns true if axis-aligned 2d rects will remain axis-aligned after being
141 // transformed by this matrix.
142 bool Preserves2dAxisAlignment() const;
143
[email protected]2c7cd6d2012-11-28 23:49:26144 // Returns true if the matrix has any perspective component that would
145 // change the w-component of a homogeneous point.
[email protected]0db13222012-12-13 21:27:54146 bool HasPerspective() const {
147 return (matrix_.getType() & SkMatrix44::kPerspective_Mask) != 0;
148 }
[email protected]2c7cd6d2012-11-28 23:49:26149
[email protected]45127922012-11-17 12:24:49150 // Returns true if this transform is non-singular.
[email protected]0db13222012-12-13 21:27:54151 bool IsInvertible() const { return matrix_.invert(NULL); }
[email protected]36df22b2011-02-24 21:47:56152
[email protected]2c7cd6d2012-11-28 23:49:26153 // Returns true if a layer with a forward-facing normal of (0, 0, 1) would
154 // have its back side facing frontwards after applying the transform.
155 bool IsBackFaceVisible() const;
156
[email protected]38919392011-10-24 22:26:23157 // Inverts the transform which is passed in. Returns true if successful.
[email protected]45127922012-11-17 12:24:49158 bool GetInverse(Transform* transform) const WARN_UNUSED_RESULT;
159
160 // Transposes this transform in place.
161 void Transpose();
[email protected]38919392011-10-24 22:26:23162
[email protected]78634b0c2013-01-15 07:49:40163 // Set 3rd row and 3rd colum to (0, 0, 1, 0). Note that this flattening
164 // operation is not quite the same as an orthographic projection and is
165 // technically not a linear operation.
166 //
167 // One useful interpretation of doing this operation:
168 // - For x and y values, the new transform behaves effectively like an
169 // orthographic projection was added to the matrix sequence.
170 // - For z values, the new transform overrides any effect that the transform
171 // had on z, and instead it preserves the z value for any points that are
172 // transformed.
173 // - Because of linearity of transforms, this flattened transform also
174 // preserves the effect that any subsequent (multiplied from the right)
175 // transforms would have on z values.
176 //
177 void FlattenTo2d();
178
[email protected]bea4c872013-08-14 18:10:00179 // Returns the translation components of the matrix. It is an error to call
180 // this function if the transform does not represent only a 2d translation.
181 Vector2dF To2dTranslation() const;
182
[email protected]598080082011-04-14 19:36:33183 // Applies the transformation on the point. Returns true if the point is
184 // transformed successfully.
[email protected]2771b1c2012-10-31 05:15:43185 void TransformPoint(Point3F& point) const;
[email protected]36df22b2011-02-24 21:47:56186
[email protected]80248e32011-07-08 15:31:11187 // Applies the transformation on the point. Returns true if the point is
188 // transformed successfully. Rounds the result to the nearest point.
[email protected]0f0453e2012-10-14 18:15:35189 void TransformPoint(Point& point) const;
[email protected]36df22b2011-02-24 21:47:56190
[email protected]80248e32011-07-08 15:31:11191 // Applies the reverse transformation on the point. Returns true if the
192 // transformation can be inverted.
[email protected]2771b1c2012-10-31 05:15:43193 bool TransformPointReverse(Point3F& point) const;
[email protected]463eb0e2011-05-10 03:11:04194
[email protected]80248e32011-07-08 15:31:11195 // Applies the reverse transformation on the point. Returns true if the
196 // transformation can be inverted. Rounds the result to the nearest point.
[email protected]0f0453e2012-10-14 18:15:35197 bool TransformPointReverse(Point& point) const;
[email protected]80248e32011-07-08 15:31:11198
199 // Applies transformation on the rectangle. Returns true if the transformed
200 // rectangle was axis aligned. If it returns false, rect will be the
[email protected]91f4c792012-06-06 02:21:19201 // smallest axis aligned bounding box containing the transformed rect.
[email protected]79fbdab02012-11-14 07:28:11202 void TransformRect(RectF* rect) const;
[email protected]80248e32011-07-08 15:31:11203
204 // Applies the reverse transformation on the rectangle. Returns true if
205 // the transformed rectangle was axis aligned. If it returns false,
[email protected]91f4c792012-06-06 02:21:19206 // rect will be the smallest axis aligned bounding box containing the
[email protected]80248e32011-07-08 15:31:11207 // transformed rect.
[email protected]79fbdab02012-11-14 07:28:11208 bool TransformRectReverse(RectF* rect) const;
[email protected]277c7b72011-06-06 15:23:09209
[email protected]2fcafa02012-11-15 01:12:55210 // Decomposes |this| and |from|, interpolates the decomposed values, and
211 // sets |this| to the reconstituted result. Returns false if either matrix
212 // can't be decomposed. Uses routines described in this spec:
213 // http://www.w3.org/TR/css3-3d-transforms/.
214 //
215 // Note: this call is expensive since we need to decompose the transform. If
216 // you're going to be calling this rapidly (e.g., in an animation) you should
217 // decompose once using gfx::DecomposeTransforms and reuse your
218 // DecomposedTransform.
[email protected]803f6b52013-09-12 00:51:26219 bool Blend(const Transform& from, SkMScalar progress);
[email protected]2fcafa02012-11-15 01:12:55220
[email protected]f7c321eb2012-11-26 20:13:08221 // Returns |this| * |other|.
[email protected]d9a6f3302012-12-07 19:17:54222 Transform operator*(const Transform& other) const {
223 return Transform(*this, other);
224 }
[email protected]f7c321eb2012-11-26 20:13:08225
226 // Sets |this| = |this| * |other|
[email protected]0db13222012-12-13 21:27:54227 Transform& operator*=(const Transform& other) {
228 PreconcatTransform(other);
229 return *this;
230 }
[email protected]f7c321eb2012-11-26 20:13:08231
[email protected]b9b1e7a42011-05-17 15:29:51232 // Returns the underlying matrix.
[email protected]80248e32011-07-08 15:31:11233 const SkMatrix44& matrix() const { return matrix_; }
234 SkMatrix44& matrix() { return matrix_; }
[email protected]b9b1e7a42011-05-17 15:29:51235
[email protected]6ab42d92012-12-20 20:36:53236 std::string ToString() const;
237
[email protected]b9b1e7a42011-05-17 15:29:51238 private:
[email protected]80248e32011-07-08 15:31:11239 void TransformPointInternal(const SkMatrix44& xform,
[email protected]0f0453e2012-10-14 18:15:35240 Point& point) const;
[email protected]80248e32011-07-08 15:31:11241
242 void TransformPointInternal(const SkMatrix44& xform,
[email protected]2771b1c2012-10-31 05:15:43243 Point3F& point) const;
[email protected]80248e32011-07-08 15:31:11244
245 SkMatrix44 matrix_;
[email protected]b9b1e7a42011-05-17 15:29:51246
247 // copy/assign are allowed.
[email protected]36df22b2011-02-24 21:47:56248};
249
[email protected]0f0453e2012-10-14 18:15:35250} // namespace gfx
[email protected]36df22b2011-02-24 21:47:56251
252#endif // UI_GFX_TRANSFORM_H_