1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/snapshot/snapshot.h"
6
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "ui/aura/root_window.h"
9 #include "ui/aura/test/aura_test_helper.h"
10 #include "ui/aura/test/test_screen.h"
11 #include "ui/aura/test/test_window_delegate.h"
12 #include "ui/aura/test/test_windows.h"
13 #include "ui/aura/window.h"
14 #include "ui/compositor/layer.h"
15 #include "ui/gfx/canvas.h"
16 #include "ui/gfx/gfx_paths.h"
17 #include "ui/gfx/image/image.h"
18 #include "ui/gfx/rect.h"
19 #include "ui/gfx/size_conversions.h"
20 #include "ui/gfx/transform.h"
21 #include "ui/gl/gl_implementation.h"
22
23 namespace ui {
24 namespace {
25 const SkColor kPaintColor = SK_ColorRED;
26
27 // Paint simple rectangle on the specified aura window.
28 class TestPaintingWindowDelegate : public aura::test::TestWindowDelegate {
29 public:
TestPaintingWindowDelegate(const gfx::Size & window_size)30 explicit TestPaintingWindowDelegate(const gfx::Size& window_size)
31 : window_size_(window_size) {
32 }
33
~TestPaintingWindowDelegate()34 virtual ~TestPaintingWindowDelegate() {
35 }
36
OnPaint(gfx::Canvas * canvas)37 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
38 canvas->FillRect(gfx::Rect(window_size_), kPaintColor);
39 }
40
41 private:
42 gfx::Size window_size_;
43
44 DISALLOW_COPY_AND_ASSIGN(TestPaintingWindowDelegate);
45 };
46
GetFailedPixelsCount(const gfx::Image & image)47 size_t GetFailedPixelsCount(const gfx::Image& image) {
48 const SkBitmap* bitmap = image.ToSkBitmap();
49 uint32* bitmap_data = reinterpret_cast<uint32*>(
50 bitmap->pixelRef()->pixels());
51 size_t result = 0;
52 for (int i = 0; i < bitmap->width() * bitmap->height(); ++i) {
53 if (static_cast<SkColor>(bitmap_data[i]) != kPaintColor)
54 ++result;
55 }
56 return result;
57 }
58
59 } // namespace
60
61 class SnapshotAuraTest : public testing::Test {
62 public:
SnapshotAuraTest()63 SnapshotAuraTest() {}
~SnapshotAuraTest()64 virtual ~SnapshotAuraTest() {}
65
SetUp()66 virtual void SetUp() OVERRIDE {
67 testing::Test::SetUp();
68 helper_.reset(
69 new aura::test::AuraTestHelper(base::MessageLoopForUI::current()));
70 helper_->SetUp();
71 }
72
TearDown()73 virtual void TearDown() OVERRIDE {
74 test_window_.reset();
75 delegate_.reset();
76 helper_->RunAllPendingInMessageLoop();
77 helper_->TearDown();
78 testing::Test::TearDown();
79 }
80
81 protected:
test_window()82 aura::Window* test_window() { return test_window_.get(); }
root_window()83 aura::Window* root_window() { return helper_->root_window(); }
dispatcher()84 aura::WindowEventDispatcher* dispatcher() { return helper_->dispatcher(); }
test_screen()85 aura::TestScreen* test_screen() { return helper_->test_screen(); }
86
WaitForDraw()87 void WaitForDraw() {
88 dispatcher()->compositor()->ScheduleDraw();
89 ui::DrawWaiterForTest::Wait(dispatcher()->compositor());
90 }
91
SetupTestWindow(const gfx::Rect & window_bounds)92 void SetupTestWindow(const gfx::Rect& window_bounds) {
93 delegate_.reset(new TestPaintingWindowDelegate(window_bounds.size()));
94 test_window_.reset(aura::test::CreateTestWindowWithDelegate(
95 delegate_.get(), 0, window_bounds, root_window()));
96 }
97
GrabSnapshotForTestWindow()98 gfx::Image GrabSnapshotForTestWindow() {
99 std::vector<unsigned char> png_representation;
100 gfx::Rect local_bounds(test_window_->bounds().size());
101 ui::GrabWindowSnapshot(test_window(), &png_representation, local_bounds);
102 return gfx::Image::CreateFrom1xPNGBytes(
103 &(png_representation[0]), png_representation.size());
104 }
105
106 private:
107 scoped_ptr<aura::test::AuraTestHelper> helper_;
108 scoped_ptr<aura::Window> test_window_;
109 scoped_ptr<TestPaintingWindowDelegate> delegate_;
110 std::vector<unsigned char> png_representation_;
111
112 DISALLOW_COPY_AND_ASSIGN(SnapshotAuraTest);
113 };
114
TEST_F(SnapshotAuraTest,FullScreenWindow)115 TEST_F(SnapshotAuraTest, FullScreenWindow) {
116 SetupTestWindow(root_window()->bounds());
117 WaitForDraw();
118
119 gfx::Image snapshot = GrabSnapshotForTestWindow();
120 EXPECT_EQ(test_window()->bounds().size().ToString(),
121 snapshot.Size().ToString());
122 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
123 }
124
TEST_F(SnapshotAuraTest,PartialBounds)125 TEST_F(SnapshotAuraTest, PartialBounds) {
126 gfx::Rect test_bounds(100, 100, 300, 200);
127 SetupTestWindow(test_bounds);
128 WaitForDraw();
129
130 gfx::Image snapshot = GrabSnapshotForTestWindow();
131 EXPECT_EQ(test_bounds.size().ToString(),
132 snapshot.Size().ToString());
133 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
134 }
135
TEST_F(SnapshotAuraTest,Rotated)136 TEST_F(SnapshotAuraTest, Rotated) {
137 test_screen()->SetDisplayRotation(gfx::Display::ROTATE_90);
138
139 gfx::Rect test_bounds(100, 100, 300, 200);
140 SetupTestWindow(test_bounds);
141 WaitForDraw();
142
143 gfx::Image snapshot = GrabSnapshotForTestWindow();
144 EXPECT_EQ(test_bounds.size().ToString(),
145 snapshot.Size().ToString());
146 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
147 }
148
TEST_F(SnapshotAuraTest,UIScale)149 TEST_F(SnapshotAuraTest, UIScale) {
150 const float kUIScale = 1.25f;
151 test_screen()->SetUIScale(kUIScale);
152
153 gfx::Rect test_bounds(100, 100, 300, 200);
154 SetupTestWindow(test_bounds);
155 WaitForDraw();
156
157 // Snapshot always captures the physical pixels.
158 gfx::SizeF snapshot_size(test_bounds.size());
159 snapshot_size.Scale(1.0f / kUIScale);
160
161 gfx::Image snapshot = GrabSnapshotForTestWindow();
162 EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
163 snapshot.Size().ToString());
164 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
165 }
166
TEST_F(SnapshotAuraTest,DeviceScaleFactor)167 TEST_F(SnapshotAuraTest, DeviceScaleFactor) {
168 test_screen()->SetDeviceScaleFactor(2.0f);
169
170 gfx::Rect test_bounds(100, 100, 150, 100);
171 SetupTestWindow(test_bounds);
172 WaitForDraw();
173
174 // Snapshot always captures the physical pixels.
175 gfx::SizeF snapshot_size(test_bounds.size());
176 snapshot_size.Scale(2.0f);
177
178 gfx::Image snapshot = GrabSnapshotForTestWindow();
179 EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
180 snapshot.Size().ToString());
181 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
182 }
183
TEST_F(SnapshotAuraTest,RotateAndUIScale)184 TEST_F(SnapshotAuraTest, RotateAndUIScale) {
185 const float kUIScale = 1.25f;
186 test_screen()->SetUIScale(kUIScale);
187 test_screen()->SetDisplayRotation(gfx::Display::ROTATE_90);
188
189 gfx::Rect test_bounds(100, 100, 300, 200);
190 SetupTestWindow(test_bounds);
191 WaitForDraw();
192
193 // Snapshot always captures the physical pixels.
194 gfx::SizeF snapshot_size(test_bounds.size());
195 snapshot_size.Scale(1.0f / kUIScale);
196
197 gfx::Image snapshot = GrabSnapshotForTestWindow();
198 EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
199 snapshot.Size().ToString());
200 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
201 }
202
TEST_F(SnapshotAuraTest,RotateAndUIScaleAndScaleFactor)203 TEST_F(SnapshotAuraTest, RotateAndUIScaleAndScaleFactor) {
204 test_screen()->SetDeviceScaleFactor(2.0f);
205 const float kUIScale = 1.25f;
206 test_screen()->SetUIScale(kUIScale);
207 test_screen()->SetDisplayRotation(gfx::Display::ROTATE_90);
208
209 gfx::Rect test_bounds(20, 30, 150, 100);
210 SetupTestWindow(test_bounds);
211 WaitForDraw();
212
213 // Snapshot always captures the physical pixels.
214 gfx::SizeF snapshot_size(test_bounds.size());
215 snapshot_size.Scale(2.0f / kUIScale);
216
217 gfx::Image snapshot = GrabSnapshotForTestWindow();
218 EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
219 snapshot.Size().ToString());
220 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
221 }
222
223 } // namespace ui
224