summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
authorvollick@chromium.org <vollick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-26 20:13:08 +0000
committervollick@chromium.org <vollick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-26 20:13:08 +0000
commitf7c321eb19e1dd8a2f8b154cacb7e13788f1fc28 (patch)
treee1f1c285d359f728fd9d270267b881a836dbea0e /ui/gfx
parenteb052c93fa488df29314bcb70bb2458982fc94c8 (diff)
downloadchromium_src-f7c321eb19e1dd8a2f8b154cacb7e13788f1fc28.zip
chromium_src-f7c321eb19e1dd8a2f8b154cacb7e13788f1fc28.tar.gz
chromium_src-f7c321eb19e1dd8a2f8b154cacb7e13788f1fc28.tar.bz2
gfx::Transform API clean-up
We have too many ways to do the same thing in gfx::Transform, and their names can lead to confusion. We have the notion of Concat-ing and Preconcat-ing. We've borrowed this verbage from skia. a.preConcat(b) means a = a * b. This may seem counter-intuitive, but is the correct definition if we are multiplying our points/vectors on the right. That said, we almost always want to pre-concat. This what is done throughout WebKit. To simplify matters, rather than having ConcatFoo and PreconcatFoo, we will now only have Foo which does what PreconcatFoo used to. Furthermore, we also have SetFoo which is almost always used immediately after a transform is created, so Foo would do fine (with the optimization mentioned below). Another bit of redundant code eliminated by this CL is InterpolatedTransform::FactorTRS. This function was brittle and naive, and now that gfx::Transform::Blend exists, it needs to go away. Other minor changes rolled into this cleanup: - RotateAbout now takes the newly minted Vector3dF - The Foo functions mentioned above also check for identity to avoid needless matrix multiplications. BUG=159972 Review URL: https://chromiumcodereview.appspot.com/11418040 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@169476 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r--ui/gfx/interpolated_transform.cc132
-rw-r--r--ui/gfx/interpolated_transform.h33
-rw-r--r--ui/gfx/interpolated_transform_unittest.cc32
-rw-r--r--ui/gfx/transform.cc300
-rw-r--r--ui/gfx/transform.h85
-rw-r--r--ui/gfx/transform_unittest.cc228
-rw-r--r--ui/gfx/transform_util.cc6
7 files changed, 300 insertions, 516 deletions
diff --git a/ui/gfx/interpolated_transform.cc b/ui/gfx/interpolated_transform.cc
index 111f621..583c27f 100644
--- a/ui/gfx/interpolated_transform.cc
+++ b/ui/gfx/interpolated_transform.cc
@@ -104,62 +104,6 @@ void InterpolatedTransform::SetChild(InterpolatedTransform* child) {
child_.reset(child);
}
-bool InterpolatedTransform::FactorTRS(const gfx::Transform& transform,
- gfx::Point* translation,
- float* rotation,
- gfx::Point3F* scale) {
- const SkMatrix44& m = transform.matrix();
- double m00 = SkMScalarToDouble(m.get(0, 0));
- double m01 = SkMScalarToDouble(m.get(0, 1));
- double m10 = SkMScalarToDouble(m.get(1, 0));
- double m11 = SkMScalarToDouble(m.get(1, 1));
-
- // A factorable 2D TRS matrix must be of the form:
- // [ sx*cos_theta -(sy*sin_theta) 0 tx ]
- // [ sx*sin_theta sy*cos_theta 0 ty ]
- // [ 0 0 1 0 ]
- // [ 0 0 0 1 ]
- if (!IsApproximatelyZero(SkMScalarToDouble(m.get(0, 2))) ||
- !IsApproximatelyZero(SkMScalarToDouble(m.get(1, 2))) ||
- !IsApproximatelyZero(SkMScalarToDouble(m.get(2, 0))) ||
- !IsApproximatelyZero(SkMScalarToDouble(m.get(2, 1))) ||
- !IsApproximatelyZero(SkMScalarToDouble(m.get(2, 2)) - 1) ||
- !IsApproximatelyZero(SkMScalarToDouble(m.get(2, 3))) ||
- !IsApproximatelyZero(SkMScalarToDouble(m.get(3, 0))) ||
- !IsApproximatelyZero(SkMScalarToDouble(m.get(3, 1))) ||
- !IsApproximatelyZero(SkMScalarToDouble(m.get(3, 2))) ||
- !IsApproximatelyZero(SkMScalarToDouble(m.get(3, 3)) - 1)) {
- return false;
- }
-
- double scale_x = std::sqrt(m00 * m00 + m10 * m10);
- double scale_y = std::sqrt(m01 * m01 + m11 * m11);
-
- if (scale_x == 0 || scale_y == 0)
- return false;
-
- double cos_theta = m00 / scale_x;
- double sin_theta = m10 / scale_x;
-
- if (!IsApproximatelyZero(cos_theta - (m11 / scale_y)) ||
- !IsApproximatelyZero(sin_theta + (m01 / scale_y)) ||
- !IsApproximatelyZero(cos_theta*cos_theta + sin_theta*sin_theta - 1.0f))
- return false;
-
- double radians = std::atan2(sin_theta, cos_theta);
-
- if (translation)
- *translation = gfx::Point(SkMScalarToFloat(m.get(0, 3)),
- SkMScalarToFloat(m.get(1, 3)));
- if (rotation)
- *rotation = static_cast<float>(radians * 180.0 / M_PI);
- if (scale)
- *scale = gfx::Point3F(static_cast<float>(scale_x),
- static_cast<float>(scale_y),
- 1.0f);
- return true;
-}
-
inline float InterpolatedTransform::ValueBetween(float time,
float start_value,
float end_value) const {
@@ -209,7 +153,7 @@ InterpolatedRotation::~InterpolatedRotation() {}
gfx::Transform InterpolatedRotation::InterpolateButDoNotCompose(float t) const {
gfx::Transform result;
float interpolated_degrees = ValueBetween(t, start_degrees_, end_degrees_);
- result.SetRotate(interpolated_degrees);
+ result.Rotate(interpolated_degrees);
if (t == 0.0f || t == 1.0f)
MassageRotationIfMultipleOfNinetyDegrees(&result, interpolated_degrees);
return result;
@@ -220,7 +164,7 @@ gfx::Transform InterpolatedRotation::InterpolateButDoNotCompose(float t) const {
//
InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation(
- gfx::Point3F axis,
+ const gfx::Vector3dF& axis,
float start_degrees,
float end_degrees)
: InterpolatedTransform(),
@@ -230,7 +174,7 @@ InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation(
}
InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation(
- gfx::Point3F axis,
+ const gfx::Vector3dF& axis,
float start_degrees,
float end_degrees,
float start_time,
@@ -246,7 +190,7 @@ InterpolatedAxisAngleRotation::~InterpolatedAxisAngleRotation() {}
gfx::Transform
InterpolatedAxisAngleRotation::InterpolateButDoNotCompose(float t) const {
gfx::Transform result;
- result.SetRotateAbout(axis_, ValueBetween(t, start_degrees_, end_degrees_));
+ result.RotateAbout(axis_, ValueBetween(t, start_degrees_, end_degrees_));
return result;
}
@@ -290,7 +234,7 @@ gfx::Transform InterpolatedScale::InterpolateButDoNotCompose(float t) const {
float scale_x = ValueBetween(t, start_scale_.x(), end_scale_.x());
float scale_y = ValueBetween(t, start_scale_.y(), end_scale_.y());
// TODO(vollick) 3d xforms.
- result.SetScale(scale_x, scale_y);
+ result.Scale(scale_x, scale_y);
return result;
}
@@ -320,7 +264,7 @@ gfx::Transform
InterpolatedTranslation::InterpolateButDoNotCompose(float t) const {
gfx::Transform result;
// TODO(vollick) 3d xforms.
- result.SetTranslate(ValueBetween(t, start_pos_.x(), end_pos_.x()),
+ result.Translate(ValueBetween(t, start_pos_.x(), end_pos_.x()),
ValueBetween(t, start_pos_.y(), end_pos_.y()));
return result;
}
@@ -376,8 +320,8 @@ void InterpolatedTransformAboutPivot::Init(const gfx::Point& pivot,
InterpolatedTransform* xform) {
gfx::Transform to_pivot;
gfx::Transform from_pivot;
- to_pivot.SetTranslate(-pivot.x(), -pivot.y());
- from_pivot.SetTranslate(pivot.x(), pivot.y());
+ to_pivot.Translate(-pivot.x(), -pivot.y());
+ from_pivot.Translate(pivot.x(), pivot.y());
scoped_ptr<InterpolatedTransform> pre_transform(
new InterpolatedConstantTransform(to_pivot));
@@ -389,14 +333,14 @@ void InterpolatedTransformAboutPivot::Init(const gfx::Point& pivot,
transform_.reset(pre_transform.release());
}
-InterpolatedTRSTransform::InterpolatedTRSTransform(
+InterpolatedMatrixTransform::InterpolatedMatrixTransform(
const gfx::Transform& start_transform,
const gfx::Transform& end_transform)
: InterpolatedTransform() {
Init(start_transform, end_transform);
}
-InterpolatedTRSTransform::InterpolatedTRSTransform(
+InterpolatedMatrixTransform::InterpolatedMatrixTransform(
const gfx::Transform& start_transform,
const gfx::Transform& end_transform,
float start_time,
@@ -405,47 +349,25 @@ InterpolatedTRSTransform::InterpolatedTRSTransform(
Init(start_transform, end_transform);
}
-InterpolatedTRSTransform::~InterpolatedTRSTransform() {}
+InterpolatedMatrixTransform::~InterpolatedMatrixTransform() {}
gfx::Transform
-InterpolatedTRSTransform::InterpolateButDoNotCompose(float t) const {
- if (transform_.get()) {
- return transform_->Interpolate(t);
- }
- return gfx::Transform();
-}
-
-void InterpolatedTRSTransform::Init(const gfx::Transform& start_transform,
- const gfx::Transform& end_transform) {
- gfx::Point start_translation, end_translation;
- gfx::Point3F start_scale, end_scale;
- float start_degrees, end_degrees;
- if (FactorTRS(start_transform,
- &start_translation,
- &start_degrees,
- &start_scale) &&
- FactorTRS(end_transform,
- &end_translation,
- &end_degrees,
- &end_scale)) {
- scoped_ptr<InterpolatedTranslation> translation(
- new InterpolatedTranslation(start_translation, end_translation,
- start_time(), end_time()));
-
- scoped_ptr<InterpolatedScale> scale(
- new InterpolatedScale(start_scale, end_scale,
- start_time(), end_time()));
-
- scoped_ptr<InterpolatedRotation> rotation(
- new InterpolatedRotation(start_degrees, end_degrees,
- start_time(), end_time()));
-
- rotation->SetChild(translation.release());
- scale->SetChild(rotation.release());
- transform_.reset(scale.release());
- } else {
- transform_.reset(new InterpolatedConstantTransform(end_transform));
- }
+InterpolatedMatrixTransform::InterpolateButDoNotCompose(float t) const {
+ gfx::DecomposedTransform blended;
+ bool success = gfx::BlendDecomposedTransforms(&blended,
+ end_decomp_,
+ start_decomp_,
+ t);
+ DCHECK(success);
+ return gfx::ComposeTransform(blended);
+}
+
+void InterpolatedMatrixTransform::Init(const gfx::Transform& start_transform,
+ const gfx::Transform& end_transform) {
+ bool success = gfx::DecomposeTransform(&start_decomp_, start_transform);
+ DCHECK(success);
+ success = gfx::DecomposeTransform(&end_decomp_, end_transform);
+ DCHECK(success);
}
} // namespace ui
diff --git a/ui/gfx/interpolated_transform.h b/ui/gfx/interpolated_transform.h
index 8a93030..474e3a9 100644
--- a/ui/gfx/interpolated_transform.h
+++ b/ui/gfx/interpolated_transform.h
@@ -10,6 +10,8 @@
#include "ui/gfx/point.h"
#include "ui/gfx/point3_f.h"
#include "ui/gfx/transform.h"
+#include "ui/gfx/transform_util.h"
+#include "ui/gfx/vector3d_f.h"
namespace ui {
@@ -46,12 +48,6 @@ class UI_EXPORT InterpolatedTransform {
void SetReversed(bool reversed) { reversed_ = reversed; }
bool Reversed() const { return reversed_; }
- // NOTE: this function is soon to be deprecated.
- static bool FactorTRS(const gfx::Transform& transform,
- gfx::Point* translation,
- float* rotation,
- gfx::Point3F* scale);
-
protected:
// Calculates the interpolated transform without considering our child.
virtual gfx::Transform InterpolateButDoNotCompose(float t) const = 0;
@@ -115,10 +111,10 @@ class UI_EXPORT InterpolatedRotation : public InterpolatedTransform {
///////////////////////////////////////////////////////////////////////////////
class UI_EXPORT InterpolatedAxisAngleRotation : public InterpolatedTransform {
public:
- InterpolatedAxisAngleRotation(gfx::Point3F axis,
+ InterpolatedAxisAngleRotation(const gfx::Vector3dF& axis,
float start_degrees,
float end_degrees);
- InterpolatedAxisAngleRotation(gfx::Point3F axis,
+ InterpolatedAxisAngleRotation(const gfx::Vector3dF& axis,
float start_degrees,
float end_degrees,
float start_time,
@@ -129,7 +125,7 @@ class UI_EXPORT InterpolatedAxisAngleRotation : public InterpolatedTransform {
virtual gfx::Transform InterpolateButDoNotCompose(float t) const OVERRIDE;
private:
- gfx::Point3F axis_;
+ gfx::Vector3dF axis_;
const float start_degrees_;
const float end_degrees_;
@@ -240,17 +236,17 @@ class UI_EXPORT InterpolatedTransformAboutPivot : public InterpolatedTransform {
DISALLOW_COPY_AND_ASSIGN(InterpolatedTransformAboutPivot);
};
-class UI_EXPORT InterpolatedTRSTransform : public InterpolatedTransform {
+class UI_EXPORT InterpolatedMatrixTransform : public InterpolatedTransform {
public:
- InterpolatedTRSTransform(const gfx::Transform& start_transform,
- const gfx::Transform& end_transform);
+ InterpolatedMatrixTransform(const gfx::Transform& start_transform,
+ const gfx::Transform& end_transform);
- InterpolatedTRSTransform(const gfx::Transform& start_transform,
- const gfx::Transform& end_transform,
- float start_time,
- float end_time);
+ InterpolatedMatrixTransform(const gfx::Transform& start_transform,
+ const gfx::Transform& end_transform,
+ float start_time,
+ float end_time);
- virtual ~InterpolatedTRSTransform();
+ virtual ~InterpolatedMatrixTransform();
protected:
virtual gfx::Transform InterpolateButDoNotCompose(float t) const OVERRIDE;
@@ -259,7 +255,8 @@ class UI_EXPORT InterpolatedTRSTransform : public InterpolatedTransform {
void Init(const gfx::Transform& start_transform,
const gfx::Transform& end_transform);
- scoped_ptr<InterpolatedTransform> transform_;
+ gfx::DecomposedTransform start_decomp_;
+ gfx::DecomposedTransform end_decomp_;
};
} // namespace ui
diff --git a/ui/gfx/interpolated_transform_unittest.cc b/ui/gfx/interpolated_transform_unittest.cc
index 65c5e2c..dd31b8b 100644
--- a/ui/gfx/interpolated_transform_unittest.cc
+++ b/ui/gfx/interpolated_transform_unittest.cc
@@ -38,7 +38,7 @@ TEST(InterpolatedTransformTest, InterpolatedRotation) {
for (int i = 0; i <= 100; ++i) {
gfx::Transform rotation;
- rotation.SetRotate(i);
+ rotation.Rotate(i);
gfx::Transform interpolated = interpolated_rotation.Interpolate(i / 100.0f);
CheckApproximatelyEqual(rotation, interpolated);
interpolated = interpolated_rotation_diff_start_end.Interpolate(i + 100);
@@ -54,7 +54,7 @@ TEST(InterpolatedTransformTest, InterpolatedScale) {
for (int i = 0; i <= 100; ++i) {
gfx::Transform scale;
- scale.SetScale(i, i);
+ scale.Scale(i, i);
gfx::Transform interpolated = interpolated_scale.Interpolate(i / 100.0f);
CheckApproximatelyEqual(scale, interpolated);
interpolated = interpolated_scale_diff_start_end.Interpolate(i + 100);
@@ -71,7 +71,7 @@ TEST(InterpolatedTransformTest, InterpolatedTranslate) {
for (int i = 0; i <= 100; ++i) {
gfx::Transform xform;
- xform.SetTranslate(i, i);
+ xform.Translate(i, i);
gfx::Transform interpolated = interpolated_xform.Interpolate(i / 100.0f);
CheckApproximatelyEqual(xform, interpolated);
interpolated = interpolated_xform_diff_start_end.Interpolate(i + 100);
@@ -114,31 +114,6 @@ TEST(InterpolatedTransformTest, InterpolatedScaleAboutPivot) {
EXPECT_EQ(expected_result, above_pivot);
}
-TEST(InterpolatedTransformTest, FactorTRS) {
- for (int degrees = 0; degrees < 360; ++degrees) {
- // build a transformation matrix.
- gfx::Transform transform;
- transform.SetScale(degrees + 1, 2 * degrees + 1);
- transform.ConcatRotate(degrees);
- transform.ConcatTranslate(degrees * 2, -degrees * 3);
-
- // factor the matrix
- gfx::Point translation;
- float rotation;
- gfx::Point3F scale;
- bool success = ui::InterpolatedTransform::FactorTRS(transform,
- &translation,
- &rotation,
- &scale);
- EXPECT_TRUE(success);
- EXPECT_FLOAT_EQ(translation.x(), degrees * 2);
- EXPECT_FLOAT_EQ(translation.y(), -degrees * 3);
- EXPECT_FLOAT_EQ(NormalizeAngle(rotation), degrees);
- EXPECT_FLOAT_EQ(scale.x(), degrees + 1);
- EXPECT_FLOAT_EQ(scale.y(), 2 * degrees + 1);
- }
-}
-
ui::InterpolatedTransform* GetScreenRotation(int degrees, bool reversed) {
gfx::Point old_pivot;
gfx::Point new_pivot;
@@ -257,4 +232,3 @@ TEST(InterpolatedTransformTest, MaximizeEndsCleanly) {
}
}
}
-
diff --git a/ui/gfx/transform.cc b/ui/gfx/transform.cc
index 7815e8d..19b59da 100644
--- a/ui/gfx/transform.cc
+++ b/ui/gfx/transform.cc
@@ -45,225 +45,128 @@ bool Transform::operator!=(const Transform& rhs) const {
return !(*this == rhs);
}
-void Transform::SetRotate(double degree) {
- matrix_.setRotateDegreesAbout(SkDoubleToMScalar(0),
- SkDoubleToMScalar(0),
- SkDoubleToMScalar(1),
- SkDoubleToMScalar(degree));
+void Transform::MakeIdentity() {
+ matrix_.setIdentity();
}
-void Transform::SetRotateAbout(const Point3F& axis, double degree) {
- matrix_.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()),
- SkDoubleToMScalar(axis.y()),
- SkDoubleToMScalar(axis.z()),
- SkDoubleToMScalar(degree));
-}
-
-void Transform::SetScaleX(double x) {
- matrix_.setDouble(0, 0, x);
-}
-
-void Transform::SetScaleY(double y) {
- matrix_.setDouble(1, 1, y);
+void Transform::Rotate(double degree) {
+ if (matrix_.isIdentity()) {
+ matrix_.setRotateDegreesAbout(SkDoubleToMScalar(0),
+ SkDoubleToMScalar(0),
+ SkDoubleToMScalar(1),
+ SkDoubleToMScalar(degree));
+ } else {
+ SkMatrix44 rot;
+ rot.setRotateDegreesAbout(SkDoubleToMScalar(0),
+ SkDoubleToMScalar(0),
+ SkDoubleToMScalar(1),
+ SkDoubleToMScalar(degree));
+ matrix_.preConcat(rot);
+ }
}
-void Transform::SetScaleZ(double z) {
- matrix_.setDouble(2, 2, z);
+void Transform::RotateAbout(const Vector3dF& axis, double degree) {
+ if (matrix_.isIdentity()) {
+ matrix_.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()),
+ SkDoubleToMScalar(axis.y()),
+ SkDoubleToMScalar(axis.z()),
+ SkDoubleToMScalar(degree));
+ } else {
+ SkMatrix44 rot;
+ rot.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()),
+ SkDoubleToMScalar(axis.y()),
+ SkDoubleToMScalar(axis.z()),
+ SkDoubleToMScalar(degree));
+ matrix_.preConcat(rot);
+ }
}
-void Transform::SetScale(double x, double y) {
- matrix_.setScale(SkDoubleToMScalar(x),
+void Transform::Scale(double x, double y) {
+ if (matrix_.isIdentity()) {
+ matrix_.setScale(SkDoubleToMScalar(x),
+ SkDoubleToMScalar(y),
+ SkDoubleToMScalar(1));
+ } else {
+ SkMatrix44 scale;
+ scale.setScale(SkDoubleToMScalar(x),
SkDoubleToMScalar(y),
- matrix_.get(2, 2));
+ SkDoubleToMScalar(1));
+ matrix_.preConcat(scale);
+ }
}
-void Transform::SetScale3d(double x, double y, double z) {
- matrix_.setScale(SkDoubleToMScalar(x),
+void Transform::Scale3d(double x, double y, double z) {
+ if (matrix_.isIdentity()) {
+ matrix_.setScale(SkDoubleToMScalar(x),
+ SkDoubleToMScalar(y),
+ SkDoubleToMScalar(z));
+ } else {
+ SkMatrix44 scale;
+ scale.setScale(SkDoubleToMScalar(x),
SkDoubleToMScalar(y),
SkDoubleToMScalar(z));
+ matrix_.preConcat(scale);
+ }
}
-void Transform::SetTranslateX(double x) {
- matrix_.setDouble(0, 3, x);
-}
-
-void Transform::SetTranslateY(double y) {
- matrix_.setDouble(1, 3, y);
-}
-
-void Transform::SetTranslateZ(double z) {
- matrix_.setDouble(2, 3, z);
-}
-
-void Transform::SetTranslate(double x, double y) {
- matrix_.setTranslate(SkDoubleToMScalar(x),
- SkDoubleToMScalar(y),
- matrix_.get(2, 3));
-}
-
-void Transform::SetTranslate3d(double x, double y, double z) {
- matrix_.setTranslate(SkDoubleToMScalar(x),
- SkDoubleToMScalar(y),
- SkDoubleToMScalar(z));
-}
-
-void Transform::SetSkewX(double angle) {
- matrix_.setDouble(0, 1, TanDegrees(angle));
-}
-
-void Transform::SetSkewY(double angle) {
- matrix_.setDouble(1, 0, TanDegrees(angle));
-}
-
-void Transform::SetPerspectiveDepth(double depth) {
- if (depth == 0)
- return;
-
- SkMatrix44 m;
- m.setDouble(3, 2, -1.0 / depth);
- matrix_ = m;
-}
-
-void Transform::ConcatRotate(double degree) {
- SkMatrix44 rot;
- rot.setRotateDegreesAbout(SkDoubleToMScalar(0),
- SkDoubleToMScalar(0),
- SkDoubleToMScalar(1),
- SkDoubleToMScalar(degree));
- matrix_.postConcat(rot);
-}
-
-void Transform::ConcatRotateAbout(const Point3F& axis, double degree) {
- SkMatrix44 rot;
- rot.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()),
- SkDoubleToMScalar(axis.y()),
- SkDoubleToMScalar(axis.z()),
- SkDoubleToMScalar(degree));
- matrix_.postConcat(rot);
-}
-
-void Transform::ConcatScale(double x, double y) {
- SkMatrix44 scale;
- scale.setScale(SkDoubleToMScalar(x),
- SkDoubleToMScalar(y),
- SkDoubleToMScalar(1));
- matrix_.postConcat(scale);
-}
-
-void Transform::ConcatScale3d(double x, double y, double z) {
- SkMatrix44 scale;
- scale.setScale(SkDoubleToMScalar(x),
- SkDoubleToMScalar(y),
- SkDoubleToMScalar(z));
- matrix_.postConcat(scale);
-}
-
-void Transform::ConcatTranslate(double x, double y) {
- SkMatrix44 translate;
- translate.setTranslate(SkDoubleToMScalar(x),
- SkDoubleToMScalar(y),
- SkDoubleToMScalar(0));
- matrix_.postConcat(translate);
-}
-
-void Transform::ConcatTranslate3d(double x, double y, double z) {
- SkMatrix44 translate;
- translate.setTranslate(SkDoubleToMScalar(x),
- SkDoubleToMScalar(y),
- SkDoubleToMScalar(z));
- matrix_.postConcat(translate);
-}
-
-void Transform::ConcatSkewX(double angle_x) {
- Transform t;
- t.SetSkewX(angle_x);
- matrix_.postConcat(t.matrix_);
-}
-
-void Transform::ConcatSkewY(double angle_y) {
- Transform t;
- t.SetSkewY(angle_y);
- matrix_.postConcat(t.matrix_);
-}
-
-void Transform::ConcatPerspectiveDepth(double depth) {
- if (depth == 0)
- return;
-
- SkMatrix44 m;
- m.setDouble(3, 2, -1.0 / depth);
- matrix_.postConcat(m);
-}
-
-void Transform::PreconcatRotate(double degree) {
- SkMatrix44 rot;
- rot.setRotateDegreesAbout(SkDoubleToMScalar(0),
- SkDoubleToMScalar(0),
- SkDoubleToMScalar(1),
- SkDoubleToMScalar(degree));
- matrix_.preConcat(rot);
-}
-
-void Transform::PreconcatRotateAbout(const Point3F& axis, double degree) {
- SkMatrix44 rot;
- rot.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()),
- SkDoubleToMScalar(axis.y()),
- SkDoubleToMScalar(axis.z()),
- SkDoubleToMScalar(degree));
- matrix_.preConcat(rot);
-}
-
-void Transform::PreconcatScale(double x, double y) {
- SkMatrix44 scale;
- scale.setScale(SkDoubleToMScalar(x),
- SkDoubleToMScalar(y),
- SkDoubleToMScalar(1));
- matrix_.preConcat(scale);
-}
-
-void Transform::PreconcatScale3d(double x, double y, double z) {
- SkMatrix44 scale;
- scale.setScale(SkDoubleToMScalar(x),
- SkDoubleToMScalar(y),
- SkDoubleToMScalar(z));
- matrix_.preConcat(scale);
-}
-
-void Transform::PreconcatTranslate(double x, double y) {
- SkMatrix44 translate;
- translate.setTranslate(SkDoubleToMScalar(x),
+void Transform::Translate(double x, double y) {
+ if (matrix_.isIdentity()) {
+ matrix_.setTranslate(SkDoubleToMScalar(x),
SkDoubleToMScalar(y),
SkDoubleToMScalar(0));
- matrix_.preConcat(translate);
+ } else {
+ SkMatrix44 translate;
+ translate.setTranslate(SkDoubleToMScalar(x),
+ SkDoubleToMScalar(y),
+ SkDoubleToMScalar(0));
+ matrix_.preConcat(translate);
+ }
}
-void Transform::PreconcatTranslate3d(double x, double y, double z) {
- SkMatrix44 translate;
- translate.setTranslate(SkDoubleToMScalar(x),
+void Transform::Translate3d(double x, double y, double z) {
+ if (matrix_.isIdentity()) {
+ matrix_.setTranslate(SkDoubleToMScalar(x),
SkDoubleToMScalar(y),
SkDoubleToMScalar(z));
- matrix_.preConcat(translate);
+ } else {
+ SkMatrix44 translate;
+ translate.setTranslate(SkDoubleToMScalar(x),
+ SkDoubleToMScalar(y),
+ SkDoubleToMScalar(z));
+ matrix_.preConcat(translate);
+ }
}
-void Transform::PreconcatSkewX(double angle_x) {
- Transform t;
- t.SetSkewX(angle_x);
- matrix_.preConcat(t.matrix_);
+void Transform::SkewX(double angle_x) {
+ if (matrix_.isIdentity())
+ matrix_.setDouble(0, 1, TanDegrees(angle_x));
+ else {
+ SkMatrix44 skew;
+ skew.setDouble(0, 1, TanDegrees(angle_x));
+ matrix_.preConcat(skew);
+ }
}
-void Transform::PreconcatSkewY(double angle_y) {
- Transform t;
- t.SetSkewY(angle_y);
- matrix_.preConcat(t.matrix_);
+void Transform::SkewY(double angle_y) {
+ if (matrix_.isIdentity())
+ matrix_.setDouble(1, 0, TanDegrees(angle_y));
+ else {
+ SkMatrix44 skew;
+ skew.setDouble(1, 0, TanDegrees(angle_y));
+ matrix_.preConcat(skew);
+ }
}
-void Transform::PreconcatPerspectiveDepth(double depth) {
+void Transform::ApplyPerspectiveDepth(double depth) {
if (depth == 0)
- return;
-
- SkMatrix44 m;
- m.setDouble(3, 2, -1.0 / depth);
- matrix_.preConcat(m);
+ return;
+ if (matrix_.isIdentity())
+ matrix_.setDouble(3, 2, -1.0 / depth);
+ else {
+ SkMatrix44 m;
+ m.setDouble(3, 2, -1.0 / depth);
+ matrix_.preConcat(m);
+ }
}
void Transform::PreconcatTransform(const Transform& transform) {
@@ -362,6 +265,17 @@ bool Transform::Blend(const Transform& from, double progress) {
return true;
}
+Transform Transform::operator*(const Transform& other) const {
+ Transform to_return;
+ to_return.matrix_.setConcat(matrix_, other.matrix_);
+ return to_return;
+}
+
+Transform& Transform::operator*=(const Transform& other) {
+ matrix_.preConcat(other.matrix_);
+ return *this;
+}
+
void Transform::TransformPointInternal(const SkMatrix44& xform,
Point3F& point) const {
SkMScalar p[4] = {
diff --git a/ui/gfx/transform.h b/ui/gfx/transform.h
index 64e5b83..52d15cf 100644
--- a/ui/gfx/transform.h
+++ b/ui/gfx/transform.h
@@ -14,6 +14,7 @@ namespace gfx {
class RectF;
class Point;
class Point3F;
+class Vector3dF;
// 4x4 transformation matrix. Transform is cheap and explicitly allows
// copy/assign.
@@ -25,91 +26,35 @@ class UI_EXPORT Transform {
bool operator==(const Transform& rhs) const;
bool operator!=(const Transform& rhs) const;
- // NOTE: The 'Set' functions overwrite the previously set transformation
- // parameters. The 'Concat' functions apply a transformation (e.g. rotation,
- // scale, translate) on top of the existing transforms, instead of overwriting
- // them.
-
- // NOTE: The order of the 'Set' function calls do not matter. However, the
- // order of the 'Concat' function calls do matter, especially when combined
- // with the 'Set' functions.
-
- // Sets the rotation of the transformation.
- void SetRotate(double degree);
-
- // Sets the rotation of the transform (about a vector).
- void SetRotateAbout(const Point3F& point, double degree);
-
- // Sets the scaling parameters.
- void SetScaleX(double x);
- void SetScaleY(double y);
- void SetScaleZ(double z);
- void SetScale(double x, double y);
- void SetScale3d(double x, double y, double z);
-
- // Sets the translation parameters.
- void SetTranslateX(double x);
- void SetTranslateY(double y);
- void SetTranslateZ(double z);
- void SetTranslate(double x, double y);
- void SetTranslate3d(double x, double y, double z);
-
- // Sets the skew parameters.
- void SetSkewX(double angle);
- void SetSkewY(double angle);
-
- // Creates a perspective matrix.
- // Based on the 'perspective' operation from
- // http://www.w3.org/TR/css3-3d-transforms/#transform-functions
- void SetPerspectiveDepth(double depth);
-
- // Applies a rotation on the current transformation.
- void ConcatRotate(double degree);
-
- // Applies an axis-angle rotation on the current transformation.
- void ConcatRotateAbout(const Point3F& point, double degree);
-
- // Applies scaling on current transform.
- void ConcatScale(double x, double y);
- void ConcatScale3d(double x, double y, double z);
-
- // Applies translation on current transform.
- void ConcatTranslate(double x, double y);
- void ConcatTranslate3d(double x, double y, double z);
-
- // Applies a perspective on current transform.
- void ConcatPerspectiveDepth(double depth);
-
- // Applies a skew on the current transform.
- void ConcatSkewX(double angle_x);
- void ConcatSkewY(double angle_y);
+ // Resets this transform to the identity transform.
+ void MakeIdentity();
// Applies the current transformation on a rotation and assigns the result
// to |this|.
- void PreconcatRotate(double degree);
+ void Rotate(double degree);
// Applies the current transformation on an axis-angle rotation and assigns
// the result to |this|.
- void PreconcatRotateAbout(const Point3F& point, double degree);
+ void RotateAbout(const Vector3dF& point, double degree);
// Applies the current transformation on a scaling and assigns the result
// to |this|.
- void PreconcatScale(double x, double y);
- void PreconcatScale3d(double x, double y, double z);
+ void Scale(double x, double y);
+ void Scale3d(double x, double y, double z);
// Applies the current transformation on a translation and assigns the result
// to |this|.
- void PreconcatTranslate(double x, double y);
- void PreconcatTranslate3d(double x, double y, double z);
+ void Translate(double x, double y);
+ void Translate3d(double x, double y, double z);
// Applies the current transformation on a skew and assigns the result
// to |this|.
- void PreconcatSkewX(double angle_x);
- void PreconcatSkewY(double angle_y);
+ void SkewX(double angle_x);
+ void SkewY(double angle_y);
// Applies the current transformation on a perspective transform and assigns
// the result to |this|.
- void PreconcatPerspectiveDepth(double depth);
+ void ApplyPerspectiveDepth(double depth);
// Applies a transformation on the current transformation
// (i.e. 'this = this * transform;').
@@ -169,6 +114,12 @@ class UI_EXPORT Transform {
// DecomposedTransform.
bool Blend(const Transform& from, double progress);
+ // Returns |this| * |other|.
+ Transform operator*(const Transform& other) const;
+
+ // Sets |this| = |this| * |other|
+ Transform& operator*=(const Transform& other);
+
// Returns the underlying matrix.
const SkMatrix44& matrix() const { return matrix_; }
SkMatrix44& matrix() { return matrix_; }
diff --git a/ui/gfx/transform_unittest.cc b/ui/gfx/transform_unittest.cc
index 9518c66..8325538 100644
--- a/ui/gfx/transform_unittest.cc
+++ b/ui/gfx/transform_unittest.cc
@@ -16,6 +16,7 @@
#include "ui/gfx/point.h"
#include "ui/gfx/point3_f.h"
#include "ui/gfx/transform_util.h"
+#include "ui/gfx/vector3d_f.h"
namespace gfx {
@@ -116,10 +117,12 @@ TEST(XFormTest, Equality) {
lhs = Transform();
rhs = Transform();
for (int i = 1; i < 100; ++i) {
- lhs.SetTranslate(i, i);
- rhs.SetTranslate(-i, -i);
+ lhs.MakeIdentity();
+ rhs.MakeIdentity();
+ lhs.Translate(i, i);
+ rhs.Translate(-i, -i);
EXPECT_TRUE(lhs != rhs);
- rhs.ConcatTranslate(2*i, 2*i);
+ rhs.Translate(2*i, 2*i);
EXPECT_TRUE(lhs == rhs);
}
}
@@ -145,7 +148,9 @@ TEST(XFormTest, ConcatTranslate) {
Transform xform;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
const TestCase& value = test_cases[i];
- xform.ConcatTranslate(value.tx, value.ty);
+ Transform translation;
+ translation.Translate(value.tx, value.ty);
+ xform = translation * xform;
Point3F p1(value.x1, value.y1, 0);
Point3F p2(value.x2, value.y2, 0);
xform.TransformPoint(p1);
@@ -172,7 +177,9 @@ TEST(XFormTest, ConcatScale) {
Transform xform;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
const TestCase& value = test_cases[i];
- xform.ConcatScale(value.scale, value.scale);
+ Transform scale;
+ scale.Scale(value.scale, value.scale);
+ xform = scale * xform;
Point3F p1(value.before, value.before, 0);
Point3F p2(value.after, value.after, 0);
xform.TransformPoint(p1);
@@ -201,7 +208,9 @@ TEST(XFormTest, ConcatRotate) {
Transform xform;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
const TestCase& value = test_cases[i];
- xform.ConcatRotate(value.degrees);
+ Transform rotation;
+ rotation.Rotate(value.degrees);
+ xform = rotation * xform;
Point3F p1(value.x1, value.y1, 0);
Point3F p2(value.x2, value.y2, 0);
xform.TransformPoint(p1);
@@ -235,17 +244,17 @@ TEST(XFormTest, SetTranslate) {
case 0:
p1.SetPoint(value.x1, 0, 0);
p2.SetPoint(value.x2, 0, 0);
- xform.SetTranslateX(value.tx);
+ xform.Translate(value.tx, 0.0);
break;
case 1:
p1.SetPoint(0, value.y1, 0);
p2.SetPoint(0, value.y2, 0);
- xform.SetTranslateY(value.ty);
+ xform.Translate(0.0, value.ty);
break;
case 2:
p1.SetPoint(value.x1, value.y1, 0);
p2.SetPoint(value.x2, value.y2, 0);
- xform.SetTranslate(value.tx, value.ty);
+ xform.Translate(value.tx, value.ty);
break;
}
p0 = p1;
@@ -282,17 +291,17 @@ TEST(XFormTest, SetScale) {
case 0:
p1.SetPoint(value.before, 0, 0);
p2.SetPoint(value.after, 0, 0);
- xform.SetScaleX(value.s);
+ xform.Scale(value.s, 1.0);
break;
case 1:
p1.SetPoint(0, value.before, 0);
p2.SetPoint(0, value.after, 0);
- xform.SetScaleY(value.s);
+ xform.Scale(1.0, value.s);
break;
case 2:
p1.SetPoint(value.before, value.before, 0);
p2.SetPoint(value.after, value.after, 0);
- xform.SetScale(value.s, value.s);
+ xform.Scale(value.s, value.s);
break;
}
p0 = p1;
@@ -333,7 +342,7 @@ TEST(XFormTest, SetRotate) {
Point3F p2(value.xprime, value.yprime, 0);
p0 = p1;
Transform xform;
- xform.SetRotate(value.degree);
+ xform.Rotate(value.degree);
// just want to make sure that we don't crash in the case of NaN.
if (value.degree == value.degree) {
xform.TransformPoint(p1);
@@ -366,7 +375,9 @@ TEST(XFormTest, ConcatTranslate2D) {
Transform xform;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
const TestCase& value = test_cases[i];
- xform.ConcatTranslate(value.tx, value.ty);
+ Transform translation;
+ translation.Translate(value.tx, value.ty);
+ xform = translation * xform;
Point p1(value.x1, value.y1);
Point p2(value.x2, value.y2);
xform.TransformPoint(p1);
@@ -394,7 +405,9 @@ TEST(XFormTest, ConcatScale2D) {
Transform xform;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
const TestCase& value = test_cases[i];
- xform.ConcatScale(value.scale, value.scale);
+ Transform scale;
+ scale.Scale(value.scale, value.scale);
+ xform = scale * xform;
Point p1(value.before, value.before);
Point p2(value.after, value.after);
xform.TransformPoint(p1);
@@ -424,7 +437,9 @@ TEST(XFormTest, ConcatRotate2D) {
Transform xform;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
const TestCase& value = test_cases[i];
- xform.ConcatRotate(value.degrees);
+ Transform rotation;
+ rotation.Rotate(value.degrees);
+ xform = rotation * xform;
Point p1(value.x1, value.y1);
Point p2(value.x2, value.y2);
xform.TransformPoint(p1);
@@ -461,18 +476,18 @@ TEST(XFormTest, SetTranslate2D) {
case 0:
p1.SetPoint(value.x1, 0);
p2.SetPoint(value.x2, 0);
- xform.SetTranslateX(value.tx + j * epsilon);
+ xform.Translate(value.tx + j * epsilon, 0.0);
break;
case 1:
p1.SetPoint(0, value.y1);
p2.SetPoint(0, value.y2);
- xform.SetTranslateY(value.ty + j * epsilon);
+ xform.Translate(0.0, value.ty + j * epsilon);
break;
case 2:
p1.SetPoint(value.x1, value.y1);
p2.SetPoint(value.x2, value.y2);
- xform.SetTranslate(value.tx + j * epsilon,
- value.ty + j * epsilon);
+ xform.Translate(value.tx + j * epsilon,
+ value.ty + j * epsilon);
break;
}
p0 = p1;
@@ -514,20 +529,20 @@ TEST(XFormTest, SetScale2D) {
case 0:
p1.SetPoint(value.before, 0);
p2.SetPoint(value.after, 0);
- xform.SetScaleX(value.s + j * epsilon);
+ xform.Scale(value.s + j * epsilon, 1.0);
break;
case 1:
p1.SetPoint(0, value.before);
p2.SetPoint(0, value.after);
- xform.SetScaleY(value.s + j * epsilon);
+ xform.Scale(1.0, value.s + j * epsilon);
break;
case 2:
p1.SetPoint(value.before,
value.before);
p2.SetPoint(value.after,
value.after);
- xform.SetScale(value.s + j * epsilon,
- value.s + j * epsilon);
+ xform.Scale(value.s + j * epsilon,
+ value.s + j * epsilon);
break;
}
p0 = p1;
@@ -571,7 +586,7 @@ TEST(XFormTest, SetRotate2D) {
Point pt(value.x, value.y);
Transform xform;
// should be invariant to small floating point errors.
- xform.SetRotate(value.degree + j * epsilon);
+ xform.Rotate(value.degree + j * epsilon);
// just want to make sure that we don't crash in the case of NaN.
if (value.degree == value.degree) {
xform.TransformPoint(pt);
@@ -589,7 +604,7 @@ TEST(XFormTest, BlendTranslate) {
Transform from;
for (int i = 0; i < 10; ++i) {
Transform to;
- to.SetTranslate3d(1, 1, 1);
+ to.Translate3d(1, 1, 1);
double t = i / 9.0;
EXPECT_TRUE(to.Blend(from, t));
EXPECT_FLOAT_EQ(t, to.matrix().get(0, 3));
@@ -599,22 +614,22 @@ TEST(XFormTest, BlendTranslate) {
}
TEST(XFormTest, BlendRotate) {
- Point3F axes[] = {
- Point3F(1, 0, 0),
- Point3F(0, 1, 0),
- Point3F(0, 0, 1),
- Point3F(1, 1, 1)
+ Vector3dF axes[] = {
+ Vector3dF(1, 0, 0),
+ Vector3dF(0, 1, 0),
+ Vector3dF(0, 0, 1),
+ Vector3dF(1, 1, 1)
};
Transform from;
for (size_t index = 0; index < ARRAYSIZE_UNSAFE(axes); ++index) {
for (int i = 0; i < 10; ++i) {
Transform to;
- to.SetRotateAbout(axes[index], 90);
+ to.RotateAbout(axes[index], 90);
double t = i / 9.0;
EXPECT_TRUE(to.Blend(from, t));
Transform expected;
- expected.SetRotateAbout(axes[index], 90 * t);
+ expected.RotateAbout(axes[index], 90 * t);
EXPECT_TRUE(MatricesAreNearlyEqual(expected, to));
}
@@ -622,16 +637,16 @@ TEST(XFormTest, BlendRotate) {
}
TEST(XFormTest, CannotBlend180DegreeRotation) {
- Point3F axes[] = {
- Point3F(1, 0, 0),
- Point3F(0, 1, 0),
- Point3F(0, 0, 1),
- Point3F(1, 1, 1)
+ Vector3dF axes[] = {
+ Vector3dF(1, 0, 0),
+ Vector3dF(0, 1, 0),
+ Vector3dF(0, 0, 1),
+ Vector3dF(1, 1, 1)
};
Transform from;
for (size_t index = 0; index < ARRAYSIZE_UNSAFE(axes); ++index) {
Transform to;
- to.SetRotateAbout(axes[index], 180);
+ to.RotateAbout(axes[index], 180);
EXPECT_FALSE(to.Blend(from, 0.5));
}
}
@@ -640,7 +655,7 @@ TEST(XFormTest, BlendScale) {
Transform from;
for (int i = 0; i < 10; ++i) {
Transform to;
- to.SetScale3d(5, 4, 3);
+ to.Scale3d(5, 4, 3);
double t = i / 9.0;
EXPECT_TRUE(to.Blend(from, t));
EXPECT_FLOAT_EQ(t * 4 + 1, to.matrix().get(0, 0));
@@ -653,12 +668,12 @@ TEST(XFormTest, BlendSkew) {
Transform from;
for (int i = 0; i < 2; ++i) {
Transform to;
- to.SetSkewX(20);
- to.PreconcatSkewY(10);
+ to.SkewX(20);
+ to.SkewY(10);
double t = i;
Transform expected;
- expected.SetSkewX(t * 20);
- expected.PreconcatSkewY(t * 10);
+ expected.SkewX(t * 20);
+ expected.SkewY(t * 10);
EXPECT_TRUE(to.Blend(from, t));
EXPECT_TRUE(MatricesAreNearlyEqual(expected, to));
}
@@ -666,13 +681,13 @@ TEST(XFormTest, BlendSkew) {
TEST(XFormTest, BlendPerspective) {
Transform from;
- from.SetPerspectiveDepth(200);
+ from.ApplyPerspectiveDepth(200);
for (int i = 0; i < 2; ++i) {
Transform to;
- to.SetPerspectiveDepth(800);
+ to.ApplyPerspectiveDepth(800);
double t = i;
Transform expected;
- expected.SetPerspectiveDepth(t * 600 + 200);
+ expected.ApplyPerspectiveDepth(t * 600 + 200);
EXPECT_TRUE(to.Blend(from, t));
EXPECT_TRUE(MatricesAreNearlyEqual(expected, to));
}
@@ -695,16 +710,16 @@ TEST(XFormTest, CannotBlendSingularMatrix) {
TEST(XFormTest, VerifyBlendForTranslation)
{
Transform from;
- from.PreconcatTranslate3d(100, 200, 100);
+ from.Translate3d(100, 200, 100);
Transform to;
- to.PreconcatTranslate3d(200, 100, 300);
+ to.Translate3d(200, 100, 300);
to.Blend(from, 0);
EXPECT_EQ(from, to);
to = Transform();
- to.PreconcatTranslate3d(200, 100, 300);
+ to.Translate3d(200, 100, 300);
to.Blend(from, 0.25);
EXPECT_ROW1_EQ(1, 0, 0, 125, to);
EXPECT_ROW2_EQ(0, 1, 0, 175, to);
@@ -712,7 +727,7 @@ TEST(XFormTest, VerifyBlendForTranslation)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatTranslate3d(200, 100, 300);
+ to.Translate3d(200, 100, 300);
to.Blend(from, 0.5);
EXPECT_ROW1_EQ(1, 0, 0, 150, to);
EXPECT_ROW2_EQ(0, 1, 0, 150, to);
@@ -720,7 +735,7 @@ TEST(XFormTest, VerifyBlendForTranslation)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatTranslate3d(200, 100, 300);
+ to.Translate3d(200, 100, 300);
to.Blend(from, 1);
EXPECT_ROW1_EQ(1, 0, 0, 200, to);
EXPECT_ROW2_EQ(0, 1, 0, 100, to);
@@ -731,16 +746,16 @@ TEST(XFormTest, VerifyBlendForTranslation)
TEST(XFormTest, VerifyBlendForScale)
{
Transform from;
- from.PreconcatScale3d(100, 200, 100);
+ from.Scale3d(100, 200, 100);
Transform to;
- to.PreconcatScale3d(200, 100, 300);
+ to.Scale3d(200, 100, 300);
to.Blend(from, 0);
EXPECT_EQ(from, to);
to = Transform();
- to.PreconcatScale3d(200, 100, 300);
+ to.Scale3d(200, 100, 300);
to.Blend(from, 0.25);
EXPECT_ROW1_EQ(125, 0, 0, 0, to);
EXPECT_ROW2_EQ(0, 175, 0, 0, to);
@@ -748,7 +763,7 @@ TEST(XFormTest, VerifyBlendForScale)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatScale3d(200, 100, 300);
+ to.Scale3d(200, 100, 300);
to.Blend(from, 0.5);
EXPECT_ROW1_EQ(150, 0, 0, 0, to);
EXPECT_ROW2_EQ(0, 150, 0, 0, to);
@@ -756,7 +771,7 @@ TEST(XFormTest, VerifyBlendForScale)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatScale3d(200, 100, 300);
+ to.Scale3d(200, 100, 300);
to.Blend(from, 1);
EXPECT_ROW1_EQ(200, 0, 0, 0, to);
EXPECT_ROW2_EQ(0, 100, 0, 0, to);
@@ -767,16 +782,16 @@ TEST(XFormTest, VerifyBlendForScale)
TEST(XFormTest, VerifyBlendForSkewX)
{
Transform from;
- from.PreconcatSkewX(0);
+ from.SkewX(0);
Transform to;
- to.PreconcatSkewX(45);
+ to.SkewX(45);
to.Blend(from, 0);
EXPECT_EQ(from, to);
to = Transform();
- to.PreconcatSkewX(45);
+ to.SkewX(45);
to.Blend(from, 0.5);
EXPECT_ROW1_EQ(1, 0.5, 0, 0, to);
EXPECT_ROW2_EQ(0, 1, 0, 0, to);
@@ -784,7 +799,7 @@ TEST(XFormTest, VerifyBlendForSkewX)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatSkewX(45);
+ to.SkewX(45);
to.Blend(from, 0.25);
EXPECT_ROW1_EQ(1, 0.25, 0, 0, to);
EXPECT_ROW2_EQ(0, 1, 0, 0, to);
@@ -792,7 +807,7 @@ TEST(XFormTest, VerifyBlendForSkewX)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatSkewX(45);
+ to.SkewX(45);
to.Blend(from, 1);
EXPECT_ROW1_EQ(1, 1, 0, 0, to);
EXPECT_ROW2_EQ(0, 1, 0, 0, to);
@@ -820,16 +835,16 @@ TEST(XFormTest, VerifyBlendForSkewY)
// error.
Transform from;
- from.PreconcatSkewY(0);
+ from.SkewY(0);
Transform to;
- to.PreconcatSkewY(45);
+ to.SkewY(45);
to.Blend(from, 0);
EXPECT_EQ(from, to);
to = Transform();
- to.PreconcatSkewY(45);
+ to.SkewY(45);
to.Blend(from, 0.25);
EXPECT_ROW1_NEAR(1.0823489449280947471976333,
0.0464370719145053845178239,
@@ -847,7 +862,7 @@ TEST(XFormTest, VerifyBlendForSkewY)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatSkewY(45);
+ to.SkewY(45);
to.Blend(from, 0.5);
EXPECT_ROW1_NEAR(1.1152212925809066312865525,
0.0676495144007326631996335,
@@ -865,7 +880,7 @@ TEST(XFormTest, VerifyBlendForSkewY)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatSkewY(45);
+ to.SkewY(45);
to.Blend(from, 1);
EXPECT_ROW1_NEAR(1, 0, 0, 0, to, LOOSE_ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(1, 1, 0, 0, to, LOOSE_ERROR_THRESHOLD);
@@ -881,17 +896,17 @@ TEST(XFormTest, VerifyBlendForRotationAboutX)
// Euler angles.
Transform from;
- from.PreconcatRotateAbout(Point3F(1, 0, 0), 0);
+ from.RotateAbout(Vector3dF(1, 0, 0), 0);
Transform to;
- to.PreconcatRotateAbout(Point3F(1, 0, 0), 90);
+ to.RotateAbout(Vector3dF(1, 0, 0), 90);
to.Blend(from, 0);
EXPECT_EQ(from, to);
double expectedRotationAngle = 22.5 * M_PI / 180.0;
to = Transform();
- to.PreconcatRotateAbout(Point3F(1, 0, 0), 90);
+ to.RotateAbout(Vector3dF(1, 0, 0), 90);
to.Blend(from, 0.25);
EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0,
@@ -910,7 +925,7 @@ TEST(XFormTest, VerifyBlendForRotationAboutX)
expectedRotationAngle = 45 * M_PI / 180.0;
to = Transform();
- to.PreconcatRotateAbout(Point3F(1, 0, 0), 90);
+ to.RotateAbout(Vector3dF(1, 0, 0), 90);
to.Blend(from, 0.5);
EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0,
@@ -928,7 +943,7 @@ TEST(XFormTest, VerifyBlendForRotationAboutX)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatRotateAbout(Point3F(1, 0, 0), 90);
+ to.RotateAbout(Vector3dF(1, 0, 0), 90);
to.Blend(from, 1);
EXPECT_ROW1_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0, 0, -1, 0, to, ERROR_THRESHOLD);
@@ -939,17 +954,17 @@ TEST(XFormTest, VerifyBlendForRotationAboutX)
TEST(XFormTest, VerifyBlendForRotationAboutY)
{
Transform from;
- from.PreconcatRotateAbout(Point3F(0, 1, 0), 0);
+ from.RotateAbout(Vector3dF(0, 1, 0), 0);
Transform to;
- to.PreconcatRotateAbout(Point3F(0, 1, 0), 90);
+ to.RotateAbout(Vector3dF(0, 1, 0), 90);
to.Blend(from, 0);
EXPECT_EQ(from, to);
double expectedRotationAngle = 22.5 * M_PI / 180.0;
to = Transform();
- to.PreconcatRotateAbout(Point3F(0, 1, 0), 90);
+ to.RotateAbout(Vector3dF(0, 1, 0), 90);
to.Blend(from, 0.25);
EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle),
0,
@@ -968,7 +983,7 @@ TEST(XFormTest, VerifyBlendForRotationAboutY)
expectedRotationAngle = 45 * M_PI / 180.0;
to = Transform();
- to.PreconcatRotateAbout(Point3F(0, 1, 0), 90);
+ to.RotateAbout(Vector3dF(0, 1, 0), 90);
to.Blend(from, 0.5);
EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle),
0,
@@ -986,7 +1001,7 @@ TEST(XFormTest, VerifyBlendForRotationAboutY)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatRotateAbout(Point3F(0, 1, 0), 90);
+ to.RotateAbout(Vector3dF(0, 1, 0), 90);
to.Blend(from, 1);
EXPECT_ROW1_NEAR(0, 0, 1, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(0, 1, 0, 0, to, ERROR_THRESHOLD);
@@ -997,17 +1012,17 @@ TEST(XFormTest, VerifyBlendForRotationAboutY)
TEST(XFormTest, VerifyBlendForRotationAboutZ)
{
Transform from;
- from.PreconcatRotateAbout(Point3F(0, 0, 1), 0);
+ from.RotateAbout(Vector3dF(0, 0, 1), 0);
Transform to;
- to.PreconcatRotateAbout(Point3F(0, 0, 1), 90);
+ to.RotateAbout(Vector3dF(0, 0, 1), 90);
to.Blend(from, 0);
EXPECT_EQ(from, to);
double expectedRotationAngle = 22.5 * M_PI / 180.0;
to = Transform();
- to.PreconcatRotateAbout(Point3F(0, 0, 1), 90);
+ to.RotateAbout(Vector3dF(0, 0, 1), 90);
to.Blend(from, 0.25);
EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle),
-std::sin(expectedRotationAngle),
@@ -1026,7 +1041,7 @@ TEST(XFormTest, VerifyBlendForRotationAboutZ)
expectedRotationAngle = 45 * M_PI / 180.0;
to = Transform();
- to.PreconcatRotateAbout(Point3F(0, 0, 1), 90);
+ to.RotateAbout(Vector3dF(0, 0, 1), 90);
to.Blend(from, 0.5);
EXPECT_ROW1_NEAR(std::cos(expectedRotationAngle),
-std::sin(expectedRotationAngle),
@@ -1044,7 +1059,7 @@ TEST(XFormTest, VerifyBlendForRotationAboutZ)
EXPECT_ROW4_EQ(0, 0, 0, 1, to);
to = Transform();
- to.PreconcatRotateAbout(Point3F(0, 0, 1), 90);
+ to.RotateAbout(Vector3dF(0, 0, 1), 90);
to.Blend(from, 1);
EXPECT_ROW1_NEAR(0, -1, 0, 0, to, ERROR_THRESHOLD);
EXPECT_ROW2_NEAR(1, 0, 0, 0, to, ERROR_THRESHOLD);
@@ -1067,11 +1082,11 @@ TEST(XFormTest, VerifyBlendForCompositeTransform)
Transform to;
Transform expectedEndOfAnimation;
- expectedEndOfAnimation.PreconcatPerspectiveDepth(1);
- expectedEndOfAnimation.PreconcatTranslate3d(10, 20, 30);
- expectedEndOfAnimation.PreconcatRotateAbout(Point3F(0, 0, 1), 25);
- expectedEndOfAnimation.PreconcatSkewY(45);
- expectedEndOfAnimation.PreconcatScale3d(6, 7, 8);
+ expectedEndOfAnimation.ApplyPerspectiveDepth(1);
+ expectedEndOfAnimation.Translate3d(10, 20, 30);
+ expectedEndOfAnimation.RotateAbout(Vector3dF(0, 0, 1), 25);
+ expectedEndOfAnimation.SkewY(45);
+ expectedEndOfAnimation.Scale3d(6, 7, 8);
to = expectedEndOfAnimation;
to.Blend(from, 0);
@@ -1101,20 +1116,6 @@ TEST(XFormTest, VerifyBlendForCompositeTransform)
EXPECT_TRUE(MatricesAreNearlyEqual(normalizedExpectedEndOfAnimation, to));
}
-TEST(XFormTest, SetScaleZ)
-{
- Transform scaled;
- scaled.SetScaleZ(2);
- EXPECT_FLOAT_EQ(2, scaled.matrix().get(2, 2));
-}
-
-TEST(XFormTest, SetTranslateZ)
-{
- Transform translated;
- translated.SetTranslateZ(2);
- EXPECT_FLOAT_EQ(2, translated.matrix().get(2, 3));
-}
-
TEST(XFormTest, DecomposedTransformCtor)
{
DecomposedTransform decomp;
@@ -1132,6 +1133,31 @@ TEST(XFormTest, DecomposedTransformCtor)
EXPECT_TRUE(MatricesAreNearlyEqual(identity, composed));
}
+TEST(XFormTest, FactorTRS) {
+ for (int degrees = 0; degrees < 180; ++degrees) {
+ // build a transformation matrix.
+ gfx::Transform transform;
+ transform.Translate(degrees * 2, -degrees * 3);
+ transform.Rotate(degrees);
+ transform.Scale(degrees + 1, 2 * degrees + 1);
+
+ // factor the matrix
+ DecomposedTransform decomp;
+ bool success = DecomposeTransform(&decomp, transform);
+ EXPECT_TRUE(success);
+ EXPECT_FLOAT_EQ(decomp.translate[0], degrees * 2);
+ EXPECT_FLOAT_EQ(decomp.translate[1], -degrees * 3);
+ double rotation = std::acos(decomp.quaternion[3]) * 360.0 / M_PI;
+ while (rotation < 0.0)
+ rotation += 360.0;
+ while (rotation > 360.0)
+ rotation -= 360.0;
+ EXPECT_FLOAT_EQ(rotation, degrees);
+ EXPECT_FLOAT_EQ(decomp.scale[0], degrees + 1);
+ EXPECT_FLOAT_EQ(decomp.scale[1], 2 * degrees + 1);
+ }
+}
+
} // namespace
} // namespace gfx
diff --git a/ui/gfx/transform_util.cc b/ui/gfx/transform_util.cc
index 54561d7..c8ef573 100644
--- a/ui/gfx/transform_util.cc
+++ b/ui/gfx/transform_util.cc
@@ -99,9 +99,9 @@ bool Normalize(SkMatrix44& m) {
Transform GetScaleTransform(const Point& anchor, float scale) {
Transform transform;
- transform.ConcatScale(scale, scale);
- transform.ConcatTranslate(anchor.x() * (1 - scale),
- anchor.y() * (1 - scale));
+ transform.Translate(anchor.x() * (1 - scale),
+ anchor.y() * (1 - scale));
+ transform.Scale(scale, scale);
return transform;
}