OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // MSVC++ requires this to be set before any other includes to get M_PI. | 5 // MSVC++ requires this to be set before any other includes to get M_PI. |
6 #define _USE_MATH_DEFINES | 6 #define _USE_MATH_DEFINES |
7 | 7 |
8 #include "ui/gfx/transform.h" | 8 #include "ui/gfx/transform.h" |
9 | 9 |
10 #include <cmath> | 10 #include <cmath> |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 } | 42 } |
43 | 43 |
44 bool Transform::operator!=(const Transform& rhs) const { | 44 bool Transform::operator!=(const Transform& rhs) const { |
45 return !(*this == rhs); | 45 return !(*this == rhs); |
46 } | 46 } |
47 | 47 |
48 void Transform::MakeIdentity() { | 48 void Transform::MakeIdentity() { |
49 matrix_.setIdentity(); | 49 matrix_.setIdentity(); |
50 } | 50 } |
51 | 51 |
52 void Transform::Rotate(double degree) { | 52 void Transform::RotateAboutXAxis(double degrees) { |
| 53 double radians = degrees * M_PI / 180; |
| 54 double cosTheta = std::cos(radians); |
| 55 double sinTheta = std::sin(radians); |
53 if (matrix_.isIdentity()) { | 56 if (matrix_.isIdentity()) { |
54 matrix_.setRotateDegreesAbout(SkDoubleToMScalar(0), | 57 matrix_.set3x3(1, 0, 0, |
55 SkDoubleToMScalar(0), | 58 0, cosTheta, sinTheta, |
56 SkDoubleToMScalar(1), | 59 0, -sinTheta, cosTheta); |
57 SkDoubleToMScalar(degree)); | |
58 } else { | 60 } else { |
59 SkMatrix44 rot; | 61 SkMatrix44 rot; |
60 rot.setRotateDegreesAbout(SkDoubleToMScalar(0), | 62 rot.set3x3(1, 0, 0, |
61 SkDoubleToMScalar(0), | 63 0, cosTheta, sinTheta, |
62 SkDoubleToMScalar(1), | 64 0, -sinTheta, cosTheta); |
63 SkDoubleToMScalar(degree)); | |
64 matrix_.preConcat(rot); | 65 matrix_.preConcat(rot); |
65 } | 66 } |
66 } | 67 } |
67 | 68 |
68 void Transform::RotateAbout(const Vector3dF& axis, double degree) { | 69 void Transform::RotateAboutYAxis(double degrees) { |
| 70 double radians = degrees * M_PI / 180; |
| 71 double cosTheta = std::cos(radians); |
| 72 double sinTheta = std::sin(radians); |
| 73 if (matrix_.isIdentity()) { |
| 74 // Note carefully the placement of the -sinTheta for rotation about |
| 75 // y-axis is different than rotation about x-axis or z-axis. |
| 76 matrix_.set3x3(cosTheta, 0, -sinTheta, |
| 77 0, 1, 0, |
| 78 sinTheta, 0, cosTheta); |
| 79 } else { |
| 80 SkMatrix44 rot; |
| 81 rot.set3x3(cosTheta, 0, -sinTheta, |
| 82 0, 1, 0, |
| 83 sinTheta, 0, cosTheta); |
| 84 matrix_.preConcat(rot); |
| 85 } |
| 86 } |
| 87 |
| 88 void Transform::RotateAboutZAxis(double degrees) { |
| 89 double radians = degrees * M_PI / 180; |
| 90 double cosTheta = std::cos(radians); |
| 91 double sinTheta = std::sin(radians); |
| 92 if (matrix_.isIdentity()) { |
| 93 matrix_.set3x3(cosTheta, sinTheta, 0, |
| 94 -sinTheta, cosTheta, 0, |
| 95 0, 0, 1); |
| 96 } else { |
| 97 SkMatrix44 rot; |
| 98 rot.set3x3(cosTheta, sinTheta, 0, |
| 99 -sinTheta, cosTheta, 0, |
| 100 0, 0, 1); |
| 101 matrix_.preConcat(rot); |
| 102 } |
| 103 } |
| 104 |
| 105 void Transform::RotateAbout(const Vector3dF& axis, double degrees) { |
69 if (matrix_.isIdentity()) { | 106 if (matrix_.isIdentity()) { |
70 matrix_.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()), | 107 matrix_.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()), |
71 SkDoubleToMScalar(axis.y()), | 108 SkDoubleToMScalar(axis.y()), |
72 SkDoubleToMScalar(axis.z()), | 109 SkDoubleToMScalar(axis.z()), |
73 SkDoubleToMScalar(degree)); | 110 SkDoubleToMScalar(degrees)); |
74 } else { | 111 } else { |
75 SkMatrix44 rot; | 112 SkMatrix44 rot; |
76 rot.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()), | 113 rot.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()), |
77 SkDoubleToMScalar(axis.y()), | 114 SkDoubleToMScalar(axis.y()), |
78 SkDoubleToMScalar(axis.z()), | 115 SkDoubleToMScalar(axis.z()), |
79 SkDoubleToMScalar(degree)); | 116 SkDoubleToMScalar(degrees)); |
80 matrix_.preConcat(rot); | 117 matrix_.preConcat(rot); |
81 } | 118 } |
82 } | 119 } |
83 | 120 |
84 void Transform::Scale(double x, double y) { | 121 void Transform::Scale(double x, double y) { |
85 if (matrix_.isIdentity()) { | 122 if (matrix_.isIdentity()) { |
86 matrix_.setScale(SkDoubleToMScalar(x), | 123 matrix_.setScale(SkDoubleToMScalar(x), |
87 SkDoubleToMScalar(y), | 124 SkDoubleToMScalar(y), |
88 SkDoubleToMScalar(1)); | 125 SkDoubleToMScalar(1)); |
89 } else { | 126 } else { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 void Transform::ConcatTransform(const Transform& transform) { | 215 void Transform::ConcatTransform(const Transform& transform) { |
179 if (!transform.matrix_.isIdentity()) { | 216 if (!transform.matrix_.isIdentity()) { |
180 matrix_.postConcat(transform.matrix_); | 217 matrix_.postConcat(transform.matrix_); |
181 } | 218 } |
182 } | 219 } |
183 | 220 |
184 bool Transform::IsIdentity() const { | 221 bool Transform::IsIdentity() const { |
185 return matrix_.isIdentity(); | 222 return matrix_.isIdentity(); |
186 } | 223 } |
187 | 224 |
| 225 bool Transform::IsIdentityOrTranslation() const { |
| 226 bool has_no_perspective = !matrix_.getDouble(3, 0) && |
| 227 !matrix_.getDouble(3, 1) && |
| 228 !matrix_.getDouble(3, 2) && |
| 229 (matrix_.getDouble(3, 3) == 1); |
| 230 |
| 231 bool has_no_rotation_or_skew = !matrix_.getDouble(0, 1) && |
| 232 !matrix_.getDouble(0, 2) && |
| 233 !matrix_.getDouble(1, 0) && |
| 234 !matrix_.getDouble(1, 2) && |
| 235 !matrix_.getDouble(2, 0) && |
| 236 !matrix_.getDouble(2, 1); |
| 237 |
| 238 bool has_no_scale = matrix_.getDouble(0, 0) == 1 && |
| 239 matrix_.getDouble(1, 1) == 1 && |
| 240 matrix_.getDouble(2, 2) == 1; |
| 241 |
| 242 return has_no_perspective && has_no_rotation_or_skew && has_no_scale; |
| 243 } |
| 244 |
| 245 bool Transform::IsScaleOrTranslation() const { |
| 246 bool has_no_perspective = !matrix_.getDouble(3, 0) && |
| 247 !matrix_.getDouble(3, 1) && |
| 248 !matrix_.getDouble(3, 2) && |
| 249 (matrix_.getDouble(3, 3) == 1); |
| 250 |
| 251 bool has_no_rotation_or_skew = !matrix_.getDouble(0, 1) && |
| 252 !matrix_.getDouble(0, 2) && |
| 253 !matrix_.getDouble(1, 0) && |
| 254 !matrix_.getDouble(1, 2) && |
| 255 !matrix_.getDouble(2, 0) && |
| 256 !matrix_.getDouble(2, 1); |
| 257 |
| 258 return has_no_perspective && has_no_rotation_or_skew; |
| 259 } |
| 260 |
| 261 bool Transform::HasPerspective() const { |
| 262 return matrix_.getDouble(3, 0) || |
| 263 matrix_.getDouble(3, 1) || |
| 264 matrix_.getDouble(3, 2) || |
| 265 (matrix_.getDouble(3, 3) != 1); |
| 266 } |
| 267 |
188 bool Transform::IsInvertible() const { | 268 bool Transform::IsInvertible() const { |
189 return std::abs(matrix_.determinant()) > kTooSmallForDeterminant; | 269 return std::abs(matrix_.determinant()) > kTooSmallForDeterminant; |
190 } | 270 } |
191 | 271 |
| 272 bool Transform::IsBackFaceVisible() const { |
| 273 // Compute whether a layer with a forward-facing normal of (0, 0, 1) would |
| 274 // have its back face visible after applying the transform. |
| 275 // |
| 276 // This is done by transforming the normal and seeing if the resulting z |
| 277 // value is positive or negative. However, note that transforming a normal |
| 278 // actually requires using the inverse-transpose of the original transform. |
| 279 |
| 280 // TODO (shawnsingh) make this perform more efficiently - we do not |
| 281 // actually need to instantiate/invert/transpose any matrices, exploiting the |
| 282 // fact that we only need to transform (0, 0, 1, 0). |
| 283 SkMatrix44 inverse; |
| 284 bool invertible = matrix_.invert(&inverse); |
| 285 |
| 286 // Assume the transform does not apply if it's not invertible, so it's |
| 287 // front face remains visible. |
| 288 if (!invertible) |
| 289 return false; |
| 290 |
| 291 return inverse.getDouble(2, 2) < 0; |
| 292 } |
| 293 |
192 bool Transform::GetInverse(Transform* transform) const { | 294 bool Transform::GetInverse(Transform* transform) const { |
193 return matrix_.invert(&transform->matrix_); | 295 return matrix_.invert(&transform->matrix_); |
194 } | 296 } |
195 | 297 |
196 void Transform::Transpose() { | 298 void Transform::Transpose() { |
197 matrix_.transpose(); | 299 matrix_.transpose(); |
198 } | 300 } |
199 | 301 |
200 void Transform::TransformPoint(Point& point) const { | 302 void Transform::TransformPoint(Point& point) const { |
201 TransformPointInternal(matrix_, point); | 303 TransformPointInternal(matrix_, point); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 SkDoubleToMScalar(0), | 404 SkDoubleToMScalar(0), |
303 SkDoubleToMScalar(1) | 405 SkDoubleToMScalar(1) |
304 }; | 406 }; |
305 | 407 |
306 xform.mapMScalars(p); | 408 xform.mapMScalars(p); |
307 | 409 |
308 point.SetPoint(ToRoundedInt(p[0]), ToRoundedInt(p[1])); | 410 point.SetPoint(ToRoundedInt(p[0]), ToRoundedInt(p[1])); |
309 } | 411 } |
310 | 412 |
311 } // namespace gfx | 413 } // namespace gfx |
OLD | NEW |