summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ui/gfx/transform.cc15
-rw-r--r--ui/gfx/transform.h6
-rw-r--r--views/view.cc16
-rw-r--r--views/view.h6
-rw-r--r--views/view_unittest.cc36
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()