diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-29 20:33:53 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-29 20:33:53 +0000 |
commit | ad72589169dcb25134e1aafef502680f8feab8e4 (patch) | |
tree | 083104f7f6d4d60363b54df434a9d0dffb342ab6 /ui | |
parent | fa70c11b670acb36641bec22c8834b06d0b9c8dc (diff) | |
download | chromium_src-ad72589169dcb25134e1aafef502680f8feab8e4.zip chromium_src-ad72589169dcb25134e1aafef502680f8feab8e4.tar.gz chromium_src-ad72589169dcb25134e1aafef502680f8feab8e4.tar.bz2 |
Adds support for point conversions to ui::Layer.
Also adds a skeleton for testing compositor API changes.
BUG=none
TEST=see unittest
Review URL: http://codereview.chromium.org/7769001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98689 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/gfx/compositor/compositor.gyp | 27 | ||||
-rw-r--r-- | ui/gfx/compositor/layer.cc | 60 | ||||
-rw-r--r-- | ui/gfx/compositor/layer.h | 16 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_unittest.cc | 162 | ||||
-rw-r--r-- | ui/gfx/compositor/run_all_unittests.cc | 9 | ||||
-rw-r--r-- | ui/gfx/compositor/test_compositor_host.h | 36 | ||||
-rw-r--r-- | ui/gfx/compositor/test_compositor_host_win.cc | 64 | ||||
-rw-r--r-- | ui/gfx/compositor/test_suite.cc | 32 | ||||
-rw-r--r-- | ui/gfx/compositor/test_suite.h | 22 | ||||
-rw-r--r-- | ui/ui.gyp | 2 |
10 files changed, 430 insertions, 0 deletions
diff --git a/ui/gfx/compositor/compositor.gyp b/ui/gfx/compositor/compositor.gyp index 5a76bce..7614e15 100644 --- a/ui/gfx/compositor/compositor.gyp +++ b/ui/gfx/compositor/compositor.gyp @@ -76,5 +76,32 @@ }], ], }, + + { + 'target_name': 'compositor_unittests', + 'type': 'executable', + 'dependencies': [ + '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/base/base.gyp:test_support_base', + '<(DEPTH)/skia/skia.gyp:skia', + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/ui/gfx/gl/gl.gyp:gl', + '<(DEPTH)/ui/ui.gyp:gfx_resources', + '<(DEPTH)/ui/ui.gyp:ui', + '<(DEPTH)/ui/ui.gyp:ui_resources', + 'compositor', + ], + 'sources': [ + 'layer_unittest.cc', + 'run_all_unittests.cc', + 'test_compositor_host.h', + 'test_compositor_host_win.cc', + 'test_suite.cc', + 'test_suite.h', + '<(SHARED_INTERMEDIATE_DIR)/ui/gfx/gfx_resources.rc', + '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_resources.rc', + ], + }, + ], } diff --git a/ui/gfx/compositor/layer.cc b/ui/gfx/compositor/layer.cc index 8061294..4f1ed241 100644 --- a/ui/gfx/compositor/layer.cc +++ b/ui/gfx/compositor/layer.cc @@ -7,6 +7,7 @@ #include <algorithm> #include "base/logging.h" +#include "ui/gfx/point3.h" namespace ui { @@ -45,6 +46,14 @@ void Layer::Remove(Layer* child) { RecomputeHole(); } +bool Layer::Contains(const Layer* other) const { + for (const Layer* parent = other; parent; parent = parent->parent()) { + if (parent == this) + return true; + } + return false; +} + void Layer::SetTransform(const ui::Transform& transform) { transform_ = transform; @@ -59,6 +68,25 @@ void Layer::SetBounds(const gfx::Rect& bounds) { parent()->RecomputeHole(); } +// static +void Layer::ConvertPointToLayer(const Layer* source, + const Layer* target, + gfx::Point* point) { + const Layer* inner = NULL; + const Layer* outer = NULL; + if (source->Contains(target)) { + inner = target; + outer = source; + inner->ConvertPointFromAncestor(outer, point); + } else if (target->Contains(source)) { + inner = source; + outer = target; + inner->ConvertPointForAncestor(outer, point); + } else { + NOTREACHED(); // |source| and |target| are in unrelated hierarchies. + } +} + void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) { if (fills_bounds_opaquely_ == fills_bounds_opaquely) return; @@ -144,4 +172,36 @@ void Layer::RecomputeHole() { hole_rect_ = gfx::Rect(); } +bool Layer::ConvertPointForAncestor(const Layer* ancestor, + gfx::Point* point) const { + ui::Transform transform; + bool result = GetTransformRelativeTo(ancestor, &transform); + gfx::Point3f p(*point); + transform.TransformPoint(p); + *point = p.AsPoint(); + return result; +} + +bool Layer::ConvertPointFromAncestor(const Layer* ancestor, + gfx::Point* point) const { + ui::Transform transform; + bool result = GetTransformRelativeTo(ancestor, &transform); + gfx::Point3f p(*point); + transform.TransformPointReverse(p); + *point = p.AsPoint(); + return result; +} + +bool Layer::GetTransformRelativeTo(const Layer* ancestor, + ui::Transform* transform) const { + const Layer* p = this; + for (; p && p != ancestor; p = p->parent()) { + if (p->transform().HasChange()) + transform->ConcatTransform(p->transform()); + transform->ConcatTranslate(static_cast<float>(p->bounds().x()), + static_cast<float>(p->bounds().y())); + } + return p == ancestor; +} + } // namespace ui diff --git a/ui/gfx/compositor/layer.h b/ui/gfx/compositor/layer.h index 7bbc890..d523c9c 100644 --- a/ui/gfx/compositor/layer.h +++ b/ui/gfx/compositor/layer.h @@ -44,6 +44,9 @@ class COMPOSITOR_EXPORT Layer { const Layer* parent() const { return parent_; } Layer* parent() { return parent_; } + // Returns true if this Layer contains |other| somewhere in its children. + bool Contains(const Layer* other) const; + // The transform, relative to the parent. void SetTransform(const ui::Transform& transform); const ui::Transform& transform() const { return transform_; } @@ -52,6 +55,13 @@ class COMPOSITOR_EXPORT Layer { void SetBounds(const gfx::Rect& bounds); const gfx::Rect& bounds() const { return bounds_; } + // Converts a point from the coordinates of |source| to the coordinates of + // |target|. Necessarily, |source| and |target| must inhabit the same Layer + // tree. + static void ConvertPointToLayer(const Layer* source, + const Layer* target, + gfx::Point* point); + // See description in View for details void SetFillsBoundsOpaquely(bool fills_bounds_opaquely); bool fills_bounds_opaquely() const { return fills_bounds_opaquely_; } @@ -102,6 +112,12 @@ class COMPOSITOR_EXPORT Layer { // view has no transfrom with respect to its parent. void RecomputeHole(); + bool ConvertPointForAncestor(const Layer* ancestor, gfx::Point* point) const; + bool ConvertPointFromAncestor(const Layer* ancestor, gfx::Point* point) const; + + bool GetTransformRelativeTo(const Layer* ancestor, + Transform* transform) const; + Compositor* compositor_; scoped_refptr<ui::Texture> texture_; diff --git a/ui/gfx/compositor/layer_unittest.cc b/ui/gfx/compositor/layer_unittest.cc new file mode 100644 index 0000000..3a82d2a --- /dev/null +++ b/ui/gfx/compositor/layer_unittest.cc @@ -0,0 +1,162 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/canvas_skia.h" +#include "ui/gfx/compositor/layer.h" +#include "ui/gfx/compositor/test_compositor_host.h" + +namespace ui { + +namespace { + +class LayerTest : public testing::Test { + public: + LayerTest() {} + virtual ~LayerTest() {} + + // Overridden from testing::Test: + virtual void SetUp() OVERRIDE { + const gfx::Rect host_bounds(10, 10, 500, 500); + window_.reset(TestCompositorHost::Create(host_bounds)); + window_->Show(); + } + + virtual void TearDown() OVERRIDE { + } + + Compositor* GetCompositor() { + return window_->GetCompositor(); + } + + Layer* CreateLayer() { + return new Layer(GetCompositor()); + } + + Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) { + Layer* layer = CreateLayer(); + layer->SetBounds(bounds); + PaintColorToLayer(layer, color); + return layer; + } + + gfx::Canvas* CreateCanvasForLayer(const Layer* layer) { + return gfx::Canvas::CreateCanvas(layer->bounds().width(), + layer->bounds().height(), + false); + } + + void PaintColorToLayer(Layer* layer, SkColor color) { + scoped_ptr<gfx::Canvas> canvas(CreateCanvasForLayer(layer)); + canvas->FillRectInt(color, 0, 0, layer->bounds().width(), + layer->bounds().height()); + layer->SetCanvas(*canvas->AsCanvasSkia(), layer->bounds().origin()); + } + + void DrawTree(Layer* root) { + window_->GetCompositor()->NotifyStart(); + DrawLayerChildren(root); + window_->GetCompositor()->NotifyEnd(); + } + + void DrawLayerChildren(Layer* layer) { + layer->Draw(); + std::vector<Layer*>::const_iterator it = layer->children().begin(); + while (it != layer->children().end()) { + DrawLayerChildren(*it); + ++it; + } + } + + void RunPendingMessages() { + MessageLoop main_message_loop(MessageLoop::TYPE_UI); + MessageLoopForUI::current()->Run(NULL); + } + + private: + scoped_ptr<TestCompositorHost> window_; + + DISALLOW_COPY_AND_ASSIGN(LayerTest); +}; + +} + +TEST_F(LayerTest, Draw) { + scoped_ptr<Layer> layer(CreateColorLayer(SK_ColorRED, + gfx::Rect(20, 20, 50, 50))); + DrawTree(layer.get()); +} + +// Create this hierarchy: +// L1 - red +// +-- L2 - blue +// | +-- L3 - yellow +// +-- L4 - magenta +// +TEST_F(LayerTest, Hierarchy) { + scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED, + gfx::Rect(20, 20, 400, 400))); + scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE, + gfx::Rect(10, 10, 350, 350))); + scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW, + gfx::Rect(5, 5, 25, 25))); + scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA, + gfx::Rect(300, 300, 100, 100))); + + l1->Add(l2.get()); + l1->Add(l4.get()); + l2->Add(l3.get()); + + DrawTree(l1.get()); +} + +// L1 +// +-- L2 +TEST_F(LayerTest, ConvertPointToLayer_Simple) { + scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED, + gfx::Rect(20, 20, 400, 400))); + scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE, + gfx::Rect(10, 10, 350, 350))); + l1->Add(l2.get()); + DrawTree(l1.get()); + + gfx::Point point1_in_l2_coords(5, 5); + Layer::ConvertPointToLayer(l2.get(), l1.get(), &point1_in_l2_coords); + gfx::Point point1_in_l1_coords(15, 15); + EXPECT_EQ(point1_in_l1_coords, point1_in_l2_coords); + + gfx::Point point2_in_l1_coords(5, 5); + Layer::ConvertPointToLayer(l1.get(), l2.get(), &point2_in_l1_coords); + gfx::Point point2_in_l2_coords(-5, -5); + EXPECT_EQ(point2_in_l2_coords, point2_in_l1_coords); +} + +// L1 +// +-- L2 +// +-- L3 +TEST_F(LayerTest, ConvertPointToLayer_Medium) { + scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED, + gfx::Rect(20, 20, 400, 400))); + scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE, + gfx::Rect(10, 10, 350, 350))); + scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW, + gfx::Rect(10, 10, 100, 100))); + l1->Add(l2.get()); + l2->Add(l3.get()); + DrawTree(l1.get()); + + gfx::Point point1_in_l3_coords(5, 5); + Layer::ConvertPointToLayer(l3.get(), l1.get(), &point1_in_l3_coords); + gfx::Point point1_in_l1_coords(25, 25); + EXPECT_EQ(point1_in_l1_coords, point1_in_l3_coords); + + gfx::Point point2_in_l1_coords(5, 5); + Layer::ConvertPointToLayer(l1.get(), l3.get(), &point2_in_l1_coords); + gfx::Point point2_in_l3_coords(-15, -15); + EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords); +} + +} // namespace ui + diff --git a/ui/gfx/compositor/run_all_unittests.cc b/ui/gfx/compositor/run_all_unittests.cc new file mode 100644 index 0000000..5419134 --- /dev/null +++ b/ui/gfx/compositor/run_all_unittests.cc @@ -0,0 +1,9 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gfx/compositor/test_suite.h" + +int main(int argc, char** argv) { + return CompositorTestSuite(argc, argv).Run(); +} diff --git a/ui/gfx/compositor/test_compositor_host.h b/ui/gfx/compositor/test_compositor_host.h new file mode 100644 index 0000000..f0bdbaa --- /dev/null +++ b/ui/gfx/compositor/test_compositor_host.h @@ -0,0 +1,36 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GFX_COMPOSITOR_TEST_COMPOSITOR_HOST_H_ +#define UI_GFX_COMPOSITOR_TEST_COMPOSITOR_HOST_H_ +#pragma once + +#include "base/message_loop.h" +#include "ui/gfx/native_widget_types.h" + +namespace gfx { +class Rect; +class Size; +} + +namespace ui { + +class Compositor; + +class TestCompositorHost : public MessageLoop::Dispatcher { + public: + virtual ~TestCompositorHost() {} + + // Creates a new TestCompositorHost. The caller owns the returned value. + static TestCompositorHost* Create(const gfx::Rect& bounds); + + // Shows the TestCompositorHost. + virtual void Show() = 0; + + virtual ui::Compositor* GetCompositor() = 0; +}; + +} // namespace ui + +#endif // UI_GFX_COMPOSITOR_TEST_COMPOSITOR_HOST_H_ diff --git a/ui/gfx/compositor/test_compositor_host_win.cc b/ui/gfx/compositor/test_compositor_host_win.cc new file mode 100644 index 0000000..f126b08 --- /dev/null +++ b/ui/gfx/compositor/test_compositor_host_win.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gfx/compositor/test_compositor_host.h" + +#include "ui/base/win/window_impl.h" +#include "ui/gfx/compositor/compositor.h" + +namespace ui { + +class TestCompositorHostWin : public TestCompositorHost, + public ui::WindowImpl { + public: + explicit TestCompositorHostWin(const gfx::Rect& bounds) { + Init(NULL, bounds); + compositor_ = ui::Compositor::Create(hwnd(), GetSize()); + } + + virtual ~TestCompositorHostWin() { + DestroyWindow(hwnd()); + } + + // Overridden from MessageLoop::Dispatcher: + virtual bool Dispatch(const MSG& msg) { + TranslateMessage(&msg); + DispatchMessage(&msg); + return true; + } + + // Overridden from TestCompositorHost: + virtual void Show() OVERRIDE { + ShowWindow(hwnd(), SW_SHOWNORMAL); + } + virtual ui::Compositor* GetCompositor() OVERRIDE { + return compositor_; + } + + private: + BEGIN_MSG_MAP_EX(TestCompositorHostWin) + MSG_WM_PAINT(OnPaint) + END_MSG_MAP() + + void OnPaint(HDC dc) { + ValidateRect(hwnd(), NULL); + } + + gfx::Size GetSize() { + RECT r; + GetClientRect(hwnd(), &r); + return gfx::Rect(r).size(); + } + + scoped_refptr<ui::Compositor> compositor_; + + DISALLOW_COPY_AND_ASSIGN(TestCompositorHostWin); +}; + +TestCompositorHost* TestCompositorHost::Create(const gfx::Rect& bounds) { + return new TestCompositorHostWin(bounds); +} + +} // namespace ui + diff --git a/ui/gfx/compositor/test_suite.cc b/ui/gfx/compositor/test_suite.cc new file mode 100644 index 0000000..bcba004 --- /dev/null +++ b/ui/gfx/compositor/test_suite.cc @@ -0,0 +1,32 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gfx/compositor/test_suite.h" + +#include "base/file_path.h" +#include "base/path_service.h" +#include "build/build_config.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/ui_base_paths.h" +#include "ui/gfx/gfx_paths.h" + +CompositorTestSuite::CompositorTestSuite(int argc, char** argv) + : TestSuite(argc, argv) {} + +void CompositorTestSuite::Initialize() { + base::TestSuite::Initialize(); + + gfx::RegisterPathProvider(); + ui::RegisterPathProvider(); + + // Force unittests to run using en-US so if we test against string + // output, it'll pass regardless of the system language. + ui::ResourceBundle::InitSharedInstance("en-US"); +} + +void CompositorTestSuite::Shutdown() { + ui::ResourceBundle::CleanupSharedInstance(); + + base::TestSuite::Shutdown(); +} diff --git a/ui/gfx/compositor/test_suite.h b/ui/gfx/compositor/test_suite.h new file mode 100644 index 0000000..0472a24 --- /dev/null +++ b/ui/gfx/compositor/test_suite.h @@ -0,0 +1,22 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GFX_COMPOSITOR_TEST_SUITE_H_ +#define UI_GFX_COMPOSITOR_TEST_SUITE_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "base/test/test_suite.h" + +class CompositorTestSuite : public base::TestSuite { + public: + CompositorTestSuite(int argc, char** argv); + + protected: + // base::TestSuite: + virtual void Initialize() OVERRIDE; + virtual void Shutdown() OVERRIDE; +}; + +#endif // UI_GFX_COMPOSITOR_TEST_SUITE_H_ @@ -293,6 +293,8 @@ ['use_aura==1', { 'sources/': [ ['exclude', 'gfx/screen_win.cc'], + ['exclude', 'base/win/mouse_wheel_util.cc'], + ['exclude', 'base/win/mouse_wheel_util.h'], ], }], ['toolkit_uses_gtk == 1', { |