blob: 66e76ea051415e7f55173679cf8fe97c9f3bf3e1 [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]507bad52011-08-06 04:51:0712#include "ui/base/ui_export.h"
[email protected]b9b1e7a42011-05-17 15:29:5113
[email protected]36df22b2011-02-24 21:47:5614namespace gfx {
[email protected]0f0453e2012-10-14 18:15:3515
[email protected]79fbdab02012-11-14 07:28:1116class RectF;
[email protected]80248e32011-07-08 15:31:1117class Point;
[email protected]2771b1c2012-10-31 05:15:4318class Point3F;
[email protected]f7c321eb2012-11-26 20:13:0819class Vector3dF;
[email protected]36df22b2011-02-24 21:47:5620
[email protected]80248e32011-07-08 15:31:1121// 4x4 transformation matrix. Transform is cheap and explicitly allows
[email protected]b9b1e7a42011-05-17 15:29:5122// copy/assign.
[email protected]507bad52011-08-06 04:51:0723class UI_EXPORT Transform {
[email protected]36df22b2011-02-24 21:47:5624 public:
[email protected]bda41962013-01-07 18:46:1725
26 enum SkipInitialization {
27 kSkipInitialization
28 };
29
[email protected]0db13222012-12-13 21:27:5430 Transform() : matrix_(SkMatrix44::kIdentity_Constructor) {}
[email protected]bda41962013-01-07 18:46:1731
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) {}
[email protected]0db13222012-12-13 21:27:5436 Transform(const Transform& rhs) : matrix_(rhs.matrix_) {}
[email protected]d9a6f3302012-12-07 19:17:5437 // Initialize with the concatenation of lhs * rhs.
[email protected]0db13222012-12-13 21:27:5438 Transform(const Transform& lhs, const Transform& rhs)
39 : matrix_(lhs.matrix_, rhs.matrix_) {}
[email protected]78634b0c2013-01-15 07:49:4040 // 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
48 // matrix.
49 Transform(double col1row1, double col2row1,
50 double col1row2, double col2row2,
51 double x_translation, double y_translation);
[email protected]0db13222012-12-13 21:27:5452 ~Transform() {}
[email protected]36df22b2011-02-24 21:47:5653
[email protected]0db13222012-12-13 21:27:5454 bool operator==(const Transform& rhs) const { return matrix_ == rhs.matrix_; }
55 bool operator!=(const Transform& rhs) const { return matrix_ != rhs.matrix_; }
[email protected]80248e32011-07-08 15:31:1156
[email protected]f7c321eb2012-11-26 20:13:0857 // Resets this transform to the identity transform.
[email protected]0db13222012-12-13 21:27:5458 void MakeIdentity() { matrix_.setIdentity(); }
[email protected]2fcafa02012-11-15 01:12:5559
[email protected]2c7cd6d2012-11-28 23:49:2660 // Applies the current transformation on a 2d rotation and assigns the result
[email protected]2fcafa02012-11-15 01:12:5561 // to |this|.
[email protected]2c7cd6d2012-11-28 23:49:2662 void Rotate(double degrees) { RotateAboutZAxis(degrees); }
[email protected]2fcafa02012-11-15 01:12:5563
64 // Applies the current transformation on an axis-angle rotation and assigns
65 // the result to |this|.
[email protected]2c7cd6d2012-11-28 23:49:2666 void RotateAboutXAxis(double degrees);
67 void RotateAboutYAxis(double degrees);
68 void RotateAboutZAxis(double degrees);
69 void RotateAbout(const Vector3dF& axis, double degrees);
[email protected]2fcafa02012-11-15 01:12:5570
71 // Applies the current transformation on a scaling and assigns the result
72 // to |this|.
[email protected]f7c321eb2012-11-26 20:13:0873 void Scale(double x, double y);
74 void Scale3d(double x, double y, double z);
[email protected]2fcafa02012-11-15 01:12:5575
76 // Applies the current transformation on a translation and assigns the result
77 // to |this|.
[email protected]f7c321eb2012-11-26 20:13:0878 void Translate(double x, double y);
79 void Translate3d(double x, double y, double z);
[email protected]2fcafa02012-11-15 01:12:5580
81 // Applies the current transformation on a skew and assigns the result
82 // to |this|.
[email protected]f7c321eb2012-11-26 20:13:0883 void SkewX(double angle_x);
84 void SkewY(double angle_y);
[email protected]2fcafa02012-11-15 01:12:5585
86 // Applies the current transformation on a perspective transform and assigns
87 // the result to |this|.
[email protected]f7c321eb2012-11-26 20:13:0888 void ApplyPerspectiveDepth(double depth);
[email protected]2fcafa02012-11-15 01:12:5589
[email protected]b9b1e7a42011-05-17 15:29:5190 // Applies a transformation on the current transformation
[email protected]80248e32011-07-08 15:31:1191 // (i.e. 'this = this * transform;').
92 void PreconcatTransform(const Transform& transform);
[email protected]36df22b2011-02-24 21:47:5693
[email protected]598080082011-04-14 19:36:3394 // Applies a transformation on the current transformation
[email protected]80248e32011-07-08 15:31:1195 // (i.e. 'this = transform * this;').
96 void ConcatTransform(const Transform& transform);
[email protected]36df22b2011-02-24 21:47:5697
[email protected]45127922012-11-17 12:24:4998 // Returns true if this is the identity matrix.
[email protected]d9a6f3302012-12-07 19:17:5499 bool IsIdentity() const { return matrix_.isIdentity(); }
[email protected]45127922012-11-17 12:24:49100
[email protected]2c7cd6d2012-11-28 23:49:26101 // Returns true if the matrix is either identity or pure translation.
[email protected]d9a6f3302012-12-07 19:17:54102 bool IsIdentityOrTranslation() const {
103 return !(matrix_.getType() & ~SkMatrix44::kTranslate_Mask);
104 }
[email protected]2c7cd6d2012-11-28 23:49:26105
[email protected]aedf4e52013-01-09 23:24:44106 // Returns true if the matrix is either a positive scale and/or a translation.
107 bool IsPositiveScaleOrTranslation() const {
108 if (!IsScaleOrTranslation())
109 return false;
110 return matrix_.getDouble(0, 0) > 0.0 &&
111 matrix_.getDouble(1, 1) > 0.0 &&
112 matrix_.getDouble(2, 2) > 0.0;
113 }
114
[email protected]d1a56f02012-12-04 12:18:30115 // Returns true if the matrix is either identity or pure, non-fractional
116 // translation.
117 bool IsIdentityOrIntegerTranslation() const;
118
[email protected]2c7cd6d2012-11-28 23:49:26119 // Returns true if the matrix is has only scaling and translation components.
[email protected]0db13222012-12-13 21:27:54120 bool IsScaleOrTranslation() const {
121 int mask = SkMatrix44::kScale_Mask | SkMatrix44::kTranslate_Mask;
122 return (matrix_.getType() & ~mask) == 0;
123 }
[email protected]2c7cd6d2012-11-28 23:49:26124
[email protected]3a9a92d2013-07-11 04:37:00125 // Returns true if axis-aligned 2d rects will remain axis-aligned after being
126 // transformed by this matrix.
127 bool Preserves2dAxisAlignment() const;
128
[email protected]2c7cd6d2012-11-28 23:49:26129 // Returns true if the matrix has any perspective component that would
130 // change the w-component of a homogeneous point.
[email protected]0db13222012-12-13 21:27:54131 bool HasPerspective() const {
132 return (matrix_.getType() & SkMatrix44::kPerspective_Mask) != 0;
133 }
[email protected]2c7cd6d2012-11-28 23:49:26134
[email protected]45127922012-11-17 12:24:49135 // Returns true if this transform is non-singular.
[email protected]0db13222012-12-13 21:27:54136 bool IsInvertible() const { return matrix_.invert(NULL); }
[email protected]36df22b2011-02-24 21:47:56137
[email protected]2c7cd6d2012-11-28 23:49:26138 // Returns true if a layer with a forward-facing normal of (0, 0, 1) would
139 // have its back side facing frontwards after applying the transform.
140 bool IsBackFaceVisible() const;
141
[email protected]38919392011-10-24 22:26:23142 // Inverts the transform which is passed in. Returns true if successful.
[email protected]45127922012-11-17 12:24:49143 bool GetInverse(Transform* transform) const WARN_UNUSED_RESULT;
144
145 // Transposes this transform in place.
146 void Transpose();
[email protected]38919392011-10-24 22:26:23147
[email protected]78634b0c2013-01-15 07:49:40148 // Set 3rd row and 3rd colum to (0, 0, 1, 0). Note that this flattening
149 // operation is not quite the same as an orthographic projection and is
150 // technically not a linear operation.
151 //
152 // One useful interpretation of doing this operation:
153 // - For x and y values, the new transform behaves effectively like an
154 // orthographic projection was added to the matrix sequence.
155 // - For z values, the new transform overrides any effect that the transform
156 // had on z, and instead it preserves the z value for any points that are
157 // transformed.
158 // - Because of linearity of transforms, this flattened transform also
159 // preserves the effect that any subsequent (multiplied from the right)
160 // transforms would have on z values.
161 //
162 void FlattenTo2d();
163
[email protected]598080082011-04-14 19:36:33164 // Applies the transformation on the point. Returns true if the point is
165 // transformed successfully.
[email protected]2771b1c2012-10-31 05:15:43166 void TransformPoint(Point3F& point) const;
[email protected]36df22b2011-02-24 21:47:56167
[email protected]80248e32011-07-08 15:31:11168 // Applies the transformation on the point. Returns true if the point is
169 // transformed successfully. Rounds the result to the nearest point.
[email protected]0f0453e2012-10-14 18:15:35170 void TransformPoint(Point& point) const;
[email protected]36df22b2011-02-24 21:47:56171
[email protected]80248e32011-07-08 15:31:11172 // Applies the reverse transformation on the point. Returns true if the
173 // transformation can be inverted.
[email protected]2771b1c2012-10-31 05:15:43174 bool TransformPointReverse(Point3F& point) const;
[email protected]463eb0e2011-05-10 03:11:04175
[email protected]80248e32011-07-08 15:31:11176 // Applies the reverse transformation on the point. Returns true if the
177 // transformation can be inverted. Rounds the result to the nearest point.
[email protected]0f0453e2012-10-14 18:15:35178 bool TransformPointReverse(Point& point) const;
[email protected]80248e32011-07-08 15:31:11179
180 // Applies transformation on the rectangle. Returns true if the transformed
181 // rectangle was axis aligned. If it returns false, rect will be the
[email protected]91f4c792012-06-06 02:21:19182 // smallest axis aligned bounding box containing the transformed rect.
[email protected]79fbdab02012-11-14 07:28:11183 void TransformRect(RectF* rect) const;
[email protected]80248e32011-07-08 15:31:11184
185 // Applies the reverse transformation on the rectangle. Returns true if
186 // the transformed rectangle was axis aligned. If it returns false,
[email protected]91f4c792012-06-06 02:21:19187 // rect will be the smallest axis aligned bounding box containing the
[email protected]80248e32011-07-08 15:31:11188 // transformed rect.
[email protected]79fbdab02012-11-14 07:28:11189 bool TransformRectReverse(RectF* rect) const;
[email protected]277c7b72011-06-06 15:23:09190
[email protected]2fcafa02012-11-15 01:12:55191 // Decomposes |this| and |from|, interpolates the decomposed values, and
192 // sets |this| to the reconstituted result. Returns false if either matrix
193 // can't be decomposed. Uses routines described in this spec:
194 // http://www.w3.org/TR/css3-3d-transforms/.
195 //
196 // Note: this call is expensive since we need to decompose the transform. If
197 // you're going to be calling this rapidly (e.g., in an animation) you should
198 // decompose once using gfx::DecomposeTransforms and reuse your
199 // DecomposedTransform.
200 bool Blend(const Transform& from, double progress);
201
[email protected]f7c321eb2012-11-26 20:13:08202 // Returns |this| * |other|.
[email protected]d9a6f3302012-12-07 19:17:54203 Transform operator*(const Transform& other) const {
204 return Transform(*this, other);
205 }
[email protected]f7c321eb2012-11-26 20:13:08206
207 // Sets |this| = |this| * |other|
[email protected]0db13222012-12-13 21:27:54208 Transform& operator*=(const Transform& other) {
209 PreconcatTransform(other);
210 return *this;
211 }
[email protected]f7c321eb2012-11-26 20:13:08212
[email protected]b9b1e7a42011-05-17 15:29:51213 // Returns the underlying matrix.
[email protected]80248e32011-07-08 15:31:11214 const SkMatrix44& matrix() const { return matrix_; }
215 SkMatrix44& matrix() { return matrix_; }
[email protected]b9b1e7a42011-05-17 15:29:51216
[email protected]6ab42d92012-12-20 20:36:53217 std::string ToString() const;
218
[email protected]b9b1e7a42011-05-17 15:29:51219 private:
[email protected]80248e32011-07-08 15:31:11220 void TransformPointInternal(const SkMatrix44& xform,
[email protected]0f0453e2012-10-14 18:15:35221 Point& point) const;
[email protected]80248e32011-07-08 15:31:11222
223 void TransformPointInternal(const SkMatrix44& xform,
[email protected]2771b1c2012-10-31 05:15:43224 Point3F& point) const;
[email protected]80248e32011-07-08 15:31:11225
226 SkMatrix44 matrix_;
[email protected]b9b1e7a42011-05-17 15:29:51227
228 // copy/assign are allowed.
[email protected]36df22b2011-02-24 21:47:56229};
230
[email protected]0f0453e2012-10-14 18:15:35231} // namespace gfx
[email protected]36df22b2011-02-24 21:47:56232
233#endif // UI_GFX_TRANSFORM_H_