1 
2 /*
3  * Copyright 2013 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 #include "SkBitmap.h"
10 #include "SkBitmapDevice.h"
11 #include "SkBlurImageFilter.h"
12 #include "SkCanvas.h"
13 #include "SkColorFilterImageFilter.h"
14 #include "SkColorMatrixFilter.h"
15 #include "SkComposeImageFilter.h"
16 #include "SkDisplacementMapEffect.h"
17 #include "SkDropShadowImageFilter.h"
18 #include "SkFlattenableSerialization.h"
19 #include "SkGradientShader.h"
20 #include "SkImage.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 "SkSurface.h"
36 #include "SkTableColorFilter.h"
37 #include "SkTileImageFilter.h"
38 #include "SkXfermodeImageFilter.h"
39 #include "Test.h"
40 
41 #if SK_SUPPORT_GPU
42 #include "GrContext.h"
43 #include "SkGpuDevice.h"
44 #endif
45 
46 static const int kBitmapSize = 4;
47 
48 namespace {
49 
50 class MatrixTestImageFilter : public SkImageFilter {
51 public:
MatrixTestImageFilter(skiatest::Reporter * reporter,const SkMatrix & expectedMatrix)52     MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
53       : SkImageFilter(0, nullptr), fReporter(reporter), fExpectedMatrix(expectedMatrix) {
54     }
55 
onFilterImageDeprecated(Proxy *,const SkBitmap & src,const Context & ctx,SkBitmap * result,SkIPoint * offset) const56     bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context& ctx,
57                                  SkBitmap* result, SkIPoint* offset) const override {
58         REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
59         return true;
60     }
61 
62     SK_TO_STRING_OVERRIDE()
63     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(MatrixTestImageFilter)
64 
65 protected:
flatten(SkWriteBuffer & buffer) const66     void flatten(SkWriteBuffer& buffer) const override {
67         this->INHERITED::flatten(buffer);
68         buffer.writeFunctionPtr(fReporter);
69         buffer.writeMatrix(fExpectedMatrix);
70     }
71 
72 private:
73     skiatest::Reporter* fReporter;
74     SkMatrix fExpectedMatrix;
75 
76     typedef SkImageFilter INHERITED;
77 };
78 
79 }
80 
CreateProc(SkReadBuffer & buffer)81 SkFlattenable* MatrixTestImageFilter::CreateProc(SkReadBuffer& buffer) {
82     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
83     skiatest::Reporter* reporter = (skiatest::Reporter*)buffer.readFunctionPtr();
84     SkMatrix matrix;
85     buffer.readMatrix(&matrix);
86     return new MatrixTestImageFilter(reporter, matrix);
87 }
88 
89 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const90 void MatrixTestImageFilter::toString(SkString* str) const {
91     str->appendf("MatrixTestImageFilter: (");
92     str->append(")");
93 }
94 #endif
95 
make_small_image()96 static SkImage* make_small_image() {
97     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(kBitmapSize, kBitmapSize));
98     SkCanvas* canvas = surface->getCanvas();
99     canvas->clear(0x00000000);
100     SkPaint darkPaint;
101     darkPaint.setColor(0xFF804020);
102     SkPaint lightPaint;
103     lightPaint.setColor(0xFF244484);
104     const int i = kBitmapSize / 4;
105     for (int y = 0; y < kBitmapSize; y += i) {
106         for (int x = 0; x < kBitmapSize; x += i) {
107             canvas->save();
108             canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
109             canvas->drawRect(SkRect::MakeXYWH(0, 0,
110                                              SkIntToScalar(i),
111                                              SkIntToScalar(i)), darkPaint);
112             canvas->drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
113                                              0,
114                                              SkIntToScalar(i),
115                                              SkIntToScalar(i)), lightPaint);
116             canvas->drawRect(SkRect::MakeXYWH(0,
117                                              SkIntToScalar(i),
118                                              SkIntToScalar(i),
119                                              SkIntToScalar(i)), lightPaint);
120             canvas->drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
121                                              SkIntToScalar(i),
122                                              SkIntToScalar(i),
123                                              SkIntToScalar(i)), darkPaint);
124             canvas->restore();
125         }
126     }
127 
128     return surface->newImageSnapshot();
129 }
130 
make_scale(float amount,SkImageFilter * input=nullptr)131 static SkImageFilter* make_scale(float amount, SkImageFilter* input = nullptr) {
132     SkScalar s = amount;
133     SkScalar matrix[20] = { s, 0, 0, 0, 0,
134                             0, s, 0, 0, 0,
135                             0, 0, s, 0, 0,
136                             0, 0, 0, s, 0 };
137     SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
138     return SkColorFilterImageFilter::Create(filter, input);
139 }
140 
make_grayscale(SkImageFilter * input,const SkImageFilter::CropRect * cropRect)141 static SkImageFilter* make_grayscale(SkImageFilter* input, const SkImageFilter::CropRect* cropRect) {
142     SkScalar matrix[20];
143     memset(matrix, 0, 20 * sizeof(SkScalar));
144     matrix[0] = matrix[5] = matrix[10] = 0.2126f;
145     matrix[1] = matrix[6] = matrix[11] = 0.7152f;
146     matrix[2] = matrix[7] = matrix[12] = 0.0722f;
147     matrix[18] = 1.0f;
148     SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
149     return SkColorFilterImageFilter::Create(filter, input, cropRect);
150 }
151 
make_blue(SkImageFilter * input,const SkImageFilter::CropRect * cropRect)152 static SkImageFilter* make_blue(SkImageFilter* input, const SkImageFilter::CropRect* cropRect) {
153     SkAutoTUnref<SkColorFilter> filter(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
154                                                                        SkXfermode::kSrcIn_Mode));
155     return SkColorFilterImageFilter::Create(filter, input, cropRect);
156 }
157 
DEF_TEST(ImageFilter,reporter)158 DEF_TEST(ImageFilter, reporter) {
159     {
160         // Check that two non-clipping color-matrice-filters concatenate into a single filter.
161         SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f));
162         SkAutoTUnref<SkImageFilter> quarterBrightness(make_scale(0.5f, halfBrightness));
163         REPORTER_ASSERT(reporter, nullptr == quarterBrightness->getInput(0));
164         SkColorFilter* cf;
165         REPORTER_ASSERT(reporter, quarterBrightness->asColorFilter(&cf));
166         REPORTER_ASSERT(reporter, cf->asColorMatrix(nullptr));
167         cf->unref();
168     }
169 
170     {
171         // Check that a clipping color-matrice-filter followed by a color-matrice-filters
172         // concatenates into a single filter, but not a matrixfilter (due to clamping).
173         SkAutoTUnref<SkImageFilter> doubleBrightness(make_scale(2.0f));
174         SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f, doubleBrightness));
175         REPORTER_ASSERT(reporter, nullptr == halfBrightness->getInput(0));
176         SkColorFilter* cf;
177         REPORTER_ASSERT(reporter, halfBrightness->asColorFilter(&cf));
178         REPORTER_ASSERT(reporter, !cf->asColorMatrix(nullptr));
179         cf->unref();
180     }
181 
182     {
183         // Check that a color filter image filter without a crop rect can be
184         // expressed as a color filter.
185         SkAutoTUnref<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
186         REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
187     }
188 
189     {
190         // Check that a colorfilterimage filter without a crop rect but with an input
191         // that is another colorfilterimage can be expressed as a colorfilter (composed).
192         SkAutoTUnref<SkImageFilter> mode(make_blue(nullptr, nullptr));
193         SkAutoTUnref<SkImageFilter> gray(make_grayscale(mode, nullptr));
194         REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
195     }
196 
197     {
198         // Test that if we exceed the limit of what ComposeColorFilter can combine, we still
199         // can build the DAG and won't assert if we call asColorFilter.
200         SkAutoTUnref<SkImageFilter> filter(make_blue(nullptr, nullptr));
201         const int kWayTooManyForComposeColorFilter = 100;
202         for (int i = 0; i < kWayTooManyForComposeColorFilter; ++i) {
203             filter.reset(make_blue(filter, nullptr));
204             // the first few of these will succeed, but after we hit the internal limit,
205             // it will then return false.
206             (void)filter->asColorFilter(nullptr);
207         }
208     }
209 
210     {
211         // Check that a color filter image filter with a crop rect cannot
212         // be expressed as a color filter.
213         SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100));
214         SkAutoTUnref<SkImageFilter> grayWithCrop(make_grayscale(nullptr, &cropRect));
215         REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(nullptr));
216     }
217 
218     {
219         // Check that two non-commutative matrices are concatenated in
220         // the correct order.
221         SkScalar blueToRedMatrix[20] = { 0 };
222         blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
223         SkScalar redToGreenMatrix[20] = { 0 };
224         redToGreenMatrix[5] = redToGreenMatrix[18] = SK_Scalar1;
225         SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix));
226         SkAutoTUnref<SkImageFilter> filter1(SkColorFilterImageFilter::Create(blueToRed.get()));
227         SkAutoTUnref<SkColorFilter> redToGreen(SkColorMatrixFilter::Create(redToGreenMatrix));
228         SkAutoTUnref<SkImageFilter> filter2(SkColorFilterImageFilter::Create(redToGreen.get(), filter1.get()));
229 
230         SkBitmap result;
231         result.allocN32Pixels(kBitmapSize, kBitmapSize);
232 
233         SkPaint paint;
234         paint.setColor(SK_ColorBLUE);
235         paint.setImageFilter(filter2.get());
236         SkCanvas canvas(result);
237         canvas.clear(0x0);
238         SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
239         canvas.drawRect(rect, paint);
240         uint32_t pixel = *result.getAddr32(0, 0);
241         // The result here should be green, since we have effectively shifted blue to green.
242         REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
243     }
244 
245     {
246         // Tests pass by not asserting
247         SkAutoTUnref<SkImage> image(make_small_image());
248         SkBitmap result;
249         result.allocN32Pixels(kBitmapSize, kBitmapSize);
250 
251         {
252             // This tests for :
253             // 1 ) location at (0,0,1)
254             SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
255             // 2 ) location and target at same value
256             SkPoint3 target = SkPoint3::Make(location.fX, location.fY, location.fZ);
257             // 3 ) large negative specular exponent value
258             SkScalar specularExponent = -1000;
259 
260             SkAutoTUnref<SkImageFilter> bmSrc(SkImageSource::Create(image));
261             SkPaint paint;
262             paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(
263                     location, target, specularExponent, 180,
264                     0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
265                     bmSrc))->unref();
266             SkCanvas canvas(result);
267             SkRect r = SkRect::MakeWH(SkIntToScalar(kBitmapSize),
268                                       SkIntToScalar(kBitmapSize));
269             canvas.drawRect(r, paint);
270         }
271     }
272 }
273 
test_crop_rects(SkImageFilter::Proxy * proxy,skiatest::Reporter * reporter)274 static void test_crop_rects(SkImageFilter::Proxy* proxy, skiatest::Reporter* reporter) {
275     // Check that all filters offset to their absolute crop rect,
276     // unaffected by the input crop rect.
277     // Tests pass by not asserting.
278     SkBitmap bitmap;
279     bitmap.allocN32Pixels(100, 100);
280     bitmap.eraseARGB(0, 0, 0, 0);
281 
282     SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
283     SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
284     SkAutoTUnref<SkImageFilter> input(make_grayscale(nullptr, &inputCropRect));
285 
286     SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
287     SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
288     SkScalar kernel[9] = {
289         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
290         SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
291         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
292     };
293     SkISize kernelSize = SkISize::Make(3, 3);
294     SkScalar gain = SK_Scalar1, bias = 0;
295 
296     SkImageFilter* filters[] = {
297         SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
298         SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType,
299                                         SkDisplacementMapEffect::kB_ChannelSelectorType,
300                                         40.0f, input.get(), input.get(), &cropRect),
301         SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
302         SkDropShadowImageFilter::Create(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1,
303             SK_ColorGREEN, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
304             input.get(), &cropRect),
305         SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
306         SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
307         SkMatrixConvolutionImageFilter::Create(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
308         SkMergeImageFilter::Create(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
309         SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
310         SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
311         SkDilateImageFilter::Create(3, 2, input.get(), &cropRect),
312         SkErodeImageFilter::Create(2, 3, input.get(), &cropRect),
313         SkTileImageFilter::Create(inputCropRect.rect(), cropRect.rect(), input.get()),
314         SkXfermodeImageFilter::Create(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
315     };
316 
317     for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
318         SkImageFilter* filter = filters[i];
319         SkBitmap result;
320         SkIPoint offset;
321         SkString str;
322         str.printf("filter %d", static_cast<int>(i));
323         SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr);
324         REPORTER_ASSERT_MESSAGE(reporter,
325                                 filter->filterImageDeprecated(proxy, bitmap, ctx,
326                                                               &result, &offset),
327                                 str.c_str());
328         REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str());
329     }
330 
331     for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
332         SkSafeUnref(filters[i]);
333     }
334 }
335 
make_gradient_circle(int width,int height)336 static SkBitmap make_gradient_circle(int width, int height) {
337     SkBitmap bitmap;
338     SkScalar x = SkIntToScalar(width / 2);
339     SkScalar y = SkIntToScalar(height / 2);
340     SkScalar radius = SkMinScalar(x, y) * 0.8f;
341     bitmap.allocN32Pixels(width, height);
342     SkCanvas canvas(bitmap);
343     canvas.clear(0x00000000);
344     SkColor colors[2];
345     colors[0] = SK_ColorWHITE;
346     colors[1] = SK_ColorBLACK;
347     SkAutoTUnref<SkShader> shader(
348         SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, nullptr, 2,
349                                        SkShader::kClamp_TileMode)
350     );
351     SkPaint paint;
352     paint.setShader(shader);
353     canvas.drawCircle(x, y, radius, paint);
354     return bitmap;
355 }
356 
test_negative_blur_sigma(SkImageFilter::Proxy * proxy,skiatest::Reporter * reporter)357 static void test_negative_blur_sigma(SkImageFilter::Proxy* proxy, skiatest::Reporter* reporter) {
358     // Check that SkBlurImageFilter will accept a negative sigma, either in
359     // the given arguments or after CTM application.
360     const int width = 32, height = 32;
361     const SkScalar five = SkIntToScalar(5);
362 
363     SkAutoTUnref<SkImageFilter> positiveFilter(SkBlurImageFilter::Create(five, five));
364     SkAutoTUnref<SkImageFilter> negativeFilter(SkBlurImageFilter::Create(-five, five));
365 
366     SkBitmap gradient = make_gradient_circle(width, height);
367     SkBitmap positiveResult1, negativeResult1;
368     SkBitmap positiveResult2, negativeResult2;
369     SkIPoint offset;
370     SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr);
371     REPORTER_ASSERT(reporter,
372                     positiveFilter->filterImageDeprecated(proxy, gradient, ctx,
373                                                           &positiveResult1, &offset));
374     REPORTER_ASSERT(reporter,
375                     negativeFilter->filterImageDeprecated(proxy, gradient, ctx,
376                                                           &negativeResult1, &offset));
377     SkMatrix negativeScale;
378     negativeScale.setScale(-SK_Scalar1, SK_Scalar1);
379     SkImageFilter::Context negativeCTX(negativeScale, SkIRect::MakeWH(32, 32), nullptr);
380     REPORTER_ASSERT(reporter,
381                     positiveFilter->filterImageDeprecated(proxy, gradient, negativeCTX,
382                                                           &negativeResult2, &offset));
383     REPORTER_ASSERT(reporter,
384                     negativeFilter->filterImageDeprecated(proxy, gradient, negativeCTX,
385                                                           &positiveResult2, &offset));
386     SkAutoLockPixels lockP1(positiveResult1);
387     SkAutoLockPixels lockP2(positiveResult2);
388     SkAutoLockPixels lockN1(negativeResult1);
389     SkAutoLockPixels lockN2(negativeResult2);
390     for (int y = 0; y < height; y++) {
391         int diffs = memcmp(positiveResult1.getAddr32(0, y), negativeResult1.getAddr32(0, y), positiveResult1.rowBytes());
392         REPORTER_ASSERT(reporter, !diffs);
393         if (diffs) {
394             break;
395         }
396         diffs = memcmp(positiveResult1.getAddr32(0, y), negativeResult2.getAddr32(0, y), positiveResult1.rowBytes());
397         REPORTER_ASSERT(reporter, !diffs);
398         if (diffs) {
399             break;
400         }
401         diffs = memcmp(positiveResult1.getAddr32(0, y), positiveResult2.getAddr32(0, y), positiveResult1.rowBytes());
402         REPORTER_ASSERT(reporter, !diffs);
403         if (diffs) {
404             break;
405         }
406     }
407 }
408 
DEF_TEST(TestNegativeBlurSigma,reporter)409 DEF_TEST(TestNegativeBlurSigma, reporter) {
410     const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
411     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
412 
413     SkAutoTUnref<SkBaseDevice> device(SkBitmapDevice::Create(info, props));
414     SkImageFilter::DeviceProxy proxy(device);
415 
416     test_negative_blur_sigma(&proxy, reporter);
417 }
418 
DEF_TEST(ImageFilterDrawTiled,reporter)419 DEF_TEST(ImageFilterDrawTiled, reporter) {
420     // Check that all filters when drawn tiled (with subsequent clip rects) exactly
421     // match the same filters drawn with a single full-canvas bitmap draw.
422     // Tests pass by not asserting.
423 
424     SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
425     SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
426     SkScalar kernel[9] = {
427         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
428         SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
429         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
430     };
431     const SkISize kernelSize = SkISize::Make(3, 3);
432     const SkScalar gain = SK_Scalar1, bias = 0;
433     const SkScalar five = SkIntToScalar(5);
434 
435     SkAutoTUnref<SkImage> gradientImage(SkImage::NewFromBitmap(make_gradient_circle(64, 64)));
436     SkAutoTUnref<SkImageFilter> gradientSource(SkImageSource::Create(gradientImage));
437     SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(five, five));
438     SkMatrix matrix;
439 
440     matrix.setTranslate(SK_Scalar1, SK_Scalar1);
441     matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
442 
443     SkRTreeFactory factory;
444     SkPictureRecorder recorder;
445     SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0);
446 
447     SkPaint greenPaint;
448     greenPaint.setColor(SK_ColorGREEN);
449     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
450     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
451     SkAutoTUnref<SkImageFilter> pictureFilter(SkPictureImageFilter::Create(picture.get()));
452     SkAutoTUnref<SkShader> shader(SkPerlinNoiseShader::CreateTurbulence(SK_Scalar1, SK_Scalar1, 1, 0));
453     SkPaint noisePaint;
454     noisePaint.setShader(shader);
455 
456     SkAutoTUnref<SkImageFilter> paintFilter(SkPaintImageFilter::Create(noisePaint));
457 
458     SkImageFilter::CropRect leftSideCropRect(SkRect::MakeXYWH(0, 0, 32, 64));
459     SkAutoTUnref<SkImageFilter> paintFilterLeft(SkPaintImageFilter::Create(greenPaint, &leftSideCropRect));
460     SkImageFilter::CropRect rightSideCropRect(SkRect::MakeXYWH(32, 0, 32, 64));
461     SkAutoTUnref<SkImageFilter> paintFilterRight(SkPaintImageFilter::Create(greenPaint, &rightSideCropRect));
462 
463     struct {
464         const char*    fName;
465         SkImageFilter* fFilter;
466     } filters[] = {
467         { "color filter", SkColorFilterImageFilter::Create(cf.get()) },
468         { "displacement map", SkDisplacementMapEffect::Create(
469               SkDisplacementMapEffect::kR_ChannelSelectorType,
470               SkDisplacementMapEffect::kB_ChannelSelectorType,
471               20.0f, gradientSource.get()) },
472         { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
473         { "drop shadow", SkDropShadowImageFilter::Create(
474               SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN,
475               SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode) },
476         { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse(
477               location, SK_ColorGREEN, 0, 0) },
478         { "specular lighting",
479               SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) },
480         { "matrix convolution",
481               SkMatrixConvolutionImageFilter::Create(
482                   kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
483                   SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) },
484         { "merge", SkMergeImageFilter::Create(nullptr, nullptr, SkXfermode::kSrcOver_Mode) },
485         { "merge with disjoint inputs", SkMergeImageFilter::Create(
486               paintFilterLeft, paintFilterRight, SkXfermode::kSrcOver_Mode) },
487         { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) },
488         { "dilate", SkDilateImageFilter::Create(3, 2) },
489         { "erode", SkErodeImageFilter::Create(2, 3) },
490         { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50),
491                                             SkRect::MakeXYWH(0, 0, 100, 100), nullptr) },
492         { "matrix", SkImageFilter::CreateMatrixFilter(matrix, kLow_SkFilterQuality) },
493         { "blur and offset", SkOffsetImageFilter::Create(five, five, blur.get()) },
494         { "picture and blur", SkBlurImageFilter::Create(five, five, pictureFilter.get()) },
495         { "paint and blur", SkBlurImageFilter::Create(five, five, paintFilter.get()) },
496     };
497 
498     SkBitmap untiledResult, tiledResult;
499     const int width = 64, height = 64;
500     untiledResult.allocN32Pixels(width, height);
501     tiledResult.allocN32Pixels(width, height);
502     SkCanvas tiledCanvas(tiledResult);
503     SkCanvas untiledCanvas(untiledResult);
504     int tileSize = 8;
505 
506     for (int scale = 1; scale <= 2; ++scale) {
507         for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
508             tiledCanvas.clear(0);
509             untiledCanvas.clear(0);
510             SkPaint paint;
511             paint.setImageFilter(filters[i].fFilter);
512             paint.setTextSize(SkIntToScalar(height));
513             paint.setColor(SK_ColorWHITE);
514             SkString str;
515             const char* text = "ABC";
516             SkScalar ypos = SkIntToScalar(height);
517             untiledCanvas.save();
518             untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
519             untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
520             untiledCanvas.restore();
521             for (int y = 0; y < height; y += tileSize) {
522                 for (int x = 0; x < width; x += tileSize) {
523                     tiledCanvas.save();
524                     tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
525                     tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
526                     tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
527                     tiledCanvas.restore();
528                 }
529             }
530             untiledCanvas.flush();
531             tiledCanvas.flush();
532             for (int y = 0; y < height; y++) {
533                 int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
534                 REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
535                 if (diffs) {
536                     break;
537                 }
538             }
539         }
540     }
541 
542     for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
543         SkSafeUnref(filters[i].fFilter);
544     }
545 }
546 
draw_saveLayer_picture(int width,int height,int tileSize,SkBBHFactory * factory,SkBitmap * result)547 static void draw_saveLayer_picture(int width, int height, int tileSize,
548                                    SkBBHFactory* factory, SkBitmap* result) {
549 
550     SkMatrix matrix;
551     matrix.setTranslate(SkIntToScalar(50), 0);
552 
553     SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorWHITE, SkXfermode::kSrc_Mode));
554     SkAutoTUnref<SkImageFilter> cfif(SkColorFilterImageFilter::Create(cf.get()));
555     SkAutoTUnref<SkImageFilter> imageFilter(SkImageFilter::CreateMatrixFilter(matrix, kNone_SkFilterQuality, cfif.get()));
556 
557     SkPaint paint;
558     paint.setImageFilter(imageFilter.get());
559     SkPictureRecorder recorder;
560     SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50));
561     SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width),
562                                                         SkIntToScalar(height),
563                                                         factory, 0);
564     recordingCanvas->translate(-55, 0);
565     recordingCanvas->saveLayer(&bounds, &paint);
566     recordingCanvas->restore();
567     SkAutoTUnref<SkPicture> picture1(recorder.endRecording());
568 
569     result->allocN32Pixels(width, height);
570     SkCanvas canvas(*result);
571     canvas.clear(0);
572     canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize)));
573     canvas.drawPicture(picture1.get());
574 }
575 
DEF_TEST(ImageFilterDrawMatrixBBH,reporter)576 DEF_TEST(ImageFilterDrawMatrixBBH, reporter) {
577     // Check that matrix filter when drawn tiled with BBH exactly
578     // matches the same thing drawn without BBH.
579     // Tests pass by not asserting.
580 
581     const int width = 200, height = 200;
582     const int tileSize = 100;
583     SkBitmap result1, result2;
584     SkRTreeFactory factory;
585 
586     draw_saveLayer_picture(width, height, tileSize, &factory, &result1);
587     draw_saveLayer_picture(width, height, tileSize, nullptr, &result2);
588 
589     for (int y = 0; y < height; y++) {
590         int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
591         REPORTER_ASSERT(reporter, !diffs);
592         if (diffs) {
593             break;
594         }
595     }
596 }
597 
makeBlur(SkImageFilter * input=nullptr)598 static SkImageFilter* makeBlur(SkImageFilter* input = nullptr) {
599     return SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input);
600 }
601 
makeDropShadow(SkImageFilter * input=nullptr)602 static SkImageFilter* makeDropShadow(SkImageFilter* input = nullptr) {
603     return SkDropShadowImageFilter::Create(
604         SkIntToScalar(100), SkIntToScalar(100),
605         SkIntToScalar(10), SkIntToScalar(10),
606         SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
607         input, nullptr);
608 }
609 
DEF_TEST(ImageFilterBlurThenShadowBounds,reporter)610 DEF_TEST(ImageFilterBlurThenShadowBounds, reporter) {
611     SkAutoTUnref<SkImageFilter> filter1(makeBlur());
612     SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get()));
613 
614     SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
615     SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
616     filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
617 
618     REPORTER_ASSERT(reporter, bounds == expectedBounds);
619 }
620 
DEF_TEST(ImageFilterShadowThenBlurBounds,reporter)621 DEF_TEST(ImageFilterShadowThenBlurBounds, reporter) {
622     SkAutoTUnref<SkImageFilter> filter1(makeDropShadow());
623     SkAutoTUnref<SkImageFilter> filter2(makeBlur(filter1.get()));
624 
625     SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
626     SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
627     filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
628 
629     REPORTER_ASSERT(reporter, bounds == expectedBounds);
630 }
631 
DEF_TEST(ImageFilterDilateThenBlurBounds,reporter)632 DEF_TEST(ImageFilterDilateThenBlurBounds, reporter) {
633     SkAutoTUnref<SkImageFilter> filter1(SkDilateImageFilter::Create(2, 2));
634     SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get()));
635 
636     SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
637     SkIRect expectedBounds = SkIRect::MakeXYWH(-132, -132, 234, 234);
638     filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
639 
640     REPORTER_ASSERT(reporter, bounds == expectedBounds);
641 }
642 
DEF_TEST(ImageFilterComposedBlurFastBounds,reporter)643 DEF_TEST(ImageFilterComposedBlurFastBounds, reporter) {
644     SkAutoTUnref<SkImageFilter> filter1(makeBlur());
645     SkAutoTUnref<SkImageFilter> filter2(makeBlur());
646     SkAutoTUnref<SkImageFilter> composedFilter(SkComposeImageFilter::Create(filter1.get(), filter2.get()));
647 
648     SkRect boundsSrc = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
649     SkRect expectedBounds = SkRect::MakeXYWH(
650         SkIntToScalar(-6), SkIntToScalar(-6), SkIntToScalar(112), SkIntToScalar(112));
651     SkRect boundsDst = SkRect::MakeEmpty();
652     composedFilter->computeFastBounds(boundsSrc, &boundsDst);
653 
654     REPORTER_ASSERT(reporter, boundsDst == expectedBounds);
655 }
656 
DEF_TEST(ImageFilterMergeResultSize,reporter)657 DEF_TEST(ImageFilterMergeResultSize, reporter) {
658     SkBitmap greenBM;
659     greenBM.allocN32Pixels(20, 20);
660     greenBM.eraseColor(SK_ColorGREEN);
661     SkAutoTUnref<SkImage> greenImage(SkImage::NewFromBitmap(greenBM));
662     SkAutoTUnref<SkImageFilter> source(SkImageSource::Create(greenImage.get()));
663     SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(source.get(), source.get()));
664 
665     SkBitmap bitmap;
666     bitmap.allocN32Pixels(1, 1);
667     bitmap.eraseColor(0);
668     const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
669     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
670     SkAutoTUnref<SkBaseDevice> device(SkBitmapDevice::Create(info, props));
671     SkImageFilter::DeviceProxy proxy(device);
672     SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(0, 0, 100, 100), nullptr);
673     SkBitmap result;
674     SkIPoint offset;
675     REPORTER_ASSERT(reporter, merge->filterImageDeprecated(&proxy, bitmap, ctx, &result, &offset));
676     REPORTER_ASSERT(reporter, result.width() == 20 && result.height() == 20);
677 }
678 
draw_blurred_rect(SkCanvas * canvas)679 static void draw_blurred_rect(SkCanvas* canvas) {
680     SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0));
681     SkPaint filterPaint;
682     filterPaint.setColor(SK_ColorWHITE);
683     filterPaint.setImageFilter(filter);
684     canvas->saveLayer(nullptr, &filterPaint);
685     SkPaint whitePaint;
686     whitePaint.setColor(SK_ColorWHITE);
687     canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
688     canvas->restore();
689 }
690 
draw_picture_clipped(SkCanvas * canvas,const SkRect & clipRect,const SkPicture * picture)691 static void draw_picture_clipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
692     canvas->save();
693     canvas->clipRect(clipRect);
694     canvas->drawPicture(picture);
695     canvas->restore();
696 }
697 
DEF_TEST(ImageFilterDrawTiledBlurRTree,reporter)698 DEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) {
699     // Check that the blur filter when recorded with RTree acceleration,
700     // and drawn tiled (with subsequent clip rects) exactly
701     // matches the same filter drawn with without RTree acceleration.
702     // This tests that the "bleed" from the blur into the otherwise-blank
703     // tiles is correctly rendered.
704     // Tests pass by not asserting.
705 
706     int width = 16, height = 8;
707     SkBitmap result1, result2;
708     result1.allocN32Pixels(width, height);
709     result2.allocN32Pixels(width, height);
710     SkCanvas canvas1(result1);
711     SkCanvas canvas2(result2);
712     int tileSize = 8;
713 
714     canvas1.clear(0);
715     canvas2.clear(0);
716 
717     SkRTreeFactory factory;
718 
719     SkPictureRecorder recorder1, recorder2;
720     // The only difference between these two pictures is that one has RTree aceleration.
721     SkCanvas* recordingCanvas1 = recorder1.beginRecording(SkIntToScalar(width),
722                                                           SkIntToScalar(height),
723                                                           nullptr, 0);
724     SkCanvas* recordingCanvas2 = recorder2.beginRecording(SkIntToScalar(width),
725                                                           SkIntToScalar(height),
726                                                           &factory, 0);
727     draw_blurred_rect(recordingCanvas1);
728     draw_blurred_rect(recordingCanvas2);
729     SkAutoTUnref<SkPicture> picture1(recorder1.endRecording());
730     SkAutoTUnref<SkPicture> picture2(recorder2.endRecording());
731     for (int y = 0; y < height; y += tileSize) {
732         for (int x = 0; x < width; x += tileSize) {
733             SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
734             draw_picture_clipped(&canvas1, tileRect, picture1);
735             draw_picture_clipped(&canvas2, tileRect, picture2);
736         }
737     }
738     for (int y = 0; y < height; y++) {
739         int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
740         REPORTER_ASSERT(reporter, !diffs);
741         if (diffs) {
742             break;
743         }
744     }
745 }
746 
DEF_TEST(ImageFilterMatrixConvolution,reporter)747 DEF_TEST(ImageFilterMatrixConvolution, reporter) {
748     // Check that a 1x3 filter does not cause a spurious assert.
749     SkScalar kernel[3] = {
750         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
751     };
752     SkISize kernelSize = SkISize::Make(1, 3);
753     SkScalar gain = SK_Scalar1, bias = 0;
754     SkIPoint kernelOffset = SkIPoint::Make(0, 0);
755 
756     SkAutoTUnref<SkImageFilter> filter(
757         SkMatrixConvolutionImageFilter::Create(
758             kernelSize, kernel, gain, bias, kernelOffset,
759             SkMatrixConvolutionImageFilter::kRepeat_TileMode, false));
760 
761     SkBitmap result;
762     int width = 16, height = 16;
763     result.allocN32Pixels(width, height);
764     SkCanvas canvas(result);
765     canvas.clear(0);
766 
767     SkPaint paint;
768     paint.setImageFilter(filter);
769     SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
770     canvas.drawRect(rect, paint);
771 }
772 
DEF_TEST(ImageFilterMatrixConvolutionBorder,reporter)773 DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
774     // Check that a filter with borders outside the target bounds
775     // does not crash.
776     SkScalar kernel[3] = {
777         0, 0, 0,
778     };
779     SkISize kernelSize = SkISize::Make(3, 1);
780     SkScalar gain = SK_Scalar1, bias = 0;
781     SkIPoint kernelOffset = SkIPoint::Make(2, 0);
782 
783     SkAutoTUnref<SkImageFilter> filter(
784         SkMatrixConvolutionImageFilter::Create(
785             kernelSize, kernel, gain, bias, kernelOffset,
786             SkMatrixConvolutionImageFilter::kClamp_TileMode, true));
787 
788     SkBitmap result;
789 
790     int width = 10, height = 10;
791     result.allocN32Pixels(width, height);
792     SkCanvas canvas(result);
793     canvas.clear(0);
794 
795     SkPaint filterPaint;
796     filterPaint.setImageFilter(filter);
797     SkRect bounds = SkRect::MakeWH(1, 10);
798     SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
799     SkPaint rectPaint;
800     canvas.saveLayer(&bounds, &filterPaint);
801     canvas.drawRect(rect, rectPaint);
802     canvas.restore();
803 }
804 
DEF_TEST(ImageFilterCropRect,reporter)805 DEF_TEST(ImageFilterCropRect, reporter) {
806     const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
807     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
808 
809     SkAutoTUnref<SkBaseDevice> device(SkBitmapDevice::Create(info, props));
810     SkImageFilter::DeviceProxy proxy(device);
811 
812     test_crop_rects(&proxy, reporter);
813 }
814 
DEF_TEST(ImageFilterMatrix,reporter)815 DEF_TEST(ImageFilterMatrix, reporter) {
816     SkBitmap temp;
817     temp.allocN32Pixels(100, 100);
818     SkCanvas canvas(temp);
819     canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
820 
821     SkMatrix expectedMatrix = canvas.getTotalMatrix();
822 
823     SkRTreeFactory factory;
824     SkPictureRecorder recorder;
825     SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
826 
827     SkPaint paint;
828     SkAutoTUnref<MatrixTestImageFilter> imageFilter(
829         new MatrixTestImageFilter(reporter, expectedMatrix));
830     paint.setImageFilter(imageFilter.get());
831     recordingCanvas->saveLayer(nullptr, &paint);
832     SkPaint solidPaint;
833     solidPaint.setColor(0xFFFFFFFF);
834     recordingCanvas->save();
835     recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
836     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
837     recordingCanvas->restore(); // scale
838     recordingCanvas->restore(); // saveLayer
839     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
840 
841     canvas.drawPicture(picture);
842 }
843 
DEF_TEST(ImageFilterCrossProcessPictureImageFilter,reporter)844 DEF_TEST(ImageFilterCrossProcessPictureImageFilter, reporter) {
845     SkRTreeFactory factory;
846     SkPictureRecorder recorder;
847     SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
848 
849     // Create an SkPicture which simply draws a green 1x1 rectangle.
850     SkPaint greenPaint;
851     greenPaint.setColor(SK_ColorGREEN);
852     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
853     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
854 
855     // Wrap that SkPicture in an SkPictureImageFilter.
856     SkAutoTUnref<SkImageFilter> imageFilter(
857         SkPictureImageFilter::Create(picture.get()));
858 
859     // Check that SkPictureImageFilter successfully serializes its contained
860     // SkPicture when not in cross-process mode.
861     SkPaint paint;
862     paint.setImageFilter(imageFilter.get());
863     SkPictureRecorder outerRecorder;
864     SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
865     SkPaint redPaintWithFilter;
866     redPaintWithFilter.setColor(SK_ColorRED);
867     redPaintWithFilter.setImageFilter(imageFilter.get());
868     outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
869     SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording());
870 
871     SkBitmap bitmap;
872     bitmap.allocN32Pixels(1, 1);
873     SkCanvas canvas(bitmap);
874 
875     // The result here should be green, since the filter replaces the primitive's red interior.
876     canvas.clear(0x0);
877     canvas.drawPicture(outerPicture);
878     uint32_t pixel = *bitmap.getAddr32(0, 0);
879     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
880 
881     // Check that, for now, SkPictureImageFilter does not serialize or
882     // deserialize its contained picture when the filter is serialized
883     // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
884     SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
885     SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
886         data->data(), data->size(), SkImageFilter::GetFlattenableType()));
887     SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
888 
889     redPaintWithFilter.setImageFilter(unflattenedFilter);
890     SkPictureRecorder crossProcessRecorder;
891     SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
892     crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
893     SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording());
894 
895     canvas.clear(0x0);
896     canvas.drawPicture(crossProcessPicture);
897     pixel = *bitmap.getAddr32(0, 0);
898     // If the security precautions are enabled, the result here should not be green, since the
899     // filter draws nothing.
900     REPORTER_ASSERT(reporter, SkPicture::PictureIOSecurityPrecautionsEnabled()
901         ? pixel != SK_ColorGREEN : pixel == SK_ColorGREEN);
902 }
903 
DEF_TEST(ImageFilterClippedPictureImageFilter,reporter)904 DEF_TEST(ImageFilterClippedPictureImageFilter, reporter) {
905     SkRTreeFactory factory;
906     SkPictureRecorder recorder;
907     SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
908 
909     // Create an SkPicture which simply draws a green 1x1 rectangle.
910     SkPaint greenPaint;
911     greenPaint.setColor(SK_ColorGREEN);
912     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
913     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
914 
915     SkAutoTUnref<SkImageFilter> imageFilter(SkPictureImageFilter::Create(picture.get()));
916 
917     SkBitmap result;
918     SkIPoint offset;
919     SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(1, 1, 1, 1), nullptr);
920     SkBitmap bitmap;
921     bitmap.allocN32Pixels(2, 2);
922     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
923     SkBitmapDevice device(bitmap, props);
924     SkImageFilter::DeviceProxy proxy(&device);
925     REPORTER_ASSERT(reporter,
926                     !imageFilter->filterImageDeprecated(&proxy, bitmap, ctx, &result, &offset));
927 }
928 
DEF_TEST(ImageFilterEmptySaveLayer,reporter)929 DEF_TEST(ImageFilterEmptySaveLayer, reporter) {
930     // Even when there's an empty saveLayer()/restore(), ensure that an image
931     // filter or color filter which affects transparent black still draws.
932 
933     SkBitmap bitmap;
934     bitmap.allocN32Pixels(10, 10);
935     SkCanvas canvas(bitmap);
936 
937     SkRTreeFactory factory;
938     SkPictureRecorder recorder;
939 
940     SkAutoTUnref<SkColorFilter> green(
941         SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode));
942     SkAutoTUnref<SkImageFilter> imageFilter(
943         SkColorFilterImageFilter::Create(green.get()));
944     SkPaint imageFilterPaint;
945     imageFilterPaint.setImageFilter(imageFilter.get());
946     SkPaint colorFilterPaint;
947     colorFilterPaint.setColorFilter(green.get());
948 
949     SkRect bounds = SkRect::MakeWH(10, 10);
950 
951     SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
952     recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
953     recordingCanvas->restore();
954     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
955 
956     canvas.clear(0);
957     canvas.drawPicture(picture);
958     uint32_t pixel = *bitmap.getAddr32(0, 0);
959     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
960 
961     recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
962     recordingCanvas->saveLayer(nullptr, &imageFilterPaint);
963     recordingCanvas->restore();
964     SkAutoTUnref<SkPicture> picture2(recorder.endRecording());
965 
966     canvas.clear(0);
967     canvas.drawPicture(picture2);
968     pixel = *bitmap.getAddr32(0, 0);
969     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
970 
971     recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
972     recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
973     recordingCanvas->restore();
974     SkAutoTUnref<SkPicture> picture3(recorder.endRecording());
975 
976     canvas.clear(0);
977     canvas.drawPicture(picture3);
978     pixel = *bitmap.getAddr32(0, 0);
979     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
980 }
981 
test_huge_blur(SkCanvas * canvas,skiatest::Reporter * reporter)982 static void test_huge_blur(SkCanvas* canvas, skiatest::Reporter* reporter) {
983     SkBitmap bitmap;
984     bitmap.allocN32Pixels(100, 100);
985     bitmap.eraseARGB(0, 0, 0, 0);
986 
987     // Check that a blur with an insane radius does not crash or assert.
988     SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(SkIntToScalar(1<<30), SkIntToScalar(1<<30)));
989 
990     SkPaint paint;
991     paint.setImageFilter(blur);
992     canvas->drawBitmap(bitmap, 0, 0, &paint);
993 }
994 
DEF_TEST(HugeBlurImageFilter,reporter)995 DEF_TEST(HugeBlurImageFilter, reporter) {
996     SkBitmap temp;
997     temp.allocN32Pixels(100, 100);
998     SkCanvas canvas(temp);
999     test_huge_blur(&canvas, reporter);
1000 }
1001 
DEF_TEST(MatrixConvolutionSanityTest,reporter)1002 DEF_TEST(MatrixConvolutionSanityTest, reporter) {
1003     SkScalar kernel[1] = { 0 };
1004     SkScalar gain = SK_Scalar1, bias = 0;
1005     SkIPoint kernelOffset = SkIPoint::Make(1, 1);
1006 
1007     // Check that an enormous (non-allocatable) kernel gives a nullptr filter.
1008     SkAutoTUnref<SkImageFilter> conv(SkMatrixConvolutionImageFilter::Create(
1009         SkISize::Make(1<<30, 1<<30),
1010         kernel,
1011         gain,
1012         bias,
1013         kernelOffset,
1014         SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1015         false));
1016 
1017     REPORTER_ASSERT(reporter, nullptr == conv.get());
1018 
1019     // Check that a nullptr kernel gives a nullptr filter.
1020     conv.reset(SkMatrixConvolutionImageFilter::Create(
1021         SkISize::Make(1, 1),
1022         nullptr,
1023         gain,
1024         bias,
1025         kernelOffset,
1026         SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1027         false));
1028 
1029     REPORTER_ASSERT(reporter, nullptr == conv.get());
1030 
1031     // Check that a kernel width < 1 gives a nullptr filter.
1032     conv.reset(SkMatrixConvolutionImageFilter::Create(
1033         SkISize::Make(0, 1),
1034         kernel,
1035         gain,
1036         bias,
1037         kernelOffset,
1038         SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1039         false));
1040 
1041     REPORTER_ASSERT(reporter, nullptr == conv.get());
1042 
1043     // Check that kernel height < 1 gives a nullptr filter.
1044     conv.reset(SkMatrixConvolutionImageFilter::Create(
1045         SkISize::Make(1, -1),
1046         kernel,
1047         gain,
1048         bias,
1049         kernelOffset,
1050         SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1051         false));
1052 
1053     REPORTER_ASSERT(reporter, nullptr == conv.get());
1054 }
1055 
test_xfermode_cropped_input(SkCanvas * canvas,skiatest::Reporter * reporter)1056 static void test_xfermode_cropped_input(SkCanvas* canvas, skiatest::Reporter* reporter) {
1057     canvas->clear(0);
1058 
1059     SkBitmap bitmap;
1060     bitmap.allocN32Pixels(1, 1);
1061     bitmap.eraseARGB(255, 255, 255, 255);
1062 
1063     SkAutoTUnref<SkColorFilter> green(
1064         SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode));
1065     SkAutoTUnref<SkImageFilter> greenFilter(SkColorFilterImageFilter::Create(green.get()));
1066     SkImageFilter::CropRect cropRect(SkRect::MakeEmpty());
1067     SkAutoTUnref<SkImageFilter> croppedOut(
1068         SkColorFilterImageFilter::Create(green.get(), nullptr, &cropRect));
1069 
1070     // Check that an xfermode image filter whose input has been cropped out still draws the other
1071     // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
1072     SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode);
1073     SkAutoTUnref<SkImageFilter> xfermodeNoFg(
1074         SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut));
1075     SkAutoTUnref<SkImageFilter> xfermodeNoBg(
1076         SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter));
1077     SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg(
1078         SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut));
1079 
1080     SkPaint paint;
1081     paint.setImageFilter(xfermodeNoFg);
1082     canvas->drawBitmap(bitmap, 0, 0, &paint);   // drawSprite
1083 
1084     uint32_t pixel;
1085     SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
1086     canvas->readPixels(info, &pixel, 4, 0, 0);
1087     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1088 
1089     paint.setImageFilter(xfermodeNoBg);
1090     canvas->drawBitmap(bitmap, 0, 0, &paint);   // drawSprite
1091     canvas->readPixels(info, &pixel, 4, 0, 0);
1092     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1093 
1094     paint.setImageFilter(xfermodeNoFgNoBg);
1095     canvas->drawBitmap(bitmap, 0, 0, &paint);   // drawSprite
1096     canvas->readPixels(info, &pixel, 4, 0, 0);
1097     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1098 }
1099 
DEF_TEST(ImageFilterNestedSaveLayer,reporter)1100 DEF_TEST(ImageFilterNestedSaveLayer, reporter) {
1101     SkBitmap temp;
1102     temp.allocN32Pixels(50, 50);
1103     SkCanvas canvas(temp);
1104     canvas.clear(0x0);
1105 
1106     SkBitmap bitmap;
1107     bitmap.allocN32Pixels(10, 10);
1108     bitmap.eraseColor(SK_ColorGREEN);
1109 
1110     SkMatrix matrix;
1111     matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
1112     matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
1113     SkAutoTUnref<SkImageFilter> matrixFilter(
1114         SkImageFilter::CreateMatrixFilter(matrix, kLow_SkFilterQuality));
1115 
1116     // Test that saveLayer() with a filter nested inside another saveLayer() applies the
1117     // correct offset to the filter matrix.
1118     SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
1119     canvas.saveLayer(&bounds1, nullptr);
1120     SkPaint filterPaint;
1121     filterPaint.setImageFilter(matrixFilter);
1122     SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
1123     canvas.saveLayer(&bounds2, &filterPaint);
1124     SkPaint greenPaint;
1125     greenPaint.setColor(SK_ColorGREEN);
1126     canvas.drawRect(bounds2, greenPaint);
1127     canvas.restore();
1128     canvas.restore();
1129     SkPaint strokePaint;
1130     strokePaint.setStyle(SkPaint::kStroke_Style);
1131     strokePaint.setColor(SK_ColorRED);
1132 
1133     SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
1134     uint32_t pixel;
1135     canvas.readPixels(info, &pixel, 4, 25, 25);
1136     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1137 
1138     // Test that drawSprite() with a filter nested inside a saveLayer() applies the
1139     // correct offset to the filter matrix.
1140     canvas.clear(0x0);
1141     canvas.readPixels(info, &pixel, 4, 25, 25);
1142     canvas.saveLayer(&bounds1, nullptr);
1143     canvas.drawBitmap(bitmap, 20, 20, &filterPaint);    // drawSprite
1144     canvas.restore();
1145 
1146     canvas.readPixels(info, &pixel, 4, 25, 25);
1147     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1148 }
1149 
DEF_TEST(XfermodeImageFilterCroppedInput,reporter)1150 DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
1151     SkBitmap temp;
1152     temp.allocN32Pixels(100, 100);
1153     SkCanvas canvas(temp);
1154     test_xfermode_cropped_input(&canvas, reporter);
1155 }
1156 
DEF_TEST(ComposedImageFilterOffset,reporter)1157 DEF_TEST(ComposedImageFilterOffset, reporter) {
1158     SkBitmap bitmap;
1159     bitmap.allocN32Pixels(100, 100);
1160     bitmap.eraseARGB(0, 0, 0, 0);
1161     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1162     SkBitmapDevice device(bitmap, props);
1163     SkImageFilter::DeviceProxy proxy(&device);
1164 
1165     SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(1, 0, 20, 20));
1166     SkAutoTUnref<SkImageFilter> offsetFilter(SkOffsetImageFilter::Create(0, 0, nullptr, &cropRect));
1167     SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1,
1168                                                                      nullptr, &cropRect));
1169     SkAutoTUnref<SkImageFilter> composedFilter(SkComposeImageFilter::Create(blurFilter,
1170                                                                             offsetFilter.get()));
1171     SkBitmap result;
1172     SkIPoint offset;
1173     SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr);
1174     REPORTER_ASSERT(reporter,
1175                     composedFilter->filterImageDeprecated(&proxy, bitmap, ctx, &result, &offset));
1176     REPORTER_ASSERT(reporter, offset.fX == 1 && offset.fY == 0);
1177 }
1178 
DEF_TEST(PartialCropRect,reporter)1179 DEF_TEST(PartialCropRect, reporter) {
1180     SkBitmap bitmap;
1181     bitmap.allocN32Pixels(100, 100);
1182     bitmap.eraseARGB(0, 0, 0, 0);
1183     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1184     SkBitmapDevice device(bitmap, props);
1185     SkImageFilter::DeviceProxy proxy(&device);
1186 
1187     SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(100, 0, 20, 30),
1188         SkImageFilter::CropRect::kHasWidth_CropEdge | SkImageFilter::CropRect::kHasHeight_CropEdge);
1189     SkAutoTUnref<SkImageFilter> filter(make_grayscale(nullptr, &cropRect));
1190     SkBitmap result;
1191     SkIPoint offset;
1192     SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr);
1193     REPORTER_ASSERT(reporter,
1194                     filter->filterImageDeprecated(&proxy, bitmap, ctx, &result, &offset));
1195     REPORTER_ASSERT(reporter, offset.fX == 0);
1196     REPORTER_ASSERT(reporter, offset.fY == 0);
1197     REPORTER_ASSERT(reporter, result.width() == 20);
1198     REPORTER_ASSERT(reporter, result.height() == 30);
1199 }
1200 
DEF_TEST(ImageFilterCanComputeFastBounds,reporter)1201 DEF_TEST(ImageFilterCanComputeFastBounds, reporter) {
1202 
1203     SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
1204     SkAutoTUnref<SkImageFilter> lighting(SkLightingImageFilter::CreatePointLitDiffuse(
1205           location, SK_ColorGREEN, 0, 0));
1206     REPORTER_ASSERT(reporter, !lighting->canComputeFastBounds());
1207 
1208     SkAutoTUnref<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
1209     REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1210     {
1211         SkColorFilter* grayCF;
1212         REPORTER_ASSERT(reporter, gray->asAColorFilter(&grayCF));
1213         REPORTER_ASSERT(reporter, !grayCF->affectsTransparentBlack());
1214         grayCF->unref();
1215     }
1216     REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1217 
1218     SkAutoTUnref<SkImageFilter> grayBlur(SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, gray.get()));
1219     REPORTER_ASSERT(reporter, grayBlur->canComputeFastBounds());
1220 
1221     SkScalar greenMatrix[20] = { 0, 0, 0, 0, 0,
1222                                  0, 0, 0, 0, 1,
1223                                  0, 0, 0, 0, 0,
1224                                  0, 0, 0, 0, 1 };
1225     SkAutoTUnref<SkColorFilter> greenCF(SkColorMatrixFilter::Create(greenMatrix));
1226     SkAutoTUnref<SkImageFilter> green(SkColorFilterImageFilter::Create(greenCF));
1227 
1228     REPORTER_ASSERT(reporter, greenCF->affectsTransparentBlack());
1229     REPORTER_ASSERT(reporter, !green->canComputeFastBounds());
1230 
1231     SkAutoTUnref<SkImageFilter> greenBlur(SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, green.get()));
1232     REPORTER_ASSERT(reporter, !greenBlur->canComputeFastBounds());
1233 
1234     uint8_t allOne[256], identity[256];
1235     for (int i = 0; i < 256; ++i) {
1236         identity[i] = i;
1237         allOne[i] = 255;
1238     }
1239 
1240     SkAutoTUnref<SkColorFilter> identityCF(
1241         SkTableColorFilter::CreateARGB(identity, identity, identity, allOne));
1242     SkAutoTUnref<SkImageFilter> identityFilter(SkColorFilterImageFilter::Create(identityCF.get()));
1243     REPORTER_ASSERT(reporter, !identityCF->affectsTransparentBlack());
1244     REPORTER_ASSERT(reporter, identityFilter->canComputeFastBounds());
1245 
1246     SkAutoTUnref<SkColorFilter> forceOpaqueCF(
1247         SkTableColorFilter::CreateARGB(allOne, identity, identity, identity));
1248     SkAutoTUnref<SkImageFilter> forceOpaque(SkColorFilterImageFilter::Create(forceOpaqueCF.get()));
1249     REPORTER_ASSERT(reporter, forceOpaqueCF->affectsTransparentBlack());
1250     REPORTER_ASSERT(reporter, !forceOpaque->canComputeFastBounds());
1251 }
1252 
1253 // Verify that SkImageSource survives serialization
DEF_TEST(ImageFilterImageSourceSerialization,reporter)1254 DEF_TEST(ImageFilterImageSourceSerialization, reporter) {
1255     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(10, 10));
1256     surface->getCanvas()->clear(SK_ColorGREEN);
1257     SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
1258     SkAutoTUnref<SkImageFilter> filter(SkImageSource::Create(image));
1259 
1260     SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(filter));
1261     SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
1262         data->data(), data->size(), SkImageFilter::GetFlattenableType()));
1263     SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
1264     REPORTER_ASSERT(reporter, unflattenedFilter);
1265 
1266     SkBitmap bm;
1267     bm.allocN32Pixels(10, 10);
1268     bm.eraseColor(SK_ColorBLUE);
1269     SkPaint paint;
1270     paint.setColor(SK_ColorRED);
1271     paint.setImageFilter(unflattenedFilter);
1272 
1273     SkCanvas canvas(bm);
1274     canvas.drawRect(SkRect::MakeWH(10, 10), paint);
1275     REPORTER_ASSERT(reporter, *bm.getAddr32(0, 0) == SkPreMultiplyColor(SK_ColorGREEN));
1276 }
1277 
test_large_blur_input(skiatest::Reporter * reporter,SkCanvas * canvas)1278 static void test_large_blur_input(skiatest::Reporter* reporter, SkCanvas* canvas) {
1279     SkBitmap largeBmp;
1280     int largeW = 5000;
1281     int largeH = 5000;
1282 #if SK_SUPPORT_GPU
1283     // If we're GPU-backed make the bitmap too large to be converted into a texture.
1284     if (GrContext* ctx = canvas->getGrContext()) {
1285         largeW = ctx->caps()->maxTextureSize() + 1;
1286     }
1287 #endif
1288 
1289     largeBmp.allocN32Pixels(largeW, largeH);
1290     largeBmp.eraseColor(0);
1291     if (!largeBmp.getPixels()) {
1292         ERRORF(reporter, "Failed to allocate large bmp.");
1293         return;
1294     }
1295 
1296     SkAutoTUnref<SkImage> largeImage(SkImage::NewFromBitmap(largeBmp));
1297     if (!largeImage) {
1298         ERRORF(reporter, "Failed to create large image.");
1299         return;
1300     }
1301 
1302     SkAutoTUnref<SkImageFilter> largeSource(SkImageSource::Create(largeImage));
1303     if (!largeSource) {
1304         ERRORF(reporter, "Failed to create large SkImageSource.");
1305         return;
1306     }
1307 
1308     SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(10.f, 10.f, largeSource));
1309     if (!blur) {
1310         ERRORF(reporter, "Failed to create SkBlurImageFilter.");
1311         return;
1312     }
1313 
1314     SkPaint paint;
1315     paint.setImageFilter(blur);
1316 
1317     // This should not crash (http://crbug.com/570479).
1318     canvas->drawRect(SkRect::MakeIWH(largeW, largeH), paint);
1319 }
1320 
DEF_TEST(BlurLargeImage,reporter)1321 DEF_TEST(BlurLargeImage, reporter) {
1322     SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(SkImageInfo::MakeN32Premul(100, 100)));
1323     test_large_blur_input(reporter, surface->getCanvas());
1324 }
1325 
1326 #if SK_SUPPORT_GPU
1327 
DEF_GPUTEST_FOR_NATIVE_CONTEXT(ImageFilterCropRect_Gpu,reporter,context)1328 DEF_GPUTEST_FOR_NATIVE_CONTEXT(ImageFilterCropRect_Gpu, reporter, context) {
1329     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1330 
1331     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
1332                                                          SkBudgeted::kNo,
1333                                                          SkImageInfo::MakeN32Premul(100, 100),
1334                                                          0,
1335                                                          &props,
1336                                                          SkGpuDevice::kUninit_InitContents));
1337     SkImageFilter::DeviceProxy proxy(device);
1338 
1339     test_crop_rects(&proxy, reporter);
1340 }
1341 
DEF_GPUTEST_FOR_NATIVE_CONTEXT(HugeBlurImageFilter_Gpu,reporter,context)1342 DEF_GPUTEST_FOR_NATIVE_CONTEXT(HugeBlurImageFilter_Gpu, reporter, context) {
1343     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1344 
1345     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
1346                                                          SkBudgeted::kNo,
1347                                                          SkImageInfo::MakeN32Premul(100, 100),
1348                                                          0,
1349                                                          &props,
1350                                                          SkGpuDevice::kUninit_InitContents));
1351     SkCanvas canvas(device);
1352 
1353     test_huge_blur(&canvas, reporter);
1354 }
1355 
DEF_GPUTEST_FOR_NATIVE_CONTEXT(XfermodeImageFilterCroppedInput_Gpu,reporter,context)1356 DEF_GPUTEST_FOR_NATIVE_CONTEXT(XfermodeImageFilterCroppedInput_Gpu, reporter, context) {
1357     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1358 
1359     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
1360                                                          SkBudgeted::kNo,
1361                                                          SkImageInfo::MakeN32Premul(1, 1),
1362                                                          0,
1363                                                          &props,
1364                                                          SkGpuDevice::kUninit_InitContents));
1365     SkCanvas canvas(device);
1366 
1367     test_xfermode_cropped_input(&canvas, reporter);
1368 }
1369 
DEF_GPUTEST_FOR_NATIVE_CONTEXT(TestNegativeBlurSigma_Gpu,reporter,context)1370 DEF_GPUTEST_FOR_NATIVE_CONTEXT(TestNegativeBlurSigma_Gpu, reporter, context) {
1371     const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1372 
1373     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
1374                                                          SkBudgeted::kNo,
1375                                                          SkImageInfo::MakeN32Premul(1, 1),
1376                                                          0,
1377                                                          &props,
1378                                                          SkGpuDevice::kUninit_InitContents));
1379     SkImageFilter::DeviceProxy proxy(device);
1380 
1381     test_negative_blur_sigma(&proxy, reporter);
1382 }
1383 
DEF_GPUTEST_FOR_ALL_CONTEXTS(BlurLargeImage_Gpu,reporter,context)1384 DEF_GPUTEST_FOR_ALL_CONTEXTS(BlurLargeImage_Gpu, reporter, context) {
1385     SkAutoTUnref<SkSurface> surface(
1386         SkSurface::NewRenderTarget(context, SkBudgeted::kYes,
1387                                    SkImageInfo::MakeN32Premul(100, 100)));
1388     test_large_blur_input(reporter, surface->getCanvas());
1389 }
1390 #endif
1391