| // Copyright 2020 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 "ash/accessibility/switch_access/point_scan_controller.h" |
| |
| #include "ash/shell.h" |
| #include "ash/test/ash_test_base.h" |
| #include "ash/test/test_window_builder.h" |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/macros.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "ui/aura/window.h" |
| #include "ui/compositor/compositor_switches.h" |
| #include "ui/gfx/image/image.h" |
| #include "ui/snapshot/snapshot.h" |
| |
| namespace ash { |
| |
| class PointScanControllerTest : public AshTestBase { |
| protected: |
| PointScanControllerTest() = default; |
| ~PointScanControllerTest() override = default; |
| |
| // AshTestBase: |
| void SetUp() override { |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| ::switches::kEnablePixelOutputInTests); |
| AshTestBase::SetUp(); |
| } |
| |
| void CaptureBeforeImage(const gfx::Rect& bounds) { |
| Capture(bounds); |
| if (before_bmp_.tryAllocPixels(image_.AsBitmap().info())) { |
| image_.AsBitmap().readPixels(before_bmp_.info(), before_bmp_.getPixels(), |
| before_bmp_.rowBytes(), 0, 0); |
| } |
| } |
| |
| void CaptureAfterImage(const gfx::Rect& bounds) { |
| Capture(bounds); |
| if (after_bmp_.tryAllocPixels(image_.AsBitmap().info())) { |
| image_.AsBitmap().readPixels(after_bmp_.info(), after_bmp_.getPixels(), |
| after_bmp_.rowBytes(), 0, 0); |
| } |
| } |
| |
| void Capture(const gfx::Rect& bounds) { |
| // Occasionally we don't get any pixels the first try. |
| // Keep trying until we get the correct size bitmap and the first pixel |
| // is transparent. |
| while (true) { |
| aura::Window* window = Shell::GetPrimaryRootWindow(); |
| base::RunLoop run_loop; |
| ui::GrabWindowSnapshotAndScaleAsync( |
| window, bounds, bounds.size(), |
| base::BindOnce( |
| [](base::RunLoop* run_loop, gfx::Image* image, |
| gfx::Image got_image) { |
| run_loop->Quit(); |
| *image = got_image; |
| }, |
| &run_loop, &image_)); |
| run_loop.Run(); |
| SkBitmap bitmap = image_.AsBitmap(); |
| if (bitmap.width() != bounds.width() || |
| bitmap.height() != bounds.height()) { |
| LOG(INFO) << "Bitmap not correct size, trying to capture again"; |
| continue; |
| } else if (255 == SkColorGetA(bitmap.getColor(0, 0))) { |
| LOG(INFO) << "Bitmap is transparent, trying to capture again"; |
| break; |
| } |
| } |
| } |
| |
| void ComputeImageStats() { |
| diff_count_ = 0; |
| row_diff_count_ = 0; |
| col_diff_count_ = 0; |
| bool row_diff_tracker_[before_bmp_.height()]; |
| for (int i = 0; i < before_bmp_.height(); ++i) { |
| row_diff_tracker_[i] = false; |
| } |
| |
| for (int x = 0; x < before_bmp_.width(); ++x) { |
| bool col_diff = false; |
| for (int y = 0; y < before_bmp_.height(); ++y) { |
| SkColor before_color = before_bmp_.getColor(x, y); |
| SkColor after_color = after_bmp_.getColor(x, y); |
| if (before_color != after_color) { |
| diff_count_++; |
| col_diff = true; |
| row_diff_tracker_[y] = true; |
| } |
| } |
| if (col_diff) |
| ++col_diff_count_; |
| } |
| |
| for (int i = 0; i < before_bmp_.height(); ++i) { |
| if (row_diff_tracker_[i]) |
| ++row_diff_count_; |
| } |
| } |
| |
| int diff_count() const { return diff_count_; } |
| int row_diff_count() const { return row_diff_count_; } |
| int col_diff_count() const { return col_diff_count_; } |
| |
| private: |
| gfx::Image image_; |
| SkBitmap before_bmp_; |
| SkBitmap after_bmp_; |
| int diff_count_ = 0; |
| int row_diff_count_ = 0; |
| int col_diff_count_ = 0; |
| |
| DISALLOW_COPY_AND_ASSIGN(PointScanControllerTest); |
| }; |
| |
| TEST_F(PointScanControllerTest, StartScanning) { |
| gfx::Rect bounds = Shell::GetPrimaryRootWindow()->bounds(); |
| |
| // Create a white background window for captured image color smoke test. |
| std::unique_ptr<aura::Window> window = |
| TestWindowBuilder() |
| .SetColorWindowDelegate(SK_ColorWHITE) |
| .SetBounds(bounds) |
| .Build(); |
| |
| // For some reason, the white window is not fully drawn the first time we call |
| // CaptureBeforeImage. |
| CaptureBeforeImage(bounds); |
| CaptureBeforeImage(bounds); |
| |
| PointScanController controller; |
| controller.StartHorizontalRangeScan(); |
| |
| CaptureAfterImage(bounds); |
| ComputeImageStats(); |
| } |
| |
| } // namespace ash |