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..6b4d4e677363048efbd76a48966f0f12aa3eceed |
--- /dev/null |
+++ b/ui/views/paint_info_unittest.cc |
@@ -0,0 +1,246 @@ |
+// 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 { |
+ |
+using PaintInfos = std::vector<std::unique_ptr<PaintInfo>>; |
+ |
+// 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}; |
+ |
+constexpr gfx::Size kLayerSize(123, 456); |
+ |
+// ___________ |
+// | 1 | |
+// |___________| |
+// | 3 | 4 | 5 | <-- 2 (encapsulates 3, 4 and 5) |
+// |___|___|___| |
+// | 7 | 8 | <-- 6 (encapsulates 7 and 8) |
+// |_______|___| |
+// |
+// |r_0| encapsulates 1, 2 and 6. |
+const gfx::Rect r_0(kLayerSize); |
+ |
+constexpr gfx::Rect r_1(0, 0, 123, 152); |
+ |
+constexpr gfx::Rect r_2(0, 152, 123, 152); |
+constexpr gfx::Rect r_3(0, 0, 41, 152); |
+constexpr gfx::Rect r_4(41, 0, 41, 152); |
+constexpr gfx::Rect r_5(82, 0, 41, 152); |
+ |
+constexpr gfx::Rect r_6(0, 304, 123, 152); |
+constexpr gfx::Rect r_7(0, 0, 82, 152); |
+constexpr gfx::Rect r_8(82, 0, 41, 152); |
+ |
+// Verifies that the child recording bounds completely cover the parent |
+// recording bounds. |
+void VerifyChildBoundsCoversParent(const PaintInfo* parent_paint_info, |
+ const std::vector<PaintInfo*>& info_list) { |
+ cc::Region remaining(gfx::Rect(parent_paint_info->paint_recording_size())); |
+ int times_empty = 0; |
+ for (auto* const 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(const PaintInfos& 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].get()); |
+ child_info_list.push_back(info_list[2].get()); |
+ child_info_list.push_back(info_list[6].get()); |
+ VerifyChildBoundsCoversParent(info_list[0].get(), 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].get()); |
+ child_info_list.push_back(info_list[4].get()); |
+ child_info_list.push_back(info_list[5].get()); |
+ VerifyChildBoundsCoversParent(info_list[2].get(), child_info_list); |
+ child_info_list.clear(); |
+ |
+ // Child 7 and 8 should completely cover child 6. |
+ child_info_list.push_back(info_list[7].get()); |
+ child_info_list.push_back(info_list[8].get()); |
+ VerifyChildBoundsCoversParent(info_list[6].get(), child_info_list); |
+ child_info_list.clear(); |
+} |
+ |
+void VerifyPixelSizesAreSameAsDIPSize(const PaintInfos& info_list) { |
+ EXPECT_EQ(info_list[0]->paint_recording_size(), r_0.size()); |
+ |
+ EXPECT_EQ(info_list[1]->paint_recording_size(), r_1.size()); |
+ |
+ EXPECT_EQ(info_list[2]->paint_recording_size(), r_2.size()); |
+ EXPECT_EQ(info_list[3]->paint_recording_size(), r_3.size()); |
+ EXPECT_EQ(info_list[4]->paint_recording_size(), r_4.size()); |
+ EXPECT_EQ(info_list[5]->paint_recording_size(), r_5.size()); |
+ |
+ EXPECT_EQ(info_list[6]->paint_recording_size(), r_6.size()); |
+ EXPECT_EQ(info_list[7]->paint_recording_size(), r_7.size()); |
+ EXPECT_EQ(info_list[8]->paint_recording_size(), r_8.size()); |
+} |
+ |
+} // namespace |
+ |
+class PaintInfoTest : public ::testing::Test { |
+ public: |
+ PaintInfoTest() {} |
+ |
+ ~PaintInfoTest() override {} |
+ |
+ // ___________ |
+ // | 1 | |
+ // |___________| |
+ // | 3 | 4 | 5 | <-- 2 (encapsulates 3, 4 and 5) |
+ // |___|___|___| |
+ // | 7 | 8 | <-- 6 (encapsulates 7 and 8) |
+ // |_______|___| |
+ // |
+ // |r_0| encapsulates 1, 2 and 6. |
+ // |
+ // Returns the following arrangement of paint recording bounds for the given |
+ // |dsf| |
+ PaintInfos GetPaintInfoSetup(const ui::PaintContext& context) { |
+ PaintInfos info_list(9); |
+ |
+ info_list[0].reset(new PaintInfo(context, kLayerSize)); |
+ |
+ info_list[1].reset(new PaintInfo(*info_list[0], r_1, r_0.size(), |
+ PaintInfo::ScaleType::kScaleToFit)); |
+ |
+ info_list[2].reset(new PaintInfo(*info_list[0], r_2, r_0.size(), |
+ PaintInfo::ScaleType::kScaleToFit)); |
+ info_list[3].reset(new PaintInfo(*info_list[2], r_3, r_2.size(), |
+ PaintInfo::ScaleType::kScaleToFit)); |
+ info_list[4].reset(new PaintInfo(*info_list[2], r_4, r_2.size(), |
+ PaintInfo::ScaleType::kScaleToFit)); |
+ info_list[5].reset(new PaintInfo(*info_list[2], r_5, r_2.size(), |
+ PaintInfo::ScaleType::kScaleToFit)); |
+ |
+ info_list[6].reset(new PaintInfo(*info_list[0], r_6, r_0.size(), |
+ PaintInfo::ScaleType::kScaleToFit)); |
+ info_list[7].reset(new PaintInfo(*info_list[6], r_7, r_6.size(), |
+ PaintInfo::ScaleType::kScaleToFit)); |
+ info_list[8].reset(new PaintInfo(*info_list[6], r_8, r_6.size(), |
+ PaintInfo::ScaleType::kScaleToFit)); |
+ |
+ return info_list; |
+ } |
+ |
+ 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}}; |
+ |
+ PaintInfos 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()))); |
+ } |
+ info_list.clear(); |
+ } |
+ } |
+}; |
+ |
+TEST_F(PaintInfoTest, CornerScalingPixelCanvasEnabled) { |
+ PaintInfos info_list; |
+ for (float dsf : kDsfList) { |
+ ui::PaintContext context(nullptr, dsf, gfx::Rect(), true); |
+ info_list = GetPaintInfoSetup(context); |
+ VerifyPixelCanvasCornerScaling(info_list); |
+ info_list.clear(); |
+ } |
+ |
+ // 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)); |
+} |
+ |
+TEST_F(PaintInfoTest, ScalingWithPixelCanvasDisabled) { |
+ for (float dsf : kDsfList) { |
+ ui::PaintContext context(nullptr, dsf, gfx::Rect(), false); |
+ PaintInfos info_list = GetPaintInfoSetup(context); |
+ VerifyPixelCanvasCornerScaling(info_list); |
+ VerifyPixelSizesAreSameAsDIPSize(info_list); |
+ info_list.clear(); |
+ } |
+} |
+ |
+TEST_F(PaintInfoTest, Invalidation) { |
+ for (float dsf : kDsfList) { |
+ VerifyInvalidationRects(dsf, false); |
+ VerifyInvalidationRects(dsf, true); |
+ } |
+} |
+ |
+} // namespace views |