[M108 Migration][HBBTV] Implement ewk_context_register_jsplugin_mime_types API
[platform/framework/web/chromium-efl.git] / pdf / paint_manager_unittest.cc
1 // Copyright 2022 The Chromium Authors
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 "pdf/paint_manager.h"
6
7 #include <utility>
8
9 #include "base/files/file_path.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_piece.h"
12 #include "cc/test/pixel_comparator.h"
13 #include "cc/test/pixel_test_utils.h"
14 #include "pdf/paint_ready_rect.h"
15 #include "pdf/test/test_helpers.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "third_party/skia/include/core/SkCanvas.h"
20 #include "third_party/skia/include/core/SkColor.h"
21 #include "third_party/skia/include/core/SkImage.h"
22 #include "third_party/skia/include/core/SkRect.h"
23 #include "third_party/skia/include/core/SkRefCnt.h"
24 #include "third_party/skia/include/core/SkSurface.h"
25 #include "ui/gfx/geometry/rect.h"
26 #include "ui/gfx/geometry/size.h"
27 #include "ui/gfx/geometry/skia_conversions.h"
28
29 namespace chrome_pdf {
30
31 namespace {
32
33 using ::testing::_;
34 using ::testing::NiceMock;
35
36 base::FilePath GetTestDataFilePath(base::StringPiece filename) {
37   return base::FilePath(FILE_PATH_LITERAL("paint_manager"))
38       .AppendASCII(filename);
39 }
40
41 class FakeClient : public PaintManager::Client {
42  public:
43   MOCK_METHOD(void, InvalidatePluginContainer, (), (override));
44   MOCK_METHOD(void,
45               OnPaint,
46               (const std::vector<gfx::Rect>& paint_rects,
47                std::vector<PaintReadyRect>& ready,
48                std::vector<gfx::Rect>& pending),
49               (override));
50   MOCK_METHOD(void, UpdateSnapshot, (sk_sp<SkImage> snapshot), (override));
51   MOCK_METHOD(void, UpdateScale, (float scale), (override));
52   MOCK_METHOD(void,
53               UpdateLayerTransform,
54               (float scale, const gfx::Vector2dF& translate),
55               (override));
56 };
57
58 class PaintManagerTest : public testing::Test {
59  protected:
60   void WaitForOnPaint() {
61     base::RunLoop run_loop;
62     EXPECT_CALL(client_, OnPaint).WillOnce([&run_loop] { run_loop.Quit(); });
63     run_loop.Run();
64   }
65
66   sk_sp<SkImage> WaitForFlush(
67       const std::vector<gfx::Rect>& expected_paint_rects,
68       std::vector<PaintReadyRect> fake_ready,
69       std::vector<gfx::Rect> fake_pending) {
70     EXPECT_CALL(client_, OnPaint(expected_paint_rects, _, _))
71         .WillOnce([&fake_ready, &fake_pending](
72                       const std::vector<gfx::Rect>& paint_rects,
73                       std::vector<PaintReadyRect>& ready,
74                       std::vector<gfx::Rect>& pending) {
75           ready = std::move(fake_ready);
76           pending = std::move(fake_pending);
77         });
78
79     sk_sp<SkImage> saved_snapshot;
80     base::RunLoop run_loop;
81     EXPECT_CALL(client_, UpdateSnapshot)
82         .WillOnce([&saved_snapshot, &run_loop](sk_sp<SkImage> snapshot) {
83           saved_snapshot = std::move(snapshot);
84           run_loop.Quit();
85         });
86     run_loop.Run();
87
88     return saved_snapshot;
89   }
90
91   void TestPaintImage(const gfx::Size& plugin_size,
92                       const gfx::Size& source_size,
93                       const gfx::Rect& paint_rect,
94                       const gfx::Rect& overlapped_rect) {
95     // Paint `paint_rect` from `source_size` image over a magenta background.
96     paint_manager_.SetSize(plugin_size, 1.0f);
97     sk_sp<SkImage> snapshot = WaitForFlush(
98         /*expected_paint_rects=*/{{gfx::Rect(plugin_size)}},
99         /*fake_ready=*/
100         {
101             {gfx::Rect(plugin_size),
102              CreateSkiaImageForTesting(plugin_size, SK_ColorMAGENTA)},
103             {paint_rect, CreateSkiaImageForTesting(source_size, SK_ColorRED)},
104         },
105         /*fake_pending=*/{});
106     ASSERT_TRUE(snapshot);
107
108     // Check if snapshot has `overlapped_rect` painted red.
109     snapshot = snapshot->makeSubset(
110         SkIRect::MakeWH(plugin_size.width(), plugin_size.height()));
111     ASSERT_TRUE(snapshot);
112
113     SkBitmap snapshot_bitmap;
114     ASSERT_TRUE(snapshot->asLegacyBitmap(&snapshot_bitmap));
115
116     sk_sp<SkSurface> expected_surface =
117         CreateSkiaSurfaceForTesting(plugin_size, SK_ColorMAGENTA);
118     expected_surface->getCanvas()->clipIRect(
119         gfx::RectToSkIRect(overlapped_rect));
120     expected_surface->getCanvas()->clear(SK_ColorRED);
121
122     SkBitmap expected_bitmap;
123     ASSERT_TRUE(expected_surface->makeImageSnapshot()->asLegacyBitmap(
124         &expected_bitmap));
125
126     EXPECT_TRUE(
127         cc::MatchesBitmap(snapshot_bitmap, expected_bitmap,
128                           cc::ExactPixelComparator(/*discard_alpha=*/false)));
129   }
130
131   void TestScroll(const gfx::Vector2d& scroll_amount,
132                   const gfx::Rect& expected_paint_rect,
133                   base::StringPiece expected_png) {
134     // Paint non-uniform initial image.
135     gfx::Size plugin_size = paint_manager_.GetEffectiveSize();
136     ASSERT_GE(plugin_size.width(), 4);
137     ASSERT_GE(plugin_size.height(), 4);
138
139     sk_sp<SkSurface> initial_surface =
140         CreateSkiaSurfaceForTesting(plugin_size, SK_ColorRED);
141     initial_surface->getCanvas()->clipIRect(SkIRect::MakeLTRB(
142         1, 1, plugin_size.width() - 1, plugin_size.height() - 2));
143     initial_surface->getCanvas()->clear(SK_ColorGREEN);
144
145     paint_manager_.Invalidate();
146     ASSERT_TRUE(WaitForFlush(
147         /*expected_paint_rects=*/{gfx::Rect(plugin_size)},
148         /*fake_ready=*/
149         {{gfx::Rect(plugin_size), initial_surface->makeImageSnapshot()}},
150         /*fake_pending=*/{}));
151
152     // Scroll by `scroll_amount`, painting `expected_paint_rect` magenta.
153     paint_manager_.ScrollRect(gfx::Rect(plugin_size), scroll_amount);
154     sk_sp<SkImage> snapshot = WaitForFlush(
155         /*expected_paint_rects=*/{expected_paint_rect},
156         /*fake_ready=*/
157         {{expected_paint_rect,
158           CreateSkiaImageForTesting(plugin_size, SK_ColorMAGENTA)}},
159         /*fake_pending=*/{});
160     ASSERT_TRUE(snapshot);
161
162     // Compare snapshot to `expected_png`.
163     snapshot = snapshot->makeSubset(
164         SkIRect::MakeWH(plugin_size.width(), plugin_size.height()));
165     ASSERT_TRUE(snapshot);
166
167     EXPECT_TRUE(
168         MatchesPngFile(snapshot.get(), GetTestDataFilePath(expected_png)));
169   }
170
171   NiceMock<FakeClient> client_;
172   PaintManager paint_manager_{&client_};
173 };
174
175 TEST_F(PaintManagerTest, GetNewContextSizeWhenGrowingBelowMaximum) {
176   EXPECT_EQ(gfx::Size(450, 350),
177             PaintManager::GetNewContextSize({450, 350}, {450, 349}));
178   EXPECT_EQ(gfx::Size(450, 350),
179             PaintManager::GetNewContextSize({450, 350}, {449, 350}));
180 }
181
182 TEST_F(PaintManagerTest, GetNewContextSizeWhenGrowingAboveMaximum) {
183   EXPECT_EQ(gfx::Size(501, 400),
184             PaintManager::GetNewContextSize({450, 350}, {451, 350}));
185   EXPECT_EQ(gfx::Size(500, 401),
186             PaintManager::GetNewContextSize({450, 350}, {450, 351}));
187 }
188
189 TEST_F(PaintManagerTest, GetNewContextSizeWhenShrinkingAboveMinimum) {
190   EXPECT_EQ(gfx::Size(450, 350),
191             PaintManager::GetNewContextSize({450, 350}, {350, 251}));
192   EXPECT_EQ(gfx::Size(450, 350),
193             PaintManager::GetNewContextSize({450, 350}, {351, 250}));
194 }
195
196 TEST_F(PaintManagerTest, GetNewContextSizeWhenShrinkingBelowMinimum) {
197   EXPECT_EQ(gfx::Size(399, 300),
198             PaintManager::GetNewContextSize({450, 350}, {349, 250}));
199   EXPECT_EQ(gfx::Size(400, 299),
200             PaintManager::GetNewContextSize({450, 350}, {350, 249}));
201 }
202
203 TEST_F(PaintManagerTest, Create) {
204   EXPECT_EQ(gfx::Size(0, 0), paint_manager_.GetEffectiveSize());
205   EXPECT_EQ(1.0f, paint_manager_.GetEffectiveDeviceScale());
206 }
207
208 TEST_F(PaintManagerTest, SetSizeWithoutPaint) {
209   EXPECT_CALL(client_, InvalidatePluginContainer).Times(0);
210   paint_manager_.SetSize({400, 300}, 2.0f);
211
212   EXPECT_EQ(gfx::Size(400, 300), paint_manager_.GetEffectiveSize());
213   EXPECT_EQ(2.0f, paint_manager_.GetEffectiveDeviceScale());
214 }
215
216 TEST_F(PaintManagerTest, SetSizeWithPaint) {
217   paint_manager_.SetSize({400, 300}, 2.0f);
218
219   EXPECT_CALL(client_, InvalidatePluginContainer);
220   EXPECT_CALL(client_, UpdateScale(0.5f));
221   WaitForOnPaint();
222 }
223
224 TEST_F(PaintManagerTest, SetTransformWithoutSurface) {
225   EXPECT_CALL(client_, UpdateLayerTransform).Times(0);
226   paint_manager_.SetTransform(0.25f, {150, 50}, {-4, 8},
227                               /*schedule_flush=*/true);
228 }
229
230 TEST_F(PaintManagerTest, SetTransformWithSurface) {
231   paint_manager_.SetSize({400, 300}, 2.0f);
232   WaitForOnPaint();
233
234   EXPECT_CALL(client_,
235               UpdateLayerTransform(0.25f, gfx::Vector2dF(116.5f, 29.5f)));
236   paint_manager_.SetTransform(0.25f, {150, 50}, {-4, 8},
237                               /*schedule_flush=*/true);
238   WaitForOnPaint();
239 }
240
241 TEST_F(PaintManagerTest, ClearTransform) {
242   paint_manager_.SetSize({400, 300}, 2.0f);
243   WaitForOnPaint();
244
245   EXPECT_CALL(client_, UpdateLayerTransform(1.0f, gfx::Vector2dF()));
246   paint_manager_.ClearTransform();
247 }
248
249 TEST_F(PaintManagerTest, DoPaintFirst) {
250   paint_manager_.SetSize({400, 300}, 2.0f);
251
252   sk_sp<SkImage> snapshot =
253       WaitForFlush(/*expected_paint_rects=*/{{0, 0, 400, 300}},
254                    /*fake_ready=*/
255                    {{{25, 50, 200, 100},
256                      CreateSkiaImageForTesting({200, 100}, SK_ColorGRAY)}},
257                    /*fake_pending=*/{});
258
259   EXPECT_TRUE(MatchesPngFile(snapshot.get(),
260                              GetTestDataFilePath("do_paint_first.png")));
261 }
262
263 TEST_F(PaintManagerTest, PaintImage) {
264   // Painted area is within the plugin area and the source image.
265   TestPaintImage(/*plugin_size=*/{20, 20}, /*source_size=*/{15, 15},
266                  /*paint_rect=*/{0, 0, 10, 10},
267                  /*overlapped_rect=*/{0, 0, 10, 10});
268
269   // Painted area straddles the plugin area and the source image.
270   TestPaintImage(/*plugin_size=*/{50, 30}, /*source_size=*/{30, 50},
271                  /*paint_rect=*/{10, 10, 30, 30},
272                  /*overlapped_rect=*/{10, 10, 20, 20});
273
274   // Painted area is outside the plugin area.
275   TestPaintImage(/*plugin_size=*/{10, 10}, /*source_size=*/{30, 30},
276                  /*paint_rect=*/{10, 10, 10, 10},
277                  /*overlapped_rect=*/{0, 0, 0, 0});
278
279   // Painted area is outside the source image.
280   TestPaintImage(/*plugin_size=*/{15, 15}, /*source_size=*/{5, 5},
281                  /*paint_rect=*/{10, 10, 5, 5},
282                  /*overlapped_rect=*/{0, 0, 0, 0});
283 }
284
285 TEST_F(PaintManagerTest, Scroll) {
286   paint_manager_.SetSize({4, 5}, 1.0f);
287
288   TestScroll(/*scroll_amount=*/{1, 0}, /*expected_paint_rect=*/{0, 0, 1, 5},
289              "scroll_right.png");
290   TestScroll(/*scroll_amount=*/{-2, 0}, /*expected_paint_rect=*/{2, 0, 2, 5},
291              "scroll_left.png");
292   TestScroll(/*scroll_amount=*/{0, 3}, /*expected_paint_rect=*/{0, 0, 4, 3},
293              "scroll_down.png");
294   TestScroll(/*scroll_amount=*/{0, -3}, /*expected_paint_rect=*/{0, 2, 4, 3},
295              "scroll_up.png");
296 }
297
298 TEST_F(PaintManagerTest, ScrollIgnored) {
299   paint_manager_.SetSize({4, 5}, 1.0f);
300
301   // Scroll to the edge of the plugin area.
302   TestScroll(/*scroll_amount=*/{4, 0}, /*expected_paint_rect=*/{0, 0, 4, 5},
303              "scroll_ignored.png");
304   TestScroll(/*scroll_amount=*/{-4, 0}, /*expected_paint_rect=*/{0, 0, 4, 5},
305              "scroll_ignored.png");
306   TestScroll(/*scroll_amount=*/{0, 5}, /*expected_paint_rect=*/{0, 0, 4, 5},
307              "scroll_ignored.png");
308   TestScroll(/*scroll_amount=*/{0, -5}, /*expected_paint_rect=*/{0, 0, 4, 5},
309              "scroll_ignored.png");
310
311   // Scroll outside of the plugin area.
312   TestScroll(/*scroll_amount=*/{5, 0}, /*expected_paint_rect=*/{0, 0, 4, 5},
313              "scroll_ignored.png");
314   TestScroll(/*scroll_amount=*/{-7, 0}, /*expected_paint_rect=*/{0, 0, 4, 5},
315              "scroll_ignored.png");
316   TestScroll(/*scroll_amount=*/{0, 8}, /*expected_paint_rect=*/{0, 0, 4, 5},
317              "scroll_ignored.png");
318   TestScroll(/*scroll_amount=*/{0, -9}, /*expected_paint_rect=*/{0, 0, 4, 5},
319              "scroll_ignored.png");
320 }
321
322 }  // namespace
323
324 }  // namespace chrome_pdf