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