diff options
35 files changed, 593 insertions, 822 deletions
diff --git a/ash/launcher/overflow_button.cc b/ash/launcher/overflow_button.cc index caa58a5..0a853bb 100644 --- a/ash/launcher/overflow_button.cc +++ b/ash/launcher/overflow_button.cc @@ -29,15 +29,19 @@ const int kButtonHoverSize = 28; const int kBackgroundOffset = (48 - kButtonHoverSize) / 2; void RotateCounterclockwise(gfx::Transform* transform) { - transform->matrix().set3x3(0, -1, 0, - 1, 0, 0, - 0, 0, 1); + SkMatrix44 rotation; + rotation.set3x3(0, -1, 0, + 1, 0, 0, + 0, 0, 1); + transform->matrix().preConcat(rotation); } void RotateClockwise(gfx::Transform* transform) { - transform->matrix().set3x3( 0, 1, 0, - -1, 0, 0, - 0, 0, 1); + SkMatrix44 rotation; + rotation.set3x3( 0, 1, 0, + -1, 0, 0, + 0, 0, 1); + transform->matrix().preConcat(rotation); } } // namesapce @@ -112,15 +116,15 @@ void OverflowButton::OnPaint(gfx::Canvas* canvas) { switch (alignment_) { case SHELF_ALIGNMENT_BOTTOM: // Shift 1 pixel left to align with overflow bubble tip. - transform.ConcatTranslate(-1, kBackgroundOffset); + transform.Translate(-1, kBackgroundOffset); break; case SHELF_ALIGNMENT_LEFT: + transform.Translate(kBackgroundOffset, -1); RotateClockwise(&transform); - transform.ConcatTranslate(kBackgroundOffset, -1); break; case SHELF_ALIGNMENT_RIGHT: + transform.Translate(kBackgroundOffset, height()); RotateCounterclockwise(&transform); - transform.ConcatTranslate(kBackgroundOffset, height()); break; } diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc index 9a980d3..7ab7a2d 100644 --- a/ash/magnifier/magnification_controller.cc +++ b/ash/magnifier/magnification_controller.cc @@ -230,8 +230,8 @@ bool MagnificationControllerImpl::RedrawDIP(const gfx::PointF& position_in_dip, gfx::Transform transform; // Flips the signs intentionally to convert them from the position of the // magnification window. - transform.ConcatTranslate(-origin_.x(), -origin_.y()); - transform.ConcatScale(scale_, scale_); + transform.Scale(scale_, scale_); + transform.Translate(-origin_.x(), -origin_.y()); ui::ScopedLayerAnimationSettings settings( root_window_->layer()->GetAnimator()); diff --git a/ash/system/tray/system_tray_bubble.cc b/ash/system/tray/system_tray_bubble.cc index aff2719..0059973 100644 --- a/ash/system/tray/system_tray_bubble.cc +++ b/ash/system/tray/system_tray_bubble.cc @@ -165,7 +165,7 @@ void SystemTrayBubble::UpdateView( settings.SetTransitionDuration(swipe_duration); settings.SetTweenType(ui::Tween::EASE_OUT); gfx::Transform transform; - transform.SetTranslateX(layer->bounds().width()); + transform.Translate(layer->bounds().width(), 0.0); layer->SetTransform(transform); } @@ -218,7 +218,7 @@ void SystemTrayBubble::UpdateView( ui::Layer* new_layer = bubble_view_->layer(); gfx::Rect bounds = new_layer->bounds(); gfx::Transform transform; - transform.SetTranslateX(bounds.width()); + transform.Translate(bounds.width(), 0.0); new_layer->SetTransform(transform); { ui::ScopedLayerAnimationSettings settings(new_layer->GetAnimator()); diff --git a/ash/system/tray/tray_item_view.cc b/ash/system/tray/tray_item_view.cc index 87644d08..b93163c 100644 --- a/ash/system/tray/tray_item_view.cc +++ b/ash/system/tray/tray_item_view.cc @@ -95,10 +95,10 @@ void TrayItemView::ChildPreferredSizeChanged(views::View* child) { void TrayItemView::AnimationProgressed(const ui::Animation* animation) { gfx::Transform transform; - transform.SetScale(animation->GetCurrentValue(), - animation->GetCurrentValue()); - transform.ConcatTranslate(0, animation->CurrentValueBetween( + transform.Translate(0, animation->CurrentValueBetween( static_cast<double>(height()) / 2, 0.)); + transform.Scale(animation->GetCurrentValue(), + animation->GetCurrentValue()); layer()->SetTransform(transform); PreferredSizeChanged(); } diff --git a/ash/wm/gestures/long_press_affordance_handler.cc b/ash/wm/gestures/long_press_affordance_handler.cc index f776e01..112a97e 100644 --- a/ash/wm/gestures/long_press_affordance_handler.cc +++ b/ash/wm/gestures/long_press_affordance_handler.cc @@ -201,7 +201,7 @@ class LongPressAffordanceHandler::LongPressAffordanceView canvas->Save(); gfx::Transform scale; - scale.SetScale(current_scale_, current_scale_); + scale.Scale(current_scale_, current_scale_); // We want to scale from the center. canvas->Translate(center.OffsetFromOrigin()); canvas->Transform(scale); diff --git a/ash/wm/session_state_animator.cc b/ash/wm/session_state_animator.cc index 82f41f8..12ddf33 100644 --- a/ash/wm/session_state_animator.cc +++ b/ash/wm/session_state_animator.cc @@ -26,16 +26,19 @@ const float kSlowCloseSizeRatio = 0.95f; // Maximum opacity of white layer when animating pre-shutdown state. const float kPartialFadeRatio = 0.3f; +// Minimum size. Not zero as it causes numeric issues. +const float kMinimumScale = 1e-4f; + // Returns the transform that should be applied to containers for the slow-close // animation. gfx::Transform GetSlowCloseTransform() { gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); gfx::Transform transform; - transform.SetScale(kSlowCloseSizeRatio, kSlowCloseSizeRatio); - transform.ConcatTranslate( + transform.Translate( floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.width() + 0.5), floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.height() + 0.5)); - return transform; + transform.Scale(kSlowCloseSizeRatio, kSlowCloseSizeRatio); + return transform; } // Returns the transform that should be applied to containers for the fast-close @@ -43,9 +46,9 @@ gfx::Transform GetSlowCloseTransform() { gfx::Transform GetFastCloseTransform() { gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); gfx::Transform transform; - transform.SetScale(0.0, 0.0); - transform.ConcatTranslate(floor(0.5 * root_size.width() + 0.5), - floor(0.5 * root_size.height() + 0.5)); + transform.Translate(floor(0.5 * root_size.width() + 0.5), + floor(0.5 * root_size.height() + 0.5)); + transform.Scale(kMinimumScale, kMinimumScale); return transform; } diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc index 855c453..415316e 100644 --- a/ash/wm/window_animations.cc +++ b/ash/wm/window_animations.cc @@ -34,6 +34,7 @@ #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/interpolated_transform.h" #include "ui/gfx/screen.h" +#include "ui/gfx/vector3d_f.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -279,40 +280,35 @@ void AnimateHideWindowCommon(aura::Window* window, window->layer()->SetVisible(false); } +static gfx::Transform GetScaleForWindow(aura::Window* window) { + gfx::Rect bounds = window->bounds(); + gfx::Transform scale = gfx::GetScaleTransform( + gfx::Point(kWindowAnimation_TranslateFactor * bounds.width(), + kWindowAnimation_TranslateFactor * bounds.height()), + kWindowAnimation_ScaleFactor); + return scale; +} + // Show/Hide windows using a shrink animation. void AnimateShowWindow_Drop(aura::Window* window) { - gfx::Transform transform; - transform.ConcatScale(kWindowAnimation_ScaleFactor, - kWindowAnimation_ScaleFactor); - gfx::Rect bounds = window->bounds(); - transform.ConcatTranslate( - kWindowAnimation_TranslateFactor * bounds.width(), - kWindowAnimation_TranslateFactor * bounds.height()); - AnimateShowWindowCommon(window, transform, gfx::Transform()); + AnimateShowWindowCommon(window, GetScaleForWindow(window), gfx::Transform()); } void AnimateHideWindow_Drop(aura::Window* window) { - gfx::Transform transform; - transform.ConcatScale(kWindowAnimation_ScaleFactor, - kWindowAnimation_ScaleFactor); - gfx::Rect bounds = window->bounds(); - transform.ConcatTranslate( - kWindowAnimation_TranslateFactor * bounds.width(), - kWindowAnimation_TranslateFactor * bounds.height()); - AnimateHideWindowCommon(window, transform); + AnimateHideWindowCommon(window, GetScaleForWindow(window)); } // Show/Hide windows using a vertical Glenimation. void AnimateShowWindow_Vertical(aura::Window* window) { gfx::Transform transform; - transform.ConcatTranslate(0, window->GetProperty( + transform.Translate(0, window->GetProperty( kWindowVisibilityAnimationVerticalPositionKey)); AnimateShowWindowCommon(window, transform, gfx::Transform()); } void AnimateHideWindow_Vertical(aura::Window* window) { gfx::Transform transform; - transform.ConcatTranslate(0, window->GetProperty( + transform.Translate(0, window->GetProperty( kWindowVisibilityAnimationVerticalPositionKey)); AnimateHideWindowCommon(window, transform); } @@ -502,9 +498,9 @@ void AddLayerAnimationsForRotate(aura::Window* window, bool show) { float xcenter = window->bounds().width() * 0.5; gfx::Transform transform; - transform.ConcatTranslate(-xcenter, 0); - transform.ConcatPerspectiveDepth(kWindowAnimation_Rotate_PerspectiveDepth); - transform.ConcatTranslate(xcenter, 0); + transform.Translate(xcenter, 0); + transform.ApplyPerspectiveDepth(kWindowAnimation_Rotate_PerspectiveDepth); + transform.Translate(-xcenter, 0); scoped_ptr<ui::InterpolatedTransform> perspective( new ui::InterpolatedConstantTransform(transform)); @@ -521,7 +517,7 @@ void AddLayerAnimationsForRotate(aura::Window* window, bool show) { scoped_ptr<ui::InterpolatedTransform> rotation( new ui::InterpolatedAxisAngleRotation( - gfx::Point3F(1, 0, 0), 0, kWindowAnimation_Rotate_DegreesX)); + gfx::Vector3dF(1, 0, 0), 0, kWindowAnimation_Rotate_DegreesX)); scale_about_pivot->SetChild(perspective.release()); translation->SetChild(scale_about_pivot.release()); @@ -692,9 +688,9 @@ TimeDelta CrossFadeImpl(aura::Window* window, static_cast<float>(old_bounds.width()); float scale_y = static_cast<float>(new_bounds.height()) / static_cast<float>(old_bounds.height()); - out_transform.ConcatScale(scale_x, scale_y); - out_transform.ConcatTranslate(new_bounds.x() - old_bounds.x(), - new_bounds.y() - old_bounds.y()); + out_transform.Translate(new_bounds.x() - old_bounds.x(), + new_bounds.y() - old_bounds.y()); + out_transform.Scale(scale_x, scale_y); old_layer->SetTransform(out_transform); if (old_on_top) { // The old layer is on top, and should fade out. The new layer below will @@ -712,9 +708,9 @@ TimeDelta CrossFadeImpl(aura::Window* window, static_cast<float>(new_bounds.width()); const float scale_y = static_cast<float>(old_bounds.height()) / static_cast<float>(new_bounds.height()); - in_transform.ConcatScale(scale_x, scale_y); - in_transform.ConcatTranslate(old_bounds.x() - new_bounds.x(), + in_transform.Translate(old_bounds.x() - new_bounds.x(), old_bounds.y() - new_bounds.y()); + in_transform.Scale(scale_x, scale_y); window->layer()->SetTransform(in_transform); if (!old_on_top) { // The new layer is on top and should fade in. The old layer below will diff --git a/ash/wm/window_animations_unittest.cc b/ash/wm/window_animations_unittest.cc index eebed14..2e3cc13 100644 --- a/ash/wm/window_animations_unittest.cc +++ b/ash/wm/window_animations_unittest.cc @@ -102,8 +102,8 @@ TEST_F(WindowAnimationsTest, CrossFadeToBounds) { EXPECT_EQ(1.0f, old_layer->GetTargetOpacity()); EXPECT_EQ("5,10 320x240", old_layer->bounds().ToString()); gfx::Transform grow_transform; - grow_transform.ConcatScale(640.f / 320.f, 480.f / 240.f); - grow_transform.ConcatTranslate(-5.f, -10.f); + grow_transform.Translate(-5.f, -10.f); + grow_transform.Scale(640.f / 320.f, 480.f / 240.f); EXPECT_EQ(grow_transform, old_layer->GetTargetTransform()); // New layer animates in to the identity transform. EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity()); @@ -124,8 +124,8 @@ TEST_F(WindowAnimationsTest, CrossFadeToBounds) { EXPECT_EQ(0.0f, old_layer->GetTargetOpacity()); EXPECT_EQ("0,0 640x480", old_layer->bounds().ToString()); gfx::Transform shrink_transform; - shrink_transform.ConcatScale(320.f / 640.f, 240.f / 480.f); - shrink_transform.ConcatTranslate(5.f, 10.f); + shrink_transform.Translate(5.f, 10.f); + shrink_transform.Scale(320.f / 640.f, 240.f / 480.f); EXPECT_EQ(shrink_transform, old_layer->GetTargetTransform()); // New layer animates in to the identity transform. EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity()); diff --git a/ash/wm/window_manager_unittest.cc b/ash/wm/window_manager_unittest.cc index 5b02d35..ed27f01 100644 --- a/ash/wm/window_manager_unittest.cc +++ b/ash/wm/window_manager_unittest.cc @@ -507,8 +507,8 @@ TEST_F(WindowManagerTest, MAYBE_TransformActivate) { // Rotate it clock-wise 90 degrees. gfx::Transform transform; - transform.SetRotate(90.0f); - transform.ConcatTranslate(size.width(), 0); + transform.Translate(size.width(), 0); + transform.Rotate(90.0f); root_window->SetTransform(transform); test::TestActivationDelegate d1; diff --git a/ash/wm/workspace/workspace_animations.cc b/ash/wm/workspace/workspace_animations.cc index ae93f6b..2bffbd5 100644 --- a/ash/wm/workspace/workspace_animations.cc +++ b/ash/wm/workspace/workspace_animations.cc @@ -34,10 +34,9 @@ void ApplyWorkspaceScale(ui::Layer* layer, WorkspaceScaleType type) { const float scale = type == WORKSPACE_SCALE_ABOVE ? kWorkspaceScaleAbove : kWorkspaceScaleBelow; gfx::Transform transform; - transform.ConcatScale(scale, scale); - transform.ConcatTranslate( - -layer->bounds().width() * (scale - 1.0f) / 2, - -layer->bounds().height() * (scale - 1.0f) / 2); + transform.Translate(-layer->bounds().width() * (scale - 1.0f) / 2, + -layer->bounds().height() * (scale - 1.0f) / 2); + transform.Scale(scale, scale); layer->SetTransform(transform); } diff --git a/cc/math_util.cc b/cc/math_util.cc index 2f885f8..a9c0c82 100644 --- a/cc/math_util.cc +++ b/cc/math_util.cc @@ -461,10 +461,8 @@ void MathUtil::rotateEulerAngles(gfx::Transform* transform, double eulerX, doubl void MathUtil::rotateAxisAngle(gfx::Transform* transform, double i, double j, double k, double degrees) { - // TODO (shawnsingh): fix gfx::Transform API to receive vector instead of - // point for the axis. - gfx::Point3F axis(i, j, k); - transform->PreconcatRotateAbout(axis, degrees); + gfx::Vector3dF axis(i, j, k); + transform->RotateAbout(axis, degrees); } gfx::Transform MathUtil::inverse(const gfx::Transform& transform) @@ -545,12 +543,4 @@ gfx::Transform MathUtil::createGfxTransform(double a, double b, double c, return result; } -gfx::Transform operator*(const gfx::Transform& A, const gfx::Transform& B) -{ - // Compute A * B. - gfx::Transform result = A; - result.PreconcatTransform(B); - return result; -} - } // namespace cc diff --git a/cc/math_util.h b/cc/math_util.h index db43aed..65fb436 100644 --- a/cc/math_util.h +++ b/cc/math_util.h @@ -143,10 +143,6 @@ public: double d, double e, double f); }; -// TODO(shawnsingh, vollick) this is a temporary home, should eventually -// be phased out in favor of gfx::Transform API. -gfx::Transform CC_EXPORT operator*(const gfx::Transform&, const gfx::Transform&); - } // namespace cc #endif // CC_MATH_UTIL_H_ diff --git a/cc/math_util_unittest.cc b/cc/math_util_unittest.cc index 93a980f..92c4405 100644 --- a/cc/math_util_unittest.cc +++ b/cc/math_util_unittest.cc @@ -331,7 +331,7 @@ TEST(MathUtilGfxTransformTest, verifyMatrixInversion) { // Invert a translation gfx::Transform translation; - translation.PreconcatTranslate3d(2, 3, 4); + translation.Translate3d(2, 3, 4); EXPECT_TRUE(MathUtil::isInvertible(translation)); gfx::Transform inverseTranslation = MathUtil::inverse(translation); @@ -348,7 +348,7 @@ TEST(MathUtilGfxTransformTest, verifyMatrixInversion) // Invert a non-uniform scale gfx::Transform scale; - scale.PreconcatScale3d(4, 10, 100); + scale.Scale3d(4, 10, 100); EXPECT_TRUE(MathUtil::isInvertible(scale)); gfx::Transform inverseScale = MathUtil::inverse(scale); @@ -512,6 +512,28 @@ TEST(MathUtilGfxTransformTest, verifyMultiplyOperator) EXPECT_FALSE(A * B == B * A); } +TEST(MathUtilGfxTransformTest, verifyMultiplyAndAssignOperator) +{ + gfx::Transform A; + initializeTestMatrix(&A); + + gfx::Transform B; + initializeTestMatrix2(&B); + + A *= B; + EXPECT_ROW1_EQ(2036, 2292, 2548, 2804, A); + EXPECT_ROW2_EQ(2162, 2434, 2706, 2978, A); + EXPECT_ROW3_EQ(2288, 2576, 2864, 3152, A); + EXPECT_ROW4_EQ(2414, 2718, 3022, 3326, A); + + // Just an additional sanity check; matrix multiplication is not commutative. + gfx::Transform C = A; + C *= B; + gfx::Transform D = B; + D *= A; + EXPECT_FALSE(C == D); +} + TEST(MathUtilGfxTransformTest, verifyMatrixMultiplication) { gfx::Transform A; @@ -542,16 +564,16 @@ TEST(MathUtilGfxTransformTest, verifyMakeIdentiy) TEST(MathUtilGfxTransformTest, verifyTranslate) { gfx::Transform A; - A.PreconcatTranslate(2, 3); + A.Translate(2, 3); EXPECT_ROW1_EQ(1, 0, 0, 2, A); EXPECT_ROW2_EQ(0, 1, 0, 3, A); EXPECT_ROW3_EQ(0, 0, 1, 0, A); EXPECT_ROW4_EQ(0, 0, 0, 1, A); - // Verify that PreconcatTranslate() post-multiplies the existing matrix. + // Verify that Translate() post-multiplies the existing matrix. MathUtil::makeIdentity(&A); - A.PreconcatScale(5, 5); - A.PreconcatTranslate(2, 3); + A.Scale(5, 5); + A.Translate(2, 3); EXPECT_ROW1_EQ(5, 0, 0, 10, A); EXPECT_ROW2_EQ(0, 5, 0, 15, A); EXPECT_ROW3_EQ(0, 0, 1, 0, A); @@ -561,16 +583,16 @@ TEST(MathUtilGfxTransformTest, verifyTranslate) TEST(MathUtilGfxTransformTest, verifyTranslate3d) { gfx::Transform A; - A.PreconcatTranslate3d(2, 3, 4); + A.Translate3d(2, 3, 4); EXPECT_ROW1_EQ(1, 0, 0, 2, A); EXPECT_ROW2_EQ(0, 1, 0, 3, A); EXPECT_ROW3_EQ(0, 0, 1, 4, A); EXPECT_ROW4_EQ(0, 0, 0, 1, A); - // Verify that PreconcatTranslate3d() post-multiplies the existing matrix. + // Verify that Translate3d() post-multiplies the existing matrix. MathUtil::makeIdentity(&A); - A.PreconcatScale3d(6, 7, 8); - A.PreconcatTranslate3d(2, 3, 4); + A.Scale3d(6, 7, 8); + A.Translate3d(2, 3, 4); EXPECT_ROW1_EQ(6, 0, 0, 12, A); EXPECT_ROW2_EQ(0, 7, 0, 21, A); EXPECT_ROW3_EQ(0, 0, 8, 32, A); @@ -580,16 +602,16 @@ TEST(MathUtilGfxTransformTest, verifyTranslate3d) TEST(MathUtilGfxTransformTest, verifyScale) { gfx::Transform A; - A.PreconcatScale(6, 7); + A.Scale(6, 7); EXPECT_ROW1_EQ(6, 0, 0, 0, A); EXPECT_ROW2_EQ(0, 7, 0, 0, A); EXPECT_ROW3_EQ(0, 0, 1, 0, A); EXPECT_ROW4_EQ(0, 0, 0, 1, A); - // Verify that PreconcatScale() post-multiplies the existing matrix. + // Verify that Scale() post-multiplies the existing matrix. MathUtil::makeIdentity(&A); - A.PreconcatTranslate3d(2, 3, 4); - A.PreconcatScale(6, 7); + A.Translate3d(2, 3, 4); + A.Scale(6, 7); EXPECT_ROW1_EQ(6, 0, 0, 2, A); EXPECT_ROW2_EQ(0, 7, 0, 3, A); EXPECT_ROW3_EQ(0, 0, 1, 4, A); @@ -599,7 +621,7 @@ TEST(MathUtilGfxTransformTest, verifyScale) TEST(MathUtilGfxTransformTest, verifyScale3d) { gfx::Transform A; - A.PreconcatScale3d(6, 7, 8); + A.Scale3d(6, 7, 8); EXPECT_ROW1_EQ(6, 0, 0, 0, A); EXPECT_ROW2_EQ(0, 7, 0, 0, A); EXPECT_ROW3_EQ(0, 0, 8, 0, A); @@ -607,8 +629,8 @@ TEST(MathUtilGfxTransformTest, verifyScale3d) // Verify that scale3d() post-multiplies the existing matrix. MathUtil::makeIdentity(&A); - A.PreconcatTranslate3d(2, 3, 4); - A.PreconcatScale3d(6, 7, 8); + A.Translate3d(2, 3, 4); + A.Scale3d(6, 7, 8); EXPECT_ROW1_EQ(6, 0, 0, 2, A); EXPECT_ROW2_EQ(0, 7, 0, 3, A); EXPECT_ROW3_EQ(0, 0, 8, 4, A); @@ -618,16 +640,16 @@ TEST(MathUtilGfxTransformTest, verifyScale3d) TEST(MathUtilGfxTransformTest, verifyRotate) { gfx::Transform A; - A.PreconcatRotate(90); + A.Rotate(90); EXPECT_ROW1_NEAR(0, -1, 0, 0, A, ERROR_THRESHOLD); EXPECT_ROW2_NEAR(1, 0, 0, 0, A, ERROR_THRESHOLD); EXPECT_ROW3_EQ(0, 0, 1, 0, A); EXPECT_ROW4_EQ(0, 0, 0, 1, A); - // Verify that PreconcatRotate() post-multiplies the existing matrix. + // Verify that Rotate() post-multiplies the existing matrix. MathUtil::makeIdentity(&A); - A.PreconcatScale3d(6, 7, 8); - A.PreconcatRotate(90); + A.Scale3d(6, 7, 8); + A.Rotate(90); EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD); EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD); EXPECT_ROW3_EQ(0, 0, 8, 0, A); @@ -665,7 +687,7 @@ TEST(MathUtilGfxTransformTest, verifyRotateEulerAngles) // Verify that rotate3d(rx, ry, rz) post-multiplies the existing matrix. MathUtil::makeIdentity(&A); - A.PreconcatScale3d(6, 7, 8); + A.Scale3d(6, 7, 8); MathUtil::rotateEulerAngles(&A, 0, 0, 90); EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD); EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD); @@ -738,7 +760,7 @@ TEST(MathUtilGfxTransformTest, verifyRotateAxisAngleForAlignedAxes) // Verify that rotate3d(axis, angle) post-multiplies the existing matrix. MathUtil::makeIdentity(&A); - A.PreconcatScale3d(6, 7, 8); + A.Scale3d(6, 7, 8); MathUtil::rotateAxisAngle(&A, 0, 0, 1, 90); EXPECT_ROW1_NEAR(0, -6, 0, 0, A, ERROR_THRESHOLD); EXPECT_ROW2_NEAR(7, 0, 0, 0, A, ERROR_THRESHOLD); @@ -789,7 +811,7 @@ TEST(MathUtilGfxTransformTest, verifyRotateAxisAngleForDegenerateAxis) TEST(MathUtilGfxTransformTest, verifySkewX) { gfx::Transform A; - A.PreconcatSkewX(45); + A.SkewX(45); EXPECT_ROW1_EQ(1, 1, 0, 0, A); EXPECT_ROW2_EQ(0, 1, 0, 0, A); EXPECT_ROW3_EQ(0, 0, 1, 0, A); @@ -798,8 +820,8 @@ TEST(MathUtilGfxTransformTest, verifySkewX) // Verify that skewX() post-multiplies the existing matrix. // Row 1, column 2, would incorrectly have value "7" if the matrix is pre-multiplied instead of post-multiplied. MathUtil::makeIdentity(&A); - A.PreconcatScale3d(6, 7, 8); - A.PreconcatSkewX(45); + A.Scale3d(6, 7, 8); + A.SkewX(45); EXPECT_ROW1_EQ(6, 6, 0, 0, A); EXPECT_ROW2_EQ(0, 7, 0, 0, A); EXPECT_ROW3_EQ(0, 0, 8, 0, A); @@ -809,7 +831,7 @@ TEST(MathUtilGfxTransformTest, verifySkewX) TEST(MathUtilGfxTransformTest, verifySkewY) { gfx::Transform A; - A.PreconcatSkewY(45); + A.SkewY(45); EXPECT_ROW1_EQ(1, 0, 0, 0, A); EXPECT_ROW2_EQ(1, 1, 0, 0, A); EXPECT_ROW3_EQ(0, 0, 1, 0, A); @@ -818,8 +840,8 @@ TEST(MathUtilGfxTransformTest, verifySkewY) // Verify that skewY() post-multiplies the existing matrix. // Row 2, column 1, would incorrectly have value "6" if the matrix is pre-multiplied instead of post-multiplied. MathUtil::makeIdentity(&A); - A.PreconcatScale3d(6, 7, 8); - A.PreconcatSkewY(45); + A.Scale3d(6, 7, 8); + A.SkewY(45); EXPECT_ROW1_EQ(6, 0, 0, 0, A); EXPECT_ROW2_EQ(7, 7, 0, 0, A); EXPECT_ROW3_EQ(0, 0, 8, 0, A); @@ -829,16 +851,16 @@ TEST(MathUtilGfxTransformTest, verifySkewY) TEST(MathUtilGfxTransformTest, verifyPerspectiveDepth) { gfx::Transform A; - A.PreconcatPerspectiveDepth(1); + A.ApplyPerspectiveDepth(1); EXPECT_ROW1_EQ(1, 0, 0, 0, A); EXPECT_ROW2_EQ(0, 1, 0, 0, A); EXPECT_ROW3_EQ(0, 0, 1, 0, A); EXPECT_ROW4_EQ(0, 0, -1, 1, A); - // Verify that PreconcatPerspectiveDepth() post-multiplies the existing matrix. + // Verify that PerspectiveDepth() post-multiplies the existing matrix. MathUtil::makeIdentity(&A); - A.PreconcatTranslate3d(2, 3, 4); - A.PreconcatPerspectiveDepth(1); + A.Translate3d(2, 3, 4); + A.ApplyPerspectiveDepth(1); EXPECT_ROW1_EQ(1, 0, -2, 2, A); EXPECT_ROW2_EQ(0, 1, -3, 3, A); EXPECT_ROW3_EQ(0, 0, -3, 4, A); @@ -848,11 +870,11 @@ TEST(MathUtilGfxTransformTest, verifyPerspectiveDepth) TEST(MathUtilGfxTransformTest, verifyHasPerspective) { gfx::Transform A; - A.PreconcatPerspectiveDepth(1); + A.ApplyPerspectiveDepth(1); EXPECT_TRUE(MathUtil::hasPerspective(A)); MathUtil::makeIdentity(&A); - A.PreconcatPerspectiveDepth(0); + A.ApplyPerspectiveDepth(0); EXPECT_FALSE(MathUtil::hasPerspective(A)); MathUtil::makeIdentity(&A); @@ -885,11 +907,11 @@ TEST(MathUtilGfxTransformTest, verifyIsInvertible) EXPECT_TRUE(MathUtil::isInvertible(A)); MathUtil::makeIdentity(&A); - A.PreconcatTranslate3d(2, 3, 4); + A.Translate3d(2, 3, 4); EXPECT_TRUE(MathUtil::isInvertible(A)); MathUtil::makeIdentity(&A); - A.PreconcatScale3d(6, 7, 8); + A.Scale3d(6, 7, 8); EXPECT_TRUE(MathUtil::isInvertible(A)); MathUtil::makeIdentity(&A); @@ -897,30 +919,30 @@ TEST(MathUtilGfxTransformTest, verifyIsInvertible) EXPECT_TRUE(MathUtil::isInvertible(A)); MathUtil::makeIdentity(&A); - A.PreconcatSkewX(45); + A.SkewX(45); EXPECT_TRUE(MathUtil::isInvertible(A)); // A perspective matrix (projection plane at z=0) is invertible. The intuitive // explanation is that perspective is eqivalent to a skew of the w-axis; skews are // invertible. MathUtil::makeIdentity(&A); - A.PreconcatPerspectiveDepth(1); + A.ApplyPerspectiveDepth(1); EXPECT_TRUE(MathUtil::isInvertible(A)); // A "pure" perspective matrix derived by similar triangles, with m44() set to zero // (i.e. camera positioned at the origin), is not invertible. MathUtil::makeIdentity(&A); - A.PreconcatPerspectiveDepth(1); + A.ApplyPerspectiveDepth(1); A.matrix().setDouble(3, 3, 0); EXPECT_FALSE(MathUtil::isInvertible(A)); // Adding more to a non-invertible matrix will not make it invertible in the general case. MathUtil::makeIdentity(&A); - A.PreconcatPerspectiveDepth(1); + A.ApplyPerspectiveDepth(1); A.matrix().setDouble(3, 3, 0); - A.PreconcatScale3d(6, 7, 8); + A.Scale3d(6, 7, 8); MathUtil::rotateEulerAngles(&A, 10, 20, 30); - A.PreconcatTranslate3d(6, 7, 8); + A.Translate3d(6, 7, 8); EXPECT_FALSE(MathUtil::isInvertible(A)); // A degenerate matrix of all zeros is not invertible. diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc index 4532e1c..bbbb262 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc @@ -622,13 +622,13 @@ void IssueAdviceView::AnimationProgressed(const ui::Animation* animation) { if (arrow_view_) { gfx::Transform rotate; if (animation->GetCurrentValue() != 0.0) { - rotate.SetTranslate(-arrow_view_->width() / 2.0, - -arrow_view_->height() / 2.0); + rotate.Translate(arrow_view_->width() / 2.0, + arrow_view_->height() / 2.0); // TODO(estade): for some reason there are rendering errors at 90 degrees. // Figure out why. - rotate.ConcatRotate(animation->GetCurrentValue() * 89); - rotate.ConcatTranslate(arrow_view_->width() / 2.0, - arrow_view_->height() / 2.0); + rotate.Rotate(animation->GetCurrentValue() * 89); + rotate.Translate(-arrow_view_->width() / 2.0, + -arrow_view_->height() / 2.0); } arrow_view_->SetTransform(rotate); } diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 1c1f94b..4ddac18 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc @@ -447,8 +447,8 @@ void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) { settings.AddObserver(this); gfx::Transform transform; int content_width = view_->GetViewBounds().width(); - transform.SetTranslateX(mode == OVERSCROLL_WEST ? -content_width : - content_width); + transform.Translate(mode == OVERSCROLL_WEST ? -content_width : content_width, + 0); target->SetTransform(transform); } @@ -735,7 +735,7 @@ void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) { settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET); gfx::Vector2d translate = GetTranslationForOverscroll(delta_x, delta_y); gfx::Transform transform; - transform.SetTranslate(translate.x(), translate.y()); + transform.Translate(translate.x(), translate.y()); target->SetTransform(transform); } diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 1531710..a19c7c5 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -588,8 +588,9 @@ gfx::Point RootWindow::QueryMouseLocationForTest() const { void RootWindow::TransformEventForDeviceScaleFactor(ui::LocatedEvent* event) { float scale = ui::GetDeviceScaleFactor(layer()); - gfx::Transform transform = layer()->transform(); - transform.ConcatScale(scale, scale); + gfx::Transform transform; + transform.Scale(scale, scale); + transform *= layer()->transform(); event->UpdateForRootTransform(transform); } @@ -1032,9 +1033,10 @@ void RootWindow::SynthesizeMouseMoveEvent() { #if !defined(OS_WIN) // Temporarily disabled for windows. See crbug.com/112222. gfx::Point3F point(GetLastMouseLocationInRoot()); - gfx::Transform transform = layer()->transform(); float scale = ui::GetDeviceScaleFactor(layer()); - transform.ConcatScale(scale, scale); + gfx::Transform transform; + transform.Scale(scale, scale); + transform *= layer()->transform(); transform.TransformPoint(point); gfx::Point orig_mouse_location = gfx::ToFlooredPoint(point.AsPointF()); diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index 14d6166..23f16ca 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -359,9 +359,9 @@ TEST_F(WindowTest, ContainsMouse) { TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) { RootWindow* root = root_window(); gfx::Transform transform; - transform.ConcatScale(2, 5); - transform.ConcatRotate(90.0f); - transform.ConcatTranslate(100, 100); + transform.Translate(100.0, 100.0); + transform.Rotate(90.0); + transform.Scale(2.0, 5.0); root->SetTransform(transform); root->MoveCursorTo(gfx::Point(10, 10)); #if !defined(OS_WIN) @@ -378,30 +378,30 @@ TEST_F(WindowTest, MoveCursorToWithTransformWindow) { CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500), NULL)); gfx::Transform transform1; - transform1.ConcatScale(2, 2); + transform1.Scale(2, 2); w1->SetTransform(transform1); w1->MoveCursorTo(gfx::Point(10, 10)); EXPECT_EQ("30,30", gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString()); gfx::Transform transform2; - transform2.ConcatTranslate(-10, 20); + transform2.Translate(-10, 20); w1->SetTransform(transform2); w1->MoveCursorTo(gfx::Point(10, 10)); EXPECT_EQ("10,40", gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString()); gfx::Transform transform3; - transform3.ConcatRotate(90.0f); + transform3.Rotate(90.0); w1->SetTransform(transform3); w1->MoveCursorTo(gfx::Point(5, 5)); EXPECT_EQ("5,15", gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString()); gfx::Transform transform4; - transform4.ConcatScale(2, 5); - transform4.ConcatRotate(90.0f); - transform4.ConcatTranslate(100, 100); + transform4.Translate(100.0, 100.0); + transform4.Rotate(90.0); + transform4.Scale(2.0, 5.0); w1->SetTransform(transform4); w1->MoveCursorTo(gfx::Point(10, 10)); EXPECT_EQ("60,130", @@ -424,15 +424,15 @@ TEST_F(WindowTest, MoveCursorToWithComplexTransform) { // The root window expects transforms that produce integer rects. gfx::Transform root_transform; - root_transform.ConcatScale(2.0f, 3.0f); - root_transform.ConcatTranslate(-50, -50); - root_transform.ConcatRotate(-90.0f); - root_transform.ConcatTranslate(60, 70); + root_transform.Translate(60.0, 70.0); + root_transform.Rotate(-90.0); + root_transform.Translate(-50.0, -50.0); + root_transform.Scale(2.0, 3.0); gfx::Transform transform; - transform.ConcatScale(0.3f, 0.5f); - transform.ConcatRotate(10.0f); - transform.ConcatTranslate(10, 20); + transform.Translate(10.0, 20.0); + transform.Rotate(10.0); + transform.Scale(0.3, 0.5); root->SetTransform(root_transform); w1->SetTransform(transform); @@ -1347,8 +1347,8 @@ TEST_F(WindowTest, Transform) { // Rotate it clock-wise 90 degrees. gfx::Transform transform; - transform.SetRotate(90.0f); - transform.ConcatTranslate(size.height(), 0); + transform.Translate(size.height(), 0); + transform.Rotate(90.0); root_window()->SetTransform(transform); // The size should be the transformed size. @@ -1375,8 +1375,8 @@ TEST_F(WindowTest, TransformGesture) { // Rotate the root-window clock-wise 90 degrees. gfx::Transform transform; - transform.SetRotate(90.0f); - transform.ConcatTranslate(size.height(), 0); + transform.Translate(size.height(), 0.0); + transform.Rotate(90.0); root_window()->SetTransform(transform); ui::TouchEvent press( @@ -2006,7 +2006,7 @@ TEST_F(WindowTest, MouseEventsOnWindowChange) { // Transform: move d11 by 100 100. gfx::Transform transform; - transform.ConcatTranslate(100, 100); + transform.Translate(100, 100); w11->SetTransform(transform); RunAllPendingInMessageLoop(); EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset()); diff --git a/ui/base/animation/tween.cc b/ui/base/animation/tween.cc index a67ab56..2991ae6 100644 --- a/ui/base/animation/tween.cc +++ b/ui/base/animation/tween.cc @@ -11,7 +11,6 @@ #endif #include "base/logging.h" -#include "ui/gfx/interpolated_transform.h" namespace ui { @@ -97,41 +96,15 @@ gfx::Rect Tween::ValueBetween(double value, // static gfx::Transform Tween::ValueBetween(double value, - const gfx::Transform& start_transform, - const gfx::Transform& end_transform) { + const gfx::Transform& start_transform, + const gfx::Transform& end_transform) { if (value >= 1.0) return end_transform; if (value <= 0.0) return start_transform; - gfx::Transform to_return; - gfx::Point start_translation, end_translation; - float start_rotation, end_rotation; - gfx::Point3F start_scale, end_scale; - if (InterpolatedTransform::FactorTRS(start_transform, - &start_translation, - &start_rotation, - &start_scale) && - InterpolatedTransform::FactorTRS(end_transform, - &end_translation, - &end_rotation, - &end_scale)) { - to_return.SetScale(ValueBetween(value, start_scale.x(), end_scale.x()), - ValueBetween(value, start_scale.y(), end_scale.y())); - to_return.ConcatRotate(ValueBetween(value, start_rotation, end_rotation)); - to_return.ConcatTranslate( - ValueBetween(value, start_translation.x(), end_translation.x()), - ValueBetween(value, start_translation.y(), end_translation.y())); - } else { - for (int row = 0; row < 4; ++row) { - for (int col = 0; col < 4; ++col) { - to_return.matrix().set(row, col, - ValueBetween(value, - start_transform.matrix().get(row, col), - end_transform.matrix().get(row, col))); - } - } - } + gfx::Transform to_return = end_transform; + to_return.Blend(start_transform, value); return to_return; } diff --git a/ui/base/events/event.cc b/ui/base/events/event.cc index b3d2a22..53cae8f 100644 --- a/ui/base/events/event.cc +++ b/ui/base/events/event.cc @@ -13,10 +13,10 @@ #include "ui/base/events/event_utils.h" #include "ui/base/keycodes/keyboard_code_conversion.h" -#include "ui/gfx/interpolated_transform.h" #include "ui/gfx/point3_f.h" #include "ui/gfx/point_conversions.h" #include "ui/gfx/transform.h" +#include "ui/gfx/transform_util.h" #if defined(USE_X11) #include "ui/base/keycodes/keyboard_code_conversion_x.h" @@ -340,12 +340,13 @@ void TouchEvent::CalibrateLocation(const gfx::Size& from, const gfx::Size& to) { void TouchEvent::UpdateForRootTransform(const gfx::Transform& root_transform) { LocatedEvent::UpdateForRootTransform(root_transform); - gfx::Point3F scale; - InterpolatedTransform::FactorTRS(root_transform, NULL, NULL, &scale); - if (scale.x()) - radius_x_ /= scale.x(); - if (scale.y()) - radius_y_ /= scale.y(); + gfx::DecomposedTransform decomp; + bool success = gfx::DecomposeTransform(&decomp, root_transform); + DCHECK(success); + if (decomp.scale[0]) + radius_x_ /= decomp.scale[0]; + if (decomp.scale[1]) + radius_y_ /= decomp.scale[1]; } //////////////////////////////////////////////////////////////////////////////// diff --git a/ui/compositor/debug_utils.cc b/ui/compositor/debug_utils.cc index 5a07604..44c2060 100644 --- a/ui/compositor/debug_utils.cc +++ b/ui/compositor/debug_utils.cc @@ -4,8 +4,11 @@ #ifndef NDEBUG +#define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. + #include "ui/compositor/debug_utils.h" +#include <cmath> #include <iomanip> #include <iostream> #include <string> @@ -57,39 +60,30 @@ void PrintLayerHierarchyImp(const Layer* layer, int indent, if (!layer->visible()) buf << L" !visible"; - buf << L'\n' << UTF8ToWide(content_indent_str); + std::string property_indent_str(indent+3, ' '); + buf << L'\n' << UTF8ToWide(property_indent_str); buf << L"bounds: " << layer->bounds().x() << L',' << layer->bounds().y(); buf << L' ' << layer->bounds().width() << L'x' << layer->bounds().height(); if (layer->opacity() != 1.0f) { - buf << L'\n' << UTF8ToWide(content_indent_str); + buf << L'\n' << UTF8ToWide(property_indent_str); buf << L"opacity: " << std::setprecision(2) << layer->opacity(); } - if (!layer->transform().IsIdentity()) { - gfx::Point translation; - float rotation; - gfx::Point3F scale; - if (ui::InterpolatedTransform::FactorTRS(layer->transform(), - &translation, - &rotation, - &scale)) { - if (!translation.IsOrigin()) { - buf << L'\n' << UTF8ToWide(content_indent_str); - buf << L"translation: " << translation.x() << L", " << translation.y(); - } - - if (fabs(rotation) > 1e-5) { - buf << L'\n' << UTF8ToWide(content_indent_str); - buf << L"rotation: " << std::setprecision(4) << rotation; - } - - if (!gfx::ToFlooredPoint(scale.AsPointF()).IsOrigin()) { - buf << L'\n' << UTF8ToWide(content_indent_str); - buf << std::setprecision(4); - buf << L"scale: " << scale.x() << L", " << scale.y(); - } - } + gfx::DecomposedTransform decomp; + if (!layer->transform().IsIdentity() && + gfx::DecomposeTransform(&decomp, layer->transform())) { + buf << L'\n' << UTF8ToWide(property_indent_str); + buf << L"translation: " << std::fixed << decomp.translate[0]; + buf << L", " << decomp.translate[1]; + + buf << L'\n' << UTF8ToWide(property_indent_str); + buf << L"rotation: "; + buf << std::acos(decomp.quaternion[3]) * 360.0 / M_PI; + + buf << L'\n' << UTF8ToWide(property_indent_str); + buf << L"scale: " << decomp.scale[0]; + buf << L", " << decomp.scale[1]; } VLOG(1) << buf.str(); diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index ff65b17..00d0c5a 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc @@ -601,10 +601,12 @@ bool Layer::GetTransformRelativeTo(const Layer* ancestor, gfx::Transform* transform) const { const Layer* p = this; for (; p && p != ancestor; p = p->parent()) { + gfx::Transform translation; + translation.Translate(static_cast<float>(p->bounds().x()), + static_cast<float>(p->bounds().y())); if (!p->transform().IsIdentity()) transform->ConcatTransform(p->transform()); - transform->ConcatTranslate(static_cast<float>(p->bounds().x()), - static_cast<float>(p->bounds().y())); + transform->ConcatTransform(translation); } return p == ancestor; } @@ -766,7 +768,9 @@ void Layer::RecomputeTransform() { 0, 1.0f / device_scale_factor_, 0, 0, 0, 1); transform.ConcatTransform(transform_); - transform.ConcatTranslate(bounds_.x(), bounds_.y()); + gfx::Transform translate; + translate.Translate(bounds_.x(), bounds_.y()); + transform.ConcatTransform(translate); transform.ConcatTransform(scale_translate); cc_layer_->setTransform(WebKit::WebTransformationMatrix(transform)); } diff --git a/ui/compositor/layer_animation_element_unittest.cc b/ui/compositor/layer_animation_element_unittest.cc index fae15e0..df9635d 100644 --- a/ui/compositor/layer_animation_element_unittest.cc +++ b/ui/compositor/layer_animation_element_unittest.cc @@ -24,8 +24,8 @@ namespace { TEST(LayerAnimationElementTest, TransformElement) { TestLayerAnimationDelegate delegate; gfx::Transform start_transform, target_transform, middle_transform; - start_transform.SetRotate(-90); - target_transform.SetRotate(90); + start_transform.Rotate(-30.0); + target_transform.Rotate(30.0); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); scoped_ptr<LayerAnimationElement> element( diff --git a/ui/compositor/layer_animation_sequence_unittest.cc b/ui/compositor/layer_animation_sequence_unittest.cc index f8db16e..827c449 100644 --- a/ui/compositor/layer_animation_sequence_unittest.cc +++ b/ui/compositor/layer_animation_sequence_unittest.cc @@ -78,8 +78,8 @@ TEST(LayerAnimationSequenceTest, MultipleElement) { LayerAnimationElement::CreatePauseElement(properties, delta)); gfx::Transform start_transform, target_transform, middle_transform; - start_transform.SetRotate(-90); - target_transform.SetRotate(90); + start_transform.Rotate(-30.0); + target_transform.Rotate(30.0); sequence.AddElement( LayerAnimationElement::CreateTransformElement(target_transform, delta)); diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index ae2ae29..80e9384 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc @@ -908,9 +908,9 @@ TEST_F(LayerWithRealCompositorTest, MAYBE_CompositorObservers) { // Setting the transform of a layer should alert the observers. observer.Reset(); gfx::Transform transform; - transform.ConcatTranslate(-200, -200); - transform.ConcatRotate(90.0f); - transform.ConcatTranslate(200, 200); + transform.Translate(200.0, 200.0); + transform.Rotate(90.0); + transform.Translate(-200.0, -200.0); l2->SetTransform(transform); RunPendingMessages(); EXPECT_TRUE(observer.notified()); 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; } diff --git a/ui/views/controls/slide_out_view.cc b/ui/views/controls/slide_out_view.cc index e3d7425..058421d 100644 --- a/ui/views/controls/slide_out_view.cc +++ b/ui/views/controls/slide_out_view.cc @@ -43,7 +43,7 @@ ui::EventResult SlideOutView::OnGestureEvent(ui::GestureEvent* event) { gesture_scroll_amount_ += event->details().scroll_x(); gfx::Transform transform; - transform.SetTranslateX(gesture_scroll_amount_); + transform.Translate(gesture_scroll_amount_, 0.0); layer()->SetTransform(transform); layer()->SetOpacity( 1.f - std::min(fabsf(gesture_scroll_amount_) / width(), 1.f)); @@ -79,7 +79,7 @@ void SlideOutView::SlideOutAndClose(SlideDirection direction) { settings.AddObserver(this); gfx::Transform transform; - transform.SetTranslateX(direction == SLIDE_LEFT ? -width() : width()); + transform.Translate(direction == SLIDE_LEFT ? -width() : width(), 0.0); layer()->SetTransform(transform); layer()->SetOpacity(0.f); } diff --git a/ui/views/corewm/image_grid.cc b/ui/views/corewm/image_grid.cc index b98af63..92f8a94 100644 --- a/ui/views/corewm/image_grid.cc +++ b/ui/views/corewm/image_grid.cc @@ -107,9 +107,9 @@ void ImageGrid::SetSize(const gfx::Size& size) { if (top_layer_.get()) { if (center_width > 0) { gfx::Transform transform; - transform.SetScaleX( - static_cast<float>(center_width) / top_layer_->bounds().width()); - transform.ConcatTranslate(left, 0); + transform.Translate(left, 0); + transform.Scale( + static_cast<float>(center_width) / top_layer_->bounds().width(), 1); top_layer_->SetTransform(transform); } top_layer_->SetVisible(center_width > 0); @@ -117,10 +117,11 @@ void ImageGrid::SetSize(const gfx::Size& size) { if (bottom_layer_.get()) { if (center_width > 0) { gfx::Transform transform; - transform.SetScaleX( - static_cast<float>(center_width) / bottom_layer_->bounds().width()); - transform.ConcatTranslate( + transform.Translate( left, size.height() - bottom_layer_->bounds().height()); + transform.Scale( + static_cast<float>(center_width) / bottom_layer_->bounds().width(), + 1.0); bottom_layer_->SetTransform(transform); } bottom_layer_->SetVisible(center_width > 0); @@ -128,9 +129,10 @@ void ImageGrid::SetSize(const gfx::Size& size) { if (left_layer_.get()) { if (center_height > 0) { gfx::Transform transform; - transform.SetScaleY( + transform.Translate(0, top); + transform.Scale( + 1.0, (static_cast<float>(center_height) / left_layer_->bounds().height())); - transform.ConcatTranslate(0, top); left_layer_->SetTransform(transform); } left_layer_->SetVisible(center_height > 0); @@ -138,10 +140,11 @@ void ImageGrid::SetSize(const gfx::Size& size) { if (right_layer_.get()) { if (center_height > 0) { gfx::Transform transform; - transform.SetScaleY( - static_cast<float>(center_height) / right_layer_->bounds().height()); - transform.ConcatTranslate( + transform.Translate( size.width() - right_layer_->bounds().width(), top); + transform.Scale( + 1.0, + static_cast<float>(center_height) / right_layer_->bounds().height()); right_layer_->SetTransform(transform); } right_layer_->SetVisible(center_height > 0); @@ -157,7 +160,7 @@ void ImageGrid::SetSize(const gfx::Size& size) { } if (top_right_layer_.get()) { gfx::Transform transform; - transform.SetTranslateX(size.width() - top_right_layer_->bounds().width()); + transform.Translate(size.width() - top_right_layer_->bounds().width(), 0.0); top_right_layer_->SetTransform(transform); top_right_painter_->SetClipRect( LayerExceedsSize(top_right_layer_.get(), gfx::Size(right, top)) ? @@ -168,8 +171,8 @@ void ImageGrid::SetSize(const gfx::Size& size) { } if (bottom_left_layer_.get()) { gfx::Transform transform; - transform.SetTranslateY( - size.height() - bottom_left_layer_->bounds().height()); + transform.Translate( + 0.0, size.height() - bottom_left_layer_->bounds().height()); bottom_left_layer_->SetTransform(transform); bottom_left_painter_->SetClipRect( LayerExceedsSize(bottom_left_layer_.get(), gfx::Size(left, bottom)) ? @@ -180,7 +183,7 @@ void ImageGrid::SetSize(const gfx::Size& size) { } if (bottom_right_layer_.get()) { gfx::Transform transform; - transform.SetTranslate( + transform.Translate( size.width() - bottom_right_layer_->bounds().width(), size.height() - bottom_right_layer_->bounds().height()); bottom_right_layer_->SetTransform(transform); @@ -196,9 +199,9 @@ void ImageGrid::SetSize(const gfx::Size& size) { if (center_layer_.get()) { if (center_width > 0 && center_height > 0) { gfx::Transform transform; - transform.SetScale(center_width / center_layer_->bounds().width(), - center_height / center_layer_->bounds().height()); - transform.ConcatTranslate(left, top); + transform.Translate(left, top); + transform.Scale(center_width / center_layer_->bounds().width(), + center_height / center_layer_->bounds().height()); center_layer_->SetTransform(transform); } center_layer_->SetVisible(center_width > 0 && center_height > 0); diff --git a/ui/views/view.cc b/ui/views/view.cc index acc04d3..fdf8c12 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc @@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. + #include "ui/views/view.h" #include <algorithm> +#include <cmath> #include "base/debug/trace_event.h" #include "base/logging.h" @@ -332,8 +335,10 @@ gfx::Rect View::GetVisibleBounds() const { while (view != NULL && !vis_bounds.IsEmpty()) { transform.ConcatTransform(view->GetTransform()); - transform.ConcatTranslate(static_cast<float>(view->GetMirroredX()), - static_cast<float>(view->y())); + gfx::Transform translation; + translation.Translate(static_cast<float>(view->GetMirroredX()), + static_cast<float>(view->y())); + transform.ConcatTransform(translation); vis_bounds = view->ConvertRectToParent(vis_bounds); const View* ancestor = view->parent_; @@ -1432,39 +1437,28 @@ std::string View::DoPrintViewGraph(bool first, View* view_with_children) { bounds().height()); result.append(bounds_buffer); - if (!GetTransform().IsIdentity()) { - gfx::Point translation; - float rotation; - gfx::Point3F scale; - if (ui::InterpolatedTransform::FactorTRS(GetTransform(), - &translation, - &rotation, - &scale)) { - if (!translation.IsOrigin()) { - base::snprintf(bounds_buffer, - arraysize(bounds_buffer), - "\\n translation: (%d, %d)", - translation.x(), - translation.y()); - result.append(bounds_buffer); - } - - if (fabs(rotation) > 1e-5) { - base::snprintf(bounds_buffer, - arraysize(bounds_buffer), - "\\n rotation: %3.2f", rotation); - result.append(bounds_buffer); - } - - if (!gfx::ToFlooredPoint(scale.AsPointF()).IsOrigin()) { - base::snprintf(bounds_buffer, - arraysize(bounds_buffer), - "\\n scale: (%2.4f, %2.4f)", - scale.x(), - scale.y()); - result.append(bounds_buffer); - } - } + gfx::DecomposedTransform decomp; + if (!GetTransform().IsIdentity() && + gfx::DecomposeTransform(&decomp, GetTransform())) { + base::snprintf(bounds_buffer, + arraysize(bounds_buffer), + "\\n translation: (%f, %f)", + decomp.translate[0], + decomp.translate[1]); + result.append(bounds_buffer); + + base::snprintf(bounds_buffer, + arraysize(bounds_buffer), + "\\n rotation: %3.2f", + std::acos(decomp.quaternion[3]) * 360.0 / M_PI); + result.append(bounds_buffer); + + base::snprintf(bounds_buffer, + arraysize(bounds_buffer), + "\\n scale: (%2.4f, %2.4f)", + decomp.scale[0], + decomp.scale[1]); + result.append(bounds_buffer); } result.append("\""); @@ -1798,8 +1792,10 @@ bool View::GetTransformRelativeTo(const View* ancestor, while (p && p != ancestor) { transform->ConcatTransform(p->GetTransform()); - transform->ConcatTranslate(static_cast<float>(p->GetMirroredX()), - static_cast<float>(p->y())); + gfx::Transform translation; + translation.Translate(static_cast<float>(p->GetMirroredX()), + static_cast<float>(p->y())); + transform->ConcatTransform(translation); p = p->parent_; } diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc index c29f11d..363c904 100644 --- a/ui/views/view_unittest.cc +++ b/ui/views/view_unittest.cc @@ -2058,7 +2058,7 @@ TEST_F(ViewTest, TransformPaint) { // Rotate |v1| counter-clockwise. gfx::Transform transform; RotateCounterclockwise(&transform); - transform.SetTranslateY(500.0f); + transform.matrix().set(1, 3, 500.0); v1->SetTransform(transform); // |v2| now occupies (100, 200) to (200, 400) in |root|. @@ -2092,7 +2092,7 @@ TEST_F(ViewTest, TransformEvent) { // Rotate |v1| counter-clockwise. gfx::Transform transform(v1->GetTransform()); RotateCounterclockwise(&transform); - transform.SetTranslateY(500.0f); + transform.matrix().set(1, 3, 500.0); v1->SetTransform(transform); // |v2| now occupies (100, 200) to (200, 400) in |root|. @@ -2114,7 +2114,7 @@ TEST_F(ViewTest, TransformEvent) { // Now rotate |v2| inside |v1| clockwise. transform = v2->GetTransform(); RotateClockwise(&transform); - transform.SetTranslateX(100.0f); + transform.matrix().setDouble(0, 3, 100.0); v2->SetTransform(transform); // Now, |v2| occupies (100, 100) to (200, 300) in |v1|, and (100, 300) to @@ -2144,12 +2144,13 @@ TEST_F(ViewTest, TransformEvent) { // Rotate |v3| clockwise with respect to |v2|. transform = v1->GetTransform(); RotateClockwise(&transform); - transform.SetTranslateX(30.0f); + transform.matrix().setDouble(0, 3, 30.0); v3->SetTransform(transform); // Scale |v2| with respect to |v1| along both axis. transform = v2->GetTransform(); - transform.SetScale(0.8f, 0.5f); + transform.matrix().setDouble(0, 0, 0.8); + transform.matrix().setDouble(1, 1, 0.5); v2->SetTransform(transform); // |v3| occupies (108, 105) to (132, 115) in |root|. @@ -2180,16 +2181,19 @@ TEST_F(ViewTest, TransformEvent) { // Rotate |v3| clockwise with respect to |v2|, and scale it along both axis. transform = v3->GetTransform(); RotateClockwise(&transform); - transform.SetTranslateX(30.0f); + transform.matrix().setDouble(0, 3, 30.0); // Rotation sets some scaling transformation. Using SetScale would overwrite // that and pollute the rotation. So combine the scaling with the existing // transforamtion. - transform.ConcatScale(0.8f, 0.5f); + gfx::Transform scale; + scale.Scale(0.8, 0.5); + transform.ConcatTransform(scale); v3->SetTransform(transform); // Translate |v2| with respect to |v1|. transform = v2->GetTransform(); - transform.SetTranslate(10, 10); + transform.matrix().setDouble(0, 3, 10.0); + transform.matrix().setDouble(1, 3, 10.0); v2->SetTransform(transform); // |v3| now occupies (120, 120) to (144, 130) in |root|. @@ -2233,7 +2237,7 @@ TEST_F(ViewTest, TransformVisibleBound) { // Rotate |child| counter-clockwise gfx::Transform transform; RotateCounterclockwise(&transform); - transform.SetTranslateY(50.0f); + transform.matrix().setDouble(1, 3, 50.0); child->SetTransform(transform); EXPECT_EQ(gfx::Rect(40, 0, 10, 50), child->GetVisibleBounds()); @@ -2347,20 +2351,20 @@ TEST_F(ViewTest, ConvertPointToViewWithTransform) { child->SetBoundsRect(gfx::Rect(7, 19, 500, 500)); gfx::Transform transform; - transform.SetScale(3.0f, 4.0f); + transform.Scale(3.0, 4.0); child->SetTransform(transform); child_child->SetBoundsRect(gfx::Rect(17, 13, 100, 100)); - transform = gfx::Transform(); - transform.SetScale(5.0f, 7.0f); + transform.MakeIdentity(); + transform.Scale(5.0, 7.0); child_child->SetTransform(transform); // Sanity check to make sure basic transforms act as expected. { gfx::Transform transform; - transform.ConcatTranslate(1, 1); - transform.ConcatScale(100, 55); - transform.ConcatTranslate(110, -110); + transform.Translate(110.0, -110.0); + transform.Scale(100.0, 55.0); + transform.Translate(1.0, 1.0); // convert to a 3x3 matrix. const SkMatrix& matrix = transform.matrix(); @@ -2375,11 +2379,11 @@ TEST_F(ViewTest, ConvertPointToViewWithTransform) { { gfx::Transform transform; - transform.SetTranslate(1, 1); + transform.Translate(1.0, 1.0); gfx::Transform t2; - t2.SetScale(100, 55); + t2.Scale(100.0, 55.0); gfx::Transform t3; - t3.SetTranslate(110, -110); + t3.Translate(110.0, -110.0); transform.ConcatTransform(t2); transform.ConcatTransform(t3); @@ -2468,7 +2472,7 @@ TEST_F(ViewTest, ConvertRectWithTransform) { // Rotate |v2| gfx::Transform t2; RotateCounterclockwise(&t2); - t2.SetTranslateY(100.0f); + t2.matrix().setDouble(1, 3, 100.0); v2->SetTransform(t2); // |v2| now occupies (30, 30) to (230, 130) in |widget| @@ -2477,7 +2481,7 @@ TEST_F(ViewTest, ConvertRectWithTransform) { // Scale down |v1| gfx::Transform t1; - t1.SetScale(0.5, 0.5); + t1.Scale(0.5, 0.5); v1->SetTransform(t1); // The rectangle should remain the same for |v1|. @@ -2981,7 +2985,7 @@ TEST_F(ViewLayerTest, LayerToggling) { // Make v1 have a layer again and verify v2s layer is wired up correctly. gfx::Transform transform; - transform.SetScale(2.0f, 2.0f); + transform.Scale(2.0, 2.0); v1->SetTransform(transform); EXPECT_TRUE(v1->layer() != NULL); EXPECT_TRUE(v2->layer() != NULL); @@ -3133,7 +3137,7 @@ TEST_F(ViewLayerTest, BoundInRTL) { TEST_F(ViewLayerTest, ToggleVisibilityWithTransform) { View* view = new View; gfx::Transform transform; - transform.SetScale(2.0f, 2.0f); + transform.Scale(2.0, 2.0); view->SetTransform(transform); widget()->SetContentsView(view); EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0)); @@ -3149,7 +3153,7 @@ TEST_F(ViewLayerTest, ToggleVisibilityWithTransform) { TEST_F(ViewLayerTest, ResetTransformOnLayerAfterAdd) { View* view = new View; gfx::Transform transform; - transform.SetScale(2.0f, 2.0f); + transform.Scale(2.0, 2.0); view->SetTransform(transform); widget()->SetContentsView(view); EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0)); |