summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-25 04:31:19 +0000
committermukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-25 04:31:19 +0000
commitf958054738592c984e713a2582ac66d0e9bd5b4c (patch)
tree6b77e3edfeb2284ee77154b79f0ef2523ceaddef
parent0847a72a829a980801b75b1722c1a03847cd8e4f (diff)
downloadchromium_src-f958054738592c984e713a2582ac66d0e9bd5b4c.zip
chromium_src-f958054738592c984e713a2582ac66d0e9bd5b4c.tar.gz
chromium_src-f958054738592c984e713a2582ac66d0e9bd5b4c.tar.bz2
Supports screen rotation / ui-scaling in snapshot_aura.cc
BUG=235007,236370 TEST=covered by the new tests R=oshima@chromium.org, sky@chromium.org, backer@chromium.org Review URL: https://chromiumcodereview.appspot.com/15160006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202268 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/aura/test/test_screen.cc44
-rw-r--r--ui/aura/test/test_screen.h8
-rw-r--r--ui/compositor/compositor.gyp4
-rw-r--r--ui/snapshot/snapshot.gyp16
-rw-r--r--ui/snapshot/snapshot_aura.cc42
-rw-r--r--ui/snapshot/snapshot_aura_unittest.cc222
-rw-r--r--ui/snapshot/test/run_all_unittests.cc14
7 files changed, 336 insertions, 14 deletions
diff --git a/ui/aura/test/test_screen.cc b/ui/aura/test/test_screen.cc
index 69bf767..16afea4 100644
--- a/ui/aura/test/test_screen.cc
+++ b/ui/aura/test/test_screen.cc
@@ -46,6 +46,46 @@ void TestScreen::SetDeviceScaleFactor(float device_scale_factor) {
root_window_->OnHostResized(bounds_in_pixel.size());
}
+void TestScreen::SetDisplayRotation(gfx::Display::Rotation rotation) {
+ display_.set_rotation(rotation);
+ root_window_->SetTransform(GetRotationTransform() * GetUIScaleTransform());
+}
+
+void TestScreen::SetUIScale(float ui_scale) {
+ ui_scale_ = ui_scale;
+ root_window_->SetTransform(GetRotationTransform() * GetUIScaleTransform());
+}
+
+gfx::Transform TestScreen::GetRotationTransform() const {
+ gfx::Transform rotate;
+ float one_pixel = 1.0f / display_.device_scale_factor();
+ switch (display_.rotation()) {
+ case gfx::Display::ROTATE_0:
+ break;
+ case gfx::Display::ROTATE_90:
+ rotate.Translate(display_.bounds().height() - one_pixel, 0);
+ rotate.Rotate(90);
+ break;
+ case gfx::Display::ROTATE_270:
+ rotate.Translate(0, display_.bounds().width() - one_pixel);
+ rotate.Rotate(270);
+ break;
+ case gfx::Display::ROTATE_180:
+ rotate.Translate(display_.bounds().width() - one_pixel,
+ display_.bounds().height() - one_pixel);
+ rotate.Rotate(180);
+ break;
+ }
+
+ return rotate;
+}
+
+gfx::Transform TestScreen::GetUIScaleTransform() const {
+ gfx::Transform ui_scale;
+ ui_scale.Scale(1.0f / ui_scale_, 1.0f / ui_scale_);
+ return ui_scale;
+}
+
bool TestScreen::IsDIPEnabled() {
return true;
}
@@ -97,7 +137,9 @@ void TestScreen::AddObserver(gfx::DisplayObserver* observer) {
void TestScreen::RemoveObserver(gfx::DisplayObserver* observer) {
}
-TestScreen::TestScreen(const gfx::Rect& screen_bounds) : root_window_(NULL) {
+TestScreen::TestScreen(const gfx::Rect& screen_bounds)
+ : root_window_(NULL),
+ ui_scale_(1.0f) {
static int64 synthesized_display_id = 2000;
display_.set_id(synthesized_display_id++);
display_.SetScaleAndBounds(1.0f, screen_bounds);
diff --git a/ui/aura/test/test_screen.h b/ui/aura/test/test_screen.h
index 1d14cbc..c4615c7 100644
--- a/ui/aura/test/test_screen.h
+++ b/ui/aura/test/test_screen.h
@@ -12,6 +12,7 @@
namespace gfx {
class Rect;
+class Transform;
}
namespace aura {
@@ -30,8 +31,13 @@ class TestScreen : public gfx::Screen,
RootWindow* CreateRootWindowForPrimaryDisplay();
void SetDeviceScaleFactor(float device_scale_fator);
+ void SetDisplayRotation(gfx::Display::Rotation rotation);
+ void SetUIScale(float ui_scale);
protected:
+ gfx::Transform GetRotationTransform() const;
+ gfx::Transform GetUIScaleTransform() const;
+
// WindowObserver overrides:
virtual void OnWindowBoundsChanged(Window* window,
const gfx::Rect& old_bounds,
@@ -60,6 +66,8 @@ class TestScreen : public gfx::Screen,
gfx::Display display_;
+ float ui_scale_;
+
DISALLOW_COPY_AND_ASSIGN(TestScreen);
};
diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp
index 3e3fbd0..464c43d 100644
--- a/ui/compositor/compositor.gyp
+++ b/ui/compositor/compositor.gyp
@@ -87,6 +87,8 @@
'test/compositor_test_support.h',
'test/test_layers.cc',
'test/test_layers.h',
+ 'test/test_suite.cc',
+ 'test/test_suite.h',
],
'conditions': [
['os_posix == 1 and OS != "mac"', {
@@ -132,8 +134,6 @@
'test/test_layer_animation_delegate.h',
'test/test_layer_animation_observer.cc',
'test/test_layer_animation_observer.h',
- 'test/test_suite.cc',
- 'test/test_suite.h',
'test/test_utils.cc',
'test/test_utils.h',
],
diff --git a/ui/snapshot/snapshot.gyp b/ui/snapshot/snapshot.gyp
index cf93fa9..6e7eb1a 100644
--- a/ui/snapshot/snapshot.gyp
+++ b/ui/snapshot/snapshot.gyp
@@ -48,14 +48,24 @@
'../../skia/skia.gyp:skia',
'../../base/base.gyp:base',
'../../testing/gtest.gyp:gtest',
- '../../testing/gmock.gyp:gmock',
- '../../testing/gtest.gyp:gtest',
'../ui.gyp:ui',
'snapshot'
],
'sources': [
+ 'snapshot_aura_unittest.cc',
'snapshot_mac_unittest.mm',
- ]
+ 'test/run_all_unittests.cc',
+ ],
+ 'conditions': [
+ ['use_aura==1', {
+ 'dependencies': [
+ '../../base/base.gyp:test_support_base',
+ '../aura/aura.gyp:aura_test_support',
+ '../compositor/compositor.gyp:compositor',
+ '../compositor/compositor.gyp:compositor_test_support',
+ ],
+ }],
+ ],
},
],
'conditions': [
diff --git a/ui/snapshot/snapshot_aura.cc b/ui/snapshot/snapshot_aura.cc
index 144ce2d..32b1340 100644
--- a/ui/snapshot/snapshot_aura.cc
+++ b/ui/snapshot/snapshot_aura.cc
@@ -6,13 +6,20 @@
#include "base/logging.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/display.h"
#include "ui/gfx/rect.h"
+#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/rect_f.h"
+#include "ui/gfx/screen.h"
+#include "ui/gfx/skbitmap_operations.h"
+#include "ui/gfx/transform.h"
namespace ui {
@@ -27,17 +34,17 @@ bool GrabWindowSnapshot(gfx::NativeWindow window,
const gfx::Rect& snapshot_bounds) {
ui::Compositor* compositor = window->layer()->GetCompositor();
- gfx::Rect read_pixels_bounds = snapshot_bounds;
+ gfx::RectF read_pixels_bounds = snapshot_bounds;
// We must take into account the window's position on the desktop.
- gfx::Point origin = window->bounds().origin();
- const aura::Window* root_window = window->GetRootWindow();
+ read_pixels_bounds.Offset(
+ window->GetBoundsInRootWindow().origin().OffsetFromOrigin());
+ aura::RootWindow* root_window = window->GetRootWindow();
if (root_window)
- aura::Window::ConvertPointToTarget(window, root_window, &origin);
+ root_window->GetRootTransform().TransformRect(&read_pixels_bounds);
- read_pixels_bounds.Offset(origin.OffsetFromOrigin());
gfx::Rect read_pixels_bounds_in_pixel =
- ui::ConvertRectToPixel(window->layer(), read_pixels_bounds);
+ gfx::ToEnclosingRect(read_pixels_bounds);
// Sometimes (i.e. when using Aero on Windows) the compositor's size is
// smaller than the window bounds. So trim appropriately.
@@ -50,10 +57,29 @@ bool GrabWindowSnapshot(gfx::NativeWindow window,
if (!compositor->ReadPixels(&bitmap, read_pixels_bounds_in_pixel))
return false;
- unsigned char* pixels = reinterpret_cast<unsigned char*>(bitmap.getPixels());
+ gfx::Display display =
+ gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window);
+ switch (display.rotation()) {
+ case gfx::Display::ROTATE_0:
+ break;
+ case gfx::Display::ROTATE_90:
+ bitmap = SkBitmapOperations::Rotate(
+ bitmap, SkBitmapOperations::ROTATION_270_CW);
+ break;
+ case gfx::Display::ROTATE_180:
+ bitmap = SkBitmapOperations::Rotate(
+ bitmap, SkBitmapOperations::ROTATION_180_CW);
+ break;
+ case gfx::Display::ROTATE_270:
+ bitmap = SkBitmapOperations::Rotate(
+ bitmap, SkBitmapOperations::ROTATION_90_CW);
+ break;
+ }
+ unsigned char* pixels = reinterpret_cast<unsigned char*>(
+ bitmap.pixelRef()->pixels());
gfx::PNGCodec::Encode(pixels, gfx::PNGCodec::FORMAT_BGRA,
- read_pixels_bounds_in_pixel.size(),
+ gfx::Size(bitmap.width(), bitmap.height()),
bitmap.rowBytes(), true,
std::vector<gfx::PNGCodec::Comment>(),
png_representation);
diff --git a/ui/snapshot/snapshot_aura_unittest.cc b/ui/snapshot/snapshot_aura_unittest.cc
new file mode 100644
index 0000000..8f93c16
--- /dev/null
+++ b/ui/snapshot/snapshot_aura_unittest.cc
@@ -0,0 +1,222 @@
+// Copyright (c) 2013 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/snapshot/snapshot.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/test/aura_test_helper.h"
+#include "ui/aura/test/test_screen.h"
+#include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura/test/test_windows.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/compositor_setup.h"
+#include "ui/compositor/layer.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/gfx_paths.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/transform.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace ui {
+namespace {
+const SkColor kPaintColor = SK_ColorRED;
+
+// Paint simple rectangle on the specified aura window.
+class TestPaintingWindowDelegate : public aura::test::TestWindowDelegate {
+ public:
+ explicit TestPaintingWindowDelegate(const gfx::Size& window_size)
+ : window_size_(window_size) {
+ }
+
+ virtual ~TestPaintingWindowDelegate() {
+ }
+
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
+ canvas->FillRect(gfx::Rect(window_size_), kPaintColor);
+ }
+
+ private:
+ gfx::Size window_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestPaintingWindowDelegate);
+};
+
+size_t GetFailedPixelsCount(const gfx::Image& image) {
+ const SkBitmap* bitmap = image.ToSkBitmap();
+ uint32* bitmap_data = reinterpret_cast<uint32*>(
+ bitmap->pixelRef()->pixels());
+ size_t result = 0;
+ for (int i = 0; i < bitmap->width() * bitmap->height(); ++i) {
+ if (static_cast<SkColor>(bitmap_data[i]) != kPaintColor)
+ ++result;
+ }
+ return result;
+}
+
+} // namespace
+
+class SnapshotAuraTest : public testing::Test {
+ public:
+ SnapshotAuraTest() {}
+ virtual ~SnapshotAuraTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ testing::Test::SetUp();
+ helper_.reset(new aura::test::AuraTestHelper(MessageLoopForUI::current()));
+ helper_->SetUp();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ test_window_.reset();
+ delegate_.reset();
+ helper_->RunAllPendingInMessageLoop();
+ helper_->TearDown();
+ testing::Test::TearDown();
+ }
+
+ protected:
+ aura::Window* test_window() { return test_window_.get(); }
+ aura::RootWindow* root_window() { return helper_->root_window(); }
+ aura::TestScreen* test_screen() { return helper_->test_screen(); }
+
+ void WaitForDraw() {
+ root_window()->compositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(root_window()->compositor());
+ }
+
+ void SetupTestWindow(const gfx::Rect& window_bounds) {
+ delegate_.reset(new TestPaintingWindowDelegate(window_bounds.size()));
+ test_window_.reset(aura::test::CreateTestWindowWithDelegate(
+ delegate_.get(), 0, window_bounds, root_window()));
+ }
+
+ gfx::Image GrabSnapshotForTestWindow() {
+ std::vector<unsigned char> png_representation;
+ gfx::Rect local_bounds(test_window_->bounds().size());
+ ui::GrabWindowSnapshot(test_window(), &png_representation, local_bounds);
+ return gfx::Image::CreateFrom1xPNGBytes(
+ &(png_representation[0]), png_representation.size());
+ }
+
+ private:
+ scoped_ptr<aura::test::AuraTestHelper> helper_;
+ scoped_ptr<aura::Window> test_window_;
+ scoped_ptr<TestPaintingWindowDelegate> delegate_;
+ std::vector<unsigned char> png_representation_;
+
+ DISALLOW_COPY_AND_ASSIGN(SnapshotAuraTest);
+};
+
+TEST_F(SnapshotAuraTest, FullScreenWindow) {
+ SetupTestWindow(root_window()->bounds());
+ WaitForDraw();
+
+ gfx::Image snapshot = GrabSnapshotForTestWindow();
+ EXPECT_EQ(test_window()->bounds().size().ToString(),
+ snapshot.Size().ToString());
+ EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
+}
+
+TEST_F(SnapshotAuraTest, PartialBounds) {
+ gfx::Rect test_bounds(100, 100, 300, 200);
+ SetupTestWindow(test_bounds);
+ WaitForDraw();
+
+ gfx::Image snapshot = GrabSnapshotForTestWindow();
+ EXPECT_EQ(test_bounds.size().ToString(),
+ snapshot.Size().ToString());
+ EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
+}
+
+TEST_F(SnapshotAuraTest, Rotated) {
+ test_screen()->SetDisplayRotation(gfx::Display::ROTATE_90);
+
+ gfx::Rect test_bounds(100, 100, 300, 200);
+ SetupTestWindow(test_bounds);
+ WaitForDraw();
+
+ gfx::Image snapshot = GrabSnapshotForTestWindow();
+ EXPECT_EQ(test_bounds.size().ToString(),
+ snapshot.Size().ToString());
+ EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
+}
+
+TEST_F(SnapshotAuraTest, UIScale) {
+ const float kUIScale = 1.25f;
+ test_screen()->SetUIScale(kUIScale);
+
+ gfx::Rect test_bounds(100, 100, 300, 200);
+ SetupTestWindow(test_bounds);
+ WaitForDraw();
+
+ // Snapshot always captures the physical pixels.
+ gfx::SizeF snapshot_size(test_bounds.size());
+ snapshot_size.Scale(1.0f / kUIScale);
+
+ gfx::Image snapshot = GrabSnapshotForTestWindow();
+ EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
+ snapshot.Size().ToString());
+ EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
+}
+
+TEST_F(SnapshotAuraTest, DeviceScaleFactor) {
+ test_screen()->SetDeviceScaleFactor(2.0f);
+
+ gfx::Rect test_bounds(100, 100, 150, 100);
+ SetupTestWindow(test_bounds);
+ WaitForDraw();
+
+ // Snapshot always captures the physical pixels.
+ gfx::SizeF snapshot_size(test_bounds.size());
+ snapshot_size.Scale(2.0f);
+
+ gfx::Image snapshot = GrabSnapshotForTestWindow();
+ EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
+ snapshot.Size().ToString());
+ EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
+}
+
+TEST_F(SnapshotAuraTest, RotateAndUIScale) {
+ const float kUIScale = 1.25f;
+ test_screen()->SetUIScale(kUIScale);
+ test_screen()->SetDisplayRotation(gfx::Display::ROTATE_90);
+
+ gfx::Rect test_bounds(100, 100, 300, 200);
+ SetupTestWindow(test_bounds);
+ WaitForDraw();
+
+ // Snapshot always captures the physical pixels.
+ gfx::SizeF snapshot_size(test_bounds.size());
+ snapshot_size.Scale(1.0f / kUIScale);
+
+ gfx::Image snapshot = GrabSnapshotForTestWindow();
+ EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
+ snapshot.Size().ToString());
+ EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
+}
+
+TEST_F(SnapshotAuraTest, RotateAndUIScaleAndScaleFactor) {
+ test_screen()->SetDeviceScaleFactor(2.0f);
+ const float kUIScale = 1.25f;
+ test_screen()->SetUIScale(kUIScale);
+ test_screen()->SetDisplayRotation(gfx::Display::ROTATE_90);
+
+ gfx::Rect test_bounds(20, 30, 150, 100);
+ SetupTestWindow(test_bounds);
+ WaitForDraw();
+
+ // Snapshot always captures the physical pixels.
+ gfx::SizeF snapshot_size(test_bounds.size());
+ snapshot_size.Scale(2.0f / kUIScale);
+
+ gfx::Image snapshot = GrabSnapshotForTestWindow();
+ EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
+ snapshot.Size().ToString());
+ EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
+}
+
+} // namespace ui
diff --git a/ui/snapshot/test/run_all_unittests.cc b/ui/snapshot/test/run_all_unittests.cc
new file mode 100644
index 0000000..5bf3d5f
--- /dev/null
+++ b/ui/snapshot/test/run_all_unittests.cc
@@ -0,0 +1,14 @@
+// Copyright (c) 2013 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/test/test_suite.h"
+#include "ui/compositor/test/test_suite.h"
+
+int main(int argc, char** argv) {
+#if defined(USE_AURA)
+ return ui::test::CompositorTestSuite(argc, argv).Run();
+#else
+ return base::TestSuite(argc, argv).Run();
+#endif
+}