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