1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
cc / paint / paint_shader_unittest.cc [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/paint/paint_shader.h"
#include "cc/paint/draw_image.h"
#include "cc/paint/image_provider.h"
#include "cc/paint/paint_image_builder.h"
#include "cc/paint/paint_op.h"
#include "cc/test/fake_paint_image_generator.h"
#include "cc/test/skia_common.h"
#include "cc/test/test_skcanvas.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPixmap.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkTileMode.h"
namespace cc {
namespace {
class MockImageGenerator : public FakePaintImageGenerator {
public:
explicit MockImageGenerator(const gfx::Size& size)
: FakePaintImageGenerator(
SkImageInfo::MakeN32Premul(size.width(), size.height())) {}
MOCK_METHOD4(GetPixels,
bool(SkPixmap, size_t, PaintImage::GeneratorClientId, uint32_t));
};
class MockImageProvider : public ImageProvider {
public:
MockImageProvider() = default;
~MockImageProvider() override = default;
ImageProvider::ScopedResult GetRasterContent(
const DrawImage& draw_image) override {
DCHECK(!draw_image.paint_image().IsPaintWorklet());
draw_image_ = draw_image;
SkBitmap bitmap;
bitmap.allocN32Pixels(10, 10);
bitmap.eraseColor(SK_ColorBLACK);
sk_sp<SkImage> image = SkImages::RasterFromBitmap(bitmap);
return ScopedResult(DecodedDrawImage(image, nullptr, SkSize::MakeEmpty(),
SkSize::Make(1.0f, 1.0f),
draw_image.filter_quality(), true));
}
const DrawImage& draw_image() const { return draw_image_; }
private:
DrawImage draw_image_;
};
} // namespace
TEST(PaintShaderTest, RasterizationRectForRecordShaders) {
SkMatrix local_matrix = SkMatrix::Scale(0.5f, 0.5f);
auto record_shader = PaintShader::MakePaintRecord(
PaintRecord(), SkRect::MakeWH(100, 100), SkTileMode::kClamp,
SkTileMode::kClamp, &local_matrix);
SkRect tile_rect;
SkMatrix ctm = SkMatrix::Scale(0.5f, 0.5f);
EXPECT_TRUE(record_shader->GetRasterizationTileRect(ctm, &tile_rect));
EXPECT_EQ(tile_rect, SkRect::MakeWH(25, 25));
}
TEST(PaintShaderTest, DecodePaintRecord) {
// Use a strict mock for the generator. It should never be used when
// rasterizing this shader, since the decode should be done by the
// ImageProvider.
auto generator =
sk_make_sp<testing::StrictMock<MockImageGenerator>>(gfx::Size(100, 100));
PaintImage paint_image = PaintImageBuilder::WithDefault()
.set_id(PaintImage::GetNextId())
.set_paint_image_generator(generator)
.TakePaintImage();
PaintOpBuffer shader_buffer;
shader_buffer.push<DrawImageOp>(paint_image, 0.f, 0.f);
SkMatrix local_matrix = SkMatrix::Scale(0.5f, 0.5f);
auto record_shader = PaintShader::MakePaintRecord(
shader_buffer.ReleaseAsRecord(), SkRect::MakeWH(100, 100),
SkTileMode::kClamp, SkTileMode::kClamp, &local_matrix);
record_shader->set_has_animated_images(true);
PaintOpBuffer buffer;
PaintFlags flags;
flags.setShader(record_shader);
buffer.push<ScaleOp>(0.5f, 0.5f);
buffer.push<DrawRectOp>(SkRect::MakeWH(100, 100), flags);
MockImageProvider image_provider;
SaveCountingCanvas canvas;
buffer.Playback(&canvas, PlaybackParams(&image_provider));
EXPECT_EQ(canvas.draw_rect_, SkRect::MakeWH(100, 100));
SkShader* shader = canvas.paint_.getShader();
ASSERT_TRUE(shader);
SkMatrix decoded_local_matrix;
SkTileMode xy[2];
SkImage* skia_image = shader->isAImage(&decoded_local_matrix, xy);
ASSERT_TRUE(skia_image);
EXPECT_TRUE(skia_image->isLazyGenerated());
EXPECT_EQ(xy[0], record_shader->tx());
EXPECT_EQ(xy[1], record_shader->ty());
EXPECT_EQ(decoded_local_matrix, SkMatrix::Scale(2.f, 2.f));
// The rasterization of the shader is internal to skia, so use a raster canvas
// to verify that the decoded paint does not have the encoded image.
auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(100, 100));
surface->getCanvas()->drawPaint(canvas.paint_);
// Using the shader requests decode for images at the correct scale.
EXPECT_TRUE(
image_provider.draw_image().paint_image().IsSameForTesting(paint_image));
EXPECT_EQ(image_provider.draw_image().scale().width(), 0.25f);
EXPECT_EQ(image_provider.draw_image().scale().height(), 0.25f);
}
} // namespace cc