Chromium Code Reviews| Index: ui/views/paint_info_unittest.cc |
| diff --git a/ui/views/paint_info_unittest.cc b/ui/views/paint_info_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..873c4ad0668580d51932b76532914e0e1984c450 |
| --- /dev/null |
| +++ b/ui/views/paint_info_unittest.cc |
| @@ -0,0 +1,242 @@ |
| +// Copyright 2017 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/views/paint_info.h" |
| + |
| +#include <vector> |
| + |
| +#include "base/macros.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "cc/base/region.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "ui/compositor/compositor_switches.h" |
| +#include "ui/compositor/paint_context.h" |
| +#include "ui/gfx/geometry/rect.h" |
| +#include "ui/gfx/geometry/size.h" |
| + |
| +namespace views { |
| +namespace { |
| + |
| +typedef testing::Test PaintInfoTest; |
| + |
| +// Device scale factors |
| +constexpr float DSF100 = 1.f; |
| +constexpr float DSF125 = 1.25f; |
| +constexpr float DSF150 = 1.5f; |
| +constexpr float DSF160 = 1.6f; |
| +constexpr float DSF166 = 1.66f; |
| + |
| +const std::vector<float> kDsfList = {DSF100, DSF125, DSF150, DSF160, DSF166}; |
| + |
| +const gfx::Size kLayerSize(123, 456); |
| + |
| +// ___________ |
| +// | 1 | |
| +// |___________| |
| +// | 3 | 4 | 5 | <-- 2 |
| +// |___|___|___| |
| +// | 7 | 8 | <-- 6 |
| +// |_______|___| |
| +const gfx::Rect r_0(kLayerSize); |
|
sky
2017/07/26 22:12:12
constexpr on these.
malaykeshav
2017/07/28 01:24:38
Done
|
| + |
| +const gfx::Rect r_0_1(0, 0, 123, 152); |
| + |
| +const gfx::Rect r_0_2(0, 152, 123, 152); |
| +const gfx::Rect r_2_3(0, 0, 41, 152); |
| +const gfx::Rect r_2_4(41, 0, 41, 152); |
| +const gfx::Rect r_2_5(82, 0, 41, 152); |
| + |
| +const gfx::Rect r_0_6(0, 304, 123, 152); |
| +const gfx::Rect r_6_7(0, 0, 82, 152); |
| +const gfx::Rect r_6_8(82, 0, 41, 152); |
| + |
| +// ___________ |
| +// | 1 | |
| +// |___________| |
| +// | 3 | 4 | 5 | <-- 2 |
|
sky
2017/07/26 22:12:12
The <-- 2 isn't clear at all. Maybe you mean there
malaykeshav
2017/07/28 01:24:38
Done. Adding further comments
|
| +// |___|___|___| |
| +// | 7 | 8 | <-- 6 |
| +// |_______|___| |
| +// Returns the following arrangement of paint recording bounds for the given |
| +// |dsf| |
| +std::vector<PaintInfo*> GetPaintInfoSetup(const ui::PaintContext& context) { |
|
sky
2017/07/26 22:12:12
Passing around raw pointers like this is a recipe
malaykeshav
2017/07/28 01:24:38
Done
|
| + std::vector<PaintInfo*> info_list(9); |
| + |
| + info_list[0] = new PaintInfo(context, kLayerSize); |
| + |
| + info_list[1] = new PaintInfo(*info_list[0], r_0_1, r_0, |
| + PaintInfo::ScaleType::kScaleToFit); |
| + |
| + info_list[2] = new PaintInfo(*info_list[0], r_0_2, r_0, |
| + PaintInfo::ScaleType::kScaleToFit); |
| + info_list[3] = new PaintInfo(*info_list[2], r_2_3, r_0_2, |
| + PaintInfo::ScaleType::kScaleToFit); |
| + info_list[4] = new PaintInfo(*info_list[2], r_2_4, r_0_2, |
| + PaintInfo::ScaleType::kScaleToFit); |
| + info_list[5] = new PaintInfo(*info_list[2], r_2_5, r_0_2, |
| + PaintInfo::ScaleType::kScaleToFit); |
| + |
| + info_list[6] = new PaintInfo(*info_list[0], r_0_6, r_0, |
| + PaintInfo::ScaleType::kScaleToFit); |
| + info_list[7] = new PaintInfo(*info_list[6], r_6_7, r_0_6, |
| + PaintInfo::ScaleType::kScaleToFit); |
| + info_list[8] = new PaintInfo(*info_list[6], r_6_8, r_0_6, |
| + PaintInfo::ScaleType::kScaleToFit); |
| + |
| + return info_list; |
| +} |
| + |
| +// Verifies that the child recording bounds completely cover the parent |
| +// recording bounds. |
| +void VerifyChildBoundsCoversParent(PaintInfo* parent_paint_info, |
|
sky
2017/07/26 22:12:12
Can both of these parameters be const refs? That m
malaykeshav
2017/07/28 01:24:38
Done
|
| + std::vector<PaintInfo*> info_list) { |
| + cc::Region remaining(gfx::Rect(parent_paint_info->paint_recording_size())); |
| + int times_empty = 0; |
| + for (auto* paint_info : info_list) { |
| + const gfx::Rect& child_recording_bounds = |
| + paint_info->paint_recording_bounds() - |
| + parent_paint_info->paint_recording_bounds().OffsetFromOrigin(); |
| + EXPECT_TRUE(remaining.Contains(child_recording_bounds)) |
| + << "Remaining: " << remaining.ToString() |
| + << " paint recording bounds: " << child_recording_bounds.ToString(); |
| + remaining.Subtract(child_recording_bounds); |
| + times_empty += remaining.IsEmpty(); |
| + } |
| + EXPECT_EQ(times_empty, 1); |
| +} |
| + |
| +void VerifyPixelCanvasCornerScaling(std::vector<PaintInfo*> info_list) { |
| + // child 1, child 2 and child 6 should completely cover child 0. |
| + std::vector<PaintInfo*> child_info_list; |
| + child_info_list.push_back(info_list[1]); |
| + child_info_list.push_back(info_list[2]); |
| + child_info_list.push_back(info_list[6]); |
| + VerifyChildBoundsCoversParent(info_list[0], child_info_list); |
| + child_info_list.clear(); |
| + |
| + // Child 3,4 and 5 should completely cover child 2. |
| + child_info_list.push_back(info_list[3]); |
| + child_info_list.push_back(info_list[4]); |
| + child_info_list.push_back(info_list[5]); |
| + VerifyChildBoundsCoversParent(info_list[2], child_info_list); |
| + child_info_list.clear(); |
| + |
| + // Child 7 and 8 should completely cover child 6. |
| + child_info_list.push_back(info_list[7]); |
| + child_info_list.push_back(info_list[8]); |
| + VerifyChildBoundsCoversParent(info_list[6], child_info_list); |
| + child_info_list.clear(); |
| +} |
| + |
| +void ClearAllPaintInfo(std::vector<PaintInfo*> info_list) { |
| + for (auto* paint_info : info_list) |
| + delete paint_info; |
| +} |
| + |
| +void VerifyPixelSizesAreSameAsDIPSize(std::vector<PaintInfo*> info_list) { |
| + EXPECT_EQ(info_list[0]->paint_recording_size(), r_0.size()); |
| + |
| + EXPECT_EQ(info_list[1]->paint_recording_size(), r_0_1.size()); |
| + |
| + EXPECT_EQ(info_list[2]->paint_recording_size(), r_0_2.size()); |
| + EXPECT_EQ(info_list[3]->paint_recording_size(), r_2_3.size()); |
| + EXPECT_EQ(info_list[4]->paint_recording_size(), r_2_4.size()); |
| + EXPECT_EQ(info_list[5]->paint_recording_size(), r_2_5.size()); |
| + |
| + EXPECT_EQ(info_list[6]->paint_recording_size(), r_0_6.size()); |
| + EXPECT_EQ(info_list[7]->paint_recording_size(), r_6_7.size()); |
| + EXPECT_EQ(info_list[8]->paint_recording_size(), r_6_8.size()); |
| +} |
| + |
| +void VerifyInvalidationRects(float dsf, bool pixel_canvas_enabled) { |
| + std::vector<gfx::Rect> invalidation_rects = { |
| + gfx::Rect(0, 0, 123, 41), // Intersects with 0 & 1. |
| + gfx::Rect(0, 76, 60, 152), // Intersects 0, 1, 2, 3 & 4. |
| + gfx::Rect(41, 152, 41, 152), // Intersects with 0, 2 & 4. |
| + gfx::Rect(80, 320, 4, 4), // Intersects with 0, 6, 7 & 8. |
| + gfx::Rect(40, 151, 43, 154), // Intersects all |
| + gfx::Rect(82, 304, 1, 1), // Intersects with 0, 6 & 8. |
| + gfx::Rect(81, 303, 2, 2) // Intersects with 0, 2, 4, 5, 6, 7, 8 |
| + }; |
| + |
| + std::vector<std::vector<int>> repaint_indices = { |
| + std::vector<int>{0, 1}, |
| + std::vector<int>{0, 1, 2, 3, 4}, |
| + std::vector<int>{0, 2, 4}, |
| + std::vector<int>{0, 6, 7, 8}, |
| + std::vector<int>{0, 1, 2, 3, 4, 5, 6, 7, 8}, |
| + std::vector<int>{0, 6, 8}, |
| + std::vector<int>{0, 2, 4, 5, 6, 7, 8}}; |
| + |
| + std::vector<PaintInfo*> info_list; |
| + |
| + EXPECT_EQ(repaint_indices.size(), invalidation_rects.size()); |
| + for (size_t i = 0; i < invalidation_rects.size(); i++) { |
| + ui::PaintContext context(nullptr, dsf, invalidation_rects[i], |
| + pixel_canvas_enabled); |
| + info_list = GetPaintInfoSetup(context); |
| + for (size_t j = 0; j < repaint_indices[i].size(); j++) { |
| + EXPECT_TRUE(info_list[repaint_indices[i][j]]->context().IsRectInvalid( |
| + gfx::Rect(info_list[repaint_indices[i][j]]->paint_recording_size()))); |
| + } |
| + ClearAllPaintInfo(info_list); |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +TEST_F(PaintInfoTest, CornerScalingPixelCanvasEnabled) { |
| + std::vector<PaintInfo*> info_list; |
| + for (float dsf : kDsfList) { |
| + ui::PaintContext context(nullptr, dsf, gfx::Rect(), true); |
| + info_list = GetPaintInfoSetup(context); |
| + VerifyPixelCanvasCornerScaling(info_list); |
| + ClearAllPaintInfo(info_list); |
| + } |
| + |
| + // More accurate testing for 1.25 dsf |
| + ui::PaintContext context(nullptr, DSF125, gfx::Rect(), true); |
| + info_list = GetPaintInfoSetup(context); |
| + VerifyPixelCanvasCornerScaling(info_list); |
| + EXPECT_EQ(info_list[0]->paint_recording_size(), gfx::Size(154, 570)); |
| + |
| + EXPECT_EQ(info_list[1]->paint_recording_size(), gfx::Size(154, 190)); |
| + |
| + EXPECT_EQ(info_list[2]->paint_recording_bounds(), |
| + gfx::Rect(0, 190, 154, 190)); |
| + EXPECT_EQ(info_list[3]->paint_recording_size(), gfx::Size(51, 190)); |
| + EXPECT_EQ(info_list[4]->paint_recording_bounds(), |
| + gfx::Rect(51, 190, 52, 190)); |
| + EXPECT_EQ(info_list[5]->paint_recording_bounds(), |
| + gfx::Rect(103, 190, 51, 190)); |
| + |
| + EXPECT_EQ(info_list[6]->paint_recording_bounds(), |
| + gfx::Rect(0, 380, 154, 190)); |
| + EXPECT_EQ(info_list[7]->paint_recording_size(), gfx::Size(103, 190)); |
| + EXPECT_EQ(info_list[8]->paint_recording_bounds(), |
| + gfx::Rect(103, 380, 51, 190)); |
| + ClearAllPaintInfo(info_list); |
| +} |
| + |
| +TEST_F(PaintInfoTest, ScalingWithPixelCanvasDisabled) { |
| + // With dsf as 1, there should be no scaling and size should be same. |
| + ui::PaintContext context_1(nullptr, DSF100, gfx::Rect(), false); |
| + std::vector<PaintInfo*> info_list = GetPaintInfoSetup(context_1); |
| + for (float dsf : kDsfList) { |
| + ui::PaintContext context_2(nullptr, dsf, gfx::Rect(), false); |
| + info_list = GetPaintInfoSetup(context_2); |
| + VerifyPixelCanvasCornerScaling(info_list); |
| + VerifyPixelSizesAreSameAsDIPSize(info_list); |
| + ClearAllPaintInfo(info_list); |
| + } |
| +} |
| + |
| +TEST_F(PaintInfoTest, Invalidation) { |
| + for (float dsf : kDsfList) { |
| + VerifyInvalidationRects(dsf, false); |
| + VerifyInvalidationRects(dsf, true); |
| + } |
| +} |
| + |
| +} // namespace views |