blob: 60c3d5c3fa3acc0444d422c689c29538b487506c [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]f4d2b9012013-10-11 19:10:5017class BoxF;
[email protected]79fbdab02012-11-14 07:28:1118class RectF;
[email protected]80248e32011-07-08 15:31:1119class Point;
[email protected]2771b1c2012-10-31 05:15:4320class Point3F;
[email protected]f7c321eb2012-11-26 20:13:0821class Vector3dF;
[email protected]36df22b2011-02-24 21:47:5622
[email protected]80248e32011-07-08 15:31:1123// 4x4 transformation matrix. Transform is cheap and explicitly allows
[email protected]b9b1e7a42011-05-17 15:29:5124// copy/assign.
[email protected]4ffa7892013-09-27 16:56:0625class GFX_EXPORT Transform {
[email protected]36df22b2011-02-24 21:47:5626 public:
[email protected]bda41962013-01-07 18:46:1727
28 enum SkipInitialization {
29 kSkipInitialization
30 };
31
[email protected]0db13222012-12-13 21:27:5432 Transform() : matrix_(SkMatrix44::kIdentity_Constructor) {}
[email protected]bda41962013-01-07 18:46:1733
34 // Skips initializing this matrix to avoid overhead, when we know it will be
35 // initialized before use.
36 Transform(SkipInitialization)
37 : matrix_(SkMatrix44::kUninitialized_Constructor) {}
[email protected]0db13222012-12-13 21:27:5438 Transform(const Transform& rhs) : matrix_(rhs.matrix_) {}
[email protected]d9a6f3302012-12-07 19:17:5439 // Initialize with the concatenation of lhs * rhs.
[email protected]0db13222012-12-13 21:27:5440 Transform(const Transform& lhs, const Transform& rhs)
41 : matrix_(lhs.matrix_, rhs.matrix_) {}
[email protected]78634b0c2013-01-15 07:49:4042 // Constructs a transform from explicit 16 matrix elements. Elements
43 // should be given in row-major order.
[email protected]803f6b52013-09-12 00:51:2644 Transform(SkMScalar col1row1,
45 SkMScalar col2row1,
46 SkMScalar col3row1,
47 SkMScalar col4row1,
48 SkMScalar col1row2,
49 SkMScalar col2row2,
50 SkMScalar col3row2,
51 SkMScalar col4row2,
52 SkMScalar col1row3,
53 SkMScalar col2row3,
54 SkMScalar col3row3,
55 SkMScalar col4row3,
56 SkMScalar col1row4,
57 SkMScalar col2row4,
58 SkMScalar col3row4,
59 SkMScalar col4row4);
[email protected]78634b0c2013-01-15 07:49:4060 // Constructs a transform from explicit 2d elements. All other matrix
61 // elements remain the same as the corresponding elements of an identity
62 // matrix.
[email protected]803f6b52013-09-12 00:51:2663 Transform(SkMScalar col1row1,
64 SkMScalar col2row1,
65 SkMScalar col1row2,
66 SkMScalar col2row2,
67 SkMScalar x_translation,
68 SkMScalar y_translation);
[email protected]0db13222012-12-13 21:27:5469 ~Transform() {}
[email protected]36df22b2011-02-24 21:47:5670
[email protected]0db13222012-12-13 21:27:5471 bool operator==(const Transform& rhs) const { return matrix_ == rhs.matrix_; }
72 bool operator!=(const Transform& rhs) const { return matrix_ != rhs.matrix_; }
[email protected]80248e32011-07-08 15:31:1173
[email protected]f7c321eb2012-11-26 20:13:0874 // Resets this transform to the identity transform.
[email protected]0db13222012-12-13 21:27:5475 void MakeIdentity() { matrix_.setIdentity(); }
[email protected]2fcafa02012-11-15 01:12:5576
[email protected]2c7cd6d2012-11-28 23:49:2677 // Applies the current transformation on a 2d rotation and assigns the result
[email protected]2fcafa02012-11-15 01:12:5578 // to |this|.
[email protected]2c7cd6d2012-11-28 23:49:2679 void Rotate(double degrees) { RotateAboutZAxis(degrees); }
[email protected]2fcafa02012-11-15 01:12:5580
81 // Applies the current transformation on an axis-angle rotation and assigns
82 // the result to |this|.
[email protected]2c7cd6d2012-11-28 23:49:2683 void RotateAboutXAxis(double degrees);
84 void RotateAboutYAxis(double degrees);
85 void RotateAboutZAxis(double degrees);
86 void RotateAbout(const Vector3dF& axis, double degrees);
[email protected]2fcafa02012-11-15 01:12:5587
88 // Applies the current transformation on a scaling and assigns the result
89 // to |this|.
[email protected]803f6b52013-09-12 00:51:2690 void Scale(SkMScalar x, SkMScalar y);
91 void Scale3d(SkMScalar x, SkMScalar y, SkMScalar z);
[email protected]2fcafa02012-11-15 01:12:5592
93 // Applies the current transformation on a translation and assigns the result
94 // to |this|.
[email protected]803f6b52013-09-12 00:51:2695 void Translate(SkMScalar x, SkMScalar y);
96 void Translate3d(SkMScalar x, SkMScalar y, SkMScalar z);
[email protected]2fcafa02012-11-15 01:12:5597
98 // Applies the current transformation on a skew and assigns the result
99 // to |this|.
[email protected]6138db702013-09-25 03:25:05100 void SkewX(double angle_x);
101 void SkewY(double angle_y);
[email protected]2fcafa02012-11-15 01:12:55102
103 // Applies the current transformation on a perspective transform and assigns
104 // the result to |this|.
[email protected]803f6b52013-09-12 00:51:26105 void ApplyPerspectiveDepth(SkMScalar depth);
[email protected]2fcafa02012-11-15 01:12:55106
[email protected]b9b1e7a42011-05-17 15:29:51107 // Applies a transformation on the current transformation
[email protected]80248e32011-07-08 15:31:11108 // (i.e. 'this = this * transform;').
109 void PreconcatTransform(const Transform& transform);
[email protected]36df22b2011-02-24 21:47:56110
[email protected]598080082011-04-14 19:36:33111 // Applies a transformation on the current transformation
[email protected]80248e32011-07-08 15:31:11112 // (i.e. 'this = transform * this;').
113 void ConcatTransform(const Transform& transform);
[email protected]36df22b2011-02-24 21:47:56114
[email protected]45127922012-11-17 12:24:49115 // Returns true if this is the identity matrix.
[email protected]d9a6f3302012-12-07 19:17:54116 bool IsIdentity() const { return matrix_.isIdentity(); }
[email protected]45127922012-11-17 12:24:49117
[email protected]2c7cd6d2012-11-28 23:49:26118 // Returns true if the matrix is either identity or pure translation.
[email protected]d9a6f3302012-12-07 19:17:54119 bool IsIdentityOrTranslation() const {
120 return !(matrix_.getType() & ~SkMatrix44::kTranslate_Mask);
121 }
[email protected]2c7cd6d2012-11-28 23:49:26122
[email protected]aedf4e52013-01-09 23:24:44123 // Returns true if the matrix is either a positive scale and/or a translation.
124 bool IsPositiveScaleOrTranslation() const {
125 if (!IsScaleOrTranslation())
126 return false;
[email protected]803f6b52013-09-12 00:51:26127 return matrix_.get(0, 0) > 0.0 && matrix_.get(1, 1) > 0.0 &&
128 matrix_.get(2, 2) > 0.0;
[email protected]aedf4e52013-01-09 23:24:44129 }
130
[email protected]d1a56f02012-12-04 12:18:30131 // Returns true if the matrix is either identity or pure, non-fractional
132 // translation.
133 bool IsIdentityOrIntegerTranslation() const;
134
[email protected]2c7cd6d2012-11-28 23:49:26135 // Returns true if the matrix is has only scaling and translation components.
[email protected]0db13222012-12-13 21:27:54136 bool IsScaleOrTranslation() const {
137 int mask = SkMatrix44::kScale_Mask | SkMatrix44::kTranslate_Mask;
138 return (matrix_.getType() & ~mask) == 0;
139 }
[email protected]2c7cd6d2012-11-28 23:49:26140
[email protected]3a9a92d2013-07-11 04:37:00141 // Returns true if axis-aligned 2d rects will remain axis-aligned after being
142 // transformed by this matrix.
143 bool Preserves2dAxisAlignment() const;
144
[email protected]2c7cd6d2012-11-28 23:49:26145 // Returns true if the matrix has any perspective component that would
146 // change the w-component of a homogeneous point.
[email protected]0db13222012-12-13 21:27:54147 bool HasPerspective() const {
148 return (matrix_.getType() & SkMatrix44::kPerspective_Mask) != 0;
149 }
[email protected]2c7cd6d2012-11-28 23:49:26150
[email protected]45127922012-11-17 12:24:49151 // Returns true if this transform is non-singular.
[email protected]0db13222012-12-13 21:27:54152 bool IsInvertible() const { return matrix_.invert(NULL); }
[email protected]36df22b2011-02-24 21:47:56153
[email protected]2c7cd6d2012-11-28 23:49:26154 // Returns true if a layer with a forward-facing normal of (0, 0, 1) would
155 // have its back side facing frontwards after applying the transform.
156 bool IsBackFaceVisible() const;
157
[email protected]38919392011-10-24 22:26:23158 // Inverts the transform which is passed in. Returns true if successful.
[email protected]45127922012-11-17 12:24:49159 bool GetInverse(Transform* transform) const WARN_UNUSED_RESULT;
160
161 // Transposes this transform in place.
162 void Transpose();
[email protected]38919392011-10-24 22:26:23163
[email protected]78634b0c2013-01-15 07:49:40164 // Set 3rd row and 3rd colum to (0, 0, 1, 0). Note that this flattening
165 // operation is not quite the same as an orthographic projection and is
166 // technically not a linear operation.
167 //
168 // One useful interpretation of doing this operation:
169 // - For x and y values, the new transform behaves effectively like an
170 // orthographic projection was added to the matrix sequence.
171 // - For z values, the new transform overrides any effect that the transform
172 // had on z, and instead it preserves the z value for any points that are
173 // transformed.
174 // - Because of linearity of transforms, this flattened transform also
175 // preserves the effect that any subsequent (multiplied from the right)
176 // transforms would have on z values.
177 //
178 void FlattenTo2d();
179
[email protected]bea4c872013-08-14 18:10:00180 // Returns the translation components of the matrix. It is an error to call
181 // this function if the transform does not represent only a 2d translation.
182 Vector2dF To2dTranslation() const;
183
[email protected]908af422013-10-10 22:22:42184 // Applies the transformation to the point.
[email protected]26d7ece2013-09-12 20:59:47185 void TransformPoint(Point3F* point) const;
[email protected]36df22b2011-02-24 21:47:56186
[email protected]908af422013-10-10 22:22:42187 // Applies the transformation to the point.
[email protected]26d7ece2013-09-12 20:59:47188 void TransformPoint(Point* point) const;
[email protected]36df22b2011-02-24 21:47:56189
[email protected]80248e32011-07-08 15:31:11190 // Applies the reverse transformation on the point. Returns true if the
191 // transformation can be inverted.
[email protected]26d7ece2013-09-12 20:59:47192 bool TransformPointReverse(Point3F* point) const;
[email protected]463eb0e2011-05-10 03:11:04193
[email protected]80248e32011-07-08 15:31:11194 // Applies the reverse transformation on the point. Returns true if the
195 // transformation can be inverted. Rounds the result to the nearest point.
[email protected]26d7ece2013-09-12 20:59:47196 bool TransformPointReverse(Point* point) const;
[email protected]80248e32011-07-08 15:31:11197
[email protected]f4d2b9012013-10-11 19:10:50198 // Applies transformation on the given rect. After the function completes,
199 // |rect| will be the smallest axis aligned bounding rect containing the
200 // transformed rect.
[email protected]79fbdab02012-11-14 07:28:11201 void TransformRect(RectF* rect) const;
[email protected]80248e32011-07-08 15:31:11202
[email protected]f4d2b9012013-10-11 19:10:50203 // Applies the reverse transformation on the given rect. After the function
204 // completes, |rect| will be the smallest axis aligned bounding rect
205 // containing the transformed rect. Returns false if the matrix cannot be
206 // inverted.
[email protected]79fbdab02012-11-14 07:28:11207 bool TransformRectReverse(RectF* rect) const;
[email protected]277c7b72011-06-06 15:23:09208
[email protected]f4d2b9012013-10-11 19:10:50209 // Applies transformation on the given box. After the function completes,
210 // |box| will be the smallest axis aligned bounding box containing the
211 // transformed box.
212 void TransformBox(BoxF* box) const;
213
214 // Applies the reverse transformation on the given box. After the function
215 // completes, |box| will be the smallest axis aligned bounding box
216 // containing the transformed box. Returns false if the matrix cannot be
217 // inverted.
218 bool TransformBoxReverse(BoxF* box) const;
219
[email protected]2fcafa02012-11-15 01:12:55220 // Decomposes |this| and |from|, interpolates the decomposed values, and
221 // sets |this| to the reconstituted result. Returns false if either matrix
222 // can't be decomposed. Uses routines described in this spec:
223 // http://www.w3.org/TR/css3-3d-transforms/.
224 //
225 // Note: this call is expensive since we need to decompose the transform. If
226 // you're going to be calling this rapidly (e.g., in an animation) you should
227 // decompose once using gfx::DecomposeTransforms and reuse your
228 // DecomposedTransform.
[email protected]6138db702013-09-25 03:25:05229 bool Blend(const Transform& from, double progress);
[email protected]2fcafa02012-11-15 01:12:55230
[email protected]f7c321eb2012-11-26 20:13:08231 // Returns |this| * |other|.
[email protected]d9a6f3302012-12-07 19:17:54232 Transform operator*(const Transform& other) const {
233 return Transform(*this, other);
234 }
[email protected]f7c321eb2012-11-26 20:13:08235
236 // Sets |this| = |this| * |other|
[email protected]0db13222012-12-13 21:27:54237 Transform& operator*=(const Transform& other) {
238 PreconcatTransform(other);
239 return *this;
240 }
[email protected]f7c321eb2012-11-26 20:13:08241
[email protected]b9b1e7a42011-05-17 15:29:51242 // Returns the underlying matrix.
[email protected]80248e32011-07-08 15:31:11243 const SkMatrix44& matrix() const { return matrix_; }
244 SkMatrix44& matrix() { return matrix_; }
[email protected]b9b1e7a42011-05-17 15:29:51245
[email protected]6ab42d92012-12-20 20:36:53246 std::string ToString() const;
247
[email protected]b9b1e7a42011-05-17 15:29:51248 private:
[email protected]80248e32011-07-08 15:31:11249 void TransformPointInternal(const SkMatrix44& xform,
[email protected]26d7ece2013-09-12 20:59:47250 Point* point) const;
[email protected]80248e32011-07-08 15:31:11251
252 void TransformPointInternal(const SkMatrix44& xform,
[email protected]26d7ece2013-09-12 20:59:47253 Point3F* point) const;
[email protected]80248e32011-07-08 15:31:11254
255 SkMatrix44 matrix_;
[email protected]b9b1e7a42011-05-17 15:29:51256
257 // copy/assign are allowed.
[email protected]36df22b2011-02-24 21:47:56258};
259
[email protected]0f0453e2012-10-14 18:15:35260} // namespace gfx
[email protected]36df22b2011-02-24 21:47:56261
262#endif // UI_GFX_TRANSFORM_H_