blob: dd284e9074e4a8342e25becdff069254fe5fe902 [file] [log] [blame]
senorblanco@chromium.org194d7752013-07-24 22:19:24 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkBitmap.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkImage.h"
11#include "include/core/SkPicture.h"
12#include "include/core/SkPictureRecorder.h"
13#include "include/core/SkPoint3.h"
14#include "include/core/SkRect.h"
15#include "include/core/SkSurface.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "include/effects/SkColorMatrixFilter.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "include/effects/SkGradientShader.h"
Michael Ludwig55edb502019-08-05 10:41:10 -040018#include "include/effects/SkImageFilters.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "include/effects/SkPerlinNoiseShader.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "include/effects/SkTableColorFilter.h"
Michael Ludwig8ee6cf32019-08-02 09:57:04 -040021#include "src/core/SkImageFilter_Base.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050022#include "src/core/SkReadBuffer.h"
23#include "src/core/SkSpecialImage.h"
24#include "src/core/SkSpecialSurface.h"
25#include "tests/Test.h"
26#include "tools/Resources.h"
27#include "tools/ToolUtils.h"
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000028
Mike Kleinc0bd9f92019-04-23 12:05:21 -050029#include "include/gpu/GrContext.h"
30#include "src/gpu/GrCaps.h"
31#include "src/gpu/GrContextPriv.h"
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +000032
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +000033static const int kBitmapSize = 4;
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +000034
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000035namespace {
36
Michael Ludwig8ee6cf32019-08-02 09:57:04 -040037class MatrixTestImageFilter : public SkImageFilter_Base {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000038public:
robertphillips43c2ad42016-04-04 05:05:11 -070039 static sk_sp<SkImageFilter> Make(skiatest::Reporter* reporter,
40 const SkMatrix& expectedMatrix) {
41 return sk_sp<SkImageFilter>(new MatrixTestImageFilter(reporter, expectedMatrix));
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000042 }
43
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000044protected:
Michael Ludwige30a4852019-08-14 14:35:42 -040045 sk_sp<SkSpecialImage> onFilterImage(const Context& ctx, SkIPoint* offset) const override {
robertphillips43c2ad42016-04-04 05:05:11 -070046 REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
robertphillips4ba94e22016-04-04 12:07:47 -070047 offset->fX = offset->fY = 0;
Michael Ludwige30a4852019-08-14 14:35:42 -040048 return sk_ref_sp<SkSpecialImage>(ctx.sourceImage());
robertphillips43c2ad42016-04-04 05:05:11 -070049 }
50
mtklein36352bf2015-03-25 18:17:31 -070051 void flatten(SkWriteBuffer& buffer) const override {
brianosman18f13f32016-05-02 07:51:08 -070052 SkDEBUGFAIL("Should never get here");
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000053 }
54
55private:
Mike Klein4fee3232018-10-18 17:27:16 -040056 SK_FLATTENABLE_HOOKS(MatrixTestImageFilter)
57
robertphillips43c2ad42016-04-04 05:05:11 -070058 MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
59 : INHERITED(nullptr, 0, nullptr)
60 , fReporter(reporter)
61 , fExpectedMatrix(expectedMatrix) {
62 }
63
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000064 skiatest::Reporter* fReporter;
65 SkMatrix fExpectedMatrix;
mtklein3f3b3d02014-12-01 11:47:08 -080066
Michael Ludwig8ee6cf32019-08-02 09:57:04 -040067 typedef SkImageFilter_Base INHERITED;
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000068};
69
Michael Ludwig8ee6cf32019-08-02 09:57:04 -040070class FailImageFilter : public SkImageFilter_Base {
senorblanco6a93fa12016-04-05 04:43:45 -070071public:
Michael Ludwig8ee6cf32019-08-02 09:57:04 -040072 FailImageFilter() : INHERITED(nullptr, 0, nullptr) { }
senorblanco6a93fa12016-04-05 04:43:45 -070073
Michael Ludwige30a4852019-08-14 14:35:42 -040074 sk_sp<SkSpecialImage> onFilterImage(const Context& ctx, SkIPoint* offset) const override {
senorblanco6a93fa12016-04-05 04:43:45 -070075 return nullptr;
76 }
77
Mike Klein4fee3232018-10-18 17:27:16 -040078 SK_FLATTENABLE_HOOKS(FailImageFilter)
senorblanco6a93fa12016-04-05 04:43:45 -070079
80private:
Michael Ludwig8ee6cf32019-08-02 09:57:04 -040081 typedef SkImageFilter_Base INHERITED;
senorblanco6a93fa12016-04-05 04:43:45 -070082};
83
84sk_sp<SkFlattenable> FailImageFilter::CreateProc(SkReadBuffer& buffer) {
85 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
86 return sk_sp<SkFlattenable>(new FailImageFilter());
87}
88
senorblanco297f7ce2016-03-23 13:44:26 -070089void draw_gradient_circle(SkCanvas* canvas, int width, int height) {
90 SkScalar x = SkIntToScalar(width / 2);
91 SkScalar y = SkIntToScalar(height / 2);
92 SkScalar radius = SkMinScalar(x, y) * 0.8f;
93 canvas->clear(0x00000000);
94 SkColor colors[2];
95 colors[0] = SK_ColorWHITE;
96 colors[1] = SK_ColorBLACK;
97 sk_sp<SkShader> shader(
98 SkGradientShader::MakeRadial(SkPoint::Make(x, y), radius, colors, nullptr, 2,
Mike Reedfae8fce2019-04-03 10:27:45 -040099 SkTileMode::kClamp)
senorblanco297f7ce2016-03-23 13:44:26 -0700100 );
101 SkPaint paint;
102 paint.setShader(shader);
103 canvas->drawCircle(x, y, radius, paint);
104}
105
106SkBitmap make_gradient_circle(int width, int height) {
107 SkBitmap bitmap;
108 bitmap.allocN32Pixels(width, height);
109 SkCanvas canvas(bitmap);
110 draw_gradient_circle(&canvas, width, height);
111 return bitmap;
112}
113
114class FilterList {
115public:
Michael Ludwig55edb502019-08-05 10:41:10 -0400116 FilterList(sk_sp<SkImageFilter> input, const SkIRect* cropRect = nullptr) {
117 static const SkScalar kBlurSigma = SkIntToScalar(5);
118
senorblanco297f7ce2016-03-23 13:44:26 -0700119 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
robertphillips6e7025a2016-04-04 04:31:25 -0700120 {
Michael Ludwig55edb502019-08-05 10:41:10 -0400121 sk_sp<SkColorFilter> cf(SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcIn));
senorblanco297f7ce2016-03-23 13:44:26 -0700122
robertphillips6e7025a2016-04-04 04:31:25 -0700123 this->addFilter("color filter",
Michael Ludwig55edb502019-08-05 10:41:10 -0400124 SkImageFilters::ColorFilter(std::move(cf), input, cropRect));
robertphillips6e7025a2016-04-04 04:31:25 -0700125 }
robertphillips6e7025a2016-04-04 04:31:25 -0700126 {
127 sk_sp<SkImage> gradientImage(SkImage::MakeFromBitmap(make_gradient_circle(64, 64)));
Michael Ludwig55edb502019-08-05 10:41:10 -0400128 sk_sp<SkImageFilter> gradientSource(SkImageFilters::Image(std::move(gradientImage)));
senorblanco297f7ce2016-03-23 13:44:26 -0700129
liyuqianbfebe222016-11-14 11:17:16 -0800130 this->addFilter("displacement map",
Michael Ludwig55edb502019-08-05 10:41:10 -0400131 SkImageFilters::DisplacementMap(SkColorChannel::kR, SkColorChannel::kB, 20.0f,
132 std::move(gradientSource), input, cropRect));
robertphillips6e7025a2016-04-04 04:31:25 -0700133 }
Michael Ludwig55edb502019-08-05 10:41:10 -0400134 this->addFilter("blur", SkImageFilters::Blur(SK_Scalar1, SK_Scalar1, input, cropRect));
135 this->addFilter("drop shadow", SkImageFilters::DropShadow(
136 SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input, cropRect));
robertphillips12fa47d2016-04-08 16:28:09 -0700137 this->addFilter("diffuse lighting",
Michael Ludwig55edb502019-08-05 10:41:10 -0400138 SkImageFilters::PointLitDiffuse(location, SK_ColorGREEN, 0, 0, input, cropRect));
senorblanco297f7ce2016-03-23 13:44:26 -0700139 this->addFilter("specular lighting",
Michael Ludwig55edb502019-08-05 10:41:10 -0400140 SkImageFilters::PointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input,
141 cropRect));
robertphillips12fa47d2016-04-08 16:28:09 -0700142 {
143 SkScalar kernel[9] = {
144 SkIntToScalar(1), SkIntToScalar(1), SkIntToScalar(1),
145 SkIntToScalar(1), SkIntToScalar(-7), SkIntToScalar(1),
146 SkIntToScalar(1), SkIntToScalar(1), SkIntToScalar(1),
147 };
148 const SkISize kernelSize = SkISize::Make(3, 3);
149 const SkScalar gain = SK_Scalar1, bias = 0;
150
Robert Phillips12078432018-05-17 11:17:39 -0400151 // This filter needs a saveLayer bc it is in repeat mode
robertphillips12fa47d2016-04-08 16:28:09 -0700152 this->addFilter("matrix convolution",
Michael Ludwig55edb502019-08-05 10:41:10 -0400153 SkImageFilters::MatrixConvolution(
154 kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
155 SkTileMode::kRepeat, false, input, cropRect),
Robert Phillips12078432018-05-17 11:17:39 -0400156 true);
robertphillips12fa47d2016-04-08 16:28:09 -0700157 }
Michael Ludwig55edb502019-08-05 10:41:10 -0400158 this->addFilter("merge", SkImageFilters::Merge(input, input, cropRect));
robertphillips12fa47d2016-04-08 16:28:09 -0700159
robertphillips6e7025a2016-04-04 04:31:25 -0700160 {
161 SkPaint greenColorShaderPaint;
Mike Reedc8bea7d2019-04-09 13:55:36 -0400162 greenColorShaderPaint.setShader(SkShaders::Color(SK_ColorGREEN));
robertphillips6e7025a2016-04-04 04:31:25 -0700163
Michael Ludwig55edb502019-08-05 10:41:10 -0400164 SkIRect leftSideCropRect = SkIRect::MakeXYWH(0, 0, 32, 64);
165 sk_sp<SkImageFilter> paintFilterLeft(SkImageFilters::Paint(greenColorShaderPaint,
166 &leftSideCropRect));
167 SkIRect rightSideCropRect = SkIRect::MakeXYWH(32, 0, 32, 64);
168 sk_sp<SkImageFilter> paintFilterRight(SkImageFilters::Paint(greenColorShaderPaint,
169 &rightSideCropRect));
robertphillips6e7025a2016-04-04 04:31:25 -0700170
171
Michael Ludwig55edb502019-08-05 10:41:10 -0400172 this->addFilter("merge with disjoint inputs", SkImageFilters::Merge(
173 std::move(paintFilterLeft), std::move(paintFilterRight), cropRect));
robertphillips6e7025a2016-04-04 04:31:25 -0700174 }
175
Michael Ludwig55edb502019-08-05 10:41:10 -0400176 this->addFilter("offset", SkImageFilters::Offset(SK_Scalar1, SK_Scalar1, input, cropRect));
177 this->addFilter("dilate", SkImageFilters::Dilate(3, 2, input, cropRect));
178 this->addFilter("erode", SkImageFilters::Erode(2, 3, input, cropRect));
179 this->addFilter("tile", SkImageFilters::Tile(SkRect::MakeXYWH(0, 0, 50, 50),
180 cropRect ? SkRect::Make(*cropRect)
181 : SkRect::MakeXYWH(0, 0, 100, 100),
182 input));
robertphillips6e7025a2016-04-04 04:31:25 -0700183
robertphillips12fa47d2016-04-08 16:28:09 -0700184 if (!cropRect) {
185 SkMatrix matrix;
186
187 matrix.setTranslate(SK_Scalar1, SK_Scalar1);
188 matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
189
190 this->addFilter("matrix",
Michael Ludwig55edb502019-08-05 10:41:10 -0400191 SkImageFilters::MatrixTransform(matrix, kLow_SkFilterQuality, input));
robertphillips12fa47d2016-04-08 16:28:09 -0700192 }
robertphillips6e7025a2016-04-04 04:31:25 -0700193 {
Michael Ludwig55edb502019-08-05 10:41:10 -0400194 sk_sp<SkImageFilter> blur(SkImageFilters::Blur(kBlurSigma, kBlurSigma, input));
robertphillips6e7025a2016-04-04 04:31:25 -0700195
Michael Ludwig55edb502019-08-05 10:41:10 -0400196 this->addFilter("blur and offset", SkImageFilters::Offset(
197 kBlurSigma, kBlurSigma, std::move(blur), cropRect));
robertphillips6e7025a2016-04-04 04:31:25 -0700198 }
199 {
robertphillips6e7025a2016-04-04 04:31:25 -0700200 SkPictureRecorder recorder;
Mike Klein26eb16f2017-04-10 09:50:25 -0400201 SkCanvas* recordingCanvas = recorder.beginRecording(64, 64);
robertphillips6e7025a2016-04-04 04:31:25 -0700202
203 SkPaint greenPaint;
204 greenPaint.setColor(SK_ColorGREEN);
205 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
206 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
Michael Ludwig55edb502019-08-05 10:41:10 -0400207 sk_sp<SkImageFilter> pictureFilter(SkImageFilters::Picture(std::move(picture)));
robertphillips6e7025a2016-04-04 04:31:25 -0700208
Michael Ludwig55edb502019-08-05 10:41:10 -0400209 this->addFilter("picture and blur", SkImageFilters::Blur(
210 kBlurSigma, kBlurSigma, std::move(pictureFilter), cropRect));
robertphillips6e7025a2016-04-04 04:31:25 -0700211 }
212 {
213 SkPaint paint;
214 paint.setShader(SkPerlinNoiseShader::MakeTurbulence(SK_Scalar1, SK_Scalar1, 1, 0));
Michael Ludwig55edb502019-08-05 10:41:10 -0400215 sk_sp<SkImageFilter> paintFilter(SkImageFilters::Paint(paint));
robertphillips6e7025a2016-04-04 04:31:25 -0700216
Michael Ludwig55edb502019-08-05 10:41:10 -0400217 this->addFilter("paint and blur", SkImageFilters::Blur(
218 kBlurSigma, kBlurSigma, std::move(paintFilter), cropRect));
robertphillips6e7025a2016-04-04 04:31:25 -0700219 }
Michael Ludwig55edb502019-08-05 10:41:10 -0400220 this->addFilter("xfermode", SkImageFilters::Xfermode(
221 SkBlendMode::kSrc, input, input, cropRect));
senorblanco297f7ce2016-03-23 13:44:26 -0700222 }
223 int count() const { return fFilters.count(); }
224 SkImageFilter* getFilter(int index) const { return fFilters[index].fFilter.get(); }
225 const char* getName(int index) const { return fFilters[index].fName; }
Robert Phillips12078432018-05-17 11:17:39 -0400226 bool needsSaveLayer(int index) const { return fFilters[index].fNeedsSaveLayer; }
senorblanco297f7ce2016-03-23 13:44:26 -0700227private:
228 struct Filter {
Robert Phillips12078432018-05-17 11:17:39 -0400229 Filter() : fName(nullptr), fNeedsSaveLayer(false) {}
230 Filter(const char* name, sk_sp<SkImageFilter> filter, bool needsSaveLayer)
robertphillips12fa47d2016-04-08 16:28:09 -0700231 : fName(name)
Robert Phillips12078432018-05-17 11:17:39 -0400232 , fFilter(std::move(filter))
233 , fNeedsSaveLayer(needsSaveLayer) {
robertphillips12fa47d2016-04-08 16:28:09 -0700234 }
senorblanco297f7ce2016-03-23 13:44:26 -0700235 const char* fName;
236 sk_sp<SkImageFilter> fFilter;
Robert Phillips12078432018-05-17 11:17:39 -0400237 bool fNeedsSaveLayer;
senorblanco297f7ce2016-03-23 13:44:26 -0700238 };
Robert Phillips12078432018-05-17 11:17:39 -0400239 void addFilter(const char* name, sk_sp<SkImageFilter> filter, bool needsSaveLayer = false) {
240 fFilters.push_back(Filter(name, std::move(filter), needsSaveLayer));
senorblanco297f7ce2016-03-23 13:44:26 -0700241 }
242
243 SkTArray<Filter> fFilters;
244};
245
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400246class FixedBoundsImageFilter : public SkImageFilter_Base {
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700247public:
248 FixedBoundsImageFilter(const SkIRect& bounds)
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400249 : INHERITED(nullptr, 0, nullptr), fBounds(bounds) {}
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700250
251private:
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700252 Factory getFactory() const override { return nullptr; }
Mike Klein4fee3232018-10-18 17:27:16 -0400253 const char* getTypeName() const override { return nullptr; }
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700254
Michael Ludwige30a4852019-08-14 14:35:42 -0400255 sk_sp<SkSpecialImage> onFilterImage(const Context&, SkIPoint* offset) const override {
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700256 return nullptr;
257 }
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700258
Robert Phillips12078432018-05-17 11:17:39 -0400259 SkIRect onFilterBounds(const SkIRect&, const SkMatrix&,
260 MapDirection, const SkIRect*) const override {
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700261 return fBounds;
262 }
263
264 SkIRect fBounds;
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400265
266 typedef SkImageFilter_Base INHERITED;
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700267};
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000268}
269
reed60c9b582016-04-03 09:11:13 -0700270sk_sp<SkFlattenable> MatrixTestImageFilter::CreateProc(SkReadBuffer& buffer) {
brianosman18f13f32016-05-02 07:51:08 -0700271 SkDEBUGFAIL("Should never get here");
272 return nullptr;
reed9fa60da2014-08-21 07:59:51 -0700273}
274
reed9ce9d672016-03-17 10:51:11 -0700275static sk_sp<SkImage> make_small_image() {
reede8f30622016-03-23 18:59:25 -0700276 auto surface(SkSurface::MakeRasterN32Premul(kBitmapSize, kBitmapSize));
fmalita5598b632015-09-15 11:26:13 -0700277 SkCanvas* canvas = surface->getCanvas();
278 canvas->clear(0x00000000);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000279 SkPaint darkPaint;
280 darkPaint.setColor(0xFF804020);
281 SkPaint lightPaint;
282 lightPaint.setColor(0xFF244484);
Michael Ludwig55edb502019-08-05 10:41:10 -0400283 const int kRectSize = kBitmapSize / 4;
284 static_assert(kBitmapSize % 4 == 0, "bitmap size not multiple of 4");
285
286 for (int y = 0; y < kBitmapSize; y += kRectSize) {
287 for (int x = 0; x < kBitmapSize; x += kRectSize) {
fmalita5598b632015-09-15 11:26:13 -0700288 canvas->save();
289 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
Michael Ludwig55edb502019-08-05 10:41:10 -0400290 canvas->drawRect(
291 SkRect::MakeXYWH(0, 0, kRectSize, kRectSize), darkPaint);
292 canvas->drawRect(
293 SkRect::MakeXYWH(kRectSize, 0, kRectSize, kRectSize), lightPaint);
294 canvas->drawRect(
295 SkRect::MakeXYWH(0, kRectSize, kRectSize, kRectSize), lightPaint);
296 canvas->drawRect(
297 SkRect::MakeXYWH(kRectSize, kRectSize, kRectSize, kRectSize), darkPaint);
fmalita5598b632015-09-15 11:26:13 -0700298 canvas->restore();
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +0000299 }
300 }
fmalita5598b632015-09-15 11:26:13 -0700301
reed9ce9d672016-03-17 10:51:11 -0700302 return surface->makeImageSnapshot();
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000303}
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000304
robertphillips5605b562016-04-05 11:50:42 -0700305static sk_sp<SkImageFilter> make_scale(float amount, sk_sp<SkImageFilter> input) {
Mike Reede869a1e2019-04-30 12:18:54 -0400306 float s = amount;
307 float matrix[20] = { s, 0, 0, 0, 0,
308 0, s, 0, 0, 0,
309 0, 0, s, 0, 0,
310 0, 0, 0, s, 0 };
311 sk_sp<SkColorFilter> filter(SkColorFilters::Matrix(matrix));
Michael Ludwig55edb502019-08-05 10:41:10 -0400312 return SkImageFilters::ColorFilter(std::move(filter), std::move(input));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000313}
314
robertphillips5605b562016-04-05 11:50:42 -0700315static sk_sp<SkImageFilter> make_grayscale(sk_sp<SkImageFilter> input,
Michael Ludwig55edb502019-08-05 10:41:10 -0400316 const SkIRect* cropRect) {
Mike Reede869a1e2019-04-30 12:18:54 -0400317 float matrix[20];
318 memset(matrix, 0, 20 * sizeof(float));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000319 matrix[0] = matrix[5] = matrix[10] = 0.2126f;
320 matrix[1] = matrix[6] = matrix[11] = 0.7152f;
321 matrix[2] = matrix[7] = matrix[12] = 0.0722f;
322 matrix[18] = 1.0f;
Mike Reede869a1e2019-04-30 12:18:54 -0400323 sk_sp<SkColorFilter> filter(SkColorFilters::Matrix(matrix));
Michael Ludwig55edb502019-08-05 10:41:10 -0400324 return SkImageFilters::ColorFilter(std::move(filter), std::move(input), cropRect);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000325}
326
Michael Ludwig55edb502019-08-05 10:41:10 -0400327static sk_sp<SkImageFilter> make_blue(sk_sp<SkImageFilter> input, const SkIRect* cropRect) {
Mike Reedb286bc22019-04-08 16:23:20 -0400328 sk_sp<SkColorFilter> filter(SkColorFilters::Blend(SK_ColorBLUE, SkBlendMode::kSrcIn));
Michael Ludwig55edb502019-08-05 10:41:10 -0400329 return SkImageFilters::ColorFilter(std::move(filter), std::move(input), cropRect);
reedcedc36f2015-03-08 04:42:52 -0700330}
331
robertphillips3e302272016-04-20 11:48:36 -0700332static sk_sp<SkSpecialSurface> create_empty_special_surface(GrContext* context, int widthHeight) {
robertphillips4418dba2016-03-07 12:45:14 -0800333 if (context) {
Brian Salomon27ae52c2019-07-03 11:27:44 -0400334 return SkSpecialSurface::MakeRenderTarget(context, widthHeight, widthHeight,
335 GrColorType::kRGBA_8888, nullptr);
Brian Osmanc7ad40f2018-05-31 14:27:17 -0400336 } else {
robertphillips4418dba2016-03-07 12:45:14 -0800337 const SkImageInfo info = SkImageInfo::MakeN32(widthHeight, widthHeight,
338 kOpaque_SkAlphaType);
robertphillips3e302272016-04-20 11:48:36 -0700339 return SkSpecialSurface::MakeRaster(info);
robertphillips4418dba2016-03-07 12:45:14 -0800340 }
senorblancobf680c32016-03-16 16:15:53 -0700341}
342
senorblanco5878dbd2016-05-19 14:50:29 -0700343static sk_sp<SkSurface> create_surface(GrContext* context, int width, int height) {
344 const SkImageInfo info = SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType);
senorblanco5878dbd2016-05-19 14:50:29 -0700345 if (context) {
346 return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
Brian Osmanc7ad40f2018-05-31 14:27:17 -0400347 } else {
senorblanco5878dbd2016-05-19 14:50:29 -0700348 return SkSurface::MakeRaster(info);
349 }
350}
351
robertphillips3e302272016-04-20 11:48:36 -0700352static sk_sp<SkSpecialImage> create_empty_special_image(GrContext* context, int widthHeight) {
353 sk_sp<SkSpecialSurface> surf(create_empty_special_surface(context, widthHeight));
robertphillips4418dba2016-03-07 12:45:14 -0800354
355 SkASSERT(surf);
356
357 SkCanvas* canvas = surf->getCanvas();
358 SkASSERT(canvas);
359
360 canvas->clear(0x0);
361
robertphillips37bd7c32016-03-17 14:31:39 -0700362 return surf->makeImageSnapshot();
robertphillips4418dba2016-03-07 12:45:14 -0800363}
364
365
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000366DEF_TEST(ImageFilter, reporter) {
367 {
Mike Kleindadac552019-03-12 10:01:28 -0500368 // Check that a color matrix filter followed by a color matrix filter
369 // concatenates into a single filter.
robertphillips5605b562016-04-05 11:50:42 -0700370 sk_sp<SkImageFilter> doubleBrightness(make_scale(2.0f, nullptr));
371 sk_sp<SkImageFilter> halfBrightness(make_scale(0.5f, std::move(doubleBrightness)));
halcanary96fcdcc2015-08-27 07:41:13 -0700372 REPORTER_ASSERT(reporter, nullptr == halfBrightness->getInput(0));
reedcedc36f2015-03-08 04:42:52 -0700373 SkColorFilter* cf;
374 REPORTER_ASSERT(reporter, halfBrightness->asColorFilter(&cf));
reedcedc36f2015-03-08 04:42:52 -0700375 cf->unref();
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000376 }
377
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000378 {
379 // Check that a color filter image filter without a crop rect can be
380 // expressed as a color filter.
robertphillips5605b562016-04-05 11:50:42 -0700381 sk_sp<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
halcanary96fcdcc2015-08-27 07:41:13 -0700382 REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000383 }
mtklein2afbe232016-02-07 12:23:10 -0800384
reedcedc36f2015-03-08 04:42:52 -0700385 {
386 // Check that a colorfilterimage filter without a crop rect but with an input
387 // that is another colorfilterimage can be expressed as a colorfilter (composed).
robertphillips5605b562016-04-05 11:50:42 -0700388 sk_sp<SkImageFilter> mode(make_blue(nullptr, nullptr));
389 sk_sp<SkImageFilter> gray(make_grayscale(std::move(mode), nullptr));
halcanary96fcdcc2015-08-27 07:41:13 -0700390 REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
reedcedc36f2015-03-08 04:42:52 -0700391 }
392
393 {
394 // Test that if we exceed the limit of what ComposeColorFilter can combine, we still
395 // can build the DAG and won't assert if we call asColorFilter.
robertphillips5605b562016-04-05 11:50:42 -0700396 sk_sp<SkImageFilter> filter(make_blue(nullptr, nullptr));
reedcedc36f2015-03-08 04:42:52 -0700397 const int kWayTooManyForComposeColorFilter = 100;
398 for (int i = 0; i < kWayTooManyForComposeColorFilter; ++i) {
robertphillips5605b562016-04-05 11:50:42 -0700399 filter = make_blue(filter, nullptr);
reedcedc36f2015-03-08 04:42:52 -0700400 // the first few of these will succeed, but after we hit the internal limit,
401 // it will then return false.
halcanary96fcdcc2015-08-27 07:41:13 -0700402 (void)filter->asColorFilter(nullptr);
reedcedc36f2015-03-08 04:42:52 -0700403 }
404 }
reed5c518a82015-03-05 14:47:29 -0800405
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000406 {
407 // Check that a color filter image filter with a crop rect cannot
408 // be expressed as a color filter.
Michael Ludwig55edb502019-08-05 10:41:10 -0400409 SkIRect cropRect = SkIRect::MakeWH(100, 100);
robertphillips5605b562016-04-05 11:50:42 -0700410 sk_sp<SkImageFilter> grayWithCrop(make_grayscale(nullptr, &cropRect));
halcanary96fcdcc2015-08-27 07:41:13 -0700411 REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(nullptr));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000412 }
413
414 {
senorblanco3df05012014-07-03 11:13:09 -0700415 // Check that two non-commutative matrices are concatenated in
416 // the correct order.
Mike Reede869a1e2019-04-30 12:18:54 -0400417 float blueToRedMatrix[20] = { 0 };
418 blueToRedMatrix[2] = blueToRedMatrix[18] = 1;
419 float redToGreenMatrix[20] = { 0 };
420 redToGreenMatrix[5] = redToGreenMatrix[18] = 1;
421 sk_sp<SkColorFilter> blueToRed(SkColorFilters::Matrix(blueToRedMatrix));
Michael Ludwig55edb502019-08-05 10:41:10 -0400422 sk_sp<SkImageFilter> filter1(SkImageFilters::ColorFilter(std::move(blueToRed), nullptr));
Mike Reede869a1e2019-04-30 12:18:54 -0400423 sk_sp<SkColorFilter> redToGreen(SkColorFilters::Matrix(redToGreenMatrix));
Michael Ludwig55edb502019-08-05 10:41:10 -0400424 sk_sp<SkImageFilter> filter2(SkImageFilters::ColorFilter(std::move(redToGreen),
425 std::move(filter1)));
senorblanco3df05012014-07-03 11:13:09 -0700426
427 SkBitmap result;
428 result.allocN32Pixels(kBitmapSize, kBitmapSize);
429
430 SkPaint paint;
431 paint.setColor(SK_ColorBLUE);
robertphillips5605b562016-04-05 11:50:42 -0700432 paint.setImageFilter(std::move(filter2));
senorblanco3df05012014-07-03 11:13:09 -0700433 SkCanvas canvas(result);
434 canvas.clear(0x0);
435 SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
436 canvas.drawRect(rect, paint);
437 uint32_t pixel = *result.getAddr32(0, 0);
438 // The result here should be green, since we have effectively shifted blue to green.
439 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
440 }
441
442 {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000443 // Tests pass by not asserting
reed9ce9d672016-03-17 10:51:11 -0700444 sk_sp<SkImage> image(make_small_image());
fmalita5598b632015-09-15 11:26:13 -0700445 SkBitmap result;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000446 result.allocN32Pixels(kBitmapSize, kBitmapSize);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000447
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000448 {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000449 // This tests for :
450 // 1 ) location at (0,0,1)
robertphillips3d32d762015-07-13 13:16:44 -0700451 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000452 // 2 ) location and target at same value
robertphillips3d32d762015-07-13 13:16:44 -0700453 SkPoint3 target = SkPoint3::Make(location.fX, location.fY, location.fZ);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000454 // 3 ) large negative specular exponent value
455 SkScalar specularExponent = -1000;
456
Michael Ludwig55edb502019-08-05 10:41:10 -0400457 sk_sp<SkImageFilter> bmSrc(SkImageFilters::Image(std::move(image)));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000458 SkPaint paint;
Michael Ludwig55edb502019-08-05 10:41:10 -0400459 paint.setImageFilter(SkImageFilters::SpotLitSpecular(
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000460 location, target, specularExponent, 180,
461 0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
robertphillips12fa47d2016-04-08 16:28:09 -0700462 std::move(bmSrc)));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000463 SkCanvas canvas(result);
Michael Ludwig55edb502019-08-05 10:41:10 -0400464 SkRect r = SkRect::MakeIWH(kBitmapSize, kBitmapSize);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000465 canvas.drawRect(r, paint);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000466 }
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000467 }
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000468}
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000469
Michael Ludwig55edb502019-08-05 10:41:10 -0400470static void test_cropRects(skiatest::Reporter* reporter, GrContext* context) {
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000471 // Check that all filters offset to their absolute crop rect,
472 // unaffected by the input crop rect.
473 // Tests pass by not asserting.
robertphillips3e302272016-04-20 11:48:36 -0700474 sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 100));
robertphillips4418dba2016-03-07 12:45:14 -0800475 SkASSERT(srcImg);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000476
Michael Ludwig55edb502019-08-05 10:41:10 -0400477 SkIRect inputCropRect = SkIRect::MakeXYWH(8, 13, 80, 80);
478 SkIRect cropRect = SkIRect::MakeXYWH(20, 30, 60, 60);
robertphillipsfc11b0a2016-04-05 09:09:36 -0700479 sk_sp<SkImageFilter> input(make_grayscale(nullptr, &inputCropRect));
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000480
robertphillipsfc11b0a2016-04-05 09:09:36 -0700481 FilterList filters(input, &cropRect);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000482
senorblanco297f7ce2016-03-23 13:44:26 -0700483 for (int i = 0; i < filters.count(); ++i) {
484 SkImageFilter* filter = filters.getFilter(i);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000485 SkIPoint offset;
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400486 SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -0400487 kN32_SkColorType, nullptr, srcImg.get());
Michael Ludwigea071232019-08-26 10:52:15 -0400488 sk_sp<SkSpecialImage> resultImg(as_IFB(filter)->filterImage(ctx).imageAndOffset(&offset));
Brian Salomon1c80e992018-01-29 09:50:47 -0500489 REPORTER_ASSERT(reporter, resultImg, filters.getName(i));
490 REPORTER_ASSERT(reporter, offset.fX == 20 && offset.fY == 30, filters.getName(i));
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000491 }
492}
493
Michael Ludwig55edb502019-08-05 10:41:10 -0400494static void test_negative_blur_sigma(skiatest::Reporter* reporter, GrContext* context) {
senorblanco32673b92014-09-09 09:15:04 -0700495 // Check that SkBlurImageFilter will accept a negative sigma, either in
496 // the given arguments or after CTM application.
Michael Ludwig55edb502019-08-05 10:41:10 -0400497 static const int kWidth = 32, kHeight = 32;
498 static const SkScalar kBlurSigma = SkIntToScalar(5);
senorblanco32673b92014-09-09 09:15:04 -0700499
Michael Ludwig55edb502019-08-05 10:41:10 -0400500 sk_sp<SkImageFilter> positiveFilter(SkImageFilters::Blur(kBlurSigma, kBlurSigma, nullptr));
501 sk_sp<SkImageFilter> negativeFilter(SkImageFilters::Blur(-kBlurSigma, kBlurSigma, nullptr));
senorblanco32673b92014-09-09 09:15:04 -0700502
Michael Ludwig55edb502019-08-05 10:41:10 -0400503 SkBitmap gradient = make_gradient_circle(kWidth, kHeight);
504 sk_sp<SkSpecialImage> imgSrc(SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(kWidth, kHeight),
robertphillips37bd7c32016-03-17 14:31:39 -0700505 gradient));
robertphillips4418dba2016-03-07 12:45:14 -0800506
senorblanco32673b92014-09-09 09:15:04 -0700507 SkIPoint offset;
Michael Ludwig03f9ca32019-08-14 14:35:15 -0400508 SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -0400509 kN32_SkColorType, nullptr, imgSrc.get());
robertphillips4418dba2016-03-07 12:45:14 -0800510
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400511 sk_sp<SkSpecialImage> positiveResult1(
Michael Ludwigea071232019-08-26 10:52:15 -0400512 as_IFB(positiveFilter)->filterImage(ctx).imageAndOffset(&offset));
robertphillips4418dba2016-03-07 12:45:14 -0800513 REPORTER_ASSERT(reporter, positiveResult1);
514
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400515 sk_sp<SkSpecialImage> negativeResult1(
Michael Ludwigea071232019-08-26 10:52:15 -0400516 as_IFB(negativeFilter)->filterImage(ctx).imageAndOffset(&offset));
robertphillips4418dba2016-03-07 12:45:14 -0800517 REPORTER_ASSERT(reporter, negativeResult1);
518
senorblanco32673b92014-09-09 09:15:04 -0700519 SkMatrix negativeScale;
520 negativeScale.setScale(-SK_Scalar1, SK_Scalar1);
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400521 SkImageFilter_Base::Context negativeCTX(negativeScale, SkIRect::MakeWH(32, 32), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -0400522 kN32_SkColorType, nullptr, imgSrc.get());
robertphillips4418dba2016-03-07 12:45:14 -0800523
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400524 sk_sp<SkSpecialImage> negativeResult2(
Michael Ludwigea071232019-08-26 10:52:15 -0400525 as_IFB(positiveFilter)->filterImage(negativeCTX).imageAndOffset(&offset));
robertphillips4418dba2016-03-07 12:45:14 -0800526 REPORTER_ASSERT(reporter, negativeResult2);
527
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400528 sk_sp<SkSpecialImage> positiveResult2(
Michael Ludwigea071232019-08-26 10:52:15 -0400529 as_IFB(negativeFilter)->filterImage(negativeCTX).imageAndOffset(&offset));
robertphillips4418dba2016-03-07 12:45:14 -0800530 REPORTER_ASSERT(reporter, positiveResult2);
531
532
533 SkBitmap positiveResultBM1, positiveResultBM2;
534 SkBitmap negativeResultBM1, negativeResultBM2;
535
robertphillips64612512016-04-08 12:10:42 -0700536 REPORTER_ASSERT(reporter, positiveResult1->getROPixels(&positiveResultBM1));
537 REPORTER_ASSERT(reporter, positiveResult2->getROPixels(&positiveResultBM2));
538 REPORTER_ASSERT(reporter, negativeResult1->getROPixels(&negativeResultBM1));
539 REPORTER_ASSERT(reporter, negativeResult2->getROPixels(&negativeResultBM2));
robertphillips4418dba2016-03-07 12:45:14 -0800540
Michael Ludwig55edb502019-08-05 10:41:10 -0400541 for (int y = 0; y < kHeight; y++) {
robertphillips4418dba2016-03-07 12:45:14 -0800542 int diffs = memcmp(positiveResultBM1.getAddr32(0, y),
543 negativeResultBM1.getAddr32(0, y),
544 positiveResultBM1.rowBytes());
senorblanco32673b92014-09-09 09:15:04 -0700545 REPORTER_ASSERT(reporter, !diffs);
546 if (diffs) {
547 break;
548 }
robertphillips4418dba2016-03-07 12:45:14 -0800549 diffs = memcmp(positiveResultBM1.getAddr32(0, y),
550 negativeResultBM2.getAddr32(0, y),
551 positiveResultBM1.rowBytes());
senorblanco32673b92014-09-09 09:15:04 -0700552 REPORTER_ASSERT(reporter, !diffs);
553 if (diffs) {
554 break;
555 }
robertphillips4418dba2016-03-07 12:45:14 -0800556 diffs = memcmp(positiveResultBM1.getAddr32(0, y),
557 positiveResultBM2.getAddr32(0, y),
558 positiveResultBM1.rowBytes());
senorblanco32673b92014-09-09 09:15:04 -0700559 REPORTER_ASSERT(reporter, !diffs);
560 if (diffs) {
561 break;
562 }
563 }
564}
565
senorblanco21a465d2016-04-11 11:58:39 -0700566DEF_TEST(ImageFilterNegativeBlurSigma, reporter) {
robertphillips3e302272016-04-20 11:48:36 -0700567 test_negative_blur_sigma(reporter, nullptr);
robertphillips4418dba2016-03-07 12:45:14 -0800568}
569
bsalomon68d91342016-04-12 09:59:58 -0700570DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterNegativeBlurSigma_Gpu, reporter, ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -0700571 test_negative_blur_sigma(reporter, ctxInfo.grContext());
robertphillips4418dba2016-03-07 12:45:14 -0800572}
robertphillips4418dba2016-03-07 12:45:14 -0800573
robertphillips3e302272016-04-20 11:48:36 -0700574static void test_zero_blur_sigma(skiatest::Reporter* reporter, GrContext* context) {
senorblancobf680c32016-03-16 16:15:53 -0700575 // Check that SkBlurImageFilter with a zero sigma and a non-zero srcOffset works correctly.
Michael Ludwig55edb502019-08-05 10:41:10 -0400576 SkIRect cropRect = SkIRect::MakeXYWH(5, 0, 5, 10);
577 sk_sp<SkImageFilter> input(SkImageFilters::Offset(0, 0, nullptr, &cropRect));
578 sk_sp<SkImageFilter> filter(SkImageFilters::Blur(0, 0, std::move(input), &cropRect));
senorblancobf680c32016-03-16 16:15:53 -0700579
robertphillips3e302272016-04-20 11:48:36 -0700580 sk_sp<SkSpecialSurface> surf(create_empty_special_surface(context, 10));
senorblancobf680c32016-03-16 16:15:53 -0700581 surf->getCanvas()->clear(SK_ColorGREEN);
robertphillips37bd7c32016-03-17 14:31:39 -0700582 sk_sp<SkSpecialImage> image(surf->makeImageSnapshot());
senorblancobf680c32016-03-16 16:15:53 -0700583
584 SkIPoint offset;
Michael Ludwig03f9ca32019-08-14 14:35:15 -0400585 SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -0400586 kN32_SkColorType, nullptr, image.get());
senorblancobf680c32016-03-16 16:15:53 -0700587
Michael Ludwigea071232019-08-26 10:52:15 -0400588 sk_sp<SkSpecialImage> result(as_IFB(filter)->filterImage(ctx).imageAndOffset(&offset));
senorblancobf680c32016-03-16 16:15:53 -0700589 REPORTER_ASSERT(reporter, offset.fX == 5 && offset.fY == 0);
590 REPORTER_ASSERT(reporter, result);
591 REPORTER_ASSERT(reporter, result->width() == 5 && result->height() == 10);
592
593 SkBitmap resultBM;
594
robertphillips64612512016-04-08 12:10:42 -0700595 REPORTER_ASSERT(reporter, result->getROPixels(&resultBM));
senorblancobf680c32016-03-16 16:15:53 -0700596
senorblancobf680c32016-03-16 16:15:53 -0700597 for (int y = 0; y < resultBM.height(); y++) {
598 for (int x = 0; x < resultBM.width(); x++) {
599 bool diff = *resultBM.getAddr32(x, y) != SK_ColorGREEN;
600 REPORTER_ASSERT(reporter, !diff);
601 if (diff) {
602 break;
603 }
604 }
605 }
606}
607
senorblanco21a465d2016-04-11 11:58:39 -0700608DEF_TEST(ImageFilterZeroBlurSigma, reporter) {
robertphillips3e302272016-04-20 11:48:36 -0700609 test_zero_blur_sigma(reporter, nullptr);
senorblancobf680c32016-03-16 16:15:53 -0700610}
611
bsalomon68d91342016-04-12 09:59:58 -0700612DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterZeroBlurSigma_Gpu, reporter, ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -0700613 test_zero_blur_sigma(reporter, ctxInfo.grContext());
senorblancobf680c32016-03-16 16:15:53 -0700614}
senorblancobf680c32016-03-16 16:15:53 -0700615
senorblanco6a93fa12016-04-05 04:43:45 -0700616
617// Tests that, even when an upstream filter has returned null (due to failure or clipping), a
618// downstream filter that affects transparent black still does so even with a nullptr input.
robertphillips3e302272016-04-20 11:48:36 -0700619static void test_fail_affects_transparent_black(skiatest::Reporter* reporter, GrContext* context) {
senorblanco6a93fa12016-04-05 04:43:45 -0700620 sk_sp<FailImageFilter> failFilter(new FailImageFilter());
robertphillips3e302272016-04-20 11:48:36 -0700621 sk_sp<SkSpecialImage> source(create_empty_special_image(context, 5));
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400622 SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(0, 0, 1, 1), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -0400623 kN32_SkColorType, nullptr, source.get());
Mike Reedb286bc22019-04-08 16:23:20 -0400624 sk_sp<SkColorFilter> green(SkColorFilters::Blend(SK_ColorGREEN, SkBlendMode::kSrc));
senorblanco6a93fa12016-04-05 04:43:45 -0700625 SkASSERT(green->affectsTransparentBlack());
Michael Ludwig55edb502019-08-05 10:41:10 -0400626 sk_sp<SkImageFilter> greenFilter(SkImageFilters::ColorFilter(std::move(green),
627 std::move(failFilter)));
senorblanco6a93fa12016-04-05 04:43:45 -0700628 SkIPoint offset;
Michael Ludwigea071232019-08-26 10:52:15 -0400629 sk_sp<SkSpecialImage> result(as_IFB(greenFilter)->filterImage(ctx).imageAndOffset(&offset));
senorblanco6a93fa12016-04-05 04:43:45 -0700630 REPORTER_ASSERT(reporter, nullptr != result.get());
631 if (result.get()) {
632 SkBitmap resultBM;
robertphillips64612512016-04-08 12:10:42 -0700633 REPORTER_ASSERT(reporter, result->getROPixels(&resultBM));
senorblanco6a93fa12016-04-05 04:43:45 -0700634 REPORTER_ASSERT(reporter, *resultBM.getAddr32(0, 0) == SK_ColorGREEN);
635 }
636}
637
638DEF_TEST(ImageFilterFailAffectsTransparentBlack, reporter) {
robertphillips3e302272016-04-20 11:48:36 -0700639 test_fail_affects_transparent_black(reporter, nullptr);
senorblanco6a93fa12016-04-05 04:43:45 -0700640}
641
bsalomon68d91342016-04-12 09:59:58 -0700642DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterFailAffectsTransparentBlack_Gpu, reporter, ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -0700643 test_fail_affects_transparent_black(reporter, ctxInfo.grContext());
senorblanco6a93fa12016-04-05 04:43:45 -0700644}
senorblanco6a93fa12016-04-05 04:43:45 -0700645
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000646DEF_TEST(ImageFilterDrawTiled, reporter) {
647 // Check that all filters when drawn tiled (with subsequent clip rects) exactly
648 // match the same filters drawn with a single full-canvas bitmap draw.
649 // Tests pass by not asserting.
650
robertphillipsfc11b0a2016-04-05 09:09:36 -0700651 FilterList filters(nullptr);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000652
653 SkBitmap untiledResult, tiledResult;
reed5ea95df2015-10-06 14:05:32 -0700654 const int width = 64, height = 64;
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000655 untiledResult.allocN32Pixels(width, height);
656 tiledResult.allocN32Pixels(width, height);
657 SkCanvas tiledCanvas(tiledResult);
658 SkCanvas untiledCanvas(untiledResult);
Robert Phillips12078432018-05-17 11:17:39 -0400659 const int tileSize = 8;
660
661 SkPaint textPaint;
Robert Phillips12078432018-05-17 11:17:39 -0400662 textPaint.setColor(SK_ColorWHITE);
Mike Kleinea3f0142019-03-20 11:12:10 -0500663 SkFont font(ToolUtils::create_portable_typeface(), height);
Robert Phillips12078432018-05-17 11:17:39 -0400664
665 const char* text = "ABC";
666 const SkScalar yPos = SkIntToScalar(height);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000667
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000668 for (int scale = 1; scale <= 2; ++scale) {
senorblanco297f7ce2016-03-23 13:44:26 -0700669 for (int i = 0; i < filters.count(); ++i) {
Robert Phillips12078432018-05-17 11:17:39 -0400670 SkPaint combinedPaint;
Robert Phillips12078432018-05-17 11:17:39 -0400671 combinedPaint.setColor(SK_ColorWHITE);
672 combinedPaint.setImageFilter(sk_ref_sp(filters.getFilter(i)));
673
674 untiledCanvas.clear(SK_ColorTRANSPARENT);
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000675 untiledCanvas.save();
676 untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
Mike Reed1af9b482019-01-07 11:01:57 -0500677 untiledCanvas.drawString(text, 0, yPos, font, combinedPaint);
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000678 untiledCanvas.restore();
Robert Phillips12078432018-05-17 11:17:39 -0400679
680 tiledCanvas.clear(SK_ColorTRANSPARENT);
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000681 for (int y = 0; y < height; y += tileSize) {
682 for (int x = 0; x < width; x += tileSize) {
683 tiledCanvas.save();
Robert Phillips12078432018-05-17 11:17:39 -0400684 const SkRect clipRect = SkRect::MakeXYWH(x, y, tileSize, tileSize);
685 tiledCanvas.clipRect(clipRect);
686 if (filters.needsSaveLayer(i)) {
Michael Ludwig55edb502019-08-05 10:41:10 -0400687 const SkRect layerBounds = SkRect::MakeIWH(width, height);
Robert Phillips12078432018-05-17 11:17:39 -0400688 tiledCanvas.saveLayer(&layerBounds, &combinedPaint);
689 tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
Mike Reed1af9b482019-01-07 11:01:57 -0500690 tiledCanvas.drawString(text, 0, yPos, font, textPaint);
Robert Phillips12078432018-05-17 11:17:39 -0400691 tiledCanvas.restore();
692 } else {
693 tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
Mike Reed1af9b482019-01-07 11:01:57 -0500694 tiledCanvas.drawString(text, 0, yPos, font, combinedPaint);
Robert Phillips12078432018-05-17 11:17:39 -0400695 }
696
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000697 tiledCanvas.restore();
698 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000699 }
Robert Phillips12078432018-05-17 11:17:39 -0400700
Mike Kleinea3f0142019-03-20 11:12:10 -0500701 if (!ToolUtils::equal_pixels(untiledResult, tiledResult)) {
Brian Salomon1c80e992018-01-29 09:50:47 -0500702 REPORTER_ASSERT(reporter, false, filters.getName(i));
Mike Reed5a625e02017-08-08 15:48:54 -0400703 break;
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000704 }
705 }
706 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000707}
708
mtklein3f3b3d02014-12-01 11:47:08 -0800709static void draw_saveLayer_picture(int width, int height, int tileSize,
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700710 SkBBHFactory* factory, SkBitmap* result) {
mtkleind910f542014-08-22 09:06:34 -0700711
712 SkMatrix matrix;
713 matrix.setTranslate(SkIntToScalar(50), 0);
714
Mike Reedb286bc22019-04-08 16:23:20 -0400715 sk_sp<SkColorFilter> cf(SkColorFilters::Blend(SK_ColorWHITE, SkBlendMode::kSrc));
Michael Ludwig55edb502019-08-05 10:41:10 -0400716 sk_sp<SkImageFilter> cfif(SkImageFilters::ColorFilter(std::move(cf), nullptr));
robertphillipsae8c9332016-04-05 15:09:00 -0700717 sk_sp<SkImageFilter> imageFilter(SkImageFilter::MakeMatrixFilter(matrix,
718 kNone_SkFilterQuality,
719 std::move(cfif)));
mtkleind910f542014-08-22 09:06:34 -0700720
721 SkPaint paint;
robertphillips5605b562016-04-05 11:50:42 -0700722 paint.setImageFilter(std::move(imageFilter));
mtkleind910f542014-08-22 09:06:34 -0700723 SkPictureRecorder recorder;
724 SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50));
mtklein3f3b3d02014-12-01 11:47:08 -0800725 SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width),
726 SkIntToScalar(height),
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700727 factory, 0);
mtkleind910f542014-08-22 09:06:34 -0700728 recordingCanvas->translate(-55, 0);
729 recordingCanvas->saveLayer(&bounds, &paint);
730 recordingCanvas->restore();
reedca2622b2016-03-18 07:25:55 -0700731 sk_sp<SkPicture> picture1(recorder.finishRecordingAsPicture());
mtkleind910f542014-08-22 09:06:34 -0700732
733 result->allocN32Pixels(width, height);
734 SkCanvas canvas(*result);
735 canvas.clear(0);
736 canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize)));
737 canvas.drawPicture(picture1.get());
738}
739
740DEF_TEST(ImageFilterDrawMatrixBBH, reporter) {
741 // Check that matrix filter when drawn tiled with BBH exactly
742 // matches the same thing drawn without BBH.
743 // Tests pass by not asserting.
744
745 const int width = 200, height = 200;
746 const int tileSize = 100;
747 SkBitmap result1, result2;
748 SkRTreeFactory factory;
749
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700750 draw_saveLayer_picture(width, height, tileSize, &factory, &result1);
halcanary96fcdcc2015-08-27 07:41:13 -0700751 draw_saveLayer_picture(width, height, tileSize, nullptr, &result2);
mtkleind910f542014-08-22 09:06:34 -0700752
753 for (int y = 0; y < height; y++) {
754 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
755 REPORTER_ASSERT(reporter, !diffs);
756 if (diffs) {
757 break;
758 }
759 }
760}
761
robertphillips6e7025a2016-04-04 04:31:25 -0700762static sk_sp<SkImageFilter> make_blur(sk_sp<SkImageFilter> input) {
Michael Ludwig55edb502019-08-05 10:41:10 -0400763 return SkImageFilters::Blur(SK_Scalar1, SK_Scalar1, std::move(input));
senorblanco1150a6d2014-08-25 12:46:58 -0700764}
765
robertphillips6e7025a2016-04-04 04:31:25 -0700766static sk_sp<SkImageFilter> make_drop_shadow(sk_sp<SkImageFilter> input) {
Michael Ludwig55edb502019-08-05 10:41:10 -0400767 return SkImageFilters::DropShadow(100, 100, 10, 10, SK_ColorBLUE, std::move(input));
senorblanco1150a6d2014-08-25 12:46:58 -0700768}
769
770DEF_TEST(ImageFilterBlurThenShadowBounds, reporter) {
robertphillips6e7025a2016-04-04 04:31:25 -0700771 sk_sp<SkImageFilter> filter1(make_blur(nullptr));
772 sk_sp<SkImageFilter> filter2(make_drop_shadow(std::move(filter1)));
senorblanco1150a6d2014-08-25 12:46:58 -0700773
774 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
Herb Derby59f8f152017-10-17 22:27:23 +0000775 SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
Robert Phillips12078432018-05-17 11:17:39 -0400776 bounds = filter2->filterBounds(bounds, SkMatrix::I(),
777 SkImageFilter::kReverse_MapDirection, &bounds);
senorblanco1150a6d2014-08-25 12:46:58 -0700778
779 REPORTER_ASSERT(reporter, bounds == expectedBounds);
780}
781
782DEF_TEST(ImageFilterShadowThenBlurBounds, reporter) {
robertphillips6e7025a2016-04-04 04:31:25 -0700783 sk_sp<SkImageFilter> filter1(make_drop_shadow(nullptr));
784 sk_sp<SkImageFilter> filter2(make_blur(std::move(filter1)));
senorblanco1150a6d2014-08-25 12:46:58 -0700785
786 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
Herb Derby59f8f152017-10-17 22:27:23 +0000787 SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
Robert Phillips12078432018-05-17 11:17:39 -0400788 bounds = filter2->filterBounds(bounds, SkMatrix::I(),
789 SkImageFilter::kReverse_MapDirection, &bounds);
senorblanco1150a6d2014-08-25 12:46:58 -0700790
791 REPORTER_ASSERT(reporter, bounds == expectedBounds);
792}
793
794DEF_TEST(ImageFilterDilateThenBlurBounds, reporter) {
Michael Ludwig55edb502019-08-05 10:41:10 -0400795 sk_sp<SkImageFilter> filter1(SkImageFilters::Dilate(2, 2, nullptr));
robertphillips6e7025a2016-04-04 04:31:25 -0700796 sk_sp<SkImageFilter> filter2(make_drop_shadow(std::move(filter1)));
senorblanco1150a6d2014-08-25 12:46:58 -0700797
798 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
799 SkIRect expectedBounds = SkIRect::MakeXYWH(-132, -132, 234, 234);
Robert Phillips12078432018-05-17 11:17:39 -0400800 bounds = filter2->filterBounds(bounds, SkMatrix::I(),
801 SkImageFilter::kReverse_MapDirection, &bounds);
senorblanco1150a6d2014-08-25 12:46:58 -0700802
803 REPORTER_ASSERT(reporter, bounds == expectedBounds);
804}
805
jbroman203a9932016-07-11 14:07:59 -0700806DEF_TEST(ImageFilterScaledBlurRadius, reporter) {
807 // Each blur should spread 3*sigma, so 3 for the blur and 30 for the shadow
808 // (before the CTM). Bounds should be computed correctly in the presence of
809 // a (possibly negative) scale.
810 sk_sp<SkImageFilter> blur(make_blur(nullptr));
811 sk_sp<SkImageFilter> dropShadow(make_drop_shadow(nullptr));
812 {
813 // Uniform scale by 2.
814 SkMatrix scaleMatrix;
815 scaleMatrix.setScale(2, 2);
816 SkIRect bounds = SkIRect::MakeLTRB(0, 0, 200, 200);
817
Herb Derby59f8f152017-10-17 22:27:23 +0000818 SkIRect expectedBlurBounds = SkIRect::MakeLTRB(-6, -6, 206, 206);
jbroman203a9932016-07-11 14:07:59 -0700819 SkIRect blurBounds = blur->filterBounds(
Michael Ludwig55edb502019-08-05 10:41:10 -0400820 bounds, scaleMatrix, SkImageFilter::kForward_MapDirection, nullptr);
jbroman203a9932016-07-11 14:07:59 -0700821 REPORTER_ASSERT(reporter, blurBounds == expectedBlurBounds);
822 SkIRect reverseBlurBounds = blur->filterBounds(
Michael Ludwig55edb502019-08-05 10:41:10 -0400823 bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &bounds);
jbroman203a9932016-07-11 14:07:59 -0700824 REPORTER_ASSERT(reporter, reverseBlurBounds == expectedBlurBounds);
825
826 SkIRect expectedShadowBounds = SkIRect::MakeLTRB(0, 0, 460, 460);
827 SkIRect shadowBounds = dropShadow->filterBounds(
Michael Ludwig55edb502019-08-05 10:41:10 -0400828 bounds, scaleMatrix, SkImageFilter::kForward_MapDirection, nullptr);
jbroman203a9932016-07-11 14:07:59 -0700829 REPORTER_ASSERT(reporter, shadowBounds == expectedShadowBounds);
830 SkIRect expectedReverseShadowBounds =
Michael Ludwig55edb502019-08-05 10:41:10 -0400831 SkIRect::MakeLTRB(-260, -260, 200, 200);
jbroman203a9932016-07-11 14:07:59 -0700832 SkIRect reverseShadowBounds = dropShadow->filterBounds(
Michael Ludwig55edb502019-08-05 10:41:10 -0400833 bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &bounds);
834 REPORTER_ASSERT(reporter, reverseShadowBounds == expectedReverseShadowBounds);
jbroman203a9932016-07-11 14:07:59 -0700835 }
836 {
837 // Vertical flip.
838 SkMatrix scaleMatrix;
839 scaleMatrix.setScale(1, -1);
840 SkIRect bounds = SkIRect::MakeLTRB(0, -100, 100, 0);
841
Herb Derby59f8f152017-10-17 22:27:23 +0000842 SkIRect expectedBlurBounds = SkIRect::MakeLTRB(-3, -103, 103, 3);
jbroman203a9932016-07-11 14:07:59 -0700843 SkIRect blurBounds = blur->filterBounds(
Michael Ludwig55edb502019-08-05 10:41:10 -0400844 bounds, scaleMatrix, SkImageFilter::kForward_MapDirection, nullptr);
jbroman203a9932016-07-11 14:07:59 -0700845 REPORTER_ASSERT(reporter, blurBounds == expectedBlurBounds);
846 SkIRect reverseBlurBounds = blur->filterBounds(
Michael Ludwig55edb502019-08-05 10:41:10 -0400847 bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &bounds);
jbroman203a9932016-07-11 14:07:59 -0700848 REPORTER_ASSERT(reporter, reverseBlurBounds == expectedBlurBounds);
849
850 SkIRect expectedShadowBounds = SkIRect::MakeLTRB(0, -230, 230, 0);
851 SkIRect shadowBounds = dropShadow->filterBounds(
Michael Ludwig55edb502019-08-05 10:41:10 -0400852 bounds, scaleMatrix, SkImageFilter::kForward_MapDirection, nullptr);
jbroman203a9932016-07-11 14:07:59 -0700853 REPORTER_ASSERT(reporter, shadowBounds == expectedShadowBounds);
854 SkIRect expectedReverseShadowBounds =
Michael Ludwig55edb502019-08-05 10:41:10 -0400855 SkIRect::MakeLTRB(-130, -100, 100, 130);
jbroman203a9932016-07-11 14:07:59 -0700856 SkIRect reverseShadowBounds = dropShadow->filterBounds(
Michael Ludwig55edb502019-08-05 10:41:10 -0400857 bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &bounds);
858 REPORTER_ASSERT(reporter, reverseShadowBounds == expectedReverseShadowBounds);
jbroman203a9932016-07-11 14:07:59 -0700859 }
860}
861
ajuma5788faa2015-02-13 09:05:47 -0800862DEF_TEST(ImageFilterComposedBlurFastBounds, reporter) {
robertphillips6e7025a2016-04-04 04:31:25 -0700863 sk_sp<SkImageFilter> filter1(make_blur(nullptr));
864 sk_sp<SkImageFilter> filter2(make_blur(nullptr));
Michael Ludwig55edb502019-08-05 10:41:10 -0400865 sk_sp<SkImageFilter> composedFilter(SkImageFilters::Compose(std::move(filter1),
866 std::move(filter2)));
ajuma5788faa2015-02-13 09:05:47 -0800867
Michael Ludwig55edb502019-08-05 10:41:10 -0400868 SkRect boundsSrc = SkRect::MakeIWH(100, 100);
869 SkRect expectedBounds = SkRect::MakeXYWH(-6, -6, 112, 112);
senorblancoe5e79842016-03-21 14:51:59 -0700870 SkRect boundsDst = composedFilter->computeFastBounds(boundsSrc);
ajuma5788faa2015-02-13 09:05:47 -0800871
872 REPORTER_ASSERT(reporter, boundsDst == expectedBounds);
873}
874
jbroman0e3129d2016-03-17 12:24:23 -0700875DEF_TEST(ImageFilterUnionBounds, reporter) {
Michael Ludwig55edb502019-08-05 10:41:10 -0400876 sk_sp<SkImageFilter> offset(SkImageFilters::Offset(50, 0, nullptr));
jbroman0e3129d2016-03-17 12:24:23 -0700877 // Regardless of which order they appear in, the image filter bounds should
878 // be combined correctly.
879 {
Michael Ludwig55edb502019-08-05 10:41:10 -0400880 sk_sp<SkImageFilter> composite(SkImageFilters::Xfermode(SkBlendMode::kSrcOver, offset));
881 SkRect bounds = SkRect::MakeIWH(100, 100);
jbroman0e3129d2016-03-17 12:24:23 -0700882 // Intentionally aliasing here, as that's what the real callers do.
senorblancoe5e79842016-03-21 14:51:59 -0700883 bounds = composite->computeFastBounds(bounds);
Michael Ludwig55edb502019-08-05 10:41:10 -0400884 REPORTER_ASSERT(reporter, bounds == SkRect::MakeIWH(150, 100));
jbroman0e3129d2016-03-17 12:24:23 -0700885 }
886 {
Michael Ludwig55edb502019-08-05 10:41:10 -0400887 sk_sp<SkImageFilter> composite(SkImageFilters::Xfermode(SkBlendMode::kSrcOver, nullptr,
888 offset, nullptr));
889 SkRect bounds = SkRect::MakeIWH(100, 100);
jbroman0e3129d2016-03-17 12:24:23 -0700890 // Intentionally aliasing here, as that's what the real callers do.
senorblancoe5e79842016-03-21 14:51:59 -0700891 bounds = composite->computeFastBounds(bounds);
Michael Ludwig55edb502019-08-05 10:41:10 -0400892 REPORTER_ASSERT(reporter, bounds == SkRect::MakeIWH(150, 100));
jbroman0e3129d2016-03-17 12:24:23 -0700893 }
894}
895
robertphillips3e302272016-04-20 11:48:36 -0700896static void test_imagefilter_merge_result_size(skiatest::Reporter* reporter, GrContext* context) {
senorblanco4a243982015-11-25 07:06:55 -0800897 SkBitmap greenBM;
898 greenBM.allocN32Pixels(20, 20);
899 greenBM.eraseColor(SK_ColorGREEN);
reed9ce9d672016-03-17 10:51:11 -0700900 sk_sp<SkImage> greenImage(SkImage::MakeFromBitmap(greenBM));
Michael Ludwig55edb502019-08-05 10:41:10 -0400901 sk_sp<SkImageFilter> source(SkImageFilters::Image(std::move(greenImage)));
902 sk_sp<SkImageFilter> merge(SkImageFilters::Merge(source, source));
senorblanco4a243982015-11-25 07:06:55 -0800903
robertphillips3e302272016-04-20 11:48:36 -0700904 sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 1));
robertphillips4418dba2016-03-07 12:45:14 -0800905
Michael Ludwig8ee6cf32019-08-02 09:57:04 -0400906 SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(0, 0, 100, 100), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -0400907 kN32_SkColorType, nullptr, srcImg.get());
senorblanco4a243982015-11-25 07:06:55 -0800908 SkIPoint offset;
robertphillips4418dba2016-03-07 12:45:14 -0800909
Michael Ludwigea071232019-08-26 10:52:15 -0400910 sk_sp<SkSpecialImage> resultImg(as_IFB(merge)->filterImage(ctx).imageAndOffset(&offset));
robertphillips4418dba2016-03-07 12:45:14 -0800911 REPORTER_ASSERT(reporter, resultImg);
912
913 REPORTER_ASSERT(reporter, resultImg->width() == 20 && resultImg->height() == 20);
senorblanco4a243982015-11-25 07:06:55 -0800914}
915
robertphillips4418dba2016-03-07 12:45:14 -0800916DEF_TEST(ImageFilterMergeResultSize, reporter) {
robertphillips3e302272016-04-20 11:48:36 -0700917 test_imagefilter_merge_result_size(reporter, nullptr);
robertphillips4418dba2016-03-07 12:45:14 -0800918}
919
egdanielab527a52016-06-28 08:07:26 -0700920DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterMergeResultSize_Gpu, reporter, ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -0700921 test_imagefilter_merge_result_size(reporter, ctxInfo.grContext());
robertphillips4418dba2016-03-07 12:45:14 -0800922}
robertphillips4418dba2016-03-07 12:45:14 -0800923
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700924static void draw_blurred_rect(SkCanvas* canvas) {
senorblanco837f5322014-07-14 10:19:54 -0700925 SkPaint filterPaint;
926 filterPaint.setColor(SK_ColorWHITE);
Michael Ludwig55edb502019-08-05 10:41:10 -0400927 filterPaint.setImageFilter(SkImageFilters::Blur(SkIntToScalar(8), 0, nullptr));
halcanary96fcdcc2015-08-27 07:41:13 -0700928 canvas->saveLayer(nullptr, &filterPaint);
senorblanco837f5322014-07-14 10:19:54 -0700929 SkPaint whitePaint;
930 whitePaint.setColor(SK_ColorWHITE);
931 canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
932 canvas->restore();
933}
934
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700935static void draw_picture_clipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
senorblanco837f5322014-07-14 10:19:54 -0700936 canvas->save();
937 canvas->clipRect(clipRect);
938 canvas->drawPicture(picture);
939 canvas->restore();
940}
941
942DEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) {
943 // Check that the blur filter when recorded with RTree acceleration,
944 // and drawn tiled (with subsequent clip rects) exactly
945 // matches the same filter drawn with without RTree acceleration.
946 // This tests that the "bleed" from the blur into the otherwise-blank
947 // tiles is correctly rendered.
948 // Tests pass by not asserting.
949
950 int width = 16, height = 8;
951 SkBitmap result1, result2;
952 result1.allocN32Pixels(width, height);
953 result2.allocN32Pixels(width, height);
954 SkCanvas canvas1(result1);
955 SkCanvas canvas2(result2);
956 int tileSize = 8;
957
958 canvas1.clear(0);
959 canvas2.clear(0);
960
961 SkRTreeFactory factory;
962
963 SkPictureRecorder recorder1, recorder2;
964 // The only difference between these two pictures is that one has RTree aceleration.
Michael Ludwig55edb502019-08-05 10:41:10 -0400965 SkCanvas* recordingCanvas1 = recorder1.beginRecording(width, height, nullptr, 0);
966 SkCanvas* recordingCanvas2 = recorder2.beginRecording(width, height, &factory, 0);
967
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700968 draw_blurred_rect(recordingCanvas1);
969 draw_blurred_rect(recordingCanvas2);
reedca2622b2016-03-18 07:25:55 -0700970 sk_sp<SkPicture> picture1(recorder1.finishRecordingAsPicture());
971 sk_sp<SkPicture> picture2(recorder2.finishRecordingAsPicture());
senorblanco837f5322014-07-14 10:19:54 -0700972 for (int y = 0; y < height; y += tileSize) {
973 for (int x = 0; x < width; x += tileSize) {
974 SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
reedca2622b2016-03-18 07:25:55 -0700975 draw_picture_clipped(&canvas1, tileRect, picture1.get());
976 draw_picture_clipped(&canvas2, tileRect, picture2.get());
senorblanco837f5322014-07-14 10:19:54 -0700977 }
978 }
979 for (int y = 0; y < height; y++) {
980 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
981 REPORTER_ASSERT(reporter, !diffs);
982 if (diffs) {
983 break;
984 }
985 }
986}
987
senorblanco@chromium.org91957432014-05-01 14:03:41 +0000988DEF_TEST(ImageFilterMatrixConvolution, reporter) {
989 // Check that a 1x3 filter does not cause a spurious assert.
990 SkScalar kernel[3] = {
991 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
992 };
993 SkISize kernelSize = SkISize::Make(1, 3);
994 SkScalar gain = SK_Scalar1, bias = 0;
995 SkIPoint kernelOffset = SkIPoint::Make(0, 0);
996
Michael Ludwig55edb502019-08-05 10:41:10 -0400997 sk_sp<SkImageFilter> filter(SkImageFilters::MatrixConvolution(
998 kernelSize, kernel, gain, bias, kernelOffset, SkTileMode::kRepeat, false, nullptr));
senorblanco@chromium.org91957432014-05-01 14:03:41 +0000999
1000 SkBitmap result;
1001 int width = 16, height = 16;
1002 result.allocN32Pixels(width, height);
1003 SkCanvas canvas(result);
1004 canvas.clear(0);
1005
1006 SkPaint paint;
robertphillipsef6a47b2016-04-08 08:01:20 -07001007 paint.setImageFilter(std::move(filter));
senorblanco@chromium.org91957432014-05-01 14:03:41 +00001008 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
1009 canvas.drawRect(rect, paint);
1010}
1011
senorblanco@chromium.org8c7372b2014-05-02 19:13:11 +00001012DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
1013 // Check that a filter with borders outside the target bounds
1014 // does not crash.
1015 SkScalar kernel[3] = {
1016 0, 0, 0,
1017 };
1018 SkISize kernelSize = SkISize::Make(3, 1);
1019 SkScalar gain = SK_Scalar1, bias = 0;
1020 SkIPoint kernelOffset = SkIPoint::Make(2, 0);
1021
Michael Ludwig55edb502019-08-05 10:41:10 -04001022 sk_sp<SkImageFilter> filter(SkImageFilters::MatrixConvolution(
1023 kernelSize, kernel, gain, bias, kernelOffset, SkTileMode::kClamp, true, nullptr));
senorblanco@chromium.org8c7372b2014-05-02 19:13:11 +00001024
1025 SkBitmap result;
1026
1027 int width = 10, height = 10;
1028 result.allocN32Pixels(width, height);
1029 SkCanvas canvas(result);
1030 canvas.clear(0);
1031
1032 SkPaint filterPaint;
robertphillipsef6a47b2016-04-08 08:01:20 -07001033 filterPaint.setImageFilter(std::move(filter));
Michael Ludwig55edb502019-08-05 10:41:10 -04001034 SkRect bounds = SkRect::MakeIWH(1, 10);
senorblanco@chromium.org8c7372b2014-05-02 19:13:11 +00001035 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
1036 SkPaint rectPaint;
1037 canvas.saveLayer(&bounds, &filterPaint);
1038 canvas.drawRect(rect, rectPaint);
1039 canvas.restore();
1040}
1041
robertphillips3e302272016-04-20 11:48:36 -07001042static void test_big_kernel(skiatest::Reporter* reporter, GrContext* context) {
robertphillipsdada4dd2016-04-13 04:54:36 -07001043 // Check that a kernel that is too big for the GPU still works
1044 SkScalar identityKernel[49] = {
1045 0, 0, 0, 0, 0, 0, 0,
1046 0, 0, 0, 0, 0, 0, 0,
1047 0, 0, 0, 0, 0, 0, 0,
1048 0, 0, 0, 1, 0, 0, 0,
1049 0, 0, 0, 0, 0, 0, 0,
1050 0, 0, 0, 0, 0, 0, 0,
1051 0, 0, 0, 0, 0, 0, 0
1052 };
1053 SkISize kernelSize = SkISize::Make(7, 7);
1054 SkScalar gain = SK_Scalar1, bias = 0;
1055 SkIPoint kernelOffset = SkIPoint::Make(0, 0);
1056
Michael Ludwig55edb502019-08-05 10:41:10 -04001057 sk_sp<SkImageFilter> filter(SkImageFilters::MatrixConvolution(
1058 kernelSize, identityKernel, gain, bias, kernelOffset,
1059 SkTileMode::kClamp, true, nullptr));
robertphillipsdada4dd2016-04-13 04:54:36 -07001060
robertphillips3e302272016-04-20 11:48:36 -07001061 sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 100));
robertphillipsdada4dd2016-04-13 04:54:36 -07001062 SkASSERT(srcImg);
1063
1064 SkIPoint offset;
Michael Ludwig8ee6cf32019-08-02 09:57:04 -04001065 SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -04001066 kN32_SkColorType, nullptr, srcImg.get());
Michael Ludwigea071232019-08-26 10:52:15 -04001067 sk_sp<SkSpecialImage> resultImg(as_IFB(filter)->filterImage(ctx).imageAndOffset(&offset));
robertphillipsdada4dd2016-04-13 04:54:36 -07001068 REPORTER_ASSERT(reporter, resultImg);
1069 REPORTER_ASSERT(reporter, SkToBool(context) == resultImg->isTextureBacked());
1070 REPORTER_ASSERT(reporter, resultImg->width() == 100 && resultImg->height() == 100);
1071 REPORTER_ASSERT(reporter, offset.fX == 0 && offset.fY == 0);
1072}
1073
1074DEF_TEST(ImageFilterMatrixConvolutionBigKernel, reporter) {
robertphillips3e302272016-04-20 11:48:36 -07001075 test_big_kernel(reporter, nullptr);
robertphillipsdada4dd2016-04-13 04:54:36 -07001076}
1077
egdanielab527a52016-06-28 08:07:26 -07001078DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterMatrixConvolutionBigKernel_Gpu,
1079 reporter, ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -07001080 test_big_kernel(reporter, ctxInfo.grContext());
robertphillipsdada4dd2016-04-13 04:54:36 -07001081}
robertphillipsdada4dd2016-04-13 04:54:36 -07001082
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +00001083DEF_TEST(ImageFilterCropRect, reporter) {
Michael Ludwig55edb502019-08-05 10:41:10 -04001084 test_cropRects(reporter, nullptr);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +00001085}
1086
bsalomon68d91342016-04-12 09:59:58 -07001087DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCropRect_Gpu, reporter, ctxInfo) {
Michael Ludwig55edb502019-08-05 10:41:10 -04001088 test_cropRects(reporter, ctxInfo.grContext());
robertphillips4418dba2016-03-07 12:45:14 -08001089}
robertphillips4418dba2016-03-07 12:45:14 -08001090
tfarina9ea53f92014-06-24 06:50:39 -07001091DEF_TEST(ImageFilterMatrix, reporter) {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +00001092 SkBitmap temp;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +00001093 temp.allocN32Pixels(100, 100);
robertphillips9a53fd72015-06-22 09:46:59 -07001094 SkCanvas canvas(temp);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +00001095 canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
1096
1097 SkMatrix expectedMatrix = canvas.getTotalMatrix();
1098
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +00001099 SkRTreeFactory factory;
1100 SkPictureRecorder recorder;
1101 SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +00001102
1103 SkPaint paint;
robertphillips43c2ad42016-04-04 05:05:11 -07001104 paint.setImageFilter(MatrixTestImageFilter::Make(reporter, expectedMatrix));
halcanary96fcdcc2015-08-27 07:41:13 -07001105 recordingCanvas->saveLayer(nullptr, &paint);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +00001106 SkPaint solidPaint;
1107 solidPaint.setColor(0xFFFFFFFF);
1108 recordingCanvas->save();
1109 recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
1110 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
1111 recordingCanvas->restore(); // scale
1112 recordingCanvas->restore(); // saveLayer
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +00001113
reedca2622b2016-03-18 07:25:55 -07001114 canvas.drawPicture(recorder.finishRecordingAsPicture());
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +00001115}
1116
robertphillips3e302272016-04-20 11:48:36 -07001117static void test_clipped_picture_imagefilter(skiatest::Reporter* reporter, GrContext* context) {
reedca2622b2016-03-18 07:25:55 -07001118 sk_sp<SkPicture> picture;
senorblanco3d822c22014-07-30 14:49:31 -07001119
robertphillips4418dba2016-03-07 12:45:14 -08001120 {
1121 SkRTreeFactory factory;
1122 SkPictureRecorder recorder;
1123 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
1124
1125 // Create an SkPicture which simply draws a green 1x1 rectangle.
1126 SkPaint greenPaint;
1127 greenPaint.setColor(SK_ColorGREEN);
1128 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
reedca2622b2016-03-18 07:25:55 -07001129 picture = recorder.finishRecordingAsPicture();
robertphillips4418dba2016-03-07 12:45:14 -08001130 }
1131
robertphillips3e302272016-04-20 11:48:36 -07001132 sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 2));
senorblanco3d822c22014-07-30 14:49:31 -07001133
Michael Ludwig55edb502019-08-05 10:41:10 -04001134 sk_sp<SkImageFilter> imageFilter(SkImageFilters::Picture(picture));
senorblanco3d822c22014-07-30 14:49:31 -07001135
senorblanco3d822c22014-07-30 14:49:31 -07001136 SkIPoint offset;
Michael Ludwig8ee6cf32019-08-02 09:57:04 -04001137 SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(1, 1, 1, 1), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -04001138 kN32_SkColorType, nullptr, srcImg.get());
robertphillips4418dba2016-03-07 12:45:14 -08001139
Michael Ludwigea071232019-08-26 10:52:15 -04001140 sk_sp<SkSpecialImage> resultImage(
1141 as_IFB(imageFilter)->filterImage(ctx).imageAndOffset(&offset));
robertphillips4418dba2016-03-07 12:45:14 -08001142 REPORTER_ASSERT(reporter, !resultImage);
senorblanco3d822c22014-07-30 14:49:31 -07001143}
1144
robertphillips4418dba2016-03-07 12:45:14 -08001145DEF_TEST(ImageFilterClippedPictureImageFilter, reporter) {
robertphillips3e302272016-04-20 11:48:36 -07001146 test_clipped_picture_imagefilter(reporter, nullptr);
robertphillips4418dba2016-03-07 12:45:14 -08001147}
1148
bsalomon68d91342016-04-12 09:59:58 -07001149DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterClippedPictureImageFilter_Gpu, reporter, ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -07001150 test_clipped_picture_imagefilter(reporter, ctxInfo.grContext());
robertphillips4418dba2016-03-07 12:45:14 -08001151}
robertphillips4418dba2016-03-07 12:45:14 -08001152
tfarina9ea53f92014-06-24 06:50:39 -07001153DEF_TEST(ImageFilterEmptySaveLayer, reporter) {
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001154 // Even when there's an empty saveLayer()/restore(), ensure that an image
1155 // filter or color filter which affects transparent black still draws.
1156
1157 SkBitmap bitmap;
1158 bitmap.allocN32Pixels(10, 10);
robertphillips9a53fd72015-06-22 09:46:59 -07001159 SkCanvas canvas(bitmap);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001160
1161 SkRTreeFactory factory;
1162 SkPictureRecorder recorder;
1163
Michael Ludwigea071232019-08-26 10:52:15 -04001164 sk_sp<SkColorFilter> green(SkColorFilters::Blend(SK_ColorGREEN, SkBlendMode::kSrc));
Michael Ludwig55edb502019-08-05 10:41:10 -04001165 sk_sp<SkImageFilter> imageFilter(SkImageFilters::ColorFilter(green, nullptr));
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001166 SkPaint imageFilterPaint;
robertphillips5605b562016-04-05 11:50:42 -07001167 imageFilterPaint.setImageFilter(std::move(imageFilter));
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001168 SkPaint colorFilterPaint;
reedd053ce92016-03-22 10:17:23 -07001169 colorFilterPaint.setColorFilter(green);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001170
Michael Ludwig55edb502019-08-05 10:41:10 -04001171 SkRect bounds = SkRect::MakeIWH(10, 10);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001172
1173 SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
1174 recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
1175 recordingCanvas->restore();
reedca2622b2016-03-18 07:25:55 -07001176 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001177
1178 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -07001179 canvas.drawPicture(picture);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001180 uint32_t pixel = *bitmap.getAddr32(0, 0);
1181 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1182
1183 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
halcanary96fcdcc2015-08-27 07:41:13 -07001184 recordingCanvas->saveLayer(nullptr, &imageFilterPaint);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001185 recordingCanvas->restore();
reedca2622b2016-03-18 07:25:55 -07001186 sk_sp<SkPicture> picture2(recorder.finishRecordingAsPicture());
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001187
1188 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -07001189 canvas.drawPicture(picture2);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001190 pixel = *bitmap.getAddr32(0, 0);
1191 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1192
1193 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
1194 recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
1195 recordingCanvas->restore();
reedca2622b2016-03-18 07:25:55 -07001196 sk_sp<SkPicture> picture3(recorder.finishRecordingAsPicture());
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001197
1198 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -07001199 canvas.drawPicture(picture3);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001200 pixel = *bitmap.getAddr32(0, 0);
1201 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1202}
1203
robertphillips9a53fd72015-06-22 09:46:59 -07001204static void test_huge_blur(SkCanvas* canvas, skiatest::Reporter* reporter) {
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001205 SkBitmap bitmap;
1206 bitmap.allocN32Pixels(100, 100);
1207 bitmap.eraseARGB(0, 0, 0, 0);
1208
1209 // Check that a blur with an insane radius does not crash or assert.
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001210 SkPaint paint;
Michael Ludwig55edb502019-08-05 10:41:10 -04001211 paint.setImageFilter(SkImageFilters::Blur(SkIntToScalar(1<<30), SkIntToScalar(1<<30), nullptr));
reedda420b92015-12-16 08:38:15 -08001212 canvas->drawBitmap(bitmap, 0, 0, &paint);
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001213}
1214
1215DEF_TEST(HugeBlurImageFilter, reporter) {
1216 SkBitmap temp;
1217 temp.allocN32Pixels(100, 100);
robertphillips9a53fd72015-06-22 09:46:59 -07001218 SkCanvas canvas(temp);
1219 test_huge_blur(&canvas, reporter);
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001220}
1221
senorblanco21a465d2016-04-11 11:58:39 -07001222DEF_TEST(ImageFilterMatrixConvolutionSanityTest, reporter) {
senorblanco3a495202014-09-29 07:57:20 -07001223 SkScalar kernel[1] = { 0 };
1224 SkScalar gain = SK_Scalar1, bias = 0;
1225 SkIPoint kernelOffset = SkIPoint::Make(1, 1);
1226
halcanary96fcdcc2015-08-27 07:41:13 -07001227 // Check that an enormous (non-allocatable) kernel gives a nullptr filter.
Michael Ludwig55edb502019-08-05 10:41:10 -04001228 sk_sp<SkImageFilter> conv(SkImageFilters::MatrixConvolution(
1229 SkISize::Make(1<<30, 1<<30), kernel, gain, bias, kernelOffset,
1230 SkTileMode::kRepeat, false, nullptr));
senorblanco3a495202014-09-29 07:57:20 -07001231
halcanary96fcdcc2015-08-27 07:41:13 -07001232 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001233
halcanary96fcdcc2015-08-27 07:41:13 -07001234 // Check that a nullptr kernel gives a nullptr filter.
Michael Ludwig55edb502019-08-05 10:41:10 -04001235 conv = SkImageFilters::MatrixConvolution(
1236 SkISize::Make(1, 1), nullptr, gain, bias, kernelOffset,
1237 SkTileMode::kRepeat, false, nullptr);
senorblanco3a495202014-09-29 07:57:20 -07001238
halcanary96fcdcc2015-08-27 07:41:13 -07001239 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001240
halcanary96fcdcc2015-08-27 07:41:13 -07001241 // Check that a kernel width < 1 gives a nullptr filter.
Michael Ludwig55edb502019-08-05 10:41:10 -04001242 conv = SkImageFilters::MatrixConvolution(
1243 SkISize::Make(0, 1), kernel, gain, bias, kernelOffset,
1244 SkTileMode::kRepeat, false, nullptr);
senorblanco3a495202014-09-29 07:57:20 -07001245
halcanary96fcdcc2015-08-27 07:41:13 -07001246 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001247
halcanary96fcdcc2015-08-27 07:41:13 -07001248 // Check that kernel height < 1 gives a nullptr filter.
Michael Ludwig55edb502019-08-05 10:41:10 -04001249 conv = SkImageFilters::MatrixConvolution(
1250 SkISize::Make(1, -1), kernel, gain, bias, kernelOffset,
1251 SkTileMode::kRepeat, false, nullptr);
senorblanco3a495202014-09-29 07:57:20 -07001252
halcanary96fcdcc2015-08-27 07:41:13 -07001253 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001254}
1255
Mike Reedf1942192017-07-21 14:24:29 -04001256static void test_xfermode_cropped_input(SkSurface* surf, skiatest::Reporter* reporter) {
1257 auto canvas = surf->getCanvas();
robertphillips9a53fd72015-06-22 09:46:59 -07001258 canvas->clear(0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001259
1260 SkBitmap bitmap;
1261 bitmap.allocN32Pixels(1, 1);
1262 bitmap.eraseARGB(255, 255, 255, 255);
1263
Mike Reedb286bc22019-04-08 16:23:20 -04001264 sk_sp<SkColorFilter> green(SkColorFilters::Blend(SK_ColorGREEN, SkBlendMode::kSrcIn));
Michael Ludwig55edb502019-08-05 10:41:10 -04001265 sk_sp<SkImageFilter> greenFilter(SkImageFilters::ColorFilter(green, nullptr));
1266 SkIRect cropRect = SkIRect::MakeEmpty();
1267 sk_sp<SkImageFilter> croppedOut(SkImageFilters::ColorFilter(green, nullptr, &cropRect));
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001268
1269 // Check that an xfermode image filter whose input has been cropped out still draws the other
1270 // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
reed374772b2016-10-05 17:33:02 -07001271 SkBlendMode mode = SkBlendMode::kSrcOver;
Michael Ludwig55edb502019-08-05 10:41:10 -04001272 sk_sp<SkImageFilter> xfermodeNoFg(SkImageFilters::Xfermode(
1273 mode, greenFilter, croppedOut, nullptr));
1274 sk_sp<SkImageFilter> xfermodeNoBg(SkImageFilters::Xfermode(
1275 mode, croppedOut, greenFilter, nullptr));
1276 sk_sp<SkImageFilter> xfermodeNoFgNoBg(SkImageFilters::Xfermode(
1277 mode, croppedOut, croppedOut, nullptr));
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001278
1279 SkPaint paint;
robertphillips8c0326d2016-04-05 12:48:34 -07001280 paint.setImageFilter(std::move(xfermodeNoFg));
reedda420b92015-12-16 08:38:15 -08001281 canvas->drawBitmap(bitmap, 0, 0, &paint); // drawSprite
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001282
1283 uint32_t pixel;
kkinnunena9d9a392015-03-06 07:16:00 -08001284 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
Mike Reedf1942192017-07-21 14:24:29 -04001285 surf->readPixels(info, &pixel, 4, 0, 0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001286 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1287
robertphillips8c0326d2016-04-05 12:48:34 -07001288 paint.setImageFilter(std::move(xfermodeNoBg));
reedda420b92015-12-16 08:38:15 -08001289 canvas->drawBitmap(bitmap, 0, 0, &paint); // drawSprite
Mike Reedf1942192017-07-21 14:24:29 -04001290 surf->readPixels(info, &pixel, 4, 0, 0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001291 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1292
robertphillips8c0326d2016-04-05 12:48:34 -07001293 paint.setImageFilter(std::move(xfermodeNoFgNoBg));
reedda420b92015-12-16 08:38:15 -08001294 canvas->drawBitmap(bitmap, 0, 0, &paint); // drawSprite
Mike Reedf1942192017-07-21 14:24:29 -04001295 surf->readPixels(info, &pixel, 4, 0, 0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001296 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1297}
1298
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001299DEF_TEST(ImageFilterNestedSaveLayer, reporter) {
1300 SkBitmap temp;
1301 temp.allocN32Pixels(50, 50);
robertphillips9a53fd72015-06-22 09:46:59 -07001302 SkCanvas canvas(temp);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001303 canvas.clear(0x0);
1304
1305 SkBitmap bitmap;
1306 bitmap.allocN32Pixels(10, 10);
1307 bitmap.eraseColor(SK_ColorGREEN);
1308
1309 SkMatrix matrix;
1310 matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
1311 matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
robertphillipsae8c9332016-04-05 15:09:00 -07001312 sk_sp<SkImageFilter> matrixFilter(
Michael Ludwig55edb502019-08-05 10:41:10 -04001313 SkImageFilter::MakeMatrixFilter(matrix, kLow_SkFilterQuality, nullptr));
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001314
1315 // Test that saveLayer() with a filter nested inside another saveLayer() applies the
1316 // correct offset to the filter matrix.
1317 SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
halcanary96fcdcc2015-08-27 07:41:13 -07001318 canvas.saveLayer(&bounds1, nullptr);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001319 SkPaint filterPaint;
robertphillipsae8c9332016-04-05 15:09:00 -07001320 filterPaint.setImageFilter(std::move(matrixFilter));
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001321 SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
1322 canvas.saveLayer(&bounds2, &filterPaint);
1323 SkPaint greenPaint;
1324 greenPaint.setColor(SK_ColorGREEN);
1325 canvas.drawRect(bounds2, greenPaint);
1326 canvas.restore();
1327 canvas.restore();
1328 SkPaint strokePaint;
1329 strokePaint.setStyle(SkPaint::kStroke_Style);
1330 strokePaint.setColor(SK_ColorRED);
1331
kkinnunena9d9a392015-03-06 07:16:00 -08001332 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001333 uint32_t pixel;
Mike Reedf1942192017-07-21 14:24:29 -04001334 temp.readPixels(info, &pixel, 4, 25, 25);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001335 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1336
1337 // Test that drawSprite() with a filter nested inside a saveLayer() applies the
1338 // correct offset to the filter matrix.
1339 canvas.clear(0x0);
Mike Reedf1942192017-07-21 14:24:29 -04001340 temp.readPixels(info, &pixel, 4, 25, 25);
halcanary96fcdcc2015-08-27 07:41:13 -07001341 canvas.saveLayer(&bounds1, nullptr);
reedda420b92015-12-16 08:38:15 -08001342 canvas.drawBitmap(bitmap, 20, 20, &filterPaint); // drawSprite
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001343 canvas.restore();
1344
Mike Reedf1942192017-07-21 14:24:29 -04001345 temp.readPixels(info, &pixel, 4, 25, 25);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001346 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1347}
1348
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001349DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
Mike Reedf1942192017-07-21 14:24:29 -04001350 test_xfermode_cropped_input(SkSurface::MakeRasterN32Premul(100, 100).get(), reporter);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001351}
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001352
robertphillips3e302272016-04-20 11:48:36 -07001353static void test_composed_imagefilter_offset(skiatest::Reporter* reporter, GrContext* context) {
1354 sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 100));
ajuma5788faa2015-02-13 09:05:47 -08001355
Michael Ludwig55edb502019-08-05 10:41:10 -04001356 SkIRect cropRect = SkIRect::MakeXYWH(1, 0, 20, 20);
1357 sk_sp<SkImageFilter> offsetFilter(SkImageFilters::Offset(0, 0, nullptr, &cropRect));
1358 sk_sp<SkImageFilter> blurFilter(SkImageFilters::Blur(SK_Scalar1, SK_Scalar1,
robertphillips6e7025a2016-04-04 04:31:25 -07001359 nullptr, &cropRect));
Michael Ludwig55edb502019-08-05 10:41:10 -04001360 sk_sp<SkImageFilter> composedFilter(SkImageFilters::Compose(std::move(blurFilter),
1361 std::move(offsetFilter)));
ajuma5788faa2015-02-13 09:05:47 -08001362 SkIPoint offset;
Michael Ludwig8ee6cf32019-08-02 09:57:04 -04001363 SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -04001364 kN32_SkColorType, nullptr, srcImg.get());
robertphillips4418dba2016-03-07 12:45:14 -08001365
Michael Ludwig8ee6cf32019-08-02 09:57:04 -04001366 sk_sp<SkSpecialImage> resultImg(
Michael Ludwigea071232019-08-26 10:52:15 -04001367 as_IFB(composedFilter)->filterImage(ctx).imageAndOffset(&offset));
robertphillips4418dba2016-03-07 12:45:14 -08001368 REPORTER_ASSERT(reporter, resultImg);
ajuma5788faa2015-02-13 09:05:47 -08001369 REPORTER_ASSERT(reporter, offset.fX == 1 && offset.fY == 0);
1370}
1371
robertphillips4418dba2016-03-07 12:45:14 -08001372DEF_TEST(ComposedImageFilterOffset, reporter) {
robertphillips3e302272016-04-20 11:48:36 -07001373 test_composed_imagefilter_offset(reporter, nullptr);
robertphillips4418dba2016-03-07 12:45:14 -08001374}
1375
bsalomon68d91342016-04-12 09:59:58 -07001376DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ComposedImageFilterOffset_Gpu, reporter, ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -07001377 test_composed_imagefilter_offset(reporter, ctxInfo.grContext());
robertphillips4418dba2016-03-07 12:45:14 -08001378}
robertphillips4418dba2016-03-07 12:45:14 -08001379
robertphillips3e302272016-04-20 11:48:36 -07001380static void test_composed_imagefilter_bounds(skiatest::Reporter* reporter, GrContext* context) {
jbroman17a65202016-03-21 08:38:58 -07001381 // The bounds passed to the inner filter must be filtered by the outer
1382 // filter, so that the inner filter produces the pixels that the outer
1383 // filter requires as input. This matters if the outer filter moves pixels.
1384 // Here, accounting for the outer offset is necessary so that the green
1385 // pixels of the picture are not clipped.
1386
1387 SkPictureRecorder recorder;
Michael Ludwig55edb502019-08-05 10:41:10 -04001388 SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeIWH(200, 100));
jbroman17a65202016-03-21 08:38:58 -07001389 recordingCanvas->clipRect(SkRect::MakeXYWH(100, 0, 100, 100));
1390 recordingCanvas->clear(SK_ColorGREEN);
robertphillips491fb172016-03-30 12:32:58 -07001391 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
Michael Ludwig55edb502019-08-05 10:41:10 -04001392 sk_sp<SkImageFilter> pictureFilter(SkImageFilters::Picture(picture));
1393 SkIRect cropRect = SkIRect::MakeWH(100, 100);
1394 sk_sp<SkImageFilter> offsetFilter(SkImageFilters::Offset(-100, 0, nullptr, &cropRect));
1395 sk_sp<SkImageFilter> composedFilter(SkImageFilters::Compose(std::move(offsetFilter),
1396 std::move(pictureFilter)));
jbroman17a65202016-03-21 08:38:58 -07001397
robertphillips3e302272016-04-20 11:48:36 -07001398 sk_sp<SkSpecialImage> sourceImage(create_empty_special_image(context, 100));
Michael Ludwig8ee6cf32019-08-02 09:57:04 -04001399 SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr,
Michael Ludwige30a4852019-08-14 14:35:42 -04001400 kN32_SkColorType, nullptr, sourceImage.get());
jbroman17a65202016-03-21 08:38:58 -07001401 SkIPoint offset;
Michael Ludwig8ee6cf32019-08-02 09:57:04 -04001402 sk_sp<SkSpecialImage> result(
Michael Ludwigea071232019-08-26 10:52:15 -04001403 as_IFB(composedFilter)->filterImage(ctx).imageAndOffset(&offset));
jbroman17a65202016-03-21 08:38:58 -07001404 REPORTER_ASSERT(reporter, offset.isZero());
1405 REPORTER_ASSERT(reporter, result);
1406 REPORTER_ASSERT(reporter, result->subset().size() == SkISize::Make(100, 100));
1407
1408 SkBitmap resultBM;
robertphillips64612512016-04-08 12:10:42 -07001409 REPORTER_ASSERT(reporter, result->getROPixels(&resultBM));
jbroman17a65202016-03-21 08:38:58 -07001410 REPORTER_ASSERT(reporter, resultBM.getColor(50, 50) == SK_ColorGREEN);
1411}
1412
1413DEF_TEST(ComposedImageFilterBounds, reporter) {
robertphillips3e302272016-04-20 11:48:36 -07001414 test_composed_imagefilter_bounds(reporter, nullptr);
jbroman17a65202016-03-21 08:38:58 -07001415}
1416
egdanielab527a52016-06-28 08:07:26 -07001417DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ComposedImageFilterBounds_Gpu, reporter, ctxInfo) {
bsalomon8b7451a2016-05-11 06:33:06 -07001418 test_composed_imagefilter_bounds(reporter, ctxInfo.grContext());
jbroman17a65202016-03-21 08:38:58 -07001419}
jbroman17a65202016-03-21 08:38:58 -07001420
senorblanco0abdf762015-08-20 11:10:41 -07001421DEF_TEST(ImageFilterCanComputeFastBounds, reporter) {
1422
robertphillips12fa47d2016-04-08 16:28:09 -07001423 {
1424 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
Michael Ludwig55edb502019-08-05 10:41:10 -04001425 sk_sp<SkImageFilter> lighting(SkImageFilters::PointLitDiffuse(
1426 location, SK_ColorGREEN, 0, 0, nullptr));
robertphillips12fa47d2016-04-08 16:28:09 -07001427 REPORTER_ASSERT(reporter, !lighting->canComputeFastBounds());
1428 }
senorblanco0abdf762015-08-20 11:10:41 -07001429
senorblanco0abdf762015-08-20 11:10:41 -07001430 {
robertphillips6e7025a2016-04-04 04:31:25 -07001431 sk_sp<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
1432 REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1433 {
1434 SkColorFilter* grayCF;
1435 REPORTER_ASSERT(reporter, gray->asAColorFilter(&grayCF));
1436 REPORTER_ASSERT(reporter, !grayCF->affectsTransparentBlack());
1437 grayCF->unref();
1438 }
1439 REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1440
Michael Ludwig55edb502019-08-05 10:41:10 -04001441 sk_sp<SkImageFilter> grayBlur(SkImageFilters::Blur(
1442 SK_Scalar1, SK_Scalar1, std::move(gray)));
robertphillips6e7025a2016-04-04 04:31:25 -07001443 REPORTER_ASSERT(reporter, grayBlur->canComputeFastBounds());
senorblanco0abdf762015-08-20 11:10:41 -07001444 }
senorblanco0abdf762015-08-20 11:10:41 -07001445
robertphillips6e7025a2016-04-04 04:31:25 -07001446 {
Mike Reede869a1e2019-04-30 12:18:54 -04001447 float greenMatrix[20] = { 0, 0, 0, 0, 0,
1448 0, 0, 0, 0, 1.0f/255,
1449 0, 0, 0, 0, 0,
1450 0, 0, 0, 0, 1.0f/255
1451 };
1452 sk_sp<SkColorFilter> greenCF(SkColorFilters::Matrix(greenMatrix));
Michael Ludwig55edb502019-08-05 10:41:10 -04001453 sk_sp<SkImageFilter> green(SkImageFilters::ColorFilter(greenCF, nullptr));
senorblanco0abdf762015-08-20 11:10:41 -07001454
robertphillips6e7025a2016-04-04 04:31:25 -07001455 REPORTER_ASSERT(reporter, greenCF->affectsTransparentBlack());
1456 REPORTER_ASSERT(reporter, !green->canComputeFastBounds());
senorblanco0abdf762015-08-20 11:10:41 -07001457
Michael Ludwig55edb502019-08-05 10:41:10 -04001458 sk_sp<SkImageFilter> greenBlur(SkImageFilters::Blur(SK_Scalar1, SK_Scalar1,
robertphillips6e7025a2016-04-04 04:31:25 -07001459 std::move(green)));
1460 REPORTER_ASSERT(reporter, !greenBlur->canComputeFastBounds());
1461 }
senorblanco0abdf762015-08-20 11:10:41 -07001462
1463 uint8_t allOne[256], identity[256];
1464 for (int i = 0; i < 256; ++i) {
1465 identity[i] = i;
1466 allOne[i] = 255;
1467 }
1468
robertphillips5605b562016-04-05 11:50:42 -07001469 sk_sp<SkColorFilter> identityCF(SkTableColorFilter::MakeARGB(identity, identity,
1470 identity, allOne));
Michael Ludwig55edb502019-08-05 10:41:10 -04001471 sk_sp<SkImageFilter> identityFilter(SkImageFilters::ColorFilter(identityCF, nullptr));
senorblanco0abdf762015-08-20 11:10:41 -07001472 REPORTER_ASSERT(reporter, !identityCF->affectsTransparentBlack());
1473 REPORTER_ASSERT(reporter, identityFilter->canComputeFastBounds());
1474
robertphillips5605b562016-04-05 11:50:42 -07001475 sk_sp<SkColorFilter> forceOpaqueCF(SkTableColorFilter::MakeARGB(allOne, identity,
1476 identity, identity));
Michael Ludwig55edb502019-08-05 10:41:10 -04001477 sk_sp<SkImageFilter> forceOpaque(SkImageFilters::ColorFilter(forceOpaqueCF, nullptr));
senorblanco0abdf762015-08-20 11:10:41 -07001478 REPORTER_ASSERT(reporter, forceOpaqueCF->affectsTransparentBlack());
1479 REPORTER_ASSERT(reporter, !forceOpaque->canComputeFastBounds());
1480}
1481
fmalitacd56f812015-09-14 13:31:18 -07001482// Verify that SkImageSource survives serialization
1483DEF_TEST(ImageFilterImageSourceSerialization, reporter) {
reede8f30622016-03-23 18:59:25 -07001484 auto surface(SkSurface::MakeRasterN32Premul(10, 10));
fmalitacd56f812015-09-14 13:31:18 -07001485 surface->getCanvas()->clear(SK_ColorGREEN);
reed9ce9d672016-03-17 10:51:11 -07001486 sk_sp<SkImage> image(surface->makeImageSnapshot());
Michael Ludwig55edb502019-08-05 10:41:10 -04001487 sk_sp<SkImageFilter> filter(SkImageFilters::Image(std::move(image)));
fmalitacd56f812015-09-14 13:31:18 -07001488
Mike Reed0331d372018-01-23 11:57:30 -05001489 sk_sp<SkData> data(filter->serialize());
1490 sk_sp<SkImageFilter> unflattenedFilter = SkImageFilter::Deserialize(data->data(), data->size());
fmalitacd56f812015-09-14 13:31:18 -07001491 REPORTER_ASSERT(reporter, unflattenedFilter);
1492
1493 SkBitmap bm;
1494 bm.allocN32Pixels(10, 10);
fmalita23cb88c2015-09-15 06:56:23 -07001495 bm.eraseColor(SK_ColorBLUE);
fmalitacd56f812015-09-14 13:31:18 -07001496 SkPaint paint;
1497 paint.setColor(SK_ColorRED);
1498 paint.setImageFilter(unflattenedFilter);
1499
1500 SkCanvas canvas(bm);
Michael Ludwig55edb502019-08-05 10:41:10 -04001501 canvas.drawRect(SkRect::MakeIWH(10, 10), paint);
fmalitacd56f812015-09-14 13:31:18 -07001502 REPORTER_ASSERT(reporter, *bm.getAddr32(0, 0) == SkPreMultiplyColor(SK_ColorGREEN));
1503}
1504
Leon Scroggins III4cdbf602017-09-28 14:33:57 -04001505DEF_TEST(ImageFilterImageSourceUninitialized, r) {
1506 sk_sp<SkData> data(GetResourceAsData("crbug769134.fil"));
1507 if (!data) {
1508 return;
1509 }
Mike Reed0331d372018-01-23 11:57:30 -05001510 sk_sp<SkImageFilter> unflattenedFilter = SkImageFilter::Deserialize(data->data(), data->size());
Leon Scroggins III4cdbf602017-09-28 14:33:57 -04001511 // This will fail. More importantly, msan will verify that we did not
1512 // compare against uninitialized memory.
1513 REPORTER_ASSERT(r, !unflattenedFilter);
1514}
1515
bsalomon45eefcf2016-01-05 08:39:28 -08001516static void test_large_blur_input(skiatest::Reporter* reporter, SkCanvas* canvas) {
1517 SkBitmap largeBmp;
1518 int largeW = 5000;
1519 int largeH = 5000;
bsalomon45eefcf2016-01-05 08:39:28 -08001520 // If we're GPU-backed make the bitmap too large to be converted into a texture.
1521 if (GrContext* ctx = canvas->getGrContext()) {
Robert Phillips9da87e02019-02-04 13:26:26 -05001522 largeW = ctx->priv().caps()->maxTextureSize() + 1;
bsalomon45eefcf2016-01-05 08:39:28 -08001523 }
bsalomon45eefcf2016-01-05 08:39:28 -08001524
1525 largeBmp.allocN32Pixels(largeW, largeH);
mtklein2afbe232016-02-07 12:23:10 -08001526 largeBmp.eraseColor(0);
bsalomon45eefcf2016-01-05 08:39:28 -08001527 if (!largeBmp.getPixels()) {
1528 ERRORF(reporter, "Failed to allocate large bmp.");
1529 return;
1530 }
1531
reed9ce9d672016-03-17 10:51:11 -07001532 sk_sp<SkImage> largeImage(SkImage::MakeFromBitmap(largeBmp));
bsalomon45eefcf2016-01-05 08:39:28 -08001533 if (!largeImage) {
1534 ERRORF(reporter, "Failed to create large image.");
1535 return;
1536 }
1537
Michael Ludwig55edb502019-08-05 10:41:10 -04001538 sk_sp<SkImageFilter> largeSource(SkImageFilters::Image(std::move(largeImage)));
bsalomon45eefcf2016-01-05 08:39:28 -08001539 if (!largeSource) {
1540 ERRORF(reporter, "Failed to create large SkImageSource.");
1541 return;
1542 }
1543
Michael Ludwig55edb502019-08-05 10:41:10 -04001544 sk_sp<SkImageFilter> blur(SkImageFilters::Blur(10.f, 10.f, std::move(largeSource)));
bsalomon45eefcf2016-01-05 08:39:28 -08001545 if (!blur) {
1546 ERRORF(reporter, "Failed to create SkBlurImageFilter.");
1547 return;
1548 }
1549
1550 SkPaint paint;
robertphillips549c8992016-04-01 09:28:51 -07001551 paint.setImageFilter(std::move(blur));
bsalomon45eefcf2016-01-05 08:39:28 -08001552
1553 // This should not crash (http://crbug.com/570479).
1554 canvas->drawRect(SkRect::MakeIWH(largeW, largeH), paint);
1555}
1556
senorblanco21a465d2016-04-11 11:58:39 -07001557DEF_TEST(ImageFilterBlurLargeImage, reporter) {
reede8f30622016-03-23 18:59:25 -07001558 auto surface(SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(100, 100)));
bsalomon45eefcf2016-01-05 08:39:28 -08001559 test_large_blur_input(reporter, surface->getCanvas());
1560}
1561
senorblanco5878dbd2016-05-19 14:50:29 -07001562static void test_make_with_filter(skiatest::Reporter* reporter, GrContext* context) {
Robert Phillipsa5fdc972017-02-18 16:58:09 -05001563 sk_sp<SkSurface> surface(create_surface(context, 192, 128));
senorblanco5878dbd2016-05-19 14:50:29 -07001564 surface->getCanvas()->clear(SK_ColorRED);
1565 SkPaint bluePaint;
1566 bluePaint.setColor(SK_ColorBLUE);
1567 SkIRect subset = SkIRect::MakeXYWH(25, 20, 50, 50);
1568 surface->getCanvas()->drawRect(SkRect::Make(subset), bluePaint);
1569 sk_sp<SkImage> sourceImage = surface->makeImageSnapshot();
1570
1571 sk_sp<SkImageFilter> filter = make_grayscale(nullptr, nullptr);
1572 SkIRect clipBounds = SkIRect::MakeXYWH(30, 35, 100, 100);
1573 SkIRect outSubset;
1574 SkIPoint offset;
1575 sk_sp<SkImage> result;
1576
1577 result = sourceImage->makeWithFilter(nullptr, subset, clipBounds, &outSubset, &offset);
1578 REPORTER_ASSERT(reporter, !result);
1579
1580 result = sourceImage->makeWithFilter(filter.get(), subset, clipBounds, nullptr, &offset);
1581 REPORTER_ASSERT(reporter, !result);
1582
1583 result = sourceImage->makeWithFilter(filter.get(), subset, clipBounds, &outSubset, nullptr);
1584 REPORTER_ASSERT(reporter, !result);
1585
1586 SkIRect bigSubset = SkIRect::MakeXYWH(-10000, -10000, 20000, 20000);
1587 result = sourceImage->makeWithFilter(filter.get(), bigSubset, clipBounds, &outSubset, &offset);
1588 REPORTER_ASSERT(reporter, !result);
1589
1590 SkIRect empty = SkIRect::MakeEmpty();
1591 result = sourceImage->makeWithFilter(filter.get(), empty, clipBounds, &outSubset, &offset);
1592 REPORTER_ASSERT(reporter, !result);
1593
1594 result = sourceImage->makeWithFilter(filter.get(), subset, empty, &outSubset, &offset);
1595 REPORTER_ASSERT(reporter, !result);
1596
1597 SkIRect leftField = SkIRect::MakeXYWH(-1000, 0, 100, 100);
1598 result = sourceImage->makeWithFilter(filter.get(), subset, leftField, &outSubset, &offset);
1599 REPORTER_ASSERT(reporter, !result);
1600
1601 result = sourceImage->makeWithFilter(filter.get(), subset, clipBounds, &outSubset, &offset);
1602
1603 REPORTER_ASSERT(reporter, result);
1604 REPORTER_ASSERT(reporter, result->bounds().contains(outSubset));
1605 SkIRect destRect = SkIRect::MakeXYWH(offset.x(), offset.y(),
1606 outSubset.width(), outSubset.height());
1607 REPORTER_ASSERT(reporter, clipBounds.contains(destRect));
Robert Phillipsa5fdc972017-02-18 16:58:09 -05001608
1609 // In GPU-mode, this case creates a special image with a backing size that differs from
1610 // the content size
1611 {
1612 clipBounds.setXYWH(0, 0, 170, 100);
1613 subset.setXYWH(0, 0, 160, 90);
1614
Michael Ludwig55edb502019-08-05 10:41:10 -04001615 filter = SkImageFilters::Xfermode(SkBlendMode::kSrc, nullptr);
Robert Phillipsa5fdc972017-02-18 16:58:09 -05001616 result = sourceImage->makeWithFilter(filter.get(), subset, clipBounds, &outSubset, &offset);
1617 REPORTER_ASSERT(reporter, result);
1618 }
senorblanco5878dbd2016-05-19 14:50:29 -07001619}
1620
1621DEF_TEST(ImageFilterMakeWithFilter, reporter) {
1622 test_make_with_filter(reporter, nullptr);
1623}
1624
senorblanco5878dbd2016-05-19 14:50:29 -07001625DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterMakeWithFilter_Gpu, reporter, ctxInfo) {
1626 test_make_with_filter(reporter, ctxInfo.grContext());
1627}
reed4a8126e2014-09-22 07:29:03 -07001628
bsalomon68d91342016-04-12 09:59:58 -07001629DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterHugeBlur_Gpu, reporter, ctxInfo) {
robertphillipsefbffed2015-06-22 12:06:08 -07001630
bsalomon8b7451a2016-05-11 06:33:06 -07001631 sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(ctxInfo.grContext(),
robertphillips3e302272016-04-20 11:48:36 -07001632 SkBudgeted::kNo,
1633 SkImageInfo::MakeN32Premul(100, 100)));
robertphillips9a53fd72015-06-22 09:46:59 -07001634
robertphillips3e302272016-04-20 11:48:36 -07001635
1636 SkCanvas* canvas = surf->getCanvas();
1637
1638 test_huge_blur(canvas, reporter);
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001639}
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001640
egdanielab527a52016-06-28 08:07:26 -07001641DEF_GPUTEST_FOR_RENDERING_CONTEXTS(XfermodeImageFilterCroppedInput_Gpu, reporter, ctxInfo) {
Brian Salomon8996e182017-07-05 17:01:48 -04001642 sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(
1643 ctxInfo.grContext(),
1644 SkBudgeted::kNo,
1645 SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType)));
robertphillips3e302272016-04-20 11:48:36 -07001646
Mike Reedf1942192017-07-21 14:24:29 -04001647 test_xfermode_cropped_input(surf.get(), reporter);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001648}
senorblanco32673b92014-09-09 09:15:04 -07001649
egdanielab527a52016-06-28 08:07:26 -07001650DEF_GPUTEST_FOR_ALL_CONTEXTS(ImageFilterBlurLargeImage_Gpu, reporter, ctxInfo) {
Brian Salomon8996e182017-07-05 17:01:48 -04001651 auto surface(SkSurface::MakeRenderTarget(
1652 ctxInfo.grContext(), SkBudgeted::kYes,
1653 SkImageInfo::Make(100, 100, kRGBA_8888_SkColorType, kPremul_SkAlphaType)));
bsalomon45eefcf2016-01-05 08:39:28 -08001654 test_large_blur_input(reporter, surface->getCanvas());
1655}
reedbb34a8a2016-04-23 15:19:07 -07001656
1657/*
1658 * Test that colorfilterimagefilter does not require its CTM to be decomposed when it has more
1659 * than just scale/translate, but that other filters do.
1660 */
reed96a04f32016-04-25 09:25:15 -07001661DEF_TEST(ImageFilterComplexCTM, reporter) {
reedbb34a8a2016-04-23 15:19:07 -07001662 // just need a colorfilter to exercise the corresponding imagefilter
Mike Reedb286bc22019-04-08 16:23:20 -04001663 sk_sp<SkColorFilter> cf = SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcATop);
Michael Ludwig55edb502019-08-05 10:41:10 -04001664 sk_sp<SkImageFilter> cfif = SkImageFilters::ColorFilter(cf, nullptr); // can handle
1665 sk_sp<SkImageFilter> blif = SkImageFilters::Blur(3, 3, nullptr); // cannot handle
reedbb34a8a2016-04-23 15:19:07 -07001666
1667 struct {
1668 sk_sp<SkImageFilter> fFilter;
1669 bool fExpectCanHandle;
1670 } recs[] = {
Michael Ludwig55edb502019-08-05 10:41:10 -04001671 { cfif, true },
1672 { SkImageFilters::ColorFilter(cf, cfif), true },
1673 { SkImageFilters::Merge(cfif, cfif), true },
1674 { SkImageFilters::Compose(cfif, cfif), true },
reed96a04f32016-04-25 09:25:15 -07001675
Michael Ludwig55edb502019-08-05 10:41:10 -04001676 { blif, false },
1677 { SkImageFilters::Blur(3, 3, cfif), false },
1678 { SkImageFilters::ColorFilter(cf, blif), false },
1679 { SkImageFilters::Merge(cfif, blif), false },
1680 { SkImageFilters::Compose(blif, cfif), false },
reedbb34a8a2016-04-23 15:19:07 -07001681 };
liyuqianbfebe222016-11-14 11:17:16 -08001682
reedbb34a8a2016-04-23 15:19:07 -07001683 for (const auto& rec : recs) {
Michael Ludwig8ee6cf32019-08-02 09:57:04 -04001684 const bool canHandle = as_IFB(rec.fFilter)->canHandleComplexCTM();
reedbb34a8a2016-04-23 15:19:07 -07001685 REPORTER_ASSERT(reporter, canHandle == rec.fExpectCanHandle);
1686 }
1687}
Florin Malita08252ec2017-07-06 12:48:15 -04001688
Xianzhu Wangb4496662017-09-25 10:26:40 -07001689// Test SkXfermodeImageFilter::filterBounds with different blending modes.
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001690DEF_TEST(XfermodeImageFilterBounds, reporter) {
1691 SkIRect background_rect = SkIRect::MakeXYWH(0, 0, 100, 100);
1692 SkIRect foreground_rect = SkIRect::MakeXYWH(50, 50, 100, 100);
1693 sk_sp<SkImageFilter> background(new FixedBoundsImageFilter(background_rect));
1694 sk_sp<SkImageFilter> foreground(new FixedBoundsImageFilter(foreground_rect));
1695
1696 const int kModeCount = static_cast<int>(SkBlendMode::kLastMode) + 1;
1697 SkIRect expectedBounds[kModeCount];
1698 // Expect union of input rects by default.
1699 for (int i = 0; i < kModeCount; ++i) {
1700 expectedBounds[i] = background_rect;
1701 expectedBounds[i].join(foreground_rect);
1702 }
1703
1704 SkIRect intersection = background_rect;
1705 intersection.intersect(foreground_rect);
1706 expectedBounds[static_cast<int>(SkBlendMode::kClear)] = SkIRect::MakeEmpty();
1707 expectedBounds[static_cast<int>(SkBlendMode::kSrc)] = foreground_rect;
1708 expectedBounds[static_cast<int>(SkBlendMode::kDst)] = background_rect;
1709 expectedBounds[static_cast<int>(SkBlendMode::kSrcIn)] = intersection;
1710 expectedBounds[static_cast<int>(SkBlendMode::kDstIn)] = intersection;
1711 expectedBounds[static_cast<int>(SkBlendMode::kSrcATop)] = background_rect;
1712 expectedBounds[static_cast<int>(SkBlendMode::kDstATop)] = foreground_rect;
1713
1714 // The value of this variable doesn't matter because we use inputs with fixed bounds.
1715 SkIRect src = SkIRect::MakeXYWH(11, 22, 33, 44);
1716 for (int i = 0; i < kModeCount; ++i) {
Michael Ludwig55edb502019-08-05 10:41:10 -04001717 sk_sp<SkImageFilter> xfermode(SkImageFilters::Xfermode(static_cast<SkBlendMode>(i),
1718 background, foreground, nullptr));
Robert Phillips12078432018-05-17 11:17:39 -04001719 auto bounds = xfermode->filterBounds(src, SkMatrix::I(),
1720 SkImageFilter::kForward_MapDirection, nullptr);
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001721 REPORTER_ASSERT(reporter, bounds == expectedBounds[i]);
1722 }
1723
1724 // Test empty intersection.
1725 sk_sp<SkImageFilter> background2(new FixedBoundsImageFilter(SkIRect::MakeXYWH(0, 0, 20, 20)));
1726 sk_sp<SkImageFilter> foreground2(new FixedBoundsImageFilter(SkIRect::MakeXYWH(40, 40, 50, 50)));
Michael Ludwig55edb502019-08-05 10:41:10 -04001727 sk_sp<SkImageFilter> xfermode(SkImageFilters::Xfermode(
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001728 SkBlendMode::kSrcIn, std::move(background2), std::move(foreground2), nullptr));
Robert Phillips12078432018-05-17 11:17:39 -04001729 auto bounds = xfermode->filterBounds(src, SkMatrix::I(),
1730 SkImageFilter::kForward_MapDirection, nullptr);
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001731 REPORTER_ASSERT(reporter, bounds.isEmpty());
1732}
1733
Fredrik Söderquistb87f7982017-10-26 13:54:16 +02001734DEF_TEST(OffsetImageFilterBounds, reporter) {
1735 SkIRect src = SkIRect::MakeXYWH(0, 0, 100, 100);
Michael Ludwig55edb502019-08-05 10:41:10 -04001736 sk_sp<SkImageFilter> offset(SkImageFilters::Offset(-50.5f, -50.5f, nullptr));
Fredrik Söderquistb87f7982017-10-26 13:54:16 +02001737
1738 SkIRect expectedForward = SkIRect::MakeXYWH(-50, -50, 100, 100);
1739 SkIRect boundsForward = offset->filterBounds(src, SkMatrix::I(),
Robert Phillips12078432018-05-17 11:17:39 -04001740 SkImageFilter::kForward_MapDirection, nullptr);
Fredrik Söderquistb87f7982017-10-26 13:54:16 +02001741 REPORTER_ASSERT(reporter, boundsForward == expectedForward);
1742
1743 SkIRect expectedReverse = SkIRect::MakeXYWH(50, 50, 100, 100);
1744 SkIRect boundsReverse = offset->filterBounds(src, SkMatrix::I(),
Robert Phillips12078432018-05-17 11:17:39 -04001745 SkImageFilter::kReverse_MapDirection, &src);
Fredrik Söderquistb87f7982017-10-26 13:54:16 +02001746 REPORTER_ASSERT(reporter, boundsReverse == expectedReverse);
1747}
1748
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001749static void test_arithmetic_bounds(skiatest::Reporter* reporter, float k1, float k2, float k3,
1750 float k4, sk_sp<SkImageFilter> background,
1751 sk_sp<SkImageFilter> foreground,
Michael Ludwig55edb502019-08-05 10:41:10 -04001752 const SkIRect* crop, const SkIRect& expected) {
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001753 sk_sp<SkImageFilter> arithmetic(
Michael Ludwig55edb502019-08-05 10:41:10 -04001754 SkImageFilters::Arithmetic(k1, k2, k3, k4, false, background, foreground, crop));
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001755 // The value of the input rect doesn't matter because we use inputs with fixed bounds.
1756 SkIRect bounds = arithmetic->filterBounds(SkIRect::MakeXYWH(11, 22, 33, 44), SkMatrix::I(),
Robert Phillips12078432018-05-17 11:17:39 -04001757 SkImageFilter::kForward_MapDirection, nullptr);
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001758 REPORTER_ASSERT(reporter, expected == bounds);
1759}
1760
1761static void test_arithmetic_combinations(skiatest::Reporter* reporter, float v) {
Michael Ludwig55edb502019-08-05 10:41:10 -04001762 SkIRect bgRect = SkIRect::MakeXYWH(0, 0, 100, 100);
1763 SkIRect fgRect = SkIRect::MakeXYWH(50, 50, 100, 100);
1764 sk_sp<SkImageFilter> background(new FixedBoundsImageFilter(bgRect));
1765 sk_sp<SkImageFilter> foreground(new FixedBoundsImageFilter(fgRect));
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001766
Michael Ludwig55edb502019-08-05 10:41:10 -04001767 SkIRect unionRect = bgRect;
1768 unionRect.join(fgRect);
1769 SkIRect intersection = bgRect;
1770 intersection.intersect(fgRect);
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001771
1772 test_arithmetic_bounds(reporter, 0, 0, 0, 0, background, foreground, nullptr,
1773 SkIRect::MakeEmpty());
Michael Ludwig55edb502019-08-05 10:41:10 -04001774 test_arithmetic_bounds(reporter, 0, 0, 0, v, background, foreground, nullptr, unionRect);
1775 test_arithmetic_bounds(reporter, 0, 0, v, 0, background, foreground, nullptr, bgRect);
1776 test_arithmetic_bounds(reporter, 0, 0, v, v, background, foreground, nullptr, unionRect);
1777 test_arithmetic_bounds(reporter, 0, v, 0, 0, background, foreground, nullptr, fgRect);
1778 test_arithmetic_bounds(reporter, 0, v, 0, v, background, foreground, nullptr, unionRect);
1779 test_arithmetic_bounds(reporter, 0, v, v, 0, background, foreground, nullptr, unionRect);
1780 test_arithmetic_bounds(reporter, 0, v, v, v, background, foreground, nullptr, unionRect);
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001781 test_arithmetic_bounds(reporter, v, 0, 0, 0, background, foreground, nullptr, intersection);
Michael Ludwig55edb502019-08-05 10:41:10 -04001782 test_arithmetic_bounds(reporter, v, 0, 0, v, background, foreground, nullptr, unionRect);
1783 test_arithmetic_bounds(reporter, v, 0, v, 0, background, foreground, nullptr, bgRect);
1784 test_arithmetic_bounds(reporter, v, 0, v, v, background, foreground, nullptr, unionRect);
1785 test_arithmetic_bounds(reporter, v, v, 0, 0, background, foreground, nullptr, fgRect);
1786 test_arithmetic_bounds(reporter, v, v, 0, v, background, foreground, nullptr, unionRect);
1787 test_arithmetic_bounds(reporter, v, v, v, 0, background, foreground, nullptr, unionRect);
1788 test_arithmetic_bounds(reporter, v, v, v, v, background, foreground, nullptr, unionRect);
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001789
Michael Ludwig55edb502019-08-05 10:41:10 -04001790 // Test with crop. When k4 is non-zero, the result is expected to be cropRect
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001791 // regardless of inputs because the filter affects the whole crop area.
Michael Ludwig55edb502019-08-05 10:41:10 -04001792 SkIRect cropRect = SkIRect::MakeXYWH(-111, -222, 333, 444);
1793 test_arithmetic_bounds(reporter, 0, 0, 0, 0, background, foreground, &cropRect,
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001794 SkIRect::MakeEmpty());
Michael Ludwig55edb502019-08-05 10:41:10 -04001795 test_arithmetic_bounds(reporter, 0, 0, 0, v, background, foreground, &cropRect, cropRect);
1796 test_arithmetic_bounds(reporter, 0, 0, v, 0, background, foreground, &cropRect, bgRect);
1797 test_arithmetic_bounds(reporter, 0, 0, v, v, background, foreground, &cropRect, cropRect);
1798 test_arithmetic_bounds(reporter, 0, v, 0, 0, background, foreground, &cropRect, fgRect);
1799 test_arithmetic_bounds(reporter, 0, v, 0, v, background, foreground, &cropRect, cropRect);
1800 test_arithmetic_bounds(reporter, 0, v, v, 0, background, foreground, &cropRect, unionRect);
1801 test_arithmetic_bounds(reporter, 0, v, v, v, background, foreground, &cropRect, cropRect);
1802 test_arithmetic_bounds(reporter, v, 0, 0, 0, background, foreground, &cropRect, intersection);
1803 test_arithmetic_bounds(reporter, v, 0, 0, v, background, foreground, &cropRect, cropRect);
1804 test_arithmetic_bounds(reporter, v, 0, v, 0, background, foreground, &cropRect, bgRect);
1805 test_arithmetic_bounds(reporter, v, 0, v, v, background, foreground, &cropRect, cropRect);
1806 test_arithmetic_bounds(reporter, v, v, 0, 0, background, foreground, &cropRect, fgRect);
1807 test_arithmetic_bounds(reporter, v, v, 0, v, background, foreground, &cropRect, cropRect);
1808 test_arithmetic_bounds(reporter, v, v, v, 0, background, foreground, &cropRect, unionRect);
1809 test_arithmetic_bounds(reporter, v, v, v, v, background, foreground, &cropRect, cropRect);
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001810}
1811
Xianzhu Wangb4496662017-09-25 10:26:40 -07001812// Test SkArithmeticImageFilter::filterBounds with different blending modes.
Xianzhu Wang0fa353c2017-08-25 16:27:04 -07001813DEF_TEST(ArithmeticImageFilterBounds, reporter) {
1814 test_arithmetic_combinations(reporter, 1);
1815 test_arithmetic_combinations(reporter, 0.5);
1816}
Xianzhu Wangb4496662017-09-25 10:26:40 -07001817
1818// Test SkImageSource::filterBounds.
1819DEF_TEST(ImageSourceBounds, reporter) {
1820 sk_sp<SkImage> image(SkImage::MakeFromBitmap(make_gradient_circle(64, 64)));
1821 // Default src and dst rects.
Michael Ludwig55edb502019-08-05 10:41:10 -04001822 sk_sp<SkImageFilter> source1(SkImageFilters::Image(image));
Xianzhu Wangb4496662017-09-25 10:26:40 -07001823 SkIRect imageBounds = SkIRect::MakeWH(64, 64);
1824 SkIRect input(SkIRect::MakeXYWH(10, 20, 30, 40));
1825 REPORTER_ASSERT(reporter,
1826 imageBounds == source1->filterBounds(input, SkMatrix::I(),
Robert Phillips12078432018-05-17 11:17:39 -04001827 SkImageFilter::kForward_MapDirection,
1828 nullptr));
Xianzhu Wangb4496662017-09-25 10:26:40 -07001829 REPORTER_ASSERT(reporter,
1830 input == source1->filterBounds(input, SkMatrix::I(),
Robert Phillips12078432018-05-17 11:17:39 -04001831 SkImageFilter::kReverse_MapDirection, &input));
Xianzhu Wangb4496662017-09-25 10:26:40 -07001832 SkMatrix scale(SkMatrix::MakeScale(2));
1833 SkIRect scaledBounds = SkIRect::MakeWH(128, 128);
1834 REPORTER_ASSERT(reporter,
1835 scaledBounds == source1->filterBounds(input, scale,
Robert Phillips12078432018-05-17 11:17:39 -04001836 SkImageFilter::kForward_MapDirection,
1837 nullptr));
1838 REPORTER_ASSERT(reporter, input == source1->filterBounds(input, scale,
1839 SkImageFilter::kReverse_MapDirection,
1840 &input));
Xianzhu Wangb4496662017-09-25 10:26:40 -07001841
1842 // Specified src and dst rects.
1843 SkRect src(SkRect::MakeXYWH(0.5, 0.5, 100.5, 100.5));
1844 SkRect dst(SkRect::MakeXYWH(-10.5, -10.5, 120.5, 120.5));
Michael Ludwig55edb502019-08-05 10:41:10 -04001845 sk_sp<SkImageFilter> source2(SkImageFilters::Image(image, src, dst, kMedium_SkFilterQuality));
Xianzhu Wangb4496662017-09-25 10:26:40 -07001846 REPORTER_ASSERT(reporter,
1847 dst.roundOut() == source2->filterBounds(input, SkMatrix::I(),
Robert Phillips12078432018-05-17 11:17:39 -04001848 SkImageFilter::kForward_MapDirection,
1849 nullptr));
Xianzhu Wangb4496662017-09-25 10:26:40 -07001850 REPORTER_ASSERT(reporter,
1851 input == source2->filterBounds(input, SkMatrix::I(),
Robert Phillips12078432018-05-17 11:17:39 -04001852 SkImageFilter::kReverse_MapDirection, &input));
Xianzhu Wangb4496662017-09-25 10:26:40 -07001853 scale.mapRect(&dst);
1854 scale.mapRect(&src);
1855 REPORTER_ASSERT(reporter,
1856 dst.roundOut() == source2->filterBounds(input, scale,
Robert Phillips12078432018-05-17 11:17:39 -04001857 SkImageFilter::kForward_MapDirection,
1858 nullptr));
1859 REPORTER_ASSERT(reporter, input == source2->filterBounds(input, scale,
1860 SkImageFilter::kReverse_MapDirection,
1861 &input));
Xianzhu Wangb4496662017-09-25 10:26:40 -07001862}
Robert Phillips12078432018-05-17 11:17:39 -04001863