1 /*
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 
8 #include "include/core/SkAlphaType.h"
9 #include "include/core/SkBBHFactory.h"
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkBlendMode.h"
12 #include "include/core/SkCanvas.h"
13 #include "include/core/SkColor.h"
14 #include "include/core/SkColorFilter.h"
15 #include "include/core/SkColorType.h"
16 #include "include/core/SkData.h"
17 #include "include/core/SkFlattenable.h"
18 #include "include/core/SkFont.h"
19 #include "include/core/SkImage.h"
20 #include "include/core/SkImageFilter.h"
21 #include "include/core/SkImageInfo.h"
22 #include "include/core/SkMatrix.h"
23 #include "include/core/SkPaint.h"
24 #include "include/core/SkPicture.h"
25 #include "include/core/SkPictureRecorder.h"
26 #include "include/core/SkPoint.h"
27 #include "include/core/SkPoint3.h"
28 #include "include/core/SkRect.h"
29 #include "include/core/SkRefCnt.h"
30 #include "include/core/SkSamplingOptions.h"
31 #include "include/core/SkScalar.h"
32 #include "include/core/SkShader.h"
33 #include "include/core/SkSize.h"
34 #include "include/core/SkSurface.h"
35 #include "include/core/SkSurfaceProps.h"
36 #include "include/core/SkTileMode.h"
37 #include "include/core/SkTypes.h"
38 #include "include/effects/SkGradientShader.h"
39 #include "include/effects/SkImageFilters.h"
40 #include "include/effects/SkPerlinNoiseShader.h"
41 #include "include/gpu/GpuTypes.h"
42 #include "include/gpu/GrDirectContext.h"
43 #include "include/gpu/GrRecordingContext.h"
44 #include "include/gpu/GrTypes.h"
45 #include "include/private/base/SkTArray.h"
46 #include "include/private/base/SkTo.h"
47 #include "src/core/SkColorFilterBase.h"
48 #include "src/core/SkImageFilterTypes.h"
49 #include "src/core/SkImageFilter_Base.h"
50 #include "src/core/SkSpecialImage.h"
51 #include "src/core/SkSpecialSurface.h"
52 #include "src/gpu/ganesh/GrCaps.h"
53 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
54 #include "src/image/SkImage_Base.h"
55 #include "tests/CtsEnforcement.h"
56 #include "tests/Test.h"
57 #include "tools/Resources.h"
58 #include "tools/ToolUtils.h"
59 
60 #include <algorithm>
61 #include <cstdint>
62 #include <cstring>
63 #include <utility>
64 #include <limits>
65 
66 class SkReadBuffer;
67 class SkWriteBuffer;
68 struct GrContextOptions;
69 
70 static const int kBitmapSize = 4;
71 
72 namespace {
73 
74 static constexpr GrSurfaceOrigin kTestSurfaceOrigin = kTopLeft_GrSurfaceOrigin;
75 
76 class MatrixTestImageFilter : public SkImageFilter_Base {
77 public:
Make(skiatest::Reporter * reporter,const SkMatrix & expectedMatrix)78     static sk_sp<SkImageFilter> Make(skiatest::Reporter* reporter,
79                                      const SkMatrix& expectedMatrix) {
80         return sk_sp<SkImageFilter>(new MatrixTestImageFilter(reporter, expectedMatrix));
81     }
82 
83 protected:
onFilterImage(const Context & ctx,SkIPoint * offset) const84     sk_sp<SkSpecialImage> onFilterImage(const Context& ctx, SkIPoint* offset) const override {
85         REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
86         offset->fX = offset->fY = 0;
87         return sk_ref_sp<SkSpecialImage>(ctx.sourceImage());
88     }
89 
flatten(SkWriteBuffer & buffer) const90     void flatten(SkWriteBuffer& buffer) const override {
91         SkDEBUGFAIL("Should never get here");
92     }
93 
94 private:
95     SK_FLATTENABLE_HOOKS(MatrixTestImageFilter)
96 
MatrixTestImageFilter(skiatest::Reporter * reporter,const SkMatrix & expectedMatrix)97     MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
98         : INHERITED(nullptr, 0, nullptr)
99         , fReporter(reporter)
100         , fExpectedMatrix(expectedMatrix) {
101     }
102 
103     skiatest::Reporter* fReporter;
104     SkMatrix fExpectedMatrix;
105 
106     using INHERITED = SkImageFilter_Base;
107 };
108 
109 class FailImageFilter : public SkImageFilter_Base {
110 public:
FailImageFilter()111     FailImageFilter() : INHERITED(nullptr, 0, nullptr) { }
112 
onFilterImage(const Context & ctx,SkIPoint * offset) const113     sk_sp<SkSpecialImage> onFilterImage(const Context& ctx, SkIPoint* offset) const override {
114         return nullptr;
115     }
116 
117     SK_FLATTENABLE_HOOKS(FailImageFilter)
118 
119 private:
120     using INHERITED = SkImageFilter_Base;
121 };
122 
CreateProc(SkReadBuffer & buffer)123 sk_sp<SkFlattenable> FailImageFilter::CreateProc(SkReadBuffer& buffer) {
124     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
125     return sk_sp<SkFlattenable>(new FailImageFilter());
126 }
127 
draw_gradient_circle(SkCanvas * canvas,int width,int height)128 void draw_gradient_circle(SkCanvas* canvas, int width, int height) {
129     SkScalar x = SkIntToScalar(width / 2);
130     SkScalar y = SkIntToScalar(height / 2);
131     SkScalar radius = std::min(x, y) * 0.8f;
132     canvas->clear(0x00000000);
133     SkColor colors[2];
134     colors[0] = SK_ColorWHITE;
135     colors[1] = SK_ColorBLACK;
136     sk_sp<SkShader> shader(
137         SkGradientShader::MakeRadial(SkPoint::Make(x, y), radius, colors, nullptr, 2,
138                                        SkTileMode::kClamp)
139     );
140     SkPaint paint;
141     paint.setShader(shader);
142     canvas->drawCircle(x, y, radius, paint);
143 }
144 
make_gradient_circle(int width,int height)145 SkBitmap make_gradient_circle(int width, int height) {
146     SkBitmap bitmap;
147     bitmap.allocN32Pixels(width, height);
148     SkCanvas canvas(bitmap);
149     draw_gradient_circle(&canvas, width, height);
150     return bitmap;
151 }
152 
153 class FilterList {
154 public:
FilterList(sk_sp<SkImageFilter> input,const SkIRect * cropRect=nullptr)155     FilterList(sk_sp<SkImageFilter> input, const SkIRect* cropRect = nullptr) {
156         static const SkScalar kBlurSigma = SkIntToScalar(5);
157 
158         SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
159         {
160             sk_sp<SkColorFilter> cf(SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcIn));
161 
162             this->addFilter("color filter",
163                     SkImageFilters::ColorFilter(std::move(cf), input, cropRect));
164         }
165         {
166             sk_sp<SkImage> gradientImage(make_gradient_circle(64, 64).asImage());
167             sk_sp<SkImageFilter> gradientSource(SkImageFilters::Image(std::move(gradientImage)));
168 
169             this->addFilter("displacement map",
170                     SkImageFilters::DisplacementMap(SkColorChannel::kR, SkColorChannel::kB, 20.0f,
171                                                     std::move(gradientSource), input, cropRect));
172         }
173         this->addFilter("blur", SkImageFilters::Blur(SK_Scalar1, SK_Scalar1, input, cropRect));
174         this->addFilter("drop shadow", SkImageFilters::DropShadow(
175                 SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input, cropRect));
176         this->addFilter("diffuse lighting",
177                 SkImageFilters::PointLitDiffuse(location, SK_ColorGREEN, 0, 0, input, cropRect));
178         this->addFilter("specular lighting",
179                 SkImageFilters::PointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input,
180                                                    cropRect));
181         {
182             SkScalar kernel[9] = {
183                 SkIntToScalar(1), SkIntToScalar(1), SkIntToScalar(1),
184                 SkIntToScalar(1), SkIntToScalar(-7), SkIntToScalar(1),
185                 SkIntToScalar(1), SkIntToScalar(1), SkIntToScalar(1),
186             };
187             const SkISize kernelSize = SkISize::Make(3, 3);
188             const SkScalar gain = SK_Scalar1, bias = 0;
189 
190             // This filter needs a saveLayer bc it is in repeat mode
191             this->addFilter("matrix convolution",
192                             SkImageFilters::MatrixConvolution(
193                                     kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
194                                     SkTileMode::kRepeat, false, input, cropRect),
195                             true);
196         }
197         this->addFilter("merge", SkImageFilters::Merge(input, input, cropRect));
198 
199         {
200             sk_sp<SkShader> greenColorShader = SkShaders::Color(SK_ColorGREEN);
201 
202             SkIRect leftSideCropRect = SkIRect::MakeXYWH(0, 0, 32, 64);
203             sk_sp<SkImageFilter> shaderFilterLeft(SkImageFilters::Shader(greenColorShader,
204                                                                          &leftSideCropRect));
205             SkIRect rightSideCropRect = SkIRect::MakeXYWH(32, 0, 32, 64);
206             sk_sp<SkImageFilter> shaderFilterRight(SkImageFilters::Shader(greenColorShader,
207                                                                           &rightSideCropRect));
208 
209 
210             this->addFilter("merge with disjoint inputs", SkImageFilters::Merge(
211                     std::move(shaderFilterLeft), std::move(shaderFilterRight), cropRect));
212         }
213 
214         this->addFilter("offset", SkImageFilters::Offset(SK_Scalar1, SK_Scalar1, input, cropRect));
215         this->addFilter("dilate", SkImageFilters::Dilate(3, 2, input, cropRect));
216         this->addFilter("erode", SkImageFilters::Erode(2, 3, input, cropRect));
217         this->addFilter("tile", SkImageFilters::Tile(SkRect::MakeXYWH(0, 0, 50, 50),
218                                                      cropRect ? SkRect::Make(*cropRect)
219                                                               : SkRect::MakeXYWH(0, 0, 100, 100),
220                                                      input));
221 
222         if (!cropRect) {
223             SkMatrix matrix;
224 
225             matrix.setTranslate(SK_Scalar1, SK_Scalar1);
226             matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
227 
228             this->addFilter("matrix",
229                     SkImageFilters::MatrixTransform(matrix,
230                                                     SkSamplingOptions(SkFilterMode::kLinear),
231                                                     input));
232         }
233         {
234             sk_sp<SkImageFilter> blur(SkImageFilters::Blur(kBlurSigma, kBlurSigma, input));
235 
236             this->addFilter("blur and offset", SkImageFilters::Offset(
237                     kBlurSigma, kBlurSigma, std::move(blur), cropRect));
238         }
239         {
240             SkPictureRecorder recorder;
241             SkCanvas* recordingCanvas = recorder.beginRecording(64, 64);
242 
243             SkPaint greenPaint;
244             greenPaint.setColor(SK_ColorGREEN);
245             recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
246             sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
247             sk_sp<SkImageFilter> pictureFilter(SkImageFilters::Picture(std::move(picture)));
248 
249             this->addFilter("picture and blur", SkImageFilters::Blur(
250                     kBlurSigma, kBlurSigma, std::move(pictureFilter), cropRect));
251         }
252         {
253             sk_sp<SkImageFilter> paintFilter(SkImageFilters::Shader(
254                     SkPerlinNoiseShader::MakeTurbulence(SK_Scalar1, SK_Scalar1, 1, 0)));
255 
256             this->addFilter("paint and blur", SkImageFilters::Blur(
257                     kBlurSigma, kBlurSigma,  std::move(paintFilter), cropRect));
258         }
259         this->addFilter("blend", SkImageFilters::Blend(
260                 SkBlendMode::kSrc, input, input, cropRect));
261     }
count() const262     int count() const { return fFilters.size(); }
getFilter(int index) const263     SkImageFilter* getFilter(int index) const { return fFilters[index].fFilter.get(); }
getName(int index) const264     const char* getName(int index) const { return fFilters[index].fName; }
needsSaveLayer(int index) const265     bool needsSaveLayer(int index) const { return fFilters[index].fNeedsSaveLayer; }
266 private:
267     struct Filter {
Filter__anon8191d8690111::FilterList::Filter268         Filter() : fName(nullptr), fNeedsSaveLayer(false) {}
Filter__anon8191d8690111::FilterList::Filter269         Filter(const char* name, sk_sp<SkImageFilter> filter, bool needsSaveLayer)
270             : fName(name)
271             , fFilter(std::move(filter))
272             , fNeedsSaveLayer(needsSaveLayer) {
273         }
274         const char*                 fName;
275         sk_sp<SkImageFilter>        fFilter;
276         bool                        fNeedsSaveLayer;
277     };
addFilter(const char * name,sk_sp<SkImageFilter> filter,bool needsSaveLayer=false)278     void addFilter(const char* name, sk_sp<SkImageFilter> filter, bool needsSaveLayer = false) {
279         fFilters.push_back(Filter(name, std::move(filter), needsSaveLayer));
280     }
281 
282     SkTArray<Filter> fFilters;
283 };
284 
285 class FixedBoundsImageFilter : public SkImageFilter_Base {
286 public:
FixedBoundsImageFilter(const SkIRect & bounds)287     FixedBoundsImageFilter(const SkIRect& bounds)
288             : INHERITED(nullptr, 0, nullptr), fBounds(bounds) {}
289 
290 private:
getFactory() const291     Factory getFactory() const override { return nullptr; }
getTypeName() const292     const char* getTypeName() const override { return nullptr; }
293 
onFilterImage(const Context &,SkIPoint * offset) const294     sk_sp<SkSpecialImage> onFilterImage(const Context&, SkIPoint* offset) const override {
295         return nullptr;
296     }
297 
onFilterBounds(const SkIRect &,const SkMatrix &,MapDirection,const SkIRect *) const298     SkIRect onFilterBounds(const SkIRect&, const SkMatrix&,
299                            MapDirection, const SkIRect*) const override {
300         return fBounds;
301     }
302 
303     SkIRect fBounds;
304 
305     using INHERITED = SkImageFilter_Base;
306 };
307 }  // namespace
308 
CreateProc(SkReadBuffer & buffer)309 sk_sp<SkFlattenable> MatrixTestImageFilter::CreateProc(SkReadBuffer& buffer) {
310     SkDEBUGFAIL("Should never get here");
311     return nullptr;
312 }
313 
make_small_image()314 static sk_sp<SkImage> make_small_image() {
315     auto surface(SkSurface::MakeRasterN32Premul(kBitmapSize, kBitmapSize));
316     SkCanvas* canvas = surface->getCanvas();
317     canvas->clear(0x00000000);
318     SkPaint darkPaint;
319     darkPaint.setColor(0xFF804020);
320     SkPaint lightPaint;
321     lightPaint.setColor(0xFF244484);
322     const int kRectSize = kBitmapSize / 4;
323     static_assert(kBitmapSize % 4 == 0, "bitmap size not multiple of 4");
324 
325     for (int y = 0; y < kBitmapSize; y += kRectSize) {
326         for (int x = 0; x < kBitmapSize; x += kRectSize) {
327             canvas->save();
328             canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
329             canvas->drawRect(
330                     SkRect::MakeXYWH(0,         0,         kRectSize, kRectSize), darkPaint);
331             canvas->drawRect(
332                     SkRect::MakeXYWH(kRectSize, 0,         kRectSize, kRectSize), lightPaint);
333             canvas->drawRect(
334                     SkRect::MakeXYWH(0,         kRectSize, kRectSize, kRectSize), lightPaint);
335             canvas->drawRect(
336                     SkRect::MakeXYWH(kRectSize, kRectSize, kRectSize, kRectSize), darkPaint);
337             canvas->restore();
338         }
339     }
340 
341     return surface->makeImageSnapshot();
342 }
343 
make_scale(float amount,sk_sp<SkImageFilter> input)344 static sk_sp<SkImageFilter> make_scale(float amount, sk_sp<SkImageFilter> input) {
345     float s = amount;
346     float matrix[20] = { s, 0, 0, 0, 0,
347                          0, s, 0, 0, 0,
348                          0, 0, s, 0, 0,
349                          0, 0, 0, s, 0 };
350     sk_sp<SkColorFilter> filter(SkColorFilters::Matrix(matrix));
351     return SkImageFilters::ColorFilter(std::move(filter), std::move(input));
352 }
353 
make_grayscale(sk_sp<SkImageFilter> input,const SkIRect * cropRect)354 static sk_sp<SkImageFilter> make_grayscale(sk_sp<SkImageFilter> input,
355                                            const SkIRect* cropRect) {
356     float matrix[20];
357     memset(matrix, 0, 20 * sizeof(float));
358     matrix[0] = matrix[5] = matrix[10] = 0.2126f;
359     matrix[1] = matrix[6] = matrix[11] = 0.7152f;
360     matrix[2] = matrix[7] = matrix[12] = 0.0722f;
361     matrix[18] = 1.0f;
362     sk_sp<SkColorFilter> filter(SkColorFilters::Matrix(matrix));
363     return SkImageFilters::ColorFilter(std::move(filter), std::move(input), cropRect);
364 }
365 
make_blue(sk_sp<SkImageFilter> input,const SkIRect * cropRect)366 static sk_sp<SkImageFilter> make_blue(sk_sp<SkImageFilter> input, const SkIRect* cropRect) {
367     sk_sp<SkColorFilter> filter(SkColorFilters::Blend(SK_ColorBLUE, SkBlendMode::kSrcIn));
368     return SkImageFilters::ColorFilter(std::move(filter), std::move(input), cropRect);
369 }
370 
create_empty_special_surface(GrRecordingContext * rContext,int widthHeight)371 static sk_sp<SkSpecialSurface> create_empty_special_surface(GrRecordingContext* rContext,
372                                                             int widthHeight) {
373 
374     const SkImageInfo ii = SkImageInfo::Make({ widthHeight, widthHeight },
375                                              kRGBA_8888_SkColorType,
376                                              kPremul_SkAlphaType);
377 
378     if (rContext) {
379         return SkSpecialSurface::MakeRenderTarget(rContext, ii, SkSurfaceProps(),
380                                                   kTestSurfaceOrigin);
381     } else {
382         return SkSpecialSurface::MakeRaster(ii, SkSurfaceProps());
383     }
384 }
385 
create_surface(GrRecordingContext * rContext,int width,int height)386 static sk_sp<SkSurface> create_surface(GrRecordingContext* rContext, int width, int height) {
387     const SkImageInfo info = SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType);
388     if (rContext) {
389         return SkSurface::MakeRenderTarget(
390                 rContext, skgpu::Budgeted::kNo, info, 0, kTestSurfaceOrigin, nullptr);
391     } else {
392         return SkSurface::MakeRaster(info);
393     }
394 }
395 
create_empty_special_image(GrRecordingContext * rContext,int widthHeight)396 static sk_sp<SkSpecialImage> create_empty_special_image(GrRecordingContext* rContext,
397                                                         int widthHeight) {
398     sk_sp<SkSpecialSurface> surf(create_empty_special_surface(rContext, widthHeight));
399 
400     SkASSERT(surf);
401 
402     SkCanvas* canvas = surf->getCanvas();
403     SkASSERT(canvas);
404 
405     canvas->clear(0x0);
406 
407     return surf->makeImageSnapshot();
408 }
409 
410 
DEF_TEST(ImageFilter,reporter)411 DEF_TEST(ImageFilter, reporter) {
412     {
413         // Check that a color matrix filter followed by a color matrix filter
414         // concatenates into a single filter.
415         sk_sp<SkImageFilter> doubleBrightness(make_scale(2.0f, nullptr));
416         sk_sp<SkImageFilter> halfBrightness(make_scale(0.5f, std::move(doubleBrightness)));
417         REPORTER_ASSERT(reporter, nullptr == halfBrightness->getInput(0));
418         SkColorFilter* cf;
419         REPORTER_ASSERT(reporter, halfBrightness->asColorFilter(&cf));
420         cf->unref();
421     }
422 
423     {
424         // Check that a color filter image filter without a crop rect can be
425         // expressed as a color filter.
426         sk_sp<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
427         REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
428     }
429 
430     {
431         // Check that a colorfilterimage filter without a crop rect but with an input
432         // that is another colorfilterimage can be expressed as a colorfilter (composed).
433         sk_sp<SkImageFilter> mode(make_blue(nullptr, nullptr));
434         sk_sp<SkImageFilter> gray(make_grayscale(std::move(mode), nullptr));
435         REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
436     }
437 
438     {
439         // Test that if we exceed the limit of what ComposeColorFilter can combine, we still
440         // can build the DAG and won't assert if we call asColorFilter.
441         sk_sp<SkImageFilter> filter(make_blue(nullptr, nullptr));
442         const int kWayTooManyForComposeColorFilter = 100;
443         for (int i = 0; i < kWayTooManyForComposeColorFilter; ++i) {
444             filter = make_blue(filter, nullptr);
445             // the first few of these will succeed, but after we hit the internal limit,
446             // it will then return false.
447             (void)filter->asColorFilter(nullptr);
448         }
449     }
450 
451     {
452         // Check that a color filter image filter with a crop rect cannot
453         // be expressed as a color filter.
454         SkIRect cropRect = SkIRect::MakeWH(100, 100);
455         sk_sp<SkImageFilter> grayWithCrop(make_grayscale(nullptr, &cropRect));
456         REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(nullptr));
457     }
458 
459     {
460         // Check that two non-commutative matrices are concatenated in
461         // the correct order.
462         float blueToRedMatrix[20] = { 0 };
463         blueToRedMatrix[2] = blueToRedMatrix[18] = 1;
464         float redToGreenMatrix[20] = { 0 };
465         redToGreenMatrix[5] = redToGreenMatrix[18] = 1;
466         sk_sp<SkColorFilter> blueToRed(SkColorFilters::Matrix(blueToRedMatrix));
467         sk_sp<SkImageFilter> filter1(SkImageFilters::ColorFilter(std::move(blueToRed), nullptr));
468         sk_sp<SkColorFilter> redToGreen(SkColorFilters::Matrix(redToGreenMatrix));
469         sk_sp<SkImageFilter> filter2(SkImageFilters::ColorFilter(std::move(redToGreen),
470                                                                  std::move(filter1)));
471 
472         SkBitmap result;
473         result.allocN32Pixels(kBitmapSize, kBitmapSize);
474 
475         SkPaint paint;
476         paint.setColor(SK_ColorBLUE);
477         paint.setImageFilter(std::move(filter2));
478         SkCanvas canvas(result);
479         canvas.clear(0x0);
480         SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
481         canvas.drawRect(rect, paint);
482         uint32_t pixel = *result.getAddr32(0, 0);
483         // The result here should be green, since we have effectively shifted blue to green.
484         REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
485     }
486 
487     {
488         // Tests pass by not asserting
489         sk_sp<SkImage> image(make_small_image());
490         SkBitmap result;
491         result.allocN32Pixels(kBitmapSize, kBitmapSize);
492 
493         {
494             // This tests for :
495             // 1 ) location at (0,0,1)
496             SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
497             // 2 ) location and target at same value
498             SkPoint3 target = SkPoint3::Make(location.fX, location.fY, location.fZ);
499             // 3 ) large negative specular exponent value
500             SkScalar specularExponent = -1000;
501 
502             sk_sp<SkImageFilter> bmSrc(SkImageFilters::Image(std::move(image)));
503             SkPaint paint;
504             paint.setImageFilter(SkImageFilters::SpotLitSpecular(
505                     location, target, specularExponent, 180,
506                     0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
507                     std::move(bmSrc)));
508             SkCanvas canvas(result);
509             SkRect r = SkRect::MakeIWH(kBitmapSize, kBitmapSize);
510             canvas.drawRect(r, paint);
511         }
512     }
513 }
514 
test_cropRects(skiatest::Reporter * reporter,GrRecordingContext * rContext)515 static void test_cropRects(skiatest::Reporter* reporter, GrRecordingContext* rContext) {
516     // Check that all filters offset to their absolute crop rect,
517     // unaffected by the input crop rect.
518     // Tests pass by not asserting.
519     sk_sp<SkSpecialImage> srcImg(create_empty_special_image(rContext, 100));
520     SkASSERT(srcImg);
521 
522     SkIRect inputCropRect = SkIRect::MakeXYWH(8, 13, 80, 80);
523     SkIRect cropRect = SkIRect::MakeXYWH(20, 30, 60, 60);
524     sk_sp<SkImageFilter> input(make_grayscale(nullptr, &inputCropRect));
525 
526     FilterList filters(input, &cropRect);
527 
528     for (int i = 0; i < filters.count(); ++i) {
529         SkImageFilter* filter = filters.getFilter(i);
530         SkIPoint offset;
531         SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr,
532                                         kN32_SkColorType, nullptr, srcImg.get());
533         sk_sp<SkSpecialImage> resultImg(as_IFB(filter)->filterImage(ctx).imageAndOffset(&offset));
534         REPORTER_ASSERT(reporter, resultImg, "%s", filters.getName(i));
535         REPORTER_ASSERT(reporter, offset.fX == 20 && offset.fY == 30, "%s", filters.getName(i));
536     }
537 }
538 
special_image_to_bitmap(GrDirectContext * dContext,const SkSpecialImage * src,SkBitmap * dst)539 static bool special_image_to_bitmap(GrDirectContext* dContext, const SkSpecialImage* src,
540                                     SkBitmap* dst) {
541     sk_sp<SkImage> img = src->asImage();
542     if (!img) {
543         return false;
544     }
545 
546     if (!dst->tryAllocN32Pixels(src->width(), src->height())) {
547         return false;
548     }
549 
550     return img->readPixels(dContext, dst->pixmap(), src->subset().fLeft, src->subset().fTop);
551 }
552 
test_negative_blur_sigma(skiatest::Reporter * reporter,GrDirectContext * dContext)553 static void test_negative_blur_sigma(skiatest::Reporter* reporter,
554                                      GrDirectContext* dContext) {
555     // Check that SkBlurImageFilter will accept a negative sigma, either in
556     // the given arguments or after CTM application.
557     static const int kWidth = 32, kHeight = 32;
558     static const SkScalar kBlurSigma = SkIntToScalar(5);
559 
560     sk_sp<SkImageFilter> positiveFilter(SkImageFilters::Blur(kBlurSigma, kBlurSigma, nullptr));
561     sk_sp<SkImageFilter> negativeFilter(SkImageFilters::Blur(-kBlurSigma, kBlurSigma, nullptr));
562 
563     sk_sp<SkImage> gradient = make_gradient_circle(kWidth, kHeight).asImage();
564     sk_sp<SkSpecialImage> imgSrc(
565             SkSpecialImage::MakeFromImage(dContext, SkIRect::MakeWH(kWidth, kHeight), gradient,
566                                           SkSurfaceProps()));
567 
568     SkIPoint offset;
569     SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr,
570                                     kN32_SkColorType, nullptr, imgSrc.get());
571 
572     sk_sp<SkSpecialImage> positiveResult1(
573             as_IFB(positiveFilter)->filterImage(ctx).imageAndOffset(&offset));
574     REPORTER_ASSERT(reporter, positiveResult1);
575 
576     sk_sp<SkSpecialImage> negativeResult1(
577             as_IFB(negativeFilter)->filterImage(ctx).imageAndOffset(&offset));
578     REPORTER_ASSERT(reporter, negativeResult1);
579 
580     SkMatrix negativeScale;
581     negativeScale.setScale(-SK_Scalar1, SK_Scalar1);
582     SkImageFilter_Base::Context negativeCTX(negativeScale, SkIRect::MakeWH(32, 32), nullptr,
583                                             kN32_SkColorType, nullptr, imgSrc.get());
584 
585     sk_sp<SkSpecialImage> negativeResult2(
586             as_IFB(positiveFilter)->filterImage(negativeCTX).imageAndOffset(&offset));
587     REPORTER_ASSERT(reporter, negativeResult2);
588 
589     sk_sp<SkSpecialImage> positiveResult2(
590             as_IFB(negativeFilter)->filterImage(negativeCTX).imageAndOffset(&offset));
591     REPORTER_ASSERT(reporter, positiveResult2);
592 
593 
594     SkBitmap positiveResultBM1, positiveResultBM2;
595     SkBitmap negativeResultBM1, negativeResultBM2;
596 
597     REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, positiveResult1.get(),
598                                                       &positiveResultBM1));
599     REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, positiveResult2.get(),
600                                                       &positiveResultBM2));
601     REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, negativeResult1.get(),
602                                                       &negativeResultBM1));
603     REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, negativeResult2.get(),
604                                                       &negativeResultBM2));
605 
606     for (int y = 0; y < kHeight; y++) {
607         int diffs = memcmp(positiveResultBM1.getAddr32(0, y),
608                            negativeResultBM1.getAddr32(0, y),
609                            positiveResultBM1.rowBytes());
610         REPORTER_ASSERT(reporter, !diffs);
611         if (diffs) {
612             break;
613         }
614         diffs = memcmp(positiveResultBM1.getAddr32(0, y),
615                        negativeResultBM2.getAddr32(0, y),
616                        positiveResultBM1.rowBytes());
617         REPORTER_ASSERT(reporter, !diffs);
618         if (diffs) {
619             break;
620         }
621         diffs = memcmp(positiveResultBM1.getAddr32(0, y),
622                        positiveResultBM2.getAddr32(0, y),
623                        positiveResultBM1.rowBytes());
624         REPORTER_ASSERT(reporter, !diffs);
625         if (diffs) {
626             break;
627         }
628     }
629 }
630 
DEF_TEST(ImageFilterNegativeBlurSigma,reporter)631 DEF_TEST(ImageFilterNegativeBlurSigma, reporter) {
632     test_negative_blur_sigma(reporter, nullptr);
633 }
634 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterNegativeBlurSigma_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)635 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterNegativeBlurSigma_Gpu,
636                                        reporter,
637                                        ctxInfo,
638                                        CtsEnforcement::kNever) {
639     test_negative_blur_sigma(reporter, ctxInfo.directContext());
640 }
641 
test_morphology_radius_with_mirror_ctm(skiatest::Reporter * reporter,GrDirectContext * dContext)642 static void test_morphology_radius_with_mirror_ctm(skiatest::Reporter* reporter,
643                                                    GrDirectContext* dContext) {
644     // Check that SkMorphologyImageFilter maps the radius correctly when the
645     // CTM contains a mirroring transform.
646     static const int kWidth = 32, kHeight = 32;
647     static const int kRadius = 8;
648 
649     sk_sp<SkImageFilter> filter(SkImageFilters::Dilate(kRadius, kRadius, nullptr));
650 
651     SkBitmap bitmap;
652     bitmap.allocN32Pixels(kWidth, kHeight);
653     SkCanvas canvas(bitmap);
654     canvas.clear(SK_ColorTRANSPARENT);
655     SkPaint paint;
656     paint.setColor(SK_ColorWHITE);
657     canvas.drawRect(SkRect::MakeXYWH(kWidth / 4, kHeight / 4, kWidth / 2, kHeight / 2),
658                     paint);
659     sk_sp<SkImage> image = bitmap.asImage();
660     sk_sp<SkSpecialImage> imgSrc(
661             SkSpecialImage::MakeFromImage(dContext, SkIRect::MakeWH(kWidth, kHeight), image,
662                                           SkSurfaceProps()));
663 
664     SkIPoint offset;
665     SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr,
666                                     kN32_SkColorType, nullptr, imgSrc.get());
667 
668     sk_sp<SkSpecialImage> normalResult(
669             as_IFB(filter)->filterImage(ctx).imageAndOffset(&offset));
670     REPORTER_ASSERT(reporter, normalResult);
671 
672     SkMatrix mirrorX;
673     mirrorX.setTranslate(0, SkIntToScalar(32));
674     mirrorX.preScale(SK_Scalar1, -SK_Scalar1);
675     SkImageFilter_Base::Context mirrorXCTX(mirrorX, SkIRect::MakeWH(32, 32), nullptr,
676                                            kN32_SkColorType, nullptr, imgSrc.get());
677 
678     sk_sp<SkSpecialImage> mirrorXResult(
679             as_IFB(filter)->filterImage(mirrorXCTX).imageAndOffset(&offset));
680     REPORTER_ASSERT(reporter, mirrorXResult);
681 
682     SkMatrix mirrorY;
683     mirrorY.setTranslate(SkIntToScalar(32), 0);
684     mirrorY.preScale(-SK_Scalar1, SK_Scalar1);
685     SkImageFilter_Base::Context mirrorYCTX(mirrorY, SkIRect::MakeWH(32, 32), nullptr,
686                                            kN32_SkColorType, nullptr, imgSrc.get());
687 
688     sk_sp<SkSpecialImage> mirrorYResult(
689             as_IFB(filter)->filterImage(mirrorYCTX).imageAndOffset(&offset));
690     REPORTER_ASSERT(reporter, mirrorYResult);
691 
692     SkBitmap normalResultBM, mirrorXResultBM, mirrorYResultBM;
693 
694     REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, normalResult.get(),
695                                                       &normalResultBM));
696     REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, mirrorXResult.get(),
697                                                       &mirrorXResultBM));
698     REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, mirrorYResult.get(),
699                                                       &mirrorYResultBM));
700 
701     for (int y = 0; y < kHeight; y++) {
702         int diffs = memcmp(normalResultBM.getAddr32(0, y),
703                            mirrorXResultBM.getAddr32(0, y),
704                            normalResultBM.rowBytes());
705         REPORTER_ASSERT(reporter, !diffs);
706         if (diffs) {
707             break;
708         }
709         diffs = memcmp(normalResultBM.getAddr32(0, y),
710                        mirrorYResultBM.getAddr32(0, y),
711                        normalResultBM.rowBytes());
712         REPORTER_ASSERT(reporter, !diffs);
713         if (diffs) {
714             break;
715         }
716     }
717 }
718 
DEF_TEST(MorphologyFilterRadiusWithMirrorCTM,reporter)719 DEF_TEST(MorphologyFilterRadiusWithMirrorCTM, reporter) {
720     test_morphology_radius_with_mirror_ctm(reporter, nullptr);
721 }
722 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(MorphologyFilterRadiusWithMirrorCTM_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)723 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(MorphologyFilterRadiusWithMirrorCTM_Gpu,
724                                        reporter,
725                                        ctxInfo,
726                                        CtsEnforcement::kNever) {
727     test_morphology_radius_with_mirror_ctm(reporter, ctxInfo.directContext());
728 }
729 
test_zero_blur_sigma(skiatest::Reporter * reporter,GrDirectContext * dContext)730 static void test_zero_blur_sigma(skiatest::Reporter* reporter, GrDirectContext* dContext) {
731     // Check that SkBlurImageFilter with a zero sigma and a non-zero srcOffset works correctly.
732     SkIRect cropRect = SkIRect::MakeXYWH(5, 0, 5, 10);
733     sk_sp<SkImageFilter> input(SkImageFilters::Offset(0, 0, nullptr, &cropRect));
734     sk_sp<SkImageFilter> filter(SkImageFilters::Blur(0, 0, std::move(input), &cropRect));
735 
736     sk_sp<SkSpecialSurface> surf(create_empty_special_surface(dContext, 10));
737     surf->getCanvas()->clear(SK_ColorGREEN);
738     sk_sp<SkSpecialImage> image(surf->makeImageSnapshot());
739 
740     SkIPoint offset;
741     SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr,
742                                     kN32_SkColorType, nullptr, image.get());
743 
744     sk_sp<SkSpecialImage> result(as_IFB(filter)->filterImage(ctx).imageAndOffset(&offset));
745     REPORTER_ASSERT(reporter, offset.fX == 5 && offset.fY == 0);
746     REPORTER_ASSERT(reporter, result);
747     REPORTER_ASSERT(reporter, result->width() == 5 && result->height() == 10);
748 
749     SkBitmap resultBM;
750 
751     REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, result.get(), &resultBM));
752 
753     for (int y = 0; y < resultBM.height(); y++) {
754         for (int x = 0; x < resultBM.width(); x++) {
755             bool diff = *resultBM.getAddr32(x, y) != SK_ColorGREEN;
756             REPORTER_ASSERT(reporter, !diff);
757             if (diff) {
758                 break;
759             }
760         }
761     }
762 }
763 
DEF_TEST(ImageFilterZeroBlurSigma,reporter)764 DEF_TEST(ImageFilterZeroBlurSigma, reporter) {
765     test_zero_blur_sigma(reporter, nullptr);
766 }
767 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterZeroBlurSigma_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)768 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterZeroBlurSigma_Gpu,
769                                        reporter,
770                                        ctxInfo,
771                                        CtsEnforcement::kNever) {
772     test_zero_blur_sigma(reporter, ctxInfo.directContext());
773 }
774 
775 // Tests that, even when an upstream filter has returned null (due to failure or clipping), a
776 // downstream filter that affects transparent black still does so even with a nullptr input.
test_fail_affects_transparent_black(skiatest::Reporter * reporter,GrDirectContext * dContext)777 static void test_fail_affects_transparent_black(skiatest::Reporter* reporter,
778                                                 GrDirectContext* dContext) {
779     sk_sp<FailImageFilter> failFilter(new FailImageFilter());
780     sk_sp<SkSpecialImage> source(create_empty_special_image(dContext, 5));
781     SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(0, 0, 1, 1), nullptr,
782                                     kN32_SkColorType, nullptr, source.get());
783     sk_sp<SkColorFilter> green(SkColorFilters::Blend(SK_ColorGREEN, SkBlendMode::kSrc));
784     SkASSERT(as_CFB(green)->affectsTransparentBlack());
785     sk_sp<SkImageFilter> greenFilter(SkImageFilters::ColorFilter(std::move(green),
786                                                                  std::move(failFilter)));
787     SkIPoint offset;
788     sk_sp<SkSpecialImage> result(as_IFB(greenFilter)->filterImage(ctx).imageAndOffset(&offset));
789     REPORTER_ASSERT(reporter, nullptr != result.get());
790     if (result) {
791         SkBitmap resultBM;
792         REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, result.get(), &resultBM));
793         REPORTER_ASSERT(reporter, *resultBM.getAddr32(0, 0) == SK_ColorGREEN);
794     }
795 }
796 
DEF_TEST(ImageFilterFailAffectsTransparentBlack,reporter)797 DEF_TEST(ImageFilterFailAffectsTransparentBlack, reporter) {
798     test_fail_affects_transparent_black(reporter, nullptr);
799 }
800 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterFailAffectsTransparentBlack_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)801 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterFailAffectsTransparentBlack_Gpu,
802                                        reporter,
803                                        ctxInfo,
804                                        CtsEnforcement::kNever) {
805     test_fail_affects_transparent_black(reporter, ctxInfo.directContext());
806 }
807 
DEF_TEST(ImageFilterDrawTiled,reporter)808 DEF_TEST(ImageFilterDrawTiled, reporter) {
809     // Check that all filters when drawn tiled (with subsequent clip rects) exactly
810     // match the same filters drawn with a single full-canvas bitmap draw.
811     // Tests pass by not asserting.
812 
813     FilterList filters(nullptr);
814 
815     SkBitmap untiledResult, tiledResult;
816     const int width = 64, height = 64;
817     untiledResult.allocN32Pixels(width, height);
818     tiledResult.allocN32Pixels(width, height);
819     SkCanvas tiledCanvas(tiledResult);
820     SkCanvas untiledCanvas(untiledResult);
821     const int tileSize = 8;
822 
823     SkPaint textPaint;
824     textPaint.setColor(SK_ColorWHITE);
825     SkFont font(ToolUtils::create_portable_typeface(), height);
826 
827     const char* text = "ABC";
828     const SkScalar yPos = SkIntToScalar(height);
829 
830     for (int scale = 1; scale <= 2; ++scale) {
831         for (int i = 0; i < filters.count(); ++i) {
832             SkPaint combinedPaint;
833             combinedPaint.setColor(SK_ColorWHITE);
834             combinedPaint.setImageFilter(sk_ref_sp(filters.getFilter(i)));
835 
836             untiledCanvas.clear(SK_ColorTRANSPARENT);
837             untiledCanvas.save();
838             untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
839             untiledCanvas.drawString(text, 0, yPos, font, combinedPaint);
840             untiledCanvas.restore();
841 
842             tiledCanvas.clear(SK_ColorTRANSPARENT);
843             for (int y = 0; y < height; y += tileSize) {
844                 for (int x = 0; x < width; x += tileSize) {
845                     tiledCanvas.save();
846                     const SkRect clipRect = SkRect::MakeXYWH(x, y, tileSize, tileSize);
847                     tiledCanvas.clipRect(clipRect);
848                     if (filters.needsSaveLayer(i)) {
849                         const SkRect layerBounds = SkRect::MakeIWH(width, height);
850                         tiledCanvas.saveLayer(&layerBounds, &combinedPaint);
851                             tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
852                             tiledCanvas.drawString(text, 0, yPos, font, textPaint);
853                         tiledCanvas.restore();
854                     } else {
855                         tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
856                         tiledCanvas.drawString(text, 0, yPos, font, combinedPaint);
857                     }
858 
859                     tiledCanvas.restore();
860                 }
861             }
862 
863             if (!ToolUtils::equal_pixels(untiledResult, tiledResult)) {
864                 ERRORF(reporter, "%s", filters.getName(i));
865                 break;
866             }
867         }
868     }
869 }
870 
draw_saveLayer_picture(int width,int height,int tileSize,SkBBHFactory * factory,SkBitmap * result)871 static void draw_saveLayer_picture(int width, int height, int tileSize,
872                                    SkBBHFactory* factory, SkBitmap* result) {
873 
874     SkMatrix matrix;
875     matrix.setTranslate(SkIntToScalar(50), 0);
876 
877     sk_sp<SkColorFilter> cf(SkColorFilters::Blend(SK_ColorWHITE, SkBlendMode::kSrc));
878     sk_sp<SkImageFilter> cfif(SkImageFilters::ColorFilter(std::move(cf), nullptr));
879     sk_sp<SkImageFilter> imageFilter(SkImageFilters::MatrixTransform(matrix,
880                                                                      SkSamplingOptions(),
881                                                                      std::move(cfif)));
882 
883     SkPaint paint;
884     paint.setImageFilter(std::move(imageFilter));
885     SkPictureRecorder recorder;
886     SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50));
887     SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width),
888                                                         SkIntToScalar(height),
889                                                         factory);
890     recordingCanvas->translate(-55, 0);
891     recordingCanvas->saveLayer(&bounds, &paint);
892     recordingCanvas->restore();
893     sk_sp<SkPicture> picture1(recorder.finishRecordingAsPicture());
894 
895     result->allocN32Pixels(width, height);
896     SkCanvas canvas(*result);
897     canvas.clear(0);
898     canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize)));
899     canvas.drawPicture(picture1.get());
900 }
901 
DEF_TEST(ImageFilterDrawMatrixBBH,reporter)902 DEF_TEST(ImageFilterDrawMatrixBBH, reporter) {
903     // Check that matrix filter when drawn tiled with BBH exactly
904     // matches the same thing drawn without BBH.
905     // Tests pass by not asserting.
906 
907     const int width = 200, height = 200;
908     const int tileSize = 100;
909     SkBitmap result1, result2;
910     SkRTreeFactory factory;
911 
912     draw_saveLayer_picture(width, height, tileSize, &factory, &result1);
913     draw_saveLayer_picture(width, height, tileSize, nullptr, &result2);
914 
915     for (int y = 0; y < height; y++) {
916         int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
917         REPORTER_ASSERT(reporter, !diffs);
918         if (diffs) {
919             break;
920         }
921     }
922 }
923 
make_blur(sk_sp<SkImageFilter> input)924 static sk_sp<SkImageFilter> make_blur(sk_sp<SkImageFilter> input) {
925     return SkImageFilters::Blur(SK_Scalar1, SK_Scalar1, std::move(input));
926 }
927 
make_drop_shadow(sk_sp<SkImageFilter> input)928 static sk_sp<SkImageFilter> make_drop_shadow(sk_sp<SkImageFilter> input) {
929     return SkImageFilters::DropShadow(100, 100, 10, 10, SK_ColorBLUE, std::move(input));
930 }
931 
DEF_TEST(ImageFilterBlurThenShadowBounds,reporter)932 DEF_TEST(ImageFilterBlurThenShadowBounds, reporter) {
933     sk_sp<SkImageFilter> filter1(make_blur(nullptr));
934     sk_sp<SkImageFilter> filter2(make_drop_shadow(std::move(filter1)));
935 
936     SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
937     SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
938     bounds = filter2->filterBounds(bounds, SkMatrix::I(),
939                                    SkImageFilter::kReverse_MapDirection, &bounds);
940 
941     REPORTER_ASSERT(reporter, bounds == expectedBounds);
942 }
943 
DEF_TEST(ImageFilterShadowThenBlurBounds,reporter)944 DEF_TEST(ImageFilterShadowThenBlurBounds, reporter) {
945     sk_sp<SkImageFilter> filter1(make_drop_shadow(nullptr));
946     sk_sp<SkImageFilter> filter2(make_blur(std::move(filter1)));
947 
948     SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
949     SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
950     bounds = filter2->filterBounds(bounds, SkMatrix::I(),
951                                    SkImageFilter::kReverse_MapDirection, &bounds);
952 
953     REPORTER_ASSERT(reporter, bounds == expectedBounds);
954 }
955 
DEF_TEST(ImageFilterDilateThenBlurBounds,reporter)956 DEF_TEST(ImageFilterDilateThenBlurBounds, reporter) {
957     sk_sp<SkImageFilter> filter1(SkImageFilters::Dilate(2, 2, nullptr));
958     sk_sp<SkImageFilter> filter2(make_drop_shadow(std::move(filter1)));
959 
960     SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
961     SkIRect expectedBounds = SkIRect::MakeXYWH(-132, -132, 234, 234);
962     bounds = filter2->filterBounds(bounds, SkMatrix::I(),
963                                    SkImageFilter::kReverse_MapDirection, &bounds);
964 
965     REPORTER_ASSERT(reporter, bounds == expectedBounds);
966 }
967 
DEF_TEST(ImageFilterScaledBlurRadius,reporter)968 DEF_TEST(ImageFilterScaledBlurRadius, reporter) {
969     // Each blur should spread 3*sigma, so 3 for the blur and 30 for the shadow
970     // (before the CTM). Bounds should be computed correctly in the presence of
971     // a (possibly negative) scale.
972     sk_sp<SkImageFilter> blur(make_blur(nullptr));
973     sk_sp<SkImageFilter> dropShadow(make_drop_shadow(nullptr));
974     {
975         // Uniform scale by 2.
976         SkMatrix scaleMatrix;
977         scaleMatrix.setScale(2, 2);
978         SkIRect bounds = SkIRect::MakeLTRB(0, 0, 200, 200);
979 
980         SkIRect expectedBlurBounds = SkIRect::MakeLTRB(-6, -6, 206, 206);
981         SkIRect blurBounds = blur->filterBounds(
982                 bounds, scaleMatrix, SkImageFilter::kForward_MapDirection, nullptr);
983         REPORTER_ASSERT(reporter, blurBounds == expectedBlurBounds);
984         SkIRect reverseBlurBounds = blur->filterBounds(
985                 bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &bounds);
986         REPORTER_ASSERT(reporter, reverseBlurBounds == expectedBlurBounds);
987 
988         SkIRect expectedShadowBounds = SkIRect::MakeLTRB(0, 0, 460, 460);
989         SkIRect shadowBounds = dropShadow->filterBounds(
990                 bounds, scaleMatrix, SkImageFilter::kForward_MapDirection, nullptr);
991         REPORTER_ASSERT(reporter, shadowBounds == expectedShadowBounds);
992         SkIRect expectedReverseShadowBounds =
993                 SkIRect::MakeLTRB(-260, -260, 200, 200);
994         SkIRect reverseShadowBounds = dropShadow->filterBounds(
995                 bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &bounds);
996         REPORTER_ASSERT(reporter, reverseShadowBounds == expectedReverseShadowBounds);
997     }
998     {
999         // Vertical flip.
1000         SkMatrix scaleMatrix;
1001         scaleMatrix.setScale(1, -1);
1002         SkIRect bounds = SkIRect::MakeLTRB(0, -100, 100, 0);
1003 
1004         SkIRect expectedBlurBounds = SkIRect::MakeLTRB(-3, -103, 103, 3);
1005         SkIRect blurBounds = blur->filterBounds(
1006                 bounds, scaleMatrix, SkImageFilter::kForward_MapDirection, nullptr);
1007         REPORTER_ASSERT(reporter, blurBounds == expectedBlurBounds);
1008         SkIRect reverseBlurBounds = blur->filterBounds(
1009                 bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &bounds);
1010         REPORTER_ASSERT(reporter, reverseBlurBounds == expectedBlurBounds);
1011 
1012         SkIRect expectedShadowBounds = SkIRect::MakeLTRB(0, -230, 230, 0);
1013         SkIRect shadowBounds = dropShadow->filterBounds(
1014                 bounds, scaleMatrix, SkImageFilter::kForward_MapDirection, nullptr);
1015         REPORTER_ASSERT(reporter, shadowBounds == expectedShadowBounds);
1016         SkIRect expectedReverseShadowBounds =
1017                 SkIRect::MakeLTRB(-130, -100, 100, 130);
1018         SkIRect reverseShadowBounds = dropShadow->filterBounds(
1019                 bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &bounds);
1020         REPORTER_ASSERT(reporter, reverseShadowBounds == expectedReverseShadowBounds);
1021     }
1022 }
1023 
DEF_TEST(ImageFilterComposedBlurFastBounds,reporter)1024 DEF_TEST(ImageFilterComposedBlurFastBounds, reporter) {
1025     sk_sp<SkImageFilter> filter1(make_blur(nullptr));
1026     sk_sp<SkImageFilter> filter2(make_blur(nullptr));
1027     sk_sp<SkImageFilter> composedFilter(SkImageFilters::Compose(std::move(filter1),
1028                                                                 std::move(filter2)));
1029 
1030     SkRect boundsSrc = SkRect::MakeIWH(100, 100);
1031     SkRect expectedBounds = SkRect::MakeXYWH(-6, -6, 112, 112);
1032     SkRect boundsDst = composedFilter->computeFastBounds(boundsSrc);
1033 
1034     REPORTER_ASSERT(reporter, boundsDst == expectedBounds);
1035 }
1036 
DEF_TEST(ImageFilterUnionBounds,reporter)1037 DEF_TEST(ImageFilterUnionBounds, reporter) {
1038     sk_sp<SkImageFilter> offset(SkImageFilters::Offset(50, 0, nullptr));
1039     // Regardless of which order they appear in, the image filter bounds should
1040     // be combined correctly.
1041     {
1042         sk_sp<SkImageFilter> composite(SkImageFilters::Blend(SkBlendMode::kSrcOver, offset));
1043         SkRect bounds = SkRect::MakeIWH(100, 100);
1044         // Intentionally aliasing here, as that's what the real callers do.
1045         bounds = composite->computeFastBounds(bounds);
1046         REPORTER_ASSERT(reporter, bounds == SkRect::MakeIWH(150, 100));
1047     }
1048     {
1049         sk_sp<SkImageFilter> composite(SkImageFilters::Blend(SkBlendMode::kSrcOver, nullptr,
1050                                                              offset, nullptr));
1051         SkRect bounds = SkRect::MakeIWH(100, 100);
1052         // Intentionally aliasing here, as that's what the real callers do.
1053         bounds = composite->computeFastBounds(bounds);
1054         REPORTER_ASSERT(reporter, bounds == SkRect::MakeIWH(150, 100));
1055     }
1056 }
1057 
test_imagefilter_merge_result_size(skiatest::Reporter * reporter,GrRecordingContext * rContext)1058 static void test_imagefilter_merge_result_size(skiatest::Reporter* reporter,
1059                                                GrRecordingContext* rContext) {
1060     SkBitmap greenBM;
1061     greenBM.allocN32Pixels(20, 20);
1062     greenBM.eraseColor(SK_ColorGREEN);
1063     sk_sp<SkImage> greenImage(greenBM.asImage());
1064     sk_sp<SkImageFilter> source(SkImageFilters::Image(std::move(greenImage)));
1065     sk_sp<SkImageFilter> merge(SkImageFilters::Merge(source, source));
1066 
1067     sk_sp<SkSpecialImage> srcImg(create_empty_special_image(rContext, 1));
1068 
1069     SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(0, 0, 100, 100), nullptr,
1070                                     kN32_SkColorType, nullptr, srcImg.get());
1071     SkIPoint offset;
1072 
1073     sk_sp<SkSpecialImage> resultImg(as_IFB(merge)->filterImage(ctx).imageAndOffset(&offset));
1074     REPORTER_ASSERT(reporter, resultImg);
1075 
1076     REPORTER_ASSERT(reporter, resultImg->width() == 20 && resultImg->height() == 20);
1077 }
1078 
DEF_TEST(ImageFilterMergeResultSize,reporter)1079 DEF_TEST(ImageFilterMergeResultSize, reporter) {
1080     test_imagefilter_merge_result_size(reporter, nullptr);
1081 }
1082 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterMergeResultSize_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1083 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterMergeResultSize_Gpu,
1084                                        reporter,
1085                                        ctxInfo,
1086                                        CtsEnforcement::kNever) {
1087     test_imagefilter_merge_result_size(reporter, ctxInfo.directContext());
1088 }
1089 
draw_blurred_rect(SkCanvas * canvas)1090 static void draw_blurred_rect(SkCanvas* canvas) {
1091     SkPaint filterPaint;
1092     filterPaint.setColor(SK_ColorWHITE);
1093     filterPaint.setImageFilter(SkImageFilters::Blur(SkIntToScalar(8), 0, nullptr));
1094     canvas->saveLayer(nullptr, &filterPaint);
1095     SkPaint whitePaint;
1096     whitePaint.setColor(SK_ColorWHITE);
1097     canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
1098     canvas->restore();
1099 }
1100 
draw_picture_clipped(SkCanvas * canvas,const SkRect & clipRect,const SkPicture * picture)1101 static void draw_picture_clipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
1102     canvas->save();
1103     canvas->clipRect(clipRect);
1104     canvas->drawPicture(picture);
1105     canvas->restore();
1106 }
1107 
DEF_TEST(ImageFilterDrawTiledBlurRTree,reporter)1108 DEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) {
1109     // Check that the blur filter when recorded with RTree acceleration,
1110     // and drawn tiled (with subsequent clip rects) exactly
1111     // matches the same filter drawn with without RTree acceleration.
1112     // This tests that the "bleed" from the blur into the otherwise-blank
1113     // tiles is correctly rendered.
1114     // Tests pass by not asserting.
1115 
1116     int width = 16, height = 8;
1117     SkBitmap result1, result2;
1118     result1.allocN32Pixels(width, height);
1119     result2.allocN32Pixels(width, height);
1120     SkCanvas canvas1(result1);
1121     SkCanvas canvas2(result2);
1122     int tileSize = 8;
1123 
1124     canvas1.clear(0);
1125     canvas2.clear(0);
1126 
1127     SkRTreeFactory factory;
1128 
1129     SkPictureRecorder recorder1, recorder2;
1130     // The only difference between these two pictures is that one has RTree aceleration.
1131     SkCanvas* recordingCanvas1 = recorder1.beginRecording(width, height);
1132     SkCanvas* recordingCanvas2 = recorder2.beginRecording(width, height, &factory);
1133 
1134     draw_blurred_rect(recordingCanvas1);
1135     draw_blurred_rect(recordingCanvas2);
1136     sk_sp<SkPicture> picture1(recorder1.finishRecordingAsPicture());
1137     sk_sp<SkPicture> picture2(recorder2.finishRecordingAsPicture());
1138     for (int y = 0; y < height; y += tileSize) {
1139         for (int x = 0; x < width; x += tileSize) {
1140             SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
1141             draw_picture_clipped(&canvas1, tileRect, picture1.get());
1142             draw_picture_clipped(&canvas2, tileRect, picture2.get());
1143         }
1144     }
1145     for (int y = 0; y < height; y++) {
1146         int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
1147         REPORTER_ASSERT(reporter, !diffs);
1148         if (diffs) {
1149             break;
1150         }
1151     }
1152 }
1153 
DEF_TEST(ImageFilterMatrixConvolution,reporter)1154 DEF_TEST(ImageFilterMatrixConvolution, reporter) {
1155     // Check that a 1x3 filter does not cause a spurious assert.
1156     SkScalar kernel[3] = {
1157         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
1158     };
1159     SkISize kernelSize = SkISize::Make(1, 3);
1160     SkScalar gain = SK_Scalar1, bias = 0;
1161     SkIPoint kernelOffset = SkIPoint::Make(0, 0);
1162 
1163     sk_sp<SkImageFilter> filter(SkImageFilters::MatrixConvolution(
1164             kernelSize, kernel, gain, bias, kernelOffset, SkTileMode::kRepeat, false, nullptr));
1165 
1166     SkBitmap result;
1167     int width = 16, height = 16;
1168     result.allocN32Pixels(width, height);
1169     SkCanvas canvas(result);
1170     canvas.clear(0);
1171 
1172     SkPaint paint;
1173     paint.setImageFilter(std::move(filter));
1174     SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
1175     canvas.drawRect(rect, paint);
1176 }
1177 
DEF_TEST(ImageFilterMatrixConvolutionBorder,reporter)1178 DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
1179     // Check that a filter with borders outside the target bounds
1180     // does not crash.
1181     SkScalar kernel[3] = {
1182         0, 0, 0,
1183     };
1184     SkISize kernelSize = SkISize::Make(3, 1);
1185     SkScalar gain = SK_Scalar1, bias = 0;
1186     SkIPoint kernelOffset = SkIPoint::Make(2, 0);
1187 
1188     sk_sp<SkImageFilter> filter(SkImageFilters::MatrixConvolution(
1189             kernelSize, kernel, gain, bias, kernelOffset, SkTileMode::kClamp, true, nullptr));
1190 
1191     SkBitmap result;
1192 
1193     int width = 10, height = 10;
1194     result.allocN32Pixels(width, height);
1195     SkCanvas canvas(result);
1196     canvas.clear(0);
1197 
1198     SkPaint filterPaint;
1199     filterPaint.setImageFilter(std::move(filter));
1200     SkRect bounds = SkRect::MakeIWH(1, 10);
1201     SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
1202     SkPaint rectPaint;
1203     canvas.saveLayer(&bounds, &filterPaint);
1204     canvas.drawRect(rect, rectPaint);
1205     canvas.restore();
1206 }
1207 
test_big_kernel(skiatest::Reporter * reporter,GrRecordingContext * rContext)1208 static void test_big_kernel(skiatest::Reporter* reporter, GrRecordingContext* rContext) {
1209     // Check that a kernel that is too big for the GPU still works
1210     SkScalar identityKernel[49] = {
1211         0, 0, 0, 0, 0, 0, 0,
1212         0, 0, 0, 0, 0, 0, 0,
1213         0, 0, 0, 0, 0, 0, 0,
1214         0, 0, 0, 1, 0, 0, 0,
1215         0, 0, 0, 0, 0, 0, 0,
1216         0, 0, 0, 0, 0, 0, 0,
1217         0, 0, 0, 0, 0, 0, 0
1218     };
1219     SkISize kernelSize = SkISize::Make(7, 7);
1220     SkScalar gain = SK_Scalar1, bias = 0;
1221     SkIPoint kernelOffset = SkIPoint::Make(0, 0);
1222 
1223     sk_sp<SkImageFilter> filter(SkImageFilters::MatrixConvolution(
1224             kernelSize, identityKernel, gain, bias, kernelOffset,
1225             SkTileMode::kClamp, true, nullptr));
1226 
1227     sk_sp<SkSpecialImage> srcImg(create_empty_special_image(rContext, 100));
1228     SkASSERT(srcImg);
1229 
1230     SkIPoint offset;
1231     SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr,
1232                                     kN32_SkColorType, nullptr, srcImg.get());
1233     sk_sp<SkSpecialImage> resultImg(as_IFB(filter)->filterImage(ctx).imageAndOffset(&offset));
1234     REPORTER_ASSERT(reporter, resultImg);
1235     REPORTER_ASSERT(reporter, SkToBool(rContext) == resultImg->isTextureBacked());
1236     REPORTER_ASSERT(reporter, resultImg->width() == 100 && resultImg->height() == 100);
1237     REPORTER_ASSERT(reporter, offset.fX == 0 && offset.fY == 0);
1238 }
1239 
DEF_TEST(ImageFilterMatrixConvolutionBigKernel,reporter)1240 DEF_TEST(ImageFilterMatrixConvolutionBigKernel, reporter) {
1241     test_big_kernel(reporter, nullptr);
1242 }
1243 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterMatrixConvolutionBigKernel_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1244 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterMatrixConvolutionBigKernel_Gpu,
1245                                        reporter,
1246                                        ctxInfo,
1247                                        CtsEnforcement::kNever) {
1248     test_big_kernel(reporter, ctxInfo.directContext());
1249 }
1250 
DEF_TEST(ImageFilterCropRect,reporter)1251 DEF_TEST(ImageFilterCropRect, reporter) {
1252     test_cropRects(reporter, nullptr);
1253 }
1254 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterCropRect_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1255 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterCropRect_Gpu,
1256                                        reporter,
1257                                        ctxInfo,
1258                                        CtsEnforcement::kNever) {
1259     test_cropRects(reporter, ctxInfo.directContext());
1260 }
1261 
DEF_TEST(ImageFilterMatrix,reporter)1262 DEF_TEST(ImageFilterMatrix, reporter) {
1263     SkBitmap temp;
1264     temp.allocN32Pixels(100, 100);
1265     SkCanvas canvas(temp);
1266     canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
1267 
1268     SkMatrix expectedMatrix = canvas.getTotalMatrix();
1269 
1270     SkRTreeFactory factory;
1271     SkPictureRecorder recorder;
1272     SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory);
1273 
1274     SkPaint paint;
1275     paint.setImageFilter(MatrixTestImageFilter::Make(reporter, expectedMatrix));
1276     recordingCanvas->saveLayer(nullptr, &paint);
1277     SkPaint solidPaint;
1278     solidPaint.setColor(0xFFFFFFFF);
1279     recordingCanvas->save();
1280     recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
1281     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
1282     recordingCanvas->restore(); // scale
1283     recordingCanvas->restore(); // saveLayer
1284 
1285     canvas.drawPicture(recorder.finishRecordingAsPicture());
1286 }
1287 
test_clipped_picture_imagefilter(skiatest::Reporter * reporter,GrRecordingContext * rContext)1288 static void test_clipped_picture_imagefilter(skiatest::Reporter* reporter,
1289                                              GrRecordingContext* rContext) {
1290     sk_sp<SkPicture> picture;
1291 
1292     {
1293         SkRTreeFactory factory;
1294         SkPictureRecorder recorder;
1295         SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory);
1296 
1297         // Create an SkPicture which simply draws a green 1x1 rectangle.
1298         SkPaint greenPaint;
1299         greenPaint.setColor(SK_ColorGREEN);
1300         recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
1301         picture = recorder.finishRecordingAsPicture();
1302     }
1303 
1304     sk_sp<SkSpecialImage> srcImg(create_empty_special_image(rContext, 2));
1305 
1306     sk_sp<SkImageFilter> imageFilter(SkImageFilters::Picture(picture));
1307 
1308     SkIPoint offset;
1309     SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(1, 1, 1, 1), nullptr,
1310                                     kN32_SkColorType, nullptr, srcImg.get());
1311 
1312     sk_sp<SkSpecialImage> resultImage(
1313             as_IFB(imageFilter)->filterImage(ctx).imageAndOffset(&offset));
1314     REPORTER_ASSERT(reporter, !resultImage);
1315 }
1316 
DEF_TEST(ImageFilterClippedPictureImageFilter,reporter)1317 DEF_TEST(ImageFilterClippedPictureImageFilter, reporter) {
1318     test_clipped_picture_imagefilter(reporter, nullptr);
1319 }
1320 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterClippedPictureImageFilter_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1321 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterClippedPictureImageFilter_Gpu,
1322                                        reporter,
1323                                        ctxInfo,
1324                                        CtsEnforcement::kNever) {
1325     test_clipped_picture_imagefilter(reporter, ctxInfo.directContext());
1326 }
1327 
DEF_TEST(ImageFilterEmptySaveLayer,reporter)1328 DEF_TEST(ImageFilterEmptySaveLayer, reporter) {
1329     // Even when there's an empty saveLayer()/restore(), ensure that an image
1330     // filter or color filter which affects transparent black still draws.
1331 
1332     SkBitmap bitmap;
1333     bitmap.allocN32Pixels(10, 10);
1334     SkCanvas canvas(bitmap);
1335 
1336     SkRTreeFactory factory;
1337     SkPictureRecorder recorder;
1338 
1339     sk_sp<SkColorFilter> green(SkColorFilters::Blend(SK_ColorGREEN, SkBlendMode::kSrc));
1340     sk_sp<SkImageFilter> imageFilter(SkImageFilters::ColorFilter(green, nullptr));
1341     SkPaint imageFilterPaint;
1342     imageFilterPaint.setImageFilter(std::move(imageFilter));
1343     SkPaint colorFilterPaint;
1344     colorFilterPaint.setColorFilter(green);
1345 
1346     SkRect bounds = SkRect::MakeIWH(10, 10);
1347 
1348     SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory);
1349     recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
1350     recordingCanvas->restore();
1351     sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
1352 
1353     canvas.clear(0);
1354     canvas.drawPicture(picture);
1355     uint32_t pixel = *bitmap.getAddr32(0, 0);
1356     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1357 
1358     recordingCanvas = recorder.beginRecording(10, 10, &factory);
1359     recordingCanvas->saveLayer(nullptr, &imageFilterPaint);
1360     recordingCanvas->restore();
1361     sk_sp<SkPicture> picture2(recorder.finishRecordingAsPicture());
1362 
1363     canvas.clear(0);
1364     canvas.drawPicture(picture2);
1365     pixel = *bitmap.getAddr32(0, 0);
1366     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1367 
1368     recordingCanvas = recorder.beginRecording(10, 10, &factory);
1369     recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
1370     recordingCanvas->restore();
1371     sk_sp<SkPicture> picture3(recorder.finishRecordingAsPicture());
1372 
1373     canvas.clear(0);
1374     canvas.drawPicture(picture3);
1375     pixel = *bitmap.getAddr32(0, 0);
1376     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1377 }
1378 
test_huge_blur(SkCanvas * canvas,skiatest::Reporter * reporter)1379 static void test_huge_blur(SkCanvas* canvas, skiatest::Reporter* reporter) {
1380     SkBitmap bitmap;
1381     bitmap.allocN32Pixels(100, 100);
1382     bitmap.eraseARGB(0, 0, 0, 0);
1383 
1384     // Check that a blur with a very large radius does not crash or assert.
1385     SkPaint paint;
1386     paint.setImageFilter(SkImageFilters::Blur(SkIntToScalar(1<<30), SkIntToScalar(1<<30), nullptr));
1387     canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);
1388 }
1389 
DEF_TEST(HugeBlurImageFilter,reporter)1390 DEF_TEST(HugeBlurImageFilter, reporter) {
1391     SkBitmap temp;
1392     temp.allocN32Pixels(100, 100);
1393     SkCanvas canvas(temp);
1394     test_huge_blur(&canvas, reporter);
1395 }
1396 
DEF_TEST(ImageFilterMatrixConvolutionTest,reporter)1397 DEF_TEST(ImageFilterMatrixConvolutionTest, reporter) {
1398     SkScalar kernel[1] = { 0 };
1399     SkScalar gain = SK_Scalar1, bias = 0;
1400     SkIPoint kernelOffset = SkIPoint::Make(1, 1);
1401 
1402     // Check that an enormous (non-allocatable) kernel gives a nullptr filter.
1403     sk_sp<SkImageFilter> conv(SkImageFilters::MatrixConvolution(
1404             SkISize::Make(1<<30, 1<<30), kernel, gain, bias, kernelOffset,
1405             SkTileMode::kRepeat, false, nullptr));
1406 
1407     REPORTER_ASSERT(reporter, nullptr == conv.get());
1408 
1409     // Check that a nullptr kernel gives a nullptr filter.
1410     conv = SkImageFilters::MatrixConvolution(
1411             SkISize::Make(1, 1), nullptr, gain, bias, kernelOffset,
1412             SkTileMode::kRepeat, false, nullptr);
1413 
1414     REPORTER_ASSERT(reporter, nullptr == conv.get());
1415 
1416     // Check that a kernel width < 1 gives a nullptr filter.
1417     conv = SkImageFilters::MatrixConvolution(
1418             SkISize::Make(0, 1), kernel, gain, bias, kernelOffset,
1419             SkTileMode::kRepeat, false, nullptr);
1420 
1421     REPORTER_ASSERT(reporter, nullptr == conv.get());
1422 
1423     // Check that kernel height < 1 gives a nullptr filter.
1424     conv = SkImageFilters::MatrixConvolution(
1425             SkISize::Make(1, -1), kernel, gain, bias, kernelOffset,
1426             SkTileMode::kRepeat, false, nullptr);
1427 
1428     REPORTER_ASSERT(reporter, nullptr == conv.get());
1429 }
1430 
test_xfermode_cropped_input(SkSurface * surf,skiatest::Reporter * reporter)1431 static void test_xfermode_cropped_input(SkSurface* surf, skiatest::Reporter* reporter) {
1432     auto canvas = surf->getCanvas();
1433     canvas->clear(0);
1434 
1435     SkBitmap bitmap;
1436     bitmap.allocN32Pixels(1, 1);
1437     bitmap.eraseARGB(255, 255, 255, 255);
1438 
1439     sk_sp<SkColorFilter> green(SkColorFilters::Blend(SK_ColorGREEN, SkBlendMode::kSrcIn));
1440     sk_sp<SkImageFilter> greenFilter(SkImageFilters::ColorFilter(green, nullptr));
1441     SkIRect cropRect = SkIRect::MakeEmpty();
1442     sk_sp<SkImageFilter> croppedOut(SkImageFilters::ColorFilter(green, nullptr, &cropRect));
1443 
1444     // Check that an blend image filter whose input has been cropped out still draws the other
1445     // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
1446     SkBlendMode mode = SkBlendMode::kSrcOver;
1447     sk_sp<SkImageFilter> xfermodeNoFg(SkImageFilters::Blend(
1448             mode, greenFilter, croppedOut, nullptr));
1449     sk_sp<SkImageFilter> xfermodeNoBg(SkImageFilters::Blend(
1450             mode, croppedOut, greenFilter, nullptr));
1451     sk_sp<SkImageFilter> xfermodeNoFgNoBg(SkImageFilters::Blend(
1452             mode, croppedOut,  croppedOut, nullptr));
1453 
1454     SkPaint paint;
1455     paint.setImageFilter(std::move(xfermodeNoFg));
1456     canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);   // drawSprite
1457 
1458     uint32_t pixel;
1459     SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
1460     surf->readPixels(info, &pixel, 4, 0, 0);
1461     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1462 
1463     paint.setImageFilter(std::move(xfermodeNoBg));
1464     canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);   // drawSprite
1465     surf->readPixels(info, &pixel, 4, 0, 0);
1466     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1467 
1468     paint.setImageFilter(std::move(xfermodeNoFgNoBg));
1469     canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);   // drawSprite
1470     surf->readPixels(info, &pixel, 4, 0, 0);
1471     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1472 }
1473 
DEF_TEST(ImageFilterNestedSaveLayer,reporter)1474 DEF_TEST(ImageFilterNestedSaveLayer, reporter) {
1475     SkBitmap temp;
1476     temp.allocN32Pixels(50, 50);
1477     SkCanvas canvas(temp);
1478     canvas.clear(0x0);
1479 
1480     SkBitmap bitmap;
1481     bitmap.allocN32Pixels(10, 10);
1482     bitmap.eraseColor(SK_ColorGREEN);
1483 
1484     SkMatrix matrix;
1485     matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
1486     matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
1487     sk_sp<SkImageFilter> matrixFilter(
1488         SkImageFilters::MatrixTransform(matrix, SkSamplingOptions(SkFilterMode::kLinear), nullptr));
1489 
1490     // Test that saveLayer() with a filter nested inside another saveLayer() applies the
1491     // correct offset to the filter matrix.
1492     SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
1493     canvas.saveLayer(&bounds1, nullptr);
1494     SkPaint filterPaint;
1495     filterPaint.setImageFilter(std::move(matrixFilter));
1496     SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
1497     canvas.saveLayer(&bounds2, &filterPaint);
1498     SkPaint greenPaint;
1499     greenPaint.setColor(SK_ColorGREEN);
1500     canvas.drawRect(bounds2, greenPaint);
1501     canvas.restore();
1502     canvas.restore();
1503     SkPaint strokePaint;
1504     strokePaint.setStyle(SkPaint::kStroke_Style);
1505     strokePaint.setColor(SK_ColorRED);
1506 
1507     SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
1508     uint32_t pixel;
1509     temp.readPixels(info, &pixel, 4, 25, 25);
1510     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1511 
1512     // Test that drawSprite() with a filter nested inside a saveLayer() applies the
1513     // correct offset to the filter matrix.
1514     canvas.clear(0x0);
1515     temp.readPixels(info, &pixel, 4, 25, 25);
1516     canvas.saveLayer(&bounds1, nullptr);
1517     canvas.drawImage(bitmap.asImage(), 20, 20, SkSamplingOptions(), &filterPaint); // drawSprite
1518     canvas.restore();
1519 
1520     temp.readPixels(info, &pixel, 4, 25, 25);
1521     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1522 }
1523 
DEF_TEST(XfermodeImageFilterCroppedInput,reporter)1524 DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
1525     test_xfermode_cropped_input(SkSurface::MakeRasterN32Premul(100, 100).get(), reporter);
1526 }
1527 
test_composed_imagefilter_offset(skiatest::Reporter * reporter,GrRecordingContext * rContext)1528 static void test_composed_imagefilter_offset(skiatest::Reporter* reporter,
1529                                              GrRecordingContext* rContext) {
1530     sk_sp<SkSpecialImage> srcImg(create_empty_special_image(rContext, 100));
1531 
1532     SkIRect cropRect = SkIRect::MakeXYWH(1, 0, 20, 20);
1533     sk_sp<SkImageFilter> offsetFilter(SkImageFilters::Offset(0, 0, nullptr, &cropRect));
1534     sk_sp<SkImageFilter> blurFilter(SkImageFilters::Blur(SK_Scalar1, SK_Scalar1,
1535                                                             nullptr, &cropRect));
1536     sk_sp<SkImageFilter> composedFilter(SkImageFilters::Compose(std::move(blurFilter),
1537                                                                 std::move(offsetFilter)));
1538     SkIPoint offset;
1539     SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr,
1540                                     kN32_SkColorType, nullptr, srcImg.get());
1541 
1542     sk_sp<SkSpecialImage> resultImg(
1543             as_IFB(composedFilter)->filterImage(ctx).imageAndOffset(&offset));
1544     REPORTER_ASSERT(reporter, resultImg);
1545     REPORTER_ASSERT(reporter, offset.fX == 1 && offset.fY == 0);
1546 }
1547 
DEF_TEST(ComposedImageFilterOffset,reporter)1548 DEF_TEST(ComposedImageFilterOffset, reporter) {
1549     test_composed_imagefilter_offset(reporter, nullptr);
1550 }
1551 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ComposedImageFilterOffset_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1552 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ComposedImageFilterOffset_Gpu,
1553                                        reporter,
1554                                        ctxInfo,
1555                                        CtsEnforcement::kNever) {
1556     test_composed_imagefilter_offset(reporter, ctxInfo.directContext());
1557 }
1558 
test_composed_imagefilter_bounds(skiatest::Reporter * reporter,GrDirectContext * dContext)1559 static void test_composed_imagefilter_bounds(skiatest::Reporter* reporter,
1560                                              GrDirectContext* dContext) {
1561     // The bounds passed to the inner filter must be filtered by the outer
1562     // filter, so that the inner filter produces the pixels that the outer
1563     // filter requires as input. This matters if the outer filter moves pixels.
1564     // Here, accounting for the outer offset is necessary so that the green
1565     // pixels of the picture are not clipped.
1566 
1567     SkPictureRecorder recorder;
1568     SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeIWH(200, 100));
1569     recordingCanvas->clipRect(SkRect::MakeXYWH(100, 0, 100, 100));
1570     recordingCanvas->clear(SK_ColorGREEN);
1571     sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
1572     sk_sp<SkImageFilter> pictureFilter(SkImageFilters::Picture(picture));
1573     SkIRect cropRect = SkIRect::MakeWH(100, 100);
1574     sk_sp<SkImageFilter> offsetFilter(SkImageFilters::Offset(-100, 0, nullptr, &cropRect));
1575     sk_sp<SkImageFilter> composedFilter(SkImageFilters::Compose(std::move(offsetFilter),
1576                                                                 std::move(pictureFilter)));
1577 
1578     sk_sp<SkSpecialImage> sourceImage(create_empty_special_image(dContext, 100));
1579     SkImageFilter_Base::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr,
1580                                     kN32_SkColorType, nullptr, sourceImage.get());
1581     SkIPoint offset;
1582     sk_sp<SkSpecialImage> result(
1583             as_IFB(composedFilter)->filterImage(ctx).imageAndOffset(&offset));
1584     REPORTER_ASSERT(reporter, offset.isZero());
1585     REPORTER_ASSERT(reporter, result);
1586     REPORTER_ASSERT(reporter, result->subset().size() == SkISize::Make(100, 100));
1587 
1588     SkBitmap resultBM;
1589     REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, result.get(), &resultBM));
1590     REPORTER_ASSERT(reporter, resultBM.getColor(50, 50) == SK_ColorGREEN);
1591 }
1592 
DEF_TEST(ComposedImageFilterBounds,reporter)1593 DEF_TEST(ComposedImageFilterBounds, reporter) {
1594     test_composed_imagefilter_bounds(reporter, nullptr);
1595 }
1596 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ComposedImageFilterBounds_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1597 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ComposedImageFilterBounds_Gpu,
1598                                        reporter,
1599                                        ctxInfo,
1600                                        CtsEnforcement::kNever) {
1601     test_composed_imagefilter_bounds(reporter, ctxInfo.directContext());
1602 }
1603 
DEF_TEST(ImageFilterCanComputeFastBounds,reporter)1604 DEF_TEST(ImageFilterCanComputeFastBounds, reporter) {
1605 
1606     {
1607         SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
1608         sk_sp<SkImageFilter> lighting(SkImageFilters::PointLitDiffuse(
1609                 location,  SK_ColorGREEN, 0, 0, nullptr));
1610         REPORTER_ASSERT(reporter, !lighting->canComputeFastBounds());
1611     }
1612 
1613     {
1614         sk_sp<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
1615         REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1616         {
1617             SkColorFilter* grayCF;
1618             REPORTER_ASSERT(reporter, gray->asAColorFilter(&grayCF));
1619             REPORTER_ASSERT(reporter, !as_CFB(grayCF)->affectsTransparentBlack());
1620             grayCF->unref();
1621         }
1622         REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1623 
1624         sk_sp<SkImageFilter> grayBlur(SkImageFilters::Blur(
1625                 SK_Scalar1, SK_Scalar1, std::move(gray)));
1626         REPORTER_ASSERT(reporter, grayBlur->canComputeFastBounds());
1627     }
1628 
1629     {
1630         float greenMatrix[20] = { 0, 0, 0, 0, 0,
1631                                   0, 0, 0, 0, 1.0f/255,
1632                                   0, 0, 0, 0, 0,
1633                                   0, 0, 0, 0, 1.0f/255
1634         };
1635         sk_sp<SkColorFilter> greenCF(SkColorFilters::Matrix(greenMatrix));
1636         sk_sp<SkImageFilter> green(SkImageFilters::ColorFilter(greenCF, nullptr));
1637 
1638         REPORTER_ASSERT(reporter, as_CFB(greenCF)->affectsTransparentBlack());
1639         REPORTER_ASSERT(reporter, !green->canComputeFastBounds());
1640 
1641         sk_sp<SkImageFilter> greenBlur(SkImageFilters::Blur(SK_Scalar1, SK_Scalar1,
1642                                                                std::move(green)));
1643         REPORTER_ASSERT(reporter, !greenBlur->canComputeFastBounds());
1644     }
1645 
1646     uint8_t allOne[256], identity[256];
1647     for (int i = 0; i < 256; ++i) {
1648         identity[i] = i;
1649         allOne[i] = 255;
1650     }
1651 
1652     sk_sp<SkColorFilter> identityCF(SkColorFilters::TableARGB(identity, identity,
1653                                                               identity, allOne));
1654     sk_sp<SkImageFilter> identityFilter(SkImageFilters::ColorFilter(identityCF, nullptr));
1655     REPORTER_ASSERT(reporter, !as_CFB(identityCF)->affectsTransparentBlack());
1656     REPORTER_ASSERT(reporter, identityFilter->canComputeFastBounds());
1657 
1658     sk_sp<SkColorFilter> forceOpaqueCF(SkColorFilters::TableARGB(allOne, identity,
1659                                                                  identity, identity));
1660     sk_sp<SkImageFilter> forceOpaque(SkImageFilters::ColorFilter(forceOpaqueCF, nullptr));
1661     REPORTER_ASSERT(reporter, as_CFB(forceOpaqueCF)->affectsTransparentBlack());
1662     REPORTER_ASSERT(reporter, !forceOpaque->canComputeFastBounds());
1663 }
1664 
1665 // Verify that SkImageSource survives serialization
DEF_TEST(ImageFilterImageSourceSerialization,reporter)1666 DEF_TEST(ImageFilterImageSourceSerialization, reporter) {
1667     auto surface(SkSurface::MakeRasterN32Premul(10, 10));
1668     surface->getCanvas()->clear(SK_ColorGREEN);
1669     sk_sp<SkImage> image(surface->makeImageSnapshot());
1670     sk_sp<SkImageFilter> filter(SkImageFilters::Image(std::move(image)));
1671 
1672     sk_sp<SkData> data(filter->serialize());
1673     sk_sp<SkImageFilter> unflattenedFilter = SkImageFilter::Deserialize(data->data(), data->size());
1674     REPORTER_ASSERT(reporter, unflattenedFilter);
1675 
1676     SkBitmap bm;
1677     bm.allocN32Pixels(10, 10);
1678     bm.eraseColor(SK_ColorBLUE);
1679     SkPaint paint;
1680     paint.setColor(SK_ColorRED);
1681     paint.setImageFilter(unflattenedFilter);
1682 
1683     SkCanvas canvas(bm);
1684     canvas.drawRect(SkRect::MakeIWH(10, 10), paint);
1685     REPORTER_ASSERT(reporter, *bm.getAddr32(0, 0) == SkPreMultiplyColor(SK_ColorGREEN));
1686 }
1687 
DEF_TEST(ImageFilterImageSourceUninitialized,r)1688 DEF_TEST(ImageFilterImageSourceUninitialized, r) {
1689     sk_sp<SkData> data(GetResourceAsData("crbug769134.fil"));
1690     if (!data) {
1691         return;
1692     }
1693     sk_sp<SkImageFilter> unflattenedFilter = SkImageFilter::Deserialize(data->data(), data->size());
1694     // This will fail. More importantly, msan will verify that we did not
1695     // compare against uninitialized memory.
1696     REPORTER_ASSERT(r, !unflattenedFilter);
1697 }
1698 
test_large_blur_input(skiatest::Reporter * reporter,SkCanvas * canvas)1699 static void test_large_blur_input(skiatest::Reporter* reporter, SkCanvas* canvas) {
1700     SkBitmap largeBmp;
1701     int largeW = 5000;
1702     int largeH = 5000;
1703     // If we're GPU-backed make the bitmap too large to be converted into a texture.
1704     if (auto ctx = canvas->recordingContext()) {
1705         largeW = ctx->priv().caps()->maxTextureSize() + 1;
1706     }
1707 
1708     largeBmp.allocN32Pixels(largeW, largeH);
1709     largeBmp.eraseColor(0);
1710     if (!largeBmp.getPixels()) {
1711         ERRORF(reporter, "Failed to allocate large bmp.");
1712         return;
1713     }
1714 
1715     sk_sp<SkImage> largeImage(largeBmp.asImage());
1716     if (!largeImage) {
1717         ERRORF(reporter, "Failed to create large image.");
1718         return;
1719     }
1720 
1721     sk_sp<SkImageFilter> largeSource(SkImageFilters::Image(std::move(largeImage)));
1722     if (!largeSource) {
1723         ERRORF(reporter, "Failed to create large SkImageSource.");
1724         return;
1725     }
1726 
1727     sk_sp<SkImageFilter> blur(SkImageFilters::Blur(10.f, 10.f, std::move(largeSource)));
1728     if (!blur) {
1729         ERRORF(reporter, "Failed to create SkBlurImageFilter.");
1730         return;
1731     }
1732 
1733     SkPaint paint;
1734     paint.setImageFilter(std::move(blur));
1735 
1736     // This should not crash (http://crbug.com/570479).
1737     canvas->drawRect(SkRect::MakeIWH(largeW, largeH), paint);
1738 }
1739 
DEF_TEST(ImageFilterBlurLargeImage,reporter)1740 DEF_TEST(ImageFilterBlurLargeImage, reporter) {
1741     auto surface(SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(100, 100)));
1742     test_large_blur_input(reporter, surface->getCanvas());
1743 }
1744 
test_make_with_filter(skiatest::Reporter * reporter,GrRecordingContext * rContext)1745 static void test_make_with_filter(skiatest::Reporter* reporter, GrRecordingContext* rContext) {
1746     sk_sp<SkSurface> surface(create_surface(rContext, 192, 128));
1747     surface->getCanvas()->clear(SK_ColorRED);
1748     SkPaint bluePaint;
1749     bluePaint.setColor(SK_ColorBLUE);
1750     SkIRect subset = SkIRect::MakeXYWH(25, 20, 50, 50);
1751     surface->getCanvas()->drawRect(SkRect::Make(subset), bluePaint);
1752     sk_sp<SkImage> sourceImage = surface->makeImageSnapshot();
1753 
1754     sk_sp<SkImageFilter> filter = make_grayscale(nullptr, nullptr);
1755     SkIRect clipBounds = SkIRect::MakeXYWH(30, 35, 100, 100);
1756     SkIRect outSubset;
1757     SkIPoint offset;
1758     sk_sp<SkImage> result;
1759 
1760     result = sourceImage->makeWithFilter(rContext, nullptr, subset, clipBounds,
1761                                          &outSubset, &offset);
1762     REPORTER_ASSERT(reporter, !result);
1763 
1764     result = sourceImage->makeWithFilter(rContext, filter.get(), subset, clipBounds,
1765                                          nullptr, &offset);
1766     REPORTER_ASSERT(reporter, !result);
1767 
1768     result = sourceImage->makeWithFilter(rContext, filter.get(), subset, clipBounds,
1769                                          &outSubset, nullptr);
1770     REPORTER_ASSERT(reporter, !result);
1771 
1772     SkIRect bigSubset = SkIRect::MakeXYWH(-10000, -10000, 20000, 20000);
1773     result = sourceImage->makeWithFilter(rContext, filter.get(), bigSubset, clipBounds,
1774                                          &outSubset, &offset);
1775     REPORTER_ASSERT(reporter, !result);
1776 
1777     SkIRect empty = SkIRect::MakeEmpty();
1778     result = sourceImage->makeWithFilter(rContext, filter.get(), empty, clipBounds,
1779                                          &outSubset, &offset);
1780     REPORTER_ASSERT(reporter, !result);
1781 
1782     result = sourceImage->makeWithFilter(rContext, filter.get(), subset, empty,
1783                                          &outSubset, &offset);
1784     REPORTER_ASSERT(reporter, !result);
1785 
1786     SkIRect leftField = SkIRect::MakeXYWH(-1000, 0, 100, 100);
1787     result = sourceImage->makeWithFilter(rContext, filter.get(), subset, leftField,
1788                                          &outSubset, &offset);
1789     REPORTER_ASSERT(reporter, !result);
1790 
1791     result = sourceImage->makeWithFilter(rContext, filter.get(), subset, clipBounds,
1792                                          &outSubset, &offset);
1793 
1794     REPORTER_ASSERT(reporter, result);
1795     REPORTER_ASSERT(reporter, result->bounds().contains(outSubset));
1796     SkIRect destRect = SkIRect::MakeXYWH(offset.x(), offset.y(),
1797                                           outSubset.width(), outSubset.height());
1798     REPORTER_ASSERT(reporter, clipBounds.contains(destRect));
1799 
1800     // In GPU-mode, this case creates a special image with a backing size that differs from
1801     // the content size
1802     {
1803         clipBounds.setXYWH(0, 0, 170, 100);
1804         subset.setXYWH(0, 0, 160, 90);
1805 
1806         filter = SkImageFilters::Blend(SkBlendMode::kSrc, nullptr);
1807         result = sourceImage->makeWithFilter(rContext, filter.get(), subset, clipBounds,
1808                                              &outSubset, &offset);
1809         REPORTER_ASSERT(reporter, result);
1810 
1811         // In GPU-mode, we want the result image (and all intermediate steps) to have used the same
1812         // origin as the original surface.
1813         if (rContext) {
1814             auto [proxyView, _] = as_IB(result)->asView(rContext, GrMipmapped::kNo);
1815             REPORTER_ASSERT(reporter, proxyView && proxyView.origin() == kTestSurfaceOrigin);
1816         }
1817     }
1818 }
1819 
DEF_TEST(ImageFilterMakeWithFilter,reporter)1820 DEF_TEST(ImageFilterMakeWithFilter, reporter) {
1821     test_make_with_filter(reporter, nullptr);
1822 }
1823 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterMakeWithFilter_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1824 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterMakeWithFilter_Gpu,
1825                                        reporter,
1826                                        ctxInfo,
1827                                        CtsEnforcement::kNever) {
1828     test_make_with_filter(reporter, ctxInfo.directContext());
1829 }
1830 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterHugeBlur_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1831 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ImageFilterHugeBlur_Gpu,
1832                                        reporter,
1833                                        ctxInfo,
1834                                        CtsEnforcement::kNever) {
1835     sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(
1836             ctxInfo.directContext(), skgpu::Budgeted::kNo, SkImageInfo::MakeN32Premul(100, 100)));
1837 
1838     SkCanvas* canvas = surf->getCanvas();
1839 
1840     test_huge_blur(canvas, reporter);
1841 }
1842 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(XfermodeImageFilterCroppedInput_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1843 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(XfermodeImageFilterCroppedInput_Gpu,
1844                                        reporter,
1845                                        ctxInfo,
1846                                        CtsEnforcement::kNever) {
1847     sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(
1848             ctxInfo.directContext(),
1849             skgpu::Budgeted::kNo,
1850             SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType)));
1851 
1852     test_xfermode_cropped_input(surf.get(), reporter);
1853 }
1854 
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(ImageFilterBlurLargeImage_Gpu,reporter,ctxInfo,CtsEnforcement::kNever)1855 DEF_GANESH_TEST_FOR_ALL_CONTEXTS(ImageFilterBlurLargeImage_Gpu,
1856                                  reporter,
1857                                  ctxInfo,
1858                                  CtsEnforcement::kNever) {
1859     auto surface(SkSurface::MakeRenderTarget(
1860             ctxInfo.directContext(),
1861             skgpu::Budgeted::kYes,
1862             SkImageInfo::Make(100, 100, kRGBA_8888_SkColorType, kPremul_SkAlphaType)));
1863     test_large_blur_input(reporter, surface->getCanvas());
1864 }
1865 
1866 /*
1867  *  Test that colorfilterimagefilter does not require its CTM to be decomposed when it has more
1868  *  than just scale/translate, but that other filters do.
1869  */
DEF_TEST(ImageFilterComplexCTM,reporter)1870 DEF_TEST(ImageFilterComplexCTM, reporter) {
1871     // just need a colorfilter to exercise the corresponding imagefilter
1872     sk_sp<SkColorFilter> cf = SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcATop);
1873     sk_sp<SkImageFilter> cfif = SkImageFilters::ColorFilter(cf, nullptr);    // can handle
1874     sk_sp<SkImageFilter> blif = SkImageFilters::Blur(3, 3, nullptr);         // cannot handle
1875     using MatrixCapability = SkImageFilter_Base::MatrixCapability;
1876 
1877     struct {
1878         sk_sp<SkImageFilter> fFilter;
1879         MatrixCapability     fExpectCapability;
1880     } recs[] = {
1881         { cfif,                                  MatrixCapability::kComplex },
1882         { SkImageFilters::ColorFilter(cf, cfif), MatrixCapability::kComplex },
1883         { SkImageFilters::Merge(cfif, cfif),     MatrixCapability::kComplex },
1884         { SkImageFilters::Compose(cfif, cfif),   MatrixCapability::kComplex },
1885 
1886         { blif,                                  MatrixCapability::kScaleTranslate },
1887         { SkImageFilters::Blur(3, 3, cfif),      MatrixCapability::kScaleTranslate },
1888         { SkImageFilters::ColorFilter(cf, blif), MatrixCapability::kScaleTranslate },
1889         { SkImageFilters::Merge(cfif, blif),     MatrixCapability::kScaleTranslate },
1890         { SkImageFilters::Compose(blif, cfif),   MatrixCapability::kScaleTranslate },
1891     };
1892 
1893     for (const auto& rec : recs) {
1894         const MatrixCapability capability = as_IFB(rec.fFilter)->getCTMCapability();
1895         REPORTER_ASSERT(reporter, capability == rec.fExpectCapability);
1896     }
1897 }
1898 
1899 // Test SkXfermodeImageFilter::filterBounds with different blending modes.
DEF_TEST(XfermodeImageFilterBounds,reporter)1900 DEF_TEST(XfermodeImageFilterBounds, reporter) {
1901     SkIRect background_rect = SkIRect::MakeXYWH(0, 0, 100, 100);
1902     SkIRect foreground_rect = SkIRect::MakeXYWH(50, 50, 100, 100);
1903     sk_sp<SkImageFilter> background(new FixedBoundsImageFilter(background_rect));
1904     sk_sp<SkImageFilter> foreground(new FixedBoundsImageFilter(foreground_rect));
1905 
1906     SkIRect expectedBounds[kSkBlendModeCount];
1907     // Expect union of input rects by default.
1908     for (int i = 0; i < kSkBlendModeCount; ++i) {
1909         expectedBounds[i] = background_rect;
1910         expectedBounds[i].join(foreground_rect);
1911     }
1912 
1913     SkIRect intersection = background_rect;
1914     intersection.intersect(foreground_rect);
1915     expectedBounds[static_cast<int>(SkBlendMode::kClear)] = SkIRect::MakeEmpty();
1916     expectedBounds[static_cast<int>(SkBlendMode::kSrc)] = foreground_rect;
1917     expectedBounds[static_cast<int>(SkBlendMode::kDst)] = background_rect;
1918     expectedBounds[static_cast<int>(SkBlendMode::kSrcIn)] = intersection;
1919     expectedBounds[static_cast<int>(SkBlendMode::kDstIn)] = intersection;
1920     expectedBounds[static_cast<int>(SkBlendMode::kSrcATop)] = background_rect;
1921     expectedBounds[static_cast<int>(SkBlendMode::kDstATop)] = foreground_rect;
1922 
1923     // The value of this variable doesn't matter because we use inputs with fixed bounds.
1924     SkIRect src = SkIRect::MakeXYWH(11, 22, 33, 44);
1925     for (int i = 0; i < kSkBlendModeCount; ++i) {
1926         sk_sp<SkImageFilter> xfermode(SkImageFilters::Blend(static_cast<SkBlendMode>(i),
1927                                                             background, foreground, nullptr));
1928         auto bounds = xfermode->filterBounds(src, SkMatrix::I(),
1929                                              SkImageFilter::kForward_MapDirection, nullptr);
1930         REPORTER_ASSERT(reporter, bounds == expectedBounds[i]);
1931     }
1932 
1933     // Test empty intersection.
1934     sk_sp<SkImageFilter> background2(new FixedBoundsImageFilter(SkIRect::MakeXYWH(0, 0, 20, 20)));
1935     sk_sp<SkImageFilter> foreground2(new FixedBoundsImageFilter(SkIRect::MakeXYWH(40, 40, 50, 50)));
1936     sk_sp<SkImageFilter> xfermode(SkImageFilters::Blend(
1937             SkBlendMode::kSrcIn, std::move(background2), std::move(foreground2), nullptr));
1938     auto bounds = xfermode->filterBounds(src, SkMatrix::I(),
1939                                          SkImageFilter::kForward_MapDirection, nullptr);
1940     REPORTER_ASSERT(reporter, bounds.isEmpty());
1941 }
1942 
DEF_TEST(OffsetImageFilterBounds,reporter)1943 DEF_TEST(OffsetImageFilterBounds, reporter) {
1944     const SkIRect src = SkIRect::MakeXYWH(0, 0, 100, 100);
1945     const SkVector srcOffset = {-50.5f, -50.5f};
1946     sk_sp<SkImageFilter> offset(SkImageFilters::Offset(srcOffset.fX, srcOffset.fY, nullptr));
1947 
1948     // Because the offset has a fractional component, the final output and required input bounds
1949     // will be rounded out to include an extra pixel.
1950     SkIRect expectedForward = SkRect::Make(src).makeOffset(srcOffset.fX, srcOffset.fY).roundOut();
1951     SkIRect boundsForward = offset->filterBounds(src, SkMatrix::I(),
1952                                                  SkImageFilter::kForward_MapDirection, nullptr);
1953     REPORTER_ASSERT(reporter, boundsForward == expectedForward);
1954 
1955     SkIRect expectedReverse = SkRect::Make(src).makeOffset(-srcOffset.fX, -srcOffset.fY).roundOut();
1956     SkIRect boundsReverse = offset->filterBounds(src, SkMatrix::I(),
1957                                                  SkImageFilter::kReverse_MapDirection, &src);
1958     REPORTER_ASSERT(reporter, boundsReverse == expectedReverse);
1959 }
1960 
DEF_TEST(OffsetImageFilterBoundsNoOverflow,reporter)1961 DEF_TEST(OffsetImageFilterBoundsNoOverflow, reporter) {
1962     const SkIRect src = SkIRect::MakeXYWH(-10.f, -10.f, 20.f, 20.f);
1963     const SkScalar bigOffset = SkIntToScalar(std::numeric_limits<int>::max()) * 2.f / 3.f;
1964 
1965     sk_sp<SkImageFilter> filter =
1966             SkImageFilters::Blend(SkBlendMode::kSrcOver,
1967                                   SkImageFilters::Offset(-bigOffset, -bigOffset, nullptr),
1968                                   SkImageFilters::Offset(bigOffset, bigOffset, nullptr));
1969     SkIRect boundsForward = filter->filterBounds(src, SkMatrix::I(),
1970                                                  SkImageFilter::kForward_MapDirection, nullptr);
1971     SkIRect boundsReverse = filter->filterBounds(src, SkMatrix::I(),
1972                                                  SkImageFilter::kReverse_MapDirection, nullptr);
1973     // NOTE: isEmpty() will return true even if the l/r or t/b didn't overflow but the dimensions
1974     // would overflow an int32. However, when isEmpty64() is false, it means the actual edge coords
1975     // are valid, which is good enough for our purposes (and gfx::Rect has its own strategies for
1976     // ensuring such a rectangle doesn't get accidentally treated as empty during chromium's
1977     // conversions).
1978     REPORTER_ASSERT(reporter, !boundsForward.isEmpty64());
1979     REPORTER_ASSERT(reporter, !boundsReverse.isEmpty64());
1980 }
1981 
test_arithmetic_bounds(skiatest::Reporter * reporter,float k1,float k2,float k3,float k4,sk_sp<SkImageFilter> background,sk_sp<SkImageFilter> foreground,const SkIRect * crop,const SkIRect & expected)1982 static void test_arithmetic_bounds(skiatest::Reporter* reporter, float k1, float k2, float k3,
1983                                    float k4, sk_sp<SkImageFilter> background,
1984                                    sk_sp<SkImageFilter> foreground,
1985                                    const SkIRect* crop, const SkIRect& expected) {
1986     sk_sp<SkImageFilter> arithmetic(
1987             SkImageFilters::Arithmetic(k1, k2, k3, k4, false, background, foreground, crop));
1988     // The value of the input rect doesn't matter because we use inputs with fixed bounds.
1989     SkIRect bounds = arithmetic->filterBounds(SkIRect::MakeXYWH(11, 22, 33, 44), SkMatrix::I(),
1990                                               SkImageFilter::kForward_MapDirection, nullptr);
1991     REPORTER_ASSERT(reporter, expected == bounds);
1992 }
1993 
test_arithmetic_combinations(skiatest::Reporter * reporter,float v)1994 static void test_arithmetic_combinations(skiatest::Reporter* reporter, float v) {
1995     SkIRect bgRect = SkIRect::MakeXYWH(0, 0, 100, 100);
1996     SkIRect fgRect = SkIRect::MakeXYWH(50, 50, 100, 100);
1997     sk_sp<SkImageFilter> background(new FixedBoundsImageFilter(bgRect));
1998     sk_sp<SkImageFilter> foreground(new FixedBoundsImageFilter(fgRect));
1999 
2000     SkIRect unionRect = bgRect;
2001     unionRect.join(fgRect);
2002     SkIRect intersection = bgRect;
2003     intersection.intersect(fgRect);
2004 
2005     test_arithmetic_bounds(reporter, 0, 0, 0, 0, background, foreground, nullptr,
2006                            SkIRect::MakeEmpty());
2007     test_arithmetic_bounds(reporter, 0, 0, 0, v, background, foreground, nullptr, unionRect);
2008     test_arithmetic_bounds(reporter, 0, 0, v, 0, background, foreground, nullptr, bgRect);
2009     test_arithmetic_bounds(reporter, 0, 0, v, v, background, foreground, nullptr, unionRect);
2010     test_arithmetic_bounds(reporter, 0, v, 0, 0, background, foreground, nullptr, fgRect);
2011     test_arithmetic_bounds(reporter, 0, v, 0, v, background, foreground, nullptr, unionRect);
2012     test_arithmetic_bounds(reporter, 0, v, v, 0, background, foreground, nullptr, unionRect);
2013     test_arithmetic_bounds(reporter, 0, v, v, v, background, foreground, nullptr, unionRect);
2014     test_arithmetic_bounds(reporter, v, 0, 0, 0, background, foreground, nullptr, intersection);
2015     test_arithmetic_bounds(reporter, v, 0, 0, v, background, foreground, nullptr, unionRect);
2016     test_arithmetic_bounds(reporter, v, 0, v, 0, background, foreground, nullptr, bgRect);
2017     test_arithmetic_bounds(reporter, v, 0, v, v, background, foreground, nullptr, unionRect);
2018     test_arithmetic_bounds(reporter, v, v, 0, 0, background, foreground, nullptr, fgRect);
2019     test_arithmetic_bounds(reporter, v, v, 0, v, background, foreground, nullptr, unionRect);
2020     test_arithmetic_bounds(reporter, v, v, v, 0, background, foreground, nullptr, unionRect);
2021     test_arithmetic_bounds(reporter, v, v, v, v, background, foreground, nullptr, unionRect);
2022 
2023     // Test with crop. When k4 is non-zero, the result is expected to be cropRect
2024     // regardless of inputs because the filter affects the whole crop area.
2025     SkIRect cropRect = SkIRect::MakeXYWH(-111, -222, 333, 444);
2026     test_arithmetic_bounds(reporter, 0, 0, 0, 0, background, foreground, &cropRect,
2027                            SkIRect::MakeEmpty());
2028     test_arithmetic_bounds(reporter, 0, 0, 0, v, background, foreground, &cropRect, cropRect);
2029     test_arithmetic_bounds(reporter, 0, 0, v, 0, background, foreground, &cropRect, bgRect);
2030     test_arithmetic_bounds(reporter, 0, 0, v, v, background, foreground, &cropRect, cropRect);
2031     test_arithmetic_bounds(reporter, 0, v, 0, 0, background, foreground, &cropRect, fgRect);
2032     test_arithmetic_bounds(reporter, 0, v, 0, v, background, foreground, &cropRect, cropRect);
2033     test_arithmetic_bounds(reporter, 0, v, v, 0, background, foreground, &cropRect, unionRect);
2034     test_arithmetic_bounds(reporter, 0, v, v, v, background, foreground, &cropRect, cropRect);
2035     test_arithmetic_bounds(reporter, v, 0, 0, 0, background, foreground, &cropRect, intersection);
2036     test_arithmetic_bounds(reporter, v, 0, 0, v, background, foreground, &cropRect, cropRect);
2037     test_arithmetic_bounds(reporter, v, 0, v, 0, background, foreground, &cropRect, bgRect);
2038     test_arithmetic_bounds(reporter, v, 0, v, v, background, foreground, &cropRect, cropRect);
2039     test_arithmetic_bounds(reporter, v, v, 0, 0, background, foreground, &cropRect, fgRect);
2040     test_arithmetic_bounds(reporter, v, v, 0, v, background, foreground, &cropRect, cropRect);
2041     test_arithmetic_bounds(reporter, v, v, v, 0, background, foreground, &cropRect, unionRect);
2042     test_arithmetic_bounds(reporter, v, v, v, v, background, foreground, &cropRect, cropRect);
2043 }
2044 
2045 // Test SkArithmeticImageFilter::filterBounds with different blending modes.
DEF_TEST(ArithmeticImageFilterBounds,reporter)2046 DEF_TEST(ArithmeticImageFilterBounds, reporter) {
2047     test_arithmetic_combinations(reporter, 1);
2048     test_arithmetic_combinations(reporter, 0.5);
2049 }
2050 
2051 // Test SkDisplacementMapEffect::filterBounds.
DEF_TEST(DisplacementMapBounds,reporter)2052 DEF_TEST(DisplacementMapBounds, reporter) {
2053     SkIRect floodBounds(SkIRect::MakeXYWH(20, 30, 10, 10));
2054     sk_sp<SkImageFilter> flood(SkImageFilters::Shader(SkShaders::Color(SK_ColorGREEN),
2055                                                       &floodBounds));
2056     SkIRect tilingBounds(SkIRect::MakeXYWH(0, 0, 200, 100));
2057     sk_sp<SkImageFilter> tiling(SkImageFilters::Tile(SkRect::Make(floodBounds),
2058                                                      SkRect::Make(tilingBounds),
2059                                                      flood));
2060     sk_sp<SkImageFilter> displace(SkImageFilters::DisplacementMap(SkColorChannel::kR,
2061                                                                   SkColorChannel::kB,
2062                                                                   20.0f, nullptr, tiling));
2063     SkIRect input(SkIRect::MakeXYWH(20, 30, 40, 50));
2064     // Expected: union(floodBounds, outset(input, 10))
2065     SkIRect expected(SkIRect::MakeXYWH(10, 20, 60, 70));
2066     REPORTER_ASSERT(reporter,
2067                     expected == displace->filterBounds(input, SkMatrix::I(),
2068                                                        SkImageFilter::kReverse_MapDirection));
2069 }
2070 
2071 // Test SkImageSource::filterBounds.
DEF_TEST(ImageSourceBounds,reporter)2072 DEF_TEST(ImageSourceBounds, reporter) {
2073     sk_sp<SkImage> image(make_gradient_circle(64, 64).asImage());
2074     // Default src and dst rects.
2075     sk_sp<SkImageFilter> source1(SkImageFilters::Image(image));
2076     SkIRect imageBounds = SkIRect::MakeWH(64, 64);
2077     SkIRect input(SkIRect::MakeXYWH(10, 20, 30, 40));
2078     REPORTER_ASSERT(reporter,
2079                     imageBounds == source1->filterBounds(input, SkMatrix::I(),
2080                                                          SkImageFilter::kForward_MapDirection,
2081                                                          nullptr));
2082     REPORTER_ASSERT(reporter,
2083                     input == source1->filterBounds(input, SkMatrix::I(),
2084                                                    SkImageFilter::kReverse_MapDirection, &input));
2085     SkMatrix scale(SkMatrix::Scale(2, 2));
2086     SkIRect scaledBounds = SkIRect::MakeWH(128, 128);
2087     REPORTER_ASSERT(reporter,
2088                     scaledBounds == source1->filterBounds(input, scale,
2089                                                           SkImageFilter::kForward_MapDirection,
2090                                                           nullptr));
2091     REPORTER_ASSERT(reporter, input == source1->filterBounds(input, scale,
2092                                                              SkImageFilter::kReverse_MapDirection,
2093                                                              &input));
2094 
2095     // Specified src and dst rects.
2096     SkRect src(SkRect::MakeXYWH(0.5, 0.5, 100.5, 100.5));
2097     SkRect dst(SkRect::MakeXYWH(-10.5, -10.5, 120.5, 120.5));
2098     sk_sp<SkImageFilter> source2(SkImageFilters::Image(image, src, dst,
2099                                                        SkSamplingOptions(SkFilterMode::kLinear,
2100                                                                          SkMipmapMode::kLinear)));
2101     REPORTER_ASSERT(reporter,
2102                     dst.roundOut() == source2->filterBounds(input, SkMatrix::I(),
2103                                                             SkImageFilter::kForward_MapDirection,
2104                                                             nullptr));
2105     REPORTER_ASSERT(reporter,
2106                     input == source2->filterBounds(input, SkMatrix::I(),
2107                                                    SkImageFilter::kReverse_MapDirection, &input));
2108     scale.mapRect(&dst);
2109     scale.mapRect(&src);
2110     REPORTER_ASSERT(reporter,
2111                     dst.roundOut() == source2->filterBounds(input, scale,
2112                                                             SkImageFilter::kForward_MapDirection,
2113                                                             nullptr));
2114     REPORTER_ASSERT(reporter, input == source2->filterBounds(input, scale,
2115                                                              SkImageFilter::kReverse_MapDirection,
2116                                                              &input));
2117 }
2118 
2119 // Test SkPictureImageFilter::filterBounds.
DEF_TEST(PictureImageSourceBounds,reporter)2120 DEF_TEST(PictureImageSourceBounds, reporter) {
2121     SkPictureRecorder recorder;
2122     SkCanvas* recordingCanvas = recorder.beginRecording(64, 64);
2123 
2124     SkPaint greenPaint;
2125     greenPaint.setColor(SK_ColorGREEN);
2126     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
2127     sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
2128 
2129     // Default target rect.
2130     sk_sp<SkImageFilter> source1(SkImageFilters::Picture(picture));
2131     SkIRect pictureBounds = SkIRect::MakeWH(64, 64);
2132     SkIRect input(SkIRect::MakeXYWH(10, 20, 30, 40));
2133     REPORTER_ASSERT(reporter,
2134                     pictureBounds == source1->filterBounds(input, SkMatrix::I(),
2135                                                            SkImageFilter::kForward_MapDirection,
2136                                                            nullptr));
2137     REPORTER_ASSERT(reporter,
2138                     input == source1->filterBounds(input, SkMatrix::I(),
2139                                                    SkImageFilter::kReverse_MapDirection, &input));
2140     SkMatrix scale(SkMatrix::Scale(2, 2));
2141     SkIRect scaledPictureBounds = SkIRect::MakeWH(128, 128);
2142     REPORTER_ASSERT(reporter,
2143                     scaledPictureBounds == source1->filterBounds(input, scale,
2144                                                                  SkImageFilter::kForward_MapDirection,
2145                                                                  nullptr));
2146     REPORTER_ASSERT(reporter, input == source1->filterBounds(input, scale,
2147                                                              SkImageFilter::kReverse_MapDirection,
2148                                                              &input));
2149 
2150     // Specified target rect.
2151     SkRect targetRect(SkRect::MakeXYWH(9.5, 9.5, 31, 21));
2152     sk_sp<SkImageFilter> source2(SkImageFilters::Picture(picture, targetRect));
2153     REPORTER_ASSERT(reporter,
2154                     targetRect.roundOut() == source2->filterBounds(input, SkMatrix::I(),
2155                                                                    SkImageFilter::kForward_MapDirection,
2156                                                                    nullptr));
2157     REPORTER_ASSERT(reporter,
2158                     input == source2->filterBounds(input, SkMatrix::I(),
2159                                                    SkImageFilter::kReverse_MapDirection, &input));
2160     scale.mapRect(&targetRect);
2161     REPORTER_ASSERT(reporter,
2162                     targetRect.roundOut() == source2->filterBounds(input, scale,
2163                                                                    SkImageFilter::kForward_MapDirection,
2164                                                                    nullptr));
2165     REPORTER_ASSERT(reporter, input == source2->filterBounds(input, scale,
2166                                                              SkImageFilter::kReverse_MapDirection,
2167                                                              &input));
2168 }
2169 
DEF_TEST(DropShadowImageFilter_Huge,reporter)2170 DEF_TEST(DropShadowImageFilter_Huge, reporter) {
2171     // Successful if it doesn't crash or trigger ASAN. (crbug.com/1264705)
2172     auto surf = SkSurface::MakeRasterN32Premul(300, 150);
2173 
2174     SkPaint paint;
2175     paint.setImageFilter(SkImageFilters::DropShadowOnly(
2176             0.0f, 0.437009f, 14129.6f, 14129.6f, SK_ColorGRAY, nullptr));
2177 
2178     surf->getCanvas()->saveLayer(nullptr, &paint);
2179     surf->getCanvas()->restore();
2180 }
2181