Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /chromium /src /refs/heads/main /. /pdf /paint_manager_unittest.cc
blob: 3c45a50b7dbe90b72b6b614dc102d6a1006d13f4 [file] [log] [blame] [edit]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include"pdf/paint_manager.h"
#include<string_view>
#include<utility>
#include"base/files/file_path.h"
#include"base/run_loop.h"
#include"cc/test/pixel_comparator.h"
#include"cc/test/pixel_test_utils.h"
#include"pdf/paint_ready_rect.h"
#include"pdf/test/test_helpers.h"
#include"testing/gmock/include/gmock/gmock.h"
#include"testing/gtest/include/gtest/gtest.h"
#include"third_party/skia/include/core/SkBitmap.h"
#include"third_party/skia/include/core/SkCPURecorder.h"
#include"third_party/skia/include/core/SkCanvas.h"
#include"third_party/skia/include/core/SkColor.h"
#include"third_party/skia/include/core/SkImage.h"
#include"third_party/skia/include/core/SkRect.h"
#include"third_party/skia/include/core/SkRefCnt.h"
#include"third_party/skia/include/core/SkSurface.h"
#include"ui/gfx/geometry/rect.h"
#include"ui/gfx/geometry/size.h"
#include"ui/gfx/geometry/skia_conversions.h"
namespace chrome_pdf{
namespace{
using::testing::_;
using::testing::NiceMock;
base::FilePathGetTestDataFilePath(std::string_view filename){
return base::FilePath(FILE_PATH_LITERAL("paint_manager"))
.AppendASCII(filename);
}
classFakeClient:publicPaintManager::Client{
public:
MOCK_METHOD(void,InvalidatePluginContainer,(),(override));
MOCK_METHOD(void,
OnPaint,
(const std::vector<gfx::Rect>& paint_rects,
std::vector<PaintReadyRect>& ready,
std::vector<gfx::Rect>& pending),
(override));
MOCK_METHOD(void,UpdateSnapshot,(sk_sp<SkImage> snapshot),(override));
MOCK_METHOD(void,UpdateScale,(float scale),(override));
MOCK_METHOD(void,
UpdateLayerTransform,
(float scale,const gfx::Vector2dF& translate),
(override));
};
classPaintManagerTest:public testing::Test{
protected:
voidWaitForOnPaint(){
base::RunLoop run_loop;
EXPECT_CALL(client_,OnPaint).WillOnce([&run_loop]{ run_loop.Quit();});
run_loop.Run();
}
sk_sp<SkImage>WaitForFlush(
const std::vector<gfx::Rect>& expected_paint_rects,
std::vector<PaintReadyRect> fake_ready,
std::vector<gfx::Rect> fake_pending){
EXPECT_CALL(client_,OnPaint(expected_paint_rects, _, _))
.WillOnce([&fake_ready,&fake_pending](
const std::vector<gfx::Rect>& paint_rects,
std::vector<PaintReadyRect>& ready,
std::vector<gfx::Rect>& pending){
ready= std::move(fake_ready);
pending= std::move(fake_pending);
});
sk_sp<SkImage> saved_snapshot;
base::RunLoop run_loop;
EXPECT_CALL(client_,UpdateSnapshot)
.WillOnce([&saved_snapshot,&run_loop](sk_sp<SkImage> snapshot){
saved_snapshot= std::move(snapshot);
run_loop.Quit();
});
run_loop.Run();
return saved_snapshot;
}
// Generates the expectations for use with TestPaintImage().
//
// - `plugin_size`: The expected image size.
// - `paint_rect`: Expected to be painted white.
// - `overlapped_rect`: Expected to be painted red.
// May paint over `paint_rect`.
SkBitmapGeneratePaintImageExpectation(const gfx::Size& plugin_size,
const gfx::Rect& paint_rect,
const gfx::Rect& overlapped_rect){
sk_sp<SkSurface> surface=
CreateSkiaSurfaceForTesting(plugin_size, SK_ColorMAGENTA);
SkCanvas* canvas= surface->getCanvas();
canvas->clipIRect(gfx::RectToSkIRect(paint_rect));
canvas->clear(SK_ColorWHITE);
canvas->clipIRect(gfx::RectToSkIRect(overlapped_rect));
canvas->clear(SK_ColorRED);
SkBitmap bitmap;
EXPECT_TRUE(surface->makeImageSnapshot()->asLegacyBitmap(&bitmap));
return bitmap;
}
voidTestPaintImage(const gfx::Size& plugin_size,
const gfx::Size& source_size,
const gfx::Rect& paint_rect,
const gfx::Rect& overlapped_rect){
// Paint `paint_rect` from `source_size` image over a magenta background.
paint_manager_.SetSize(plugin_size,1.0f);
sk_sp<SkImage> snapshot=WaitForFlush(
/*expected_paint_rects=*/{{gfx::Rect(plugin_size)}},
/*fake_ready=*/
{
{gfx::Rect(plugin_size),
CreateSkiaImageForTesting(plugin_size, SK_ColorMAGENTA)},
{paint_rect,CreateSkiaImageForTesting(source_size, SK_ColorRED)},
},
/*fake_pending=*/{});
ASSERT_TRUE(snapshot);
// Check if `snapshot` matches `expected_bitmap`.
snapshot= snapshot->makeSubset(
skcpu::Recorder::TODO(),
SkIRect::MakeWH(plugin_size.width(), plugin_size.height()),{});
ASSERT_TRUE(snapshot);
SkBitmap snapshot_bitmap;
ASSERT_TRUE(snapshot->asLegacyBitmap(&snapshot_bitmap));
SkBitmap expected_bitmap=
GeneratePaintImageExpectation(plugin_size, paint_rect, overlapped_rect);
EXPECT_TRUE(cc::MatchesBitmap(snapshot_bitmap, expected_bitmap,
cc::ExactPixelComparator()));
}
voidTestScroll(const gfx::Vector2d& scroll_amount,
const gfx::Rect& expected_paint_rect,
std::string_view expected_png){
// Paint non-uniform initial image.
gfx::Size plugin_size= paint_manager_.GetEffectiveSize();
ASSERT_GE(plugin_size.width(),4);
ASSERT_GE(plugin_size.height(),4);
sk_sp<SkSurface> initial_surface=
CreateSkiaSurfaceForTesting(plugin_size, SK_ColorRED);
initial_surface->getCanvas()->clipIRect(SkIRect::MakeLTRB(
1,1, plugin_size.width()-1, plugin_size.height()-2));
initial_surface->getCanvas()->clear(SK_ColorGREEN);
paint_manager_.Invalidate();
ASSERT_TRUE(WaitForFlush(
/*expected_paint_rects=*/{gfx::Rect(plugin_size)},
/*fake_ready=*/
{{gfx::Rect(plugin_size), initial_surface->makeImageSnapshot()}},
/*fake_pending=*/{}));
// Scroll by `scroll_amount`, painting `expected_paint_rect` magenta.
paint_manager_.ScrollRect(gfx::Rect(plugin_size), scroll_amount);
sk_sp<SkImage> snapshot=WaitForFlush(
/*expected_paint_rects=*/{expected_paint_rect},
/*fake_ready=*/
{{expected_paint_rect,
CreateSkiaImageForTesting(plugin_size, SK_ColorMAGENTA)}},
/*fake_pending=*/{});
ASSERT_TRUE(snapshot);
// Compare snapshot to `expected_png`.
snapshot= snapshot->makeSubset(
skcpu::Recorder::TODO(),
SkIRect::MakeWH(plugin_size.width(), plugin_size.height()),{});
ASSERT_TRUE(snapshot);
EXPECT_TRUE(
MatchesPngFile(snapshot.get(),GetTestDataFilePath(expected_png)));
}
NiceMock<FakeClient> client_;
PaintManager paint_manager_{&client_};
};
TEST_F(PaintManagerTest,GetNewContextSizeWhenGrowingBelowMaximum){
EXPECT_EQ(gfx::Size(450,350),
PaintManager::GetNewContextSize({450,350},{450,349}));
EXPECT_EQ(gfx::Size(450,350),
PaintManager::GetNewContextSize({450,350},{449,350}));
}
TEST_F(PaintManagerTest,GetNewContextSizeWhenGrowingAboveMaximum){
EXPECT_EQ(gfx::Size(501,400),
PaintManager::GetNewContextSize({450,350},{451,350}));
EXPECT_EQ(gfx::Size(500,401),
PaintManager::GetNewContextSize({450,350},{450,351}));
}
TEST_F(PaintManagerTest,GetNewContextSizeWhenShrinkingAboveMinimum){
EXPECT_EQ(gfx::Size(450,350),
PaintManager::GetNewContextSize({450,350},{350,251}));
EXPECT_EQ(gfx::Size(450,350),
PaintManager::GetNewContextSize({450,350},{351,250}));
}
TEST_F(PaintManagerTest,GetNewContextSizeWhenShrinkingBelowMinimum){
EXPECT_EQ(gfx::Size(399,300),
PaintManager::GetNewContextSize({450,350},{349,250}));
EXPECT_EQ(gfx::Size(400,299),
PaintManager::GetNewContextSize({450,350},{350,249}));
}
TEST_F(PaintManagerTest,Create){
EXPECT_EQ(gfx::Size(0,0), paint_manager_.GetEffectiveSize());
EXPECT_EQ(1.0f, paint_manager_.GetEffectiveDeviceScale());
}
TEST_F(PaintManagerTest,SetSizeWithoutPaint){
EXPECT_CALL(client_,InvalidatePluginContainer).Times(0);
paint_manager_.SetSize({400,300},2.0f);
EXPECT_EQ(gfx::Size(400,300), paint_manager_.GetEffectiveSize());
EXPECT_EQ(2.0f, paint_manager_.GetEffectiveDeviceScale());
}
TEST_F(PaintManagerTest,SetSizeWithPaint){
paint_manager_.SetSize({400,300},2.0f);
EXPECT_CALL(client_,InvalidatePluginContainer);
EXPECT_CALL(client_,UpdateScale(0.5f));
WaitForOnPaint();
}
TEST_F(PaintManagerTest,SetTransformWithoutSurface){
EXPECT_CALL(client_,UpdateLayerTransform).Times(0);
paint_manager_.SetTransform(0.25f,{150,50},{-4,8},
/*schedule_flush=*/true);
}
TEST_F(PaintManagerTest,SetTransformWithSurface){
paint_manager_.SetSize({400,300},2.0f);
WaitForOnPaint();
EXPECT_CALL(client_,
UpdateLayerTransform(0.25f, gfx::Vector2dF(116.5f,29.5f)));
paint_manager_.SetTransform(0.25f,{150,50},{-4,8},
/*schedule_flush=*/true);
WaitForOnPaint();
}
TEST_F(PaintManagerTest,ClearTransform){
paint_manager_.SetSize({400,300},2.0f);
WaitForOnPaint();
EXPECT_CALL(client_,UpdateLayerTransform(1.0f, gfx::Vector2dF()));
paint_manager_.ClearTransform();
}
TEST_F(PaintManagerTest,DoPaintFirst){
paint_manager_.SetSize({400,300},2.0f);
sk_sp<SkImage> snapshot=
WaitForFlush(/*expected_paint_rects=*/{{0,0,400,300}},
/*fake_ready=*/
{{{25,50,200,100},
CreateSkiaImageForTesting({200,100}, SK_ColorGRAY)}},
/*fake_pending=*/{});
EXPECT_TRUE(MatchesPngFile(snapshot.get(),
GetTestDataFilePath("do_paint_first.png")));
}
TEST_F(PaintManagerTest,PaintImage){
// Painted area is within the plugin area and the source image.
TestPaintImage(/*plugin_size=*/{20,20},/*source_size=*/{15,15},
/*paint_rect=*/{0,0,10,10},
/*overlapped_rect=*/{0,0,10,10});
// Painted area straddles the plugin area and the source image.
TestPaintImage(/*plugin_size=*/{50,30},/*source_size=*/{30,50},
/*paint_rect=*/{10,10,30,30},
/*overlapped_rect=*/{10,10,20,20});
// Painted area is outside the plugin area.
TestPaintImage(/*plugin_size=*/{10,10},/*source_size=*/{30,30},
/*paint_rect=*/{10,10,10,10},
/*overlapped_rect=*/{0,0,0,0});
// Painted area is outside the source image.
TestPaintImage(/*plugin_size=*/{15,15},/*source_size=*/{5,5},
/*paint_rect=*/{10,10,5,5},
/*overlapped_rect=*/{0,0,0,0});
}
TEST_F(PaintManagerTest,Scroll){
paint_manager_.SetSize({4,5},1.0f);
TestScroll(/*scroll_amount=*/{1,0},/*expected_paint_rect=*/{0,0,1,5},
"scroll_right.png");
TestScroll(/*scroll_amount=*/{-2,0},/*expected_paint_rect=*/{2,0,2,5},
"scroll_left.png");
TestScroll(/*scroll_amount=*/{0,3},/*expected_paint_rect=*/{0,0,4,3},
"scroll_down.png");
TestScroll(/*scroll_amount=*/{0,-3},/*expected_paint_rect=*/{0,2,4,3},
"scroll_up.png");
}
TEST_F(PaintManagerTest,ScrollIgnored){
paint_manager_.SetSize({4,5},1.0f);
// Scroll to the edge of the plugin area.
TestScroll(/*scroll_amount=*/{4,0},/*expected_paint_rect=*/{0,0,4,5},
"scroll_ignored.png");
TestScroll(/*scroll_amount=*/{-4,0},/*expected_paint_rect=*/{0,0,4,5},
"scroll_ignored.png");
TestScroll(/*scroll_amount=*/{0,5},/*expected_paint_rect=*/{0,0,4,5},
"scroll_ignored.png");
TestScroll(/*scroll_amount=*/{0,-5},/*expected_paint_rect=*/{0,0,4,5},
"scroll_ignored.png");
// Scroll outside of the plugin area.
TestScroll(/*scroll_amount=*/{5,0},/*expected_paint_rect=*/{0,0,4,5},
"scroll_ignored.png");
TestScroll(/*scroll_amount=*/{-7,0},/*expected_paint_rect=*/{0,0,4,5},
"scroll_ignored.png");
TestScroll(/*scroll_amount=*/{0,8},/*expected_paint_rect=*/{0,0,4,5},
"scroll_ignored.png");
TestScroll(/*scroll_amount=*/{0,-9},/*expected_paint_rect=*/{0,0,4,5},
"scroll_ignored.png");
}
}// namespace
}// namespace chrome_pdf

[8]ページ先頭

©2009-2025 Movatter.jp