blob: 1cf676527c64c8e7f801630659fbd4702c19a96a [file] [log] [blame]
// Copyright 2018 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_filter.h"
#include "cc/paint/paint_op_buffer.h"
#include "cc/test/skia_common.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/effects/SkLumaColorFilter.h"
namespace cc {
namespace {
class MockImageProvider : public ImageProvider {
public:
MockImageProvider() = default;
~MockImageProvider() override = default;
ScopedResult GetRasterContent(const DrawImage& draw_image) override {
DCHECK(!draw_image.paint_image().IsPaintWorklet());
image_count_++;
return ScopedResult(DecodedDrawImage(
CreateBitmapImage(gfx::Size(10, 10)).GetSkImage(), SkSize::MakeEmpty(),
SkSize::Make(1.0f, 1.0f), draw_image.filter_quality(), true));
}
int image_count_ = 0;
};
sk_sp<PaintFilter> CreateTestFilter(PaintFilter::Type filter_type,
bool has_discardable_images) {
PaintImage image;
if (has_discardable_images)
image = CreateDiscardablePaintImage(gfx::Size(100, 100));
else
image = CreateNonDiscardablePaintImage(gfx::Size(100, 100));
auto image_filter = sk_make_sp<ImagePaintFilter>(
image, SkRect::MakeWH(100.f, 100.f), SkRect::MakeWH(100.f, 100.f),
kNone_SkFilterQuality);
auto record = sk_make_sp<PaintOpBuffer>();
record->push<DrawImageOp>(image, 0.f, 0.f, nullptr);
auto record_filter =
sk_make_sp<RecordPaintFilter>(record, SkRect::MakeWH(100.f, 100.f));
SkImageFilter::CropRect crop_rect(SkRect::MakeWH(100.f, 100.f));
switch (filter_type) {
case PaintFilter::Type::kNullFilter:
NOTREACHED();
return nullptr;
case PaintFilter::Type::kColorFilter:
return sk_make_sp<ColorFilterPaintFilter>(SkLumaColorFilter::Make(),
image_filter, &crop_rect);
case PaintFilter::Type::kBlur:
return sk_make_sp<BlurPaintFilter>(0.1f, 0.2f,
SkBlurImageFilter::kClamp_TileMode,
record_filter, &crop_rect);
case PaintFilter::Type::kDropShadow:
return sk_make_sp<DropShadowPaintFilter>(
0.1, 0.2f, 0.3f, 0.4f, SK_ColorWHITE,
SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode, image_filter,
&crop_rect);
case PaintFilter::Type::kMagnifier:
return sk_make_sp<MagnifierPaintFilter>(SkRect::MakeWH(100.f, 100.f),
0.1f, record_filter, &crop_rect);
case PaintFilter::Type::kCompose:
return sk_make_sp<ComposePaintFilter>(image_filter, record_filter);
case PaintFilter::Type::kAlphaThreshold:
return sk_make_sp<AlphaThresholdPaintFilter>(
SkRegion(SkIRect::MakeWH(100, 100)), 0.1f, 0.2f, image_filter,
&crop_rect);
case PaintFilter::Type::kXfermode:
return sk_make_sp<XfermodePaintFilter>(SkBlendMode::kSrc, image_filter,
record_filter, &crop_rect);
case PaintFilter::Type::kArithmetic:
return sk_make_sp<ArithmeticPaintFilter>(0.1f, 0.2f, 0.3f, 0.4f, true,
image_filter, record_filter,
&crop_rect);
case PaintFilter::Type::kMatrixConvolution: {
SkScalar scalars[9] = {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f};
return sk_make_sp<MatrixConvolutionPaintFilter>(
SkISize::Make(3, 3), scalars, 0.1f, 0.2f, SkIPoint::Make(2, 2),
SkMatrixConvolutionImageFilter::TileMode::kRepeat_TileMode, false,
image_filter, &crop_rect);
}
case PaintFilter::Type::kDisplacementMapEffect:
return sk_make_sp<DisplacementMapEffectPaintFilter>(
SkDisplacementMapEffect::ChannelSelectorType::kR_ChannelSelectorType,
SkDisplacementMapEffect::ChannelSelectorType::kR_ChannelSelectorType,
0.1f, image_filter, record_filter, &crop_rect);
case PaintFilter::Type::kImage:
return image_filter;
case PaintFilter::Type::kPaintRecord:
return record_filter;
case PaintFilter::Type::kMerge: {
sk_sp<PaintFilter> filters[2] = {image_filter, record_filter};
return sk_make_sp<MergePaintFilter>(filters, 2, &crop_rect);
}
case PaintFilter::Type::kMorphology:
return sk_make_sp<MorphologyPaintFilter>(
MorphologyPaintFilter::MorphType::kDilate, 1, 2, image_filter,
&crop_rect);
case PaintFilter::Type::kOffset:
return sk_make_sp<OffsetPaintFilter>(0.1f, 0.2f, image_filter,
&crop_rect);
case PaintFilter::Type::kTile:
return sk_make_sp<TilePaintFilter>(SkRect::MakeWH(100.f, 100.f),
SkRect::MakeWH(200.f, 200.f),
record_filter);
case PaintFilter::Type::kTurbulence:
return sk_make_sp<TurbulencePaintFilter>(
TurbulencePaintFilter::TurbulenceType::kTurbulence, 0.1f, 0.2f, 2,
0.3f, nullptr, &crop_rect);
case PaintFilter::Type::kPaintFlags: {
PaintFlags flags;
flags.setShader(PaintShader::MakeImage(image, SkTileMode::kClamp,
SkTileMode::kClamp, nullptr));
return sk_make_sp<PaintFlagsPaintFilter>(flags, &crop_rect);
}
case PaintFilter::Type::kMatrix:
return sk_make_sp<MatrixPaintFilter>(SkMatrix::I(), kNone_SkFilterQuality,
record_filter);
case PaintFilter::Type::kLightingDistant:
return sk_make_sp<LightingDistantPaintFilter>(
PaintFilter::LightingType::kDiffuse, SkPoint3::Make(0.1f, 0.2f, 0.3f),
SK_ColorWHITE, 0.1f, 0.2f, 0.3f, image_filter, &crop_rect);
case PaintFilter::Type::kLightingPoint:
return sk_make_sp<LightingPointPaintFilter>(
PaintFilter::LightingType::kDiffuse, SkPoint3::Make(0.1f, 0.2f, 0.3f),
SK_ColorWHITE, 0.1f, 0.2f, 0.3f, record_filter, &crop_rect);
case PaintFilter::Type::kLightingSpot:
return sk_make_sp<LightingSpotPaintFilter>(
PaintFilter::LightingType::kDiffuse, SkPoint3::Make(0.1f, 0.2f, 0.3f),
SkPoint3::Make(0.4f, 0.5f, 0.6f), 0.1f, 0.2f, SK_ColorWHITE, 0.4f,
0.5f, 0.6f, image_filter, &crop_rect);
}
NOTREACHED();
return nullptr;
}
} // namespace
class PaintFilterTest : public ::testing::TestWithParam<uint8_t> {
public:
PaintFilter::Type GetParamType() const {
return static_cast<PaintFilter::Type>(GetParam());
}
};
INSTANTIATE_TEST_SUITE_P(
P,
PaintFilterTest,
::testing::Range(static_cast<uint8_t>(PaintFilter::Type::kColorFilter),
static_cast<uint8_t>(PaintFilter::Type::kMaxFilterType)));
TEST_P(PaintFilterTest, HasDiscardableImagesYes) {
// TurbulencePaintFilter can not embed images.
if (GetParamType() == PaintFilter::Type::kTurbulence)
return;
EXPECT_TRUE(CreateTestFilter(GetParamType(), true)->has_discardable_images())
<< PaintFilter::TypeToString(GetParamType());
}
TEST_P(PaintFilterTest, HasDiscardableImagesNo) {
EXPECT_FALSE(
CreateTestFilter(GetParamType(), false)->has_discardable_images())
<< PaintFilter::TypeToString(GetParamType());
}
TEST_P(PaintFilterTest, SnapshotWithImages) {
auto filter = CreateTestFilter(GetParamType(), true);
MockImageProvider image_provider;
auto snapshot_filter = filter->SnapshotWithImages(&image_provider);
if (GetParamType() != PaintFilter::Type::kTurbulence) {
// TurbulencePaintFilter can not embed images.
EXPECT_GT(image_provider.image_count_, 0)
<< PaintFilter::TypeToString(GetParamType());
}
EXPECT_EQ(*filter, *snapshot_filter)
<< PaintFilter::TypeToString(GetParamType());
}
TEST(PaintFilterTest, ImageAnalysisState) {
auto filter = CreateTestFilter(PaintFilter::Type::kImage, true);
EXPECT_EQ(filter->image_analysis_state(), ImageAnalysisState::kNoAnalysis);
filter->set_has_animated_images(true);
EXPECT_EQ(filter->image_analysis_state(),
ImageAnalysisState::kAnimatedImages);
filter->set_has_animated_images(false);
EXPECT_EQ(filter->image_analysis_state(),
ImageAnalysisState::kNoAnimatedImages);
}
} // namespace cc