diff options
-rw-r--r-- | ui/gfx/transform.cc | 15 | ||||
-rw-r--r-- | ui/gfx/transform.h | 6 | ||||
-rw-r--r-- | views/view.cc | 16 | ||||
-rw-r--r-- | views/view.h | 6 | ||||
-rw-r--r-- | views/view_unittest.cc | 36 |
5 files changed, 63 insertions, 16 deletions
diff --git a/ui/gfx/transform.cc b/ui/gfx/transform.cc index 55edb4c..03e2873 100644 --- a/ui/gfx/transform.cc +++ b/ui/gfx/transform.cc @@ -95,8 +95,19 @@ bool Transform::TransformRect(gfx::Rect* rect) { SkRect src = gfx::RectToSkRect(*rect); if (!matrix_.mapRect(&src)) return false; - gfx::Rect xrect = gfx::SkRectToRect(src); - rect->SetRect(xrect.x(), xrect.y(), xrect.width(), xrect.height()); + *rect = gfx::SkRectToRect(src); + return true; +} + +bool Transform::TransformRectReverse(gfx::Rect* rect) { + SkMatrix inverse; + if (!matrix_.invert(&inverse)) + return false; + + SkRect src = gfx::RectToSkRect(*rect); + if (!inverse.mapRect(&src)) + return false; + *rect = gfx::SkRectToRect(src); return true; } diff --git a/ui/gfx/transform.h b/ui/gfx/transform.h index 39b2159..3fdfc32 100644 --- a/ui/gfx/transform.h +++ b/ui/gfx/transform.h @@ -77,10 +77,14 @@ class Transform { // is transformed successfully. bool TransformPointReverse(gfx::Point* point); - // Applies transformation on the rectangle. Returns true of the rectangle is + // Applies transformation on the rectangle. Returns true if the rectangle is // transformed successfully. bool TransformRect(gfx::Rect* rect); + // Applies the reverse transformation on the rectangle. Returns true if the + // rectangle is transformed successfully. + bool TransformRectReverse(gfx::Rect* rect); + // Returns the underlying matrix. const SkMatrix& matrix() const { return matrix_; } diff --git a/views/view.cc b/views/view.cc index 20d20ef..3004c83 100644 --- a/views/view.cc +++ b/views/view.cc @@ -300,12 +300,16 @@ gfx::Rect View::GetVisibleBounds() const { gfx::Rect vis_bounds(0, 0, width(), height()); gfx::Rect ancestor_bounds; const View* view = this; - int root_x = 0; - int root_y = 0; + ui::Transform transform; + while (view != NULL && !vis_bounds.IsEmpty()) { - root_x += view->GetMirroredX(); - root_y += view->y(); - vis_bounds.Offset(view->GetMirroredX(), view->y()); + if (view->transform_.get()) + transform.ConcatTransform(*view->transform_); + transform.ConcatTranslate(static_cast<float>(view->GetMirroredX()), + static_cast<float>(view->y())); + + vis_bounds = view->ConvertRectToParent(vis_bounds); + vis_bounds.Offset(view->GetMirroredPosition()); const View* ancestor = view->parent(); if (ancestor != NULL) { ancestor_bounds.SetRect(0, 0, ancestor->width(), ancestor->height()); @@ -319,7 +323,7 @@ gfx::Rect View::GetVisibleBounds() const { if (vis_bounds.IsEmpty()) return vis_bounds; // Convert back to this views coordinate system. - vis_bounds.Offset(-root_x, -root_y); + transform.TransformRectReverse(&vis_bounds); return vis_bounds; } diff --git a/views/view.h b/views/view.h index 744f59c..fc37a00 100644 --- a/views/view.h +++ b/views/view.h @@ -276,9 +276,9 @@ class View : public AcceleratorTarget { // system. // // When traversing the View hierarchy in order to compute the bounds, the - // function takes into account the mirroring setting for each View and - // therefore it will return the mirrored version of the visible bounds if - // need be. + // function takes into account the mirroring setting and transformation for + // each View and therefore it will return the mirrored and transformed version + // of the visible bounds if need be. gfx::Rect GetVisibleBounds() const; // Return the bounds of the View in screen coordinate system. diff --git a/views/view_unittest.cc b/views/view_unittest.cc index 7057bc2..45341fb 100644 --- a/views/view_unittest.cc +++ b/views/view_unittest.cc @@ -1772,6 +1772,38 @@ TEST_F(ViewTest, TransformEvent) { widget->CloseNow(); } +TEST_F(ViewTest, TransformVisibleBound) { + gfx::Rect viewport_bounds(0, 0, 100, 100); + + scoped_ptr<Widget> widget(new Widget); + Widget::InitParams params(Widget::InitParams::TYPE_WINDOW); + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.bounds = viewport_bounds; + widget->Init(params); + widget->GetRootView()->SetBoundsRect(viewport_bounds); + + View* viewport = new View; + widget->SetContentsView(viewport); + View* contents = new View; + viewport->AddChildView(contents); + viewport->SetBoundsRect(viewport_bounds); + contents->SetBounds(0, 0, 100, 200); + + View* child = new View; + contents->AddChildView(child); + child->SetBounds(10, 90, 50, 50); + EXPECT_EQ(gfx::Rect(0, 0, 50, 10), child->GetVisibleBounds()); + + // Rotate |child| counter-clockwise + ui::Transform transform; + transform.SetRotate(-90.0f); + transform.SetTranslateY(50.0f); + child->SetTransform(transform); + EXPECT_EQ(gfx::Rect(40, 0, 10, 50), child->GetVisibleBounds()); + + widget->CloseNow(); +} + //////////////////////////////////////////////////////////////////////////////// // OnVisibleBoundsChanged() @@ -1799,8 +1831,6 @@ class VisibleBoundsView : public View { DISALLOW_COPY_AND_ASSIGN(VisibleBoundsView); }; -#if defined(OS_WIN) -// TODO(beng): This can be cross platform when widget construction/init is. TEST_F(ViewTest, OnVisibleBoundsChanged) { gfx::Rect viewport_bounds(0, 0, 100, 100); @@ -1846,8 +1876,6 @@ TEST_F(ViewTest, OnVisibleBoundsChanged) { widget->CloseNow(); } -#endif - //////////////////////////////////////////////////////////////////////////////// // BoundsChanged() |