blob: e097e43d3bfd5339a3d0c74b977c60ac82352939 [file] [log] [blame]
// Copyright 2015 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 "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_buffer.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/SkSurface.h"
namespace cc {
namespace {
class MockImageGenerator : public FakePaintImageGenerator {
public:
explicit MockImageGenerator(const gfx::Size& size)
: FakePaintImageGenerator(
SkImageInfo::MakeN32Premul(size.width(), size.height())) {}
MOCK_METHOD6(GetPixels,
bool(const SkImageInfo&,
void*,
size_t,
size_t,
PaintImage::GeneratorClientId,
uint32_t));
};
class MockImageProvider : public ImageProvider {
public:
MockImageProvider() = default;
~MockImageProvider() override = default;
ScopedDecodedDrawImage GetDecodedDrawImage(
const DrawImage& draw_image) override {
draw_image_ = draw_image;
SkBitmap bitmap;
bitmap.allocN32Pixels(10, 10);
bitmap.eraseColor(SK_ColorBLACK);
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
return ScopedDecodedDrawImage(
DecodedDrawImage(image, 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::MakeScale(0.5f, 0.5f);
auto record_shader = PaintShader::MakePaintRecord(
sk_make_sp<PaintOpBuffer>(), SkRect::MakeWH(100, 100),
SkShader::TileMode::kClamp_TileMode, SkShader::TileMode::kClamp_TileMode,
&local_matrix);
SkRect tile_rect;
SkMatrix ctm = SkMatrix::MakeScale(0.5f, 0.5f);
EXPECT_TRUE(record_shader->GetRasterizationTileRect(ctm, &tile_rect));
EXPECT_EQ(tile_rect, SkRect::MakeWH(25, 25));
}
TEST(PaintShaderTest, DecodePaintRecord) {
auto record = sk_make_sp<PaintOpBuffer>();
// 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();
record->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr);
SkMatrix local_matrix = SkMatrix::MakeScale(0.5f, 0.5f);
auto record_shader = PaintShader::MakePaintRecord(
record, SkRect::MakeWH(100, 100), SkShader::TileMode::kClamp_TileMode,
SkShader::TileMode::kClamp_TileMode, &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;
SkShader::TileMode 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::MakeScale(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 = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(100, 100));
surface->getCanvas()->drawPaint(canvas.paint_);
// Using the shader requests decode for images at the correct scale.
EXPECT_EQ(image_provider.draw_image().paint_image(), paint_image);
EXPECT_EQ(image_provider.draw_image().scale().width(), 0.25f);
EXPECT_EQ(image_provider.draw_image().scale().height(), 0.25f);
}
} // namespace cc