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: 30 explicit TestPaintingWindowDelegate(const gfx::Size& window_size) 31 : window_size_(window_size) { 32 } 33 34 virtual ~TestPaintingWindowDelegate() { 35 } 36 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 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: 63 SnapshotAuraTest() {} 64 virtual ~SnapshotAuraTest() {} 65 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 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: 82 aura::Window* test_window() { return test_window_.get(); } 83 aura::Window* root_window() { return helper_->root_window(); } 84 aura::WindowEventDispatcher* dispatcher() { return helper_->dispatcher(); } 85 aura::TestScreen* test_screen() { return helper_->test_screen(); } 86 87 void WaitForDraw() { 88 dispatcher()->compositor()->ScheduleDraw(); 89 ui::DrawWaiterForTest::Wait(dispatcher()->compositor()); 90 } 91 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 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 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 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 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 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 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 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 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