Commit ad725891 authored by ben@chromium.org's avatar ben@chromium.org

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
parent fa70c11b
...@@ -76,5 +76,32 @@ ...@@ -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',
],
},
], ],
} }
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include "base/logging.h" #include "base/logging.h"
#include "ui/gfx/point3.h"
namespace ui { namespace ui {
...@@ -45,6 +46,14 @@ void Layer::Remove(Layer* child) { ...@@ -45,6 +46,14 @@ void Layer::Remove(Layer* child) {
RecomputeHole(); 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) { void Layer::SetTransform(const ui::Transform& transform) {
transform_ = transform; transform_ = transform;
...@@ -59,6 +68,25 @@ void Layer::SetBounds(const gfx::Rect& bounds) { ...@@ -59,6 +68,25 @@ void Layer::SetBounds(const gfx::Rect& bounds) {
parent()->RecomputeHole(); 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) { void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
if (fills_bounds_opaquely_ == fills_bounds_opaquely) if (fills_bounds_opaquely_ == fills_bounds_opaquely)
return; return;
...@@ -144,4 +172,36 @@ void Layer::RecomputeHole() { ...@@ -144,4 +172,36 @@ void Layer::RecomputeHole() {
hole_rect_ = gfx::Rect(); 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 } // namespace ui
...@@ -44,6 +44,9 @@ class COMPOSITOR_EXPORT Layer { ...@@ -44,6 +44,9 @@ class COMPOSITOR_EXPORT Layer {
const Layer* parent() const { return parent_; } const Layer* parent() const { return parent_; }
Layer* parent() { 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. // The transform, relative to the parent.
void SetTransform(const ui::Transform& transform); void SetTransform(const ui::Transform& transform);
const ui::Transform& transform() const { return transform_; } const ui::Transform& transform() const { return transform_; }
...@@ -52,6 +55,13 @@ class COMPOSITOR_EXPORT Layer { ...@@ -52,6 +55,13 @@ class COMPOSITOR_EXPORT Layer {
void SetBounds(const gfx::Rect& bounds); void SetBounds(const gfx::Rect& bounds);
const gfx::Rect& bounds() const { return 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 // See description in View for details
void SetFillsBoundsOpaquely(bool fills_bounds_opaquely); void SetFillsBoundsOpaquely(bool fills_bounds_opaquely);
bool fills_bounds_opaquely() const { return fills_bounds_opaquely_; } bool fills_bounds_opaquely() const { return fills_bounds_opaquely_; }
...@@ -102,6 +112,12 @@ class COMPOSITOR_EXPORT Layer { ...@@ -102,6 +112,12 @@ class COMPOSITOR_EXPORT Layer {
// view has no transfrom with respect to its parent. // view has no transfrom with respect to its parent.
void RecomputeHole(); 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_; Compositor* compositor_;
scoped_refptr<ui::Texture> texture_; scoped_refptr<ui::Texture> texture_;
......
// 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
// 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();
}
// 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_
// 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
// 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();
}
// 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 @@ ...@@ -293,6 +293,8 @@
['use_aura==1', { ['use_aura==1', {
'sources/': [ 'sources/': [
['exclude', 'gfx/screen_win.cc'], ['exclude', 'gfx/screen_win.cc'],
['exclude', 'base/win/mouse_wheel_util.cc'],
['exclude', 'base/win/mouse_wheel_util.h'],
], ],
}], }],
['toolkit_uses_gtk == 1', { ['toolkit_uses_gtk == 1', {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment