Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / tests / ImageFilterTest.cpp
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 "SkBitmap.h"
9 #include "SkBitmapDevice.h"
10 #include "SkBitmapSource.h"
11 #include "SkBlurImageFilter.h"
12 #include "SkCanvas.h"
13 #include "SkColorFilterImageFilter.h"
14 #include "SkColorMatrixFilter.h"
15 #include "SkDeviceImageFilterProxy.h"
16 #include "SkDisplacementMapEffect.h"
17 #include "SkDropShadowImageFilter.h"
18 #include "SkFlattenableSerialization.h"
19 #include "SkGradientShader.h"
20 #include "SkLightingImageFilter.h"
21 #include "SkMatrixConvolutionImageFilter.h"
22 #include "SkMatrixImageFilter.h"
23 #include "SkMergeImageFilter.h"
24 #include "SkMorphologyImageFilter.h"
25 #include "SkOffsetImageFilter.h"
26 #include "SkPicture.h"
27 #include "SkPictureImageFilter.h"
28 #include "SkPictureRecorder.h"
29 #include "SkReadBuffer.h"
30 #include "SkRect.h"
31 #include "SkTileImageFilter.h"
32 #include "SkXfermodeImageFilter.h"
33 #include "Test.h"
34
35 #if SK_SUPPORT_GPU
36 #include "GrContextFactory.h"
37 #include "SkGpuDevice.h"
38 #endif
39
40 static const int kBitmapSize = 4;
41
42 namespace {
43
44 class MatrixTestImageFilter : public SkImageFilter {
45 public:
46     MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
47       : SkImageFilter(0, NULL), fReporter(reporter), fExpectedMatrix(expectedMatrix) {
48     }
49
50     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context& ctx,
51                                SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE {
52         REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
53         return true;
54     }
55
56     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(MatrixTestImageFilter)
57
58 protected:
59 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
60     explicit MatrixTestImageFilter(SkReadBuffer& buffer) : SkImageFilter(0, NULL) {
61         fReporter = static_cast<skiatest::Reporter*>(buffer.readFunctionPtr());
62         buffer.readMatrix(&fExpectedMatrix);
63     }
64 #endif
65
66     virtual void flatten(SkWriteBuffer& buffer) const SK_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
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 SkNEW_ARGS(MatrixTestImageFilter, (reporter, matrix));
87 }
88
89 static void make_small_bitmap(SkBitmap& bitmap) {
90     bitmap.allocN32Pixels(kBitmapSize, kBitmapSize);
91     SkCanvas canvas(bitmap);
92     canvas.clear(0x00000000);
93     SkPaint darkPaint;
94     darkPaint.setColor(0xFF804020);
95     SkPaint lightPaint;
96     lightPaint.setColor(0xFF244484);
97     const int i = kBitmapSize / 4;
98     for (int y = 0; y < kBitmapSize; y += i) {
99         for (int x = 0; x < kBitmapSize; x += i) {
100             canvas.save();
101             canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
102             canvas.drawRect(SkRect::MakeXYWH(0, 0,
103                                              SkIntToScalar(i),
104                                              SkIntToScalar(i)), darkPaint);
105             canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
106                                              0,
107                                              SkIntToScalar(i),
108                                              SkIntToScalar(i)), lightPaint);
109             canvas.drawRect(SkRect::MakeXYWH(0,
110                                              SkIntToScalar(i),
111                                              SkIntToScalar(i),
112                                              SkIntToScalar(i)), lightPaint);
113             canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
114                                              SkIntToScalar(i),
115                                              SkIntToScalar(i),
116                                              SkIntToScalar(i)), darkPaint);
117             canvas.restore();
118         }
119     }
120 }
121
122 static SkImageFilter* make_scale(float amount, SkImageFilter* input = NULL) {
123     SkScalar s = amount;
124     SkScalar matrix[20] = { s, 0, 0, 0, 0,
125                             0, s, 0, 0, 0,
126                             0, 0, s, 0, 0,
127                             0, 0, 0, s, 0 };
128     SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
129     return SkColorFilterImageFilter::Create(filter, input);
130 }
131
132 static SkImageFilter* make_grayscale(SkImageFilter* input = NULL, const SkImageFilter::CropRect* cropRect = NULL) {
133     SkScalar matrix[20];
134     memset(matrix, 0, 20 * sizeof(SkScalar));
135     matrix[0] = matrix[5] = matrix[10] = 0.2126f;
136     matrix[1] = matrix[6] = matrix[11] = 0.7152f;
137     matrix[2] = matrix[7] = matrix[12] = 0.0722f;
138     matrix[18] = 1.0f;
139     SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
140     return SkColorFilterImageFilter::Create(filter, input, cropRect);
141 }
142
143 DEF_TEST(ImageFilter, reporter) {
144     {
145         // Check that two non-clipping color matrices concatenate into a single filter.
146         SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f));
147         SkAutoTUnref<SkImageFilter> quarterBrightness(make_scale(0.5f, halfBrightness));
148         REPORTER_ASSERT(reporter, NULL == quarterBrightness->getInput(0));
149     }
150
151     {
152         // Check that a clipping color matrix followed by a grayscale does not concatenate into a single filter.
153         SkAutoTUnref<SkImageFilter> doubleBrightness(make_scale(2.0f));
154         SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f, doubleBrightness));
155         REPORTER_ASSERT(reporter, halfBrightness->getInput(0));
156     }
157
158     {
159         // Check that a color filter image filter without a crop rect can be
160         // expressed as a color filter.
161         SkAutoTUnref<SkImageFilter> gray(make_grayscale());
162         REPORTER_ASSERT(reporter, true == gray->asColorFilter(NULL));
163     }
164
165     {
166         // Check that a color filter image filter with a crop rect cannot
167         // be expressed as a color filter.
168         SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100));
169         SkAutoTUnref<SkImageFilter> grayWithCrop(make_grayscale(NULL, &cropRect));
170         REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(NULL));
171     }
172
173     {
174         // Check that two non-commutative matrices are concatenated in
175         // the correct order.
176         SkScalar blueToRedMatrix[20] = { 0 };
177         blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
178         SkScalar redToGreenMatrix[20] = { 0 };
179         redToGreenMatrix[5] = redToGreenMatrix[18] = SK_Scalar1;
180         SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix));
181         SkAutoTUnref<SkImageFilter> filter1(SkColorFilterImageFilter::Create(blueToRed.get()));
182         SkAutoTUnref<SkColorFilter> redToGreen(SkColorMatrixFilter::Create(redToGreenMatrix));
183         SkAutoTUnref<SkImageFilter> filter2(SkColorFilterImageFilter::Create(redToGreen.get(), filter1.get()));
184
185         SkBitmap result;
186         result.allocN32Pixels(kBitmapSize, kBitmapSize);
187
188         SkPaint paint;
189         paint.setColor(SK_ColorBLUE);
190         paint.setImageFilter(filter2.get());
191         SkCanvas canvas(result);
192         canvas.clear(0x0);
193         SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
194         canvas.drawRect(rect, paint);
195         uint32_t pixel = *result.getAddr32(0, 0);
196         // The result here should be green, since we have effectively shifted blue to green.
197         REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
198     }
199
200     {
201         // Tests pass by not asserting
202         SkBitmap bitmap, result;
203         make_small_bitmap(bitmap);
204         result.allocN32Pixels(kBitmapSize, kBitmapSize);
205
206         {
207             // This tests for :
208             // 1 ) location at (0,0,1)
209             SkPoint3 location(0, 0, SK_Scalar1);
210             // 2 ) location and target at same value
211             SkPoint3 target(location.fX, location.fY, location.fZ);
212             // 3 ) large negative specular exponent value
213             SkScalar specularExponent = -1000;
214
215             SkAutoTUnref<SkImageFilter> bmSrc(SkBitmapSource::Create(bitmap));
216             SkPaint paint;
217             paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(
218                     location, target, specularExponent, 180,
219                     0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
220                     bmSrc))->unref();
221             SkCanvas canvas(result);
222             SkRect r = SkRect::MakeWH(SkIntToScalar(kBitmapSize),
223                                       SkIntToScalar(kBitmapSize));
224             canvas.drawRect(r, paint);
225         }
226     }
227 }
228
229 static void test_crop_rects(SkBaseDevice* device, skiatest::Reporter* reporter) {
230     // Check that all filters offset to their absolute crop rect,
231     // unaffected by the input crop rect.
232     // Tests pass by not asserting.
233     SkBitmap bitmap;
234     bitmap.allocN32Pixels(100, 100);
235     bitmap.eraseARGB(0, 0, 0, 0);
236     SkDeviceImageFilterProxy proxy(device);
237
238     SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
239     SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
240     SkAutoTUnref<SkImageFilter> input(make_grayscale(NULL, &inputCropRect));
241
242     SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
243     SkPoint3 location(0, 0, SK_Scalar1);
244     SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
245     SkScalar kernel[9] = {
246         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
247         SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
248         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
249     };
250     SkISize kernelSize = SkISize::Make(3, 3);
251     SkScalar gain = SK_Scalar1, bias = 0;
252
253     SkImageFilter* filters[] = {
254         SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
255         SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType,
256                                         SkDisplacementMapEffect::kB_ChannelSelectorType,
257                                         40.0f, input.get(), input.get(), &cropRect),
258         SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
259         SkDropShadowImageFilter::Create(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input.get(), &cropRect),
260         SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
261         SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
262         SkMatrixConvolutionImageFilter::Create(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
263         SkMergeImageFilter::Create(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
264         SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
265         SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
266         SkDilateImageFilter::Create(3, 2, input.get(), &cropRect),
267         SkErodeImageFilter::Create(2, 3, input.get(), &cropRect),
268         SkTileImageFilter::Create(inputCropRect.rect(), cropRect.rect(), input.get()),
269         SkXfermodeImageFilter::Create(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
270     };
271
272     for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
273         SkImageFilter* filter = filters[i];
274         SkBitmap result;
275         SkIPoint offset;
276         SkString str;
277         str.printf("filter %d", static_cast<int>(i));
278         SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), NULL);
279         REPORTER_ASSERT_MESSAGE(reporter, filter->filterImage(&proxy, bitmap, ctx,
280                                 &result, &offset), str.c_str());
281         REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str());
282     }
283
284     for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
285         SkSafeUnref(filters[i]);
286     }
287 }
288
289 static SkBitmap make_gradient_circle(int width, int height) {
290     SkBitmap bitmap;
291     SkScalar x = SkIntToScalar(width / 2);
292     SkScalar y = SkIntToScalar(height / 2);
293     SkScalar radius = SkMinScalar(x, y) * 0.8f;
294     bitmap.allocN32Pixels(width, height);
295     SkCanvas canvas(bitmap);
296     canvas.clear(0x00000000);
297     SkColor colors[2];
298     colors[0] = SK_ColorWHITE;
299     colors[1] = SK_ColorBLACK;
300     SkAutoTUnref<SkShader> shader(
301         SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, NULL, 2,
302                                        SkShader::kClamp_TileMode)
303     );
304     SkPaint paint;
305     paint.setShader(shader);
306     canvas.drawCircle(x, y, radius, paint);
307     return bitmap;
308 }
309
310 static void test_negative_blur_sigma(SkBaseDevice* device, skiatest::Reporter* reporter) {
311     // Check that SkBlurImageFilter will accept a negative sigma, either in
312     // the given arguments or after CTM application.
313     int width = 32, height = 32;
314     SkDeviceImageFilterProxy proxy(device);
315     SkScalar five = SkIntToScalar(5);
316
317     SkAutoTUnref<SkBlurImageFilter> positiveFilter(
318         SkBlurImageFilter::Create(five, five)
319     );
320
321     SkAutoTUnref<SkBlurImageFilter> negativeFilter(
322         SkBlurImageFilter::Create(-five, five)
323     );
324
325     SkBitmap gradient = make_gradient_circle(width, height);
326     SkBitmap positiveResult1, negativeResult1;
327     SkBitmap positiveResult2, negativeResult2;
328     SkIPoint offset;
329     SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), NULL);
330     positiveFilter->filterImage(&proxy, gradient, ctx, &positiveResult1, &offset);
331     negativeFilter->filterImage(&proxy, gradient, ctx, &negativeResult1, &offset);
332     SkMatrix negativeScale;
333     negativeScale.setScale(-SK_Scalar1, SK_Scalar1);
334     SkImageFilter::Context negativeCTX(negativeScale, SkIRect::MakeLargest(), NULL);
335     positiveFilter->filterImage(&proxy, gradient, negativeCTX, &negativeResult2, &offset);
336     negativeFilter->filterImage(&proxy, gradient, negativeCTX, &positiveResult2, &offset);
337     SkAutoLockPixels lockP1(positiveResult1);
338     SkAutoLockPixels lockP2(positiveResult2);
339     SkAutoLockPixels lockN1(negativeResult1);
340     SkAutoLockPixels lockN2(negativeResult2);
341     for (int y = 0; y < height; y++) {
342         int diffs = memcmp(positiveResult1.getAddr32(0, y), negativeResult1.getAddr32(0, y), positiveResult1.rowBytes());
343         REPORTER_ASSERT(reporter, !diffs);
344         if (diffs) {
345             break;
346         }
347         diffs = memcmp(positiveResult1.getAddr32(0, y), negativeResult2.getAddr32(0, y), positiveResult1.rowBytes());
348         REPORTER_ASSERT(reporter, !diffs);
349         if (diffs) {
350             break;
351         }
352         diffs = memcmp(positiveResult1.getAddr32(0, y), positiveResult2.getAddr32(0, y), positiveResult1.rowBytes());
353         REPORTER_ASSERT(reporter, !diffs);
354         if (diffs) {
355             break;
356         }
357     }
358 }
359
360 DEF_TEST(TestNegativeBlurSigma, reporter) {
361     SkBitmap temp;
362     temp.allocN32Pixels(100, 100);
363     SkBitmapDevice device(temp);
364     test_negative_blur_sigma(&device, reporter);
365 }
366
367 DEF_TEST(ImageFilterDrawTiled, reporter) {
368     // Check that all filters when drawn tiled (with subsequent clip rects) exactly
369     // match the same filters drawn with a single full-canvas bitmap draw.
370     // Tests pass by not asserting.
371
372     SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
373     SkPoint3 location(0, 0, SK_Scalar1);
374     SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
375     SkScalar kernel[9] = {
376         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
377         SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
378         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
379     };
380     SkISize kernelSize = SkISize::Make(3, 3);
381     SkScalar gain = SK_Scalar1, bias = 0;
382     SkScalar five = SkIntToScalar(5);
383
384     SkAutoTUnref<SkImageFilter> gradient_source(SkBitmapSource::Create(make_gradient_circle(64, 64)));
385     SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(five, five));
386     SkMatrix matrix;
387
388     matrix.setTranslate(SK_Scalar1, SK_Scalar1);
389     matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
390
391     SkRTreeFactory factory;
392     SkPictureRecorder recorder;
393     SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0);
394
395     SkPaint greenPaint;
396     greenPaint.setColor(SK_ColorGREEN);
397     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
398     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
399     SkAutoTUnref<SkImageFilter> pictureFilter(SkPictureImageFilter::Create(picture.get()));
400
401     struct {
402         const char*    fName;
403         SkImageFilter* fFilter;
404     } filters[] = {
405         { "color filter", SkColorFilterImageFilter::Create(cf.get()) },
406         { "displacement map", SkDisplacementMapEffect::Create(
407               SkDisplacementMapEffect::kR_ChannelSelectorType,
408               SkDisplacementMapEffect::kB_ChannelSelectorType,
409               20.0f, gradient_source.get()) },
410         { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
411         { "drop shadow", SkDropShadowImageFilter::Create(
412               SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN) },
413         { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse(
414               location, SK_ColorGREEN, 0, 0) },
415         { "specular lighting",
416               SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) },
417         { "matrix convolution",
418               SkMatrixConvolutionImageFilter::Create(
419                   kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
420                   SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) },
421         { "merge", SkMergeImageFilter::Create(NULL, NULL, SkXfermode::kSrcOver_Mode) },
422         { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) },
423         { "dilate", SkDilateImageFilter::Create(3, 2) },
424         { "erode", SkErodeImageFilter::Create(2, 3) },
425         { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50),
426                                             SkRect::MakeXYWH(0, 0, 100, 100), NULL) },
427         { "matrix", SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel) },
428         { "blur and offset", SkOffsetImageFilter::Create(five, five, blur.get()) },
429         { "picture and blur", SkBlurImageFilter::Create(five, five, pictureFilter.get()) },
430     };
431
432     SkBitmap untiledResult, tiledResult;
433     int width = 64, height = 64;
434     untiledResult.allocN32Pixels(width, height);
435     tiledResult.allocN32Pixels(width, height);
436     SkCanvas tiledCanvas(tiledResult);
437     SkCanvas untiledCanvas(untiledResult);
438     int tileSize = 8;
439
440     for (int scale = 1; scale <= 2; ++scale) {
441         for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
442             tiledCanvas.clear(0);
443             untiledCanvas.clear(0);
444             SkPaint paint;
445             paint.setImageFilter(filters[i].fFilter);
446             paint.setTextSize(SkIntToScalar(height));
447             paint.setColor(SK_ColorWHITE);
448             SkString str;
449             const char* text = "ABC";
450             SkScalar ypos = SkIntToScalar(height);
451             untiledCanvas.save();
452             untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
453             untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
454             untiledCanvas.restore();
455             for (int y = 0; y < height; y += tileSize) {
456                 for (int x = 0; x < width; x += tileSize) {
457                     tiledCanvas.save();
458                     tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
459                     tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
460                     tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
461                     tiledCanvas.restore();
462                 }
463             }
464             untiledCanvas.flush();
465             tiledCanvas.flush();
466             for (int y = 0; y < height; y++) {
467                 int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
468                 REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
469                 if (diffs) {
470                     break;
471                 }
472             }
473         }
474     }
475
476     for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
477         SkSafeUnref(filters[i].fFilter);
478     }
479 }
480
481 static void draw_saveLayer_picture(int width, int height, int tileSize, 
482                                    SkBBHFactory* factory, SkBitmap* result) {
483
484     SkMatrix matrix;
485     matrix.setTranslate(SkIntToScalar(50), 0);
486
487     SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorWHITE, SkXfermode::kSrc_Mode));
488     SkAutoTUnref<SkImageFilter> cfif(SkColorFilterImageFilter::Create(cf.get()));
489     SkAutoTUnref<SkImageFilter> imageFilter(SkMatrixImageFilter::Create(matrix, SkPaint::kNone_FilterLevel, cfif.get()));
490
491     SkPaint paint;
492     paint.setImageFilter(imageFilter.get());
493     SkPictureRecorder recorder;
494     SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50));
495     SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width), 
496                                                         SkIntToScalar(height), 
497                                                         factory, 0);
498     recordingCanvas->translate(-55, 0);
499     recordingCanvas->saveLayer(&bounds, &paint);
500     recordingCanvas->restore();
501     SkAutoTUnref<SkPicture> picture1(recorder.endRecording());
502
503     result->allocN32Pixels(width, height);
504     SkCanvas canvas(*result);
505     canvas.clear(0);
506     canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize)));
507     canvas.drawPicture(picture1.get());
508 }
509
510 DEF_TEST(ImageFilterDrawMatrixBBH, reporter) {
511     // Check that matrix filter when drawn tiled with BBH exactly
512     // matches the same thing drawn without BBH.
513     // Tests pass by not asserting.
514
515     const int width = 200, height = 200;
516     const int tileSize = 100;
517     SkBitmap result1, result2;
518     SkRTreeFactory factory;
519
520     draw_saveLayer_picture(width, height, tileSize, &factory, &result1);
521     draw_saveLayer_picture(width, height, tileSize, NULL, &result2);
522
523     for (int y = 0; y < height; y++) {
524         int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
525         REPORTER_ASSERT(reporter, !diffs);
526         if (diffs) {
527             break;
528         }
529     }
530 }
531
532 static SkImageFilter* makeBlur(SkImageFilter* input = NULL) {
533     return SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input);
534 }
535
536 static SkImageFilter* makeDropShadow(SkImageFilter* input = NULL) {
537     return SkDropShadowImageFilter::Create(
538         SkIntToScalar(100), SkIntToScalar(100),
539         SkIntToScalar(10), SkIntToScalar(10),
540         SK_ColorBLUE, input);
541 }
542
543 DEF_TEST(ImageFilterBlurThenShadowBounds, reporter) {
544     SkAutoTUnref<SkImageFilter> filter1(makeBlur());
545     SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get()));
546
547     SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
548     SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
549     filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
550
551     REPORTER_ASSERT(reporter, bounds == expectedBounds);
552 }
553
554 DEF_TEST(ImageFilterShadowThenBlurBounds, reporter) {
555     SkAutoTUnref<SkImageFilter> filter1(makeDropShadow());
556     SkAutoTUnref<SkImageFilter> filter2(makeBlur(filter1.get()));
557
558     SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
559     SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
560     filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
561
562     REPORTER_ASSERT(reporter, bounds == expectedBounds);
563 }
564
565 DEF_TEST(ImageFilterDilateThenBlurBounds, reporter) {
566     SkAutoTUnref<SkImageFilter> filter1(SkDilateImageFilter::Create(2, 2));
567     SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get()));
568
569     SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
570     SkIRect expectedBounds = SkIRect::MakeXYWH(-132, -132, 234, 234);
571     filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
572
573     REPORTER_ASSERT(reporter, bounds == expectedBounds);
574 }
575
576 static void draw_blurred_rect(SkCanvas* canvas) {
577     SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0));
578     SkPaint filterPaint;
579     filterPaint.setColor(SK_ColorWHITE);
580     filterPaint.setImageFilter(filter);
581     canvas->saveLayer(NULL, &filterPaint);
582     SkPaint whitePaint;
583     whitePaint.setColor(SK_ColorWHITE);
584     canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
585     canvas->restore();
586 }
587
588 static void draw_picture_clipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
589     canvas->save();
590     canvas->clipRect(clipRect);
591     canvas->drawPicture(picture);
592     canvas->restore();
593 }
594
595 DEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) {
596     // Check that the blur filter when recorded with RTree acceleration,
597     // and drawn tiled (with subsequent clip rects) exactly
598     // matches the same filter drawn with without RTree acceleration.
599     // This tests that the "bleed" from the blur into the otherwise-blank
600     // tiles is correctly rendered.
601     // Tests pass by not asserting.
602
603     int width = 16, height = 8;
604     SkBitmap result1, result2;
605     result1.allocN32Pixels(width, height);
606     result2.allocN32Pixels(width, height);
607     SkCanvas canvas1(result1);
608     SkCanvas canvas2(result2);
609     int tileSize = 8;
610
611     canvas1.clear(0);
612     canvas2.clear(0);
613
614     SkRTreeFactory factory;
615
616     SkPictureRecorder recorder1, recorder2;
617     // The only difference between these two pictures is that one has RTree aceleration.
618     SkCanvas* recordingCanvas1 = recorder1.beginRecording(SkIntToScalar(width), 
619                                                           SkIntToScalar(height), 
620                                                           NULL, 0);
621     SkCanvas* recordingCanvas2 = recorder2.beginRecording(SkIntToScalar(width), 
622                                                           SkIntToScalar(height), 
623                                                           &factory, 0);
624     draw_blurred_rect(recordingCanvas1);
625     draw_blurred_rect(recordingCanvas2);
626     SkAutoTUnref<SkPicture> picture1(recorder1.endRecording());
627     SkAutoTUnref<SkPicture> picture2(recorder2.endRecording());
628     for (int y = 0; y < height; y += tileSize) {
629         for (int x = 0; x < width; x += tileSize) {
630             SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
631             draw_picture_clipped(&canvas1, tileRect, picture1);
632             draw_picture_clipped(&canvas2, tileRect, picture2);
633         }
634     }
635     for (int y = 0; y < height; y++) {
636         int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
637         REPORTER_ASSERT(reporter, !diffs);
638         if (diffs) {
639             break;
640         }
641     }
642 }
643
644 DEF_TEST(ImageFilterMatrixConvolution, reporter) {
645     // Check that a 1x3 filter does not cause a spurious assert.
646     SkScalar kernel[3] = {
647         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
648     };
649     SkISize kernelSize = SkISize::Make(1, 3);
650     SkScalar gain = SK_Scalar1, bias = 0;
651     SkIPoint kernelOffset = SkIPoint::Make(0, 0);
652
653     SkAutoTUnref<SkImageFilter> filter(
654         SkMatrixConvolutionImageFilter::Create(
655             kernelSize, kernel, gain, bias, kernelOffset,
656             SkMatrixConvolutionImageFilter::kRepeat_TileMode, false));
657
658     SkBitmap result;
659     int width = 16, height = 16;
660     result.allocN32Pixels(width, height);
661     SkCanvas canvas(result);
662     canvas.clear(0);
663
664     SkPaint paint;
665     paint.setImageFilter(filter);
666     SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
667     canvas.drawRect(rect, paint);
668 }
669
670 DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
671     // Check that a filter with borders outside the target bounds
672     // does not crash.
673     SkScalar kernel[3] = {
674         0, 0, 0,
675     };
676     SkISize kernelSize = SkISize::Make(3, 1);
677     SkScalar gain = SK_Scalar1, bias = 0;
678     SkIPoint kernelOffset = SkIPoint::Make(2, 0);
679
680     SkAutoTUnref<SkImageFilter> filter(
681         SkMatrixConvolutionImageFilter::Create(
682             kernelSize, kernel, gain, bias, kernelOffset,
683             SkMatrixConvolutionImageFilter::kClamp_TileMode, true));
684
685     SkBitmap result;
686
687     int width = 10, height = 10;
688     result.allocN32Pixels(width, height);
689     SkCanvas canvas(result);
690     canvas.clear(0);
691
692     SkPaint filterPaint;
693     filterPaint.setImageFilter(filter);
694     SkRect bounds = SkRect::MakeWH(1, 10);
695     SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
696     SkPaint rectPaint;
697     canvas.saveLayer(&bounds, &filterPaint);
698     canvas.drawRect(rect, rectPaint);
699     canvas.restore();
700 }
701
702 DEF_TEST(ImageFilterCropRect, reporter) {
703     SkBitmap temp;
704     temp.allocN32Pixels(100, 100);
705     SkBitmapDevice device(temp);
706     test_crop_rects(&device, reporter);
707 }
708
709 DEF_TEST(ImageFilterMatrix, reporter) {
710     SkBitmap temp;
711     temp.allocN32Pixels(100, 100);
712     SkBitmapDevice device(temp);
713     SkCanvas canvas(&device);
714     canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
715
716     SkMatrix expectedMatrix = canvas.getTotalMatrix();
717
718     SkRTreeFactory factory;
719     SkPictureRecorder recorder;
720     SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
721
722     SkPaint paint;
723     SkAutoTUnref<MatrixTestImageFilter> imageFilter(
724         new MatrixTestImageFilter(reporter, expectedMatrix));
725     paint.setImageFilter(imageFilter.get());
726     recordingCanvas->saveLayer(NULL, &paint);
727     SkPaint solidPaint;
728     solidPaint.setColor(0xFFFFFFFF);
729     recordingCanvas->save();
730     recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
731     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
732     recordingCanvas->restore(); // scale
733     recordingCanvas->restore(); // saveLayer
734     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
735
736     canvas.drawPicture(picture);
737 }
738
739 DEF_TEST(ImageFilterCrossProcessPictureImageFilter, reporter) {
740     SkRTreeFactory factory;
741     SkPictureRecorder recorder;
742     SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
743
744     // Create an SkPicture which simply draws a green 1x1 rectangle.
745     SkPaint greenPaint;
746     greenPaint.setColor(SK_ColorGREEN);
747     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
748     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
749
750     // Wrap that SkPicture in an SkPictureImageFilter.
751     SkAutoTUnref<SkImageFilter> imageFilter(
752         SkPictureImageFilter::Create(picture.get()));
753
754     // Check that SkPictureImageFilter successfully serializes its contained
755     // SkPicture when not in cross-process mode.
756     SkPaint paint;
757     paint.setImageFilter(imageFilter.get());
758     SkPictureRecorder outerRecorder;
759     SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
760     SkPaint redPaintWithFilter;
761     redPaintWithFilter.setColor(SK_ColorRED);
762     redPaintWithFilter.setImageFilter(imageFilter.get());
763     outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
764     SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording());
765
766     SkBitmap bitmap;
767     bitmap.allocN32Pixels(1, 1);
768     SkBitmapDevice device(bitmap);
769     SkCanvas canvas(&device);
770
771     // The result here should be green, since the filter replaces the primitive's red interior.
772     canvas.clear(0x0);
773     canvas.drawPicture(outerPicture);
774     uint32_t pixel = *bitmap.getAddr32(0, 0);
775     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
776
777     // Check that, for now, SkPictureImageFilter does not serialize or
778     // deserialize its contained picture when the filter is serialized
779     // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
780     SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
781     SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
782         data->data(), data->size(), SkImageFilter::GetFlattenableType()));
783     SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
784
785     redPaintWithFilter.setImageFilter(unflattenedFilter);
786     SkPictureRecorder crossProcessRecorder;
787     SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
788     crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
789     SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording());
790
791     canvas.clear(0x0);
792     canvas.drawPicture(crossProcessPicture);
793     pixel = *bitmap.getAddr32(0, 0);
794     // The result here should not be green, since the filter draws nothing.
795     REPORTER_ASSERT(reporter, pixel != SK_ColorGREEN);
796 }
797
798 DEF_TEST(ImageFilterClippedPictureImageFilter, reporter) {
799     SkRTreeFactory factory;
800     SkPictureRecorder recorder;
801     SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
802
803     // Create an SkPicture which simply draws a green 1x1 rectangle.
804     SkPaint greenPaint;
805     greenPaint.setColor(SK_ColorGREEN);
806     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
807     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
808
809     SkAutoTUnref<SkImageFilter> imageFilter(
810         SkPictureImageFilter::Create(picture.get()));
811
812     SkBitmap result;
813     SkIPoint offset;
814     SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(1, 1, 1, 1), NULL);
815     SkBitmap bitmap;
816     bitmap.allocN32Pixels(2, 2);
817     SkBitmapDevice device(bitmap);
818     SkDeviceImageFilterProxy proxy(&device);
819     REPORTER_ASSERT(reporter, !imageFilter->filterImage(&proxy, bitmap, ctx, &result, &offset));
820 }
821
822 DEF_TEST(ImageFilterEmptySaveLayer, reporter) {
823     // Even when there's an empty saveLayer()/restore(), ensure that an image
824     // filter or color filter which affects transparent black still draws.
825
826     SkBitmap bitmap;
827     bitmap.allocN32Pixels(10, 10);
828     SkBitmapDevice device(bitmap);
829     SkCanvas canvas(&device);
830
831     SkRTreeFactory factory;
832     SkPictureRecorder recorder;
833
834     SkAutoTUnref<SkColorFilter> green(
835         SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode));
836     SkAutoTUnref<SkColorFilterImageFilter> imageFilter(
837         SkColorFilterImageFilter::Create(green.get()));
838     SkPaint imageFilterPaint;
839     imageFilterPaint.setImageFilter(imageFilter.get());
840     SkPaint colorFilterPaint;
841     colorFilterPaint.setColorFilter(green.get());
842
843     SkRect bounds = SkRect::MakeWH(10, 10);
844
845     SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
846     recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
847     recordingCanvas->restore();
848     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
849
850     canvas.clear(0);
851     canvas.drawPicture(picture);
852     uint32_t pixel = *bitmap.getAddr32(0, 0);
853     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
854
855     recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
856     recordingCanvas->saveLayer(NULL, &imageFilterPaint);
857     recordingCanvas->restore();
858     SkAutoTUnref<SkPicture> picture2(recorder.endRecording());
859
860     canvas.clear(0);
861     canvas.drawPicture(picture2);
862     pixel = *bitmap.getAddr32(0, 0);
863     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
864
865     recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
866     recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
867     recordingCanvas->restore();
868     SkAutoTUnref<SkPicture> picture3(recorder.endRecording());
869
870     canvas.clear(0);
871     canvas.drawPicture(picture3);
872     pixel = *bitmap.getAddr32(0, 0);
873     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
874 }
875
876 static void test_huge_blur(SkBaseDevice* device, skiatest::Reporter* reporter) {
877     SkCanvas canvas(device);
878
879     SkBitmap bitmap;
880     bitmap.allocN32Pixels(100, 100);
881     bitmap.eraseARGB(0, 0, 0, 0);
882
883     // Check that a blur with an insane radius does not crash or assert.
884     SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(SkIntToScalar(1<<30), SkIntToScalar(1<<30)));
885
886     SkPaint paint;
887     paint.setImageFilter(blur);
888     canvas.drawSprite(bitmap, 0, 0, &paint);
889 }
890
891 DEF_TEST(HugeBlurImageFilter, reporter) {
892     SkBitmap temp;
893     temp.allocN32Pixels(100, 100);
894     SkBitmapDevice device(temp);
895     test_huge_blur(&device, reporter);
896 }
897
898 DEF_TEST(MatrixConvolutionSanityTest, reporter) {
899     SkScalar kernel[1] = { 0 };
900     SkScalar gain = SK_Scalar1, bias = 0;
901     SkIPoint kernelOffset = SkIPoint::Make(1, 1);
902
903     // Check that an enormous (non-allocatable) kernel gives a NULL filter.
904     SkAutoTUnref<SkImageFilter> conv(SkMatrixConvolutionImageFilter::Create(
905         SkISize::Make(1<<30, 1<<30),
906         kernel,
907         gain,
908         bias,
909         kernelOffset,
910         SkMatrixConvolutionImageFilter::kRepeat_TileMode,
911         false));
912
913     REPORTER_ASSERT(reporter, NULL == conv.get());
914
915     // Check that a NULL kernel gives a NULL filter.
916     conv.reset(SkMatrixConvolutionImageFilter::Create(
917         SkISize::Make(1, 1),
918         NULL,
919         gain,
920         bias,
921         kernelOffset,
922         SkMatrixConvolutionImageFilter::kRepeat_TileMode,
923         false));
924
925     REPORTER_ASSERT(reporter, NULL == conv.get());
926
927     // Check that a kernel width < 1 gives a NULL filter.
928     conv.reset(SkMatrixConvolutionImageFilter::Create(
929         SkISize::Make(0, 1),
930         kernel,
931         gain,
932         bias,
933         kernelOffset,
934         SkMatrixConvolutionImageFilter::kRepeat_TileMode,
935         false));
936
937     REPORTER_ASSERT(reporter, NULL == conv.get());
938
939     // Check that kernel height < 1 gives a NULL filter.
940     conv.reset(SkMatrixConvolutionImageFilter::Create(
941         SkISize::Make(1, -1),
942         kernel,
943         gain,
944         bias,
945         kernelOffset,
946         SkMatrixConvolutionImageFilter::kRepeat_TileMode,
947         false));
948
949     REPORTER_ASSERT(reporter, NULL == conv.get());
950 }
951
952 static void test_xfermode_cropped_input(SkBaseDevice* device, skiatest::Reporter* reporter) {
953     SkCanvas canvas(device);
954     canvas.clear(0);
955
956     SkBitmap bitmap;
957     bitmap.allocN32Pixels(1, 1);
958     bitmap.eraseARGB(255, 255, 255, 255);
959
960     SkAutoTUnref<SkColorFilter> green(
961         SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode));
962     SkAutoTUnref<SkColorFilterImageFilter> greenFilter(
963         SkColorFilterImageFilter::Create(green.get()));
964     SkImageFilter::CropRect cropRect(SkRect::MakeEmpty());
965     SkAutoTUnref<SkColorFilterImageFilter> croppedOut(
966         SkColorFilterImageFilter::Create(green.get(), NULL, &cropRect));
967
968     // Check that an xfermode image filter whose input has been cropped out still draws the other
969     // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
970     SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode);
971     SkAutoTUnref<SkImageFilter> xfermodeNoFg(
972         SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut));
973     SkAutoTUnref<SkImageFilter> xfermodeNoBg(
974         SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter));
975     SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg(
976         SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut));
977
978     SkPaint paint;
979     paint.setImageFilter(xfermodeNoFg);
980     canvas.drawSprite(bitmap, 0, 0, &paint);
981
982     uint32_t pixel;
983     SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
984     canvas.readPixels(info, &pixel, 4, 0, 0);
985     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
986
987     paint.setImageFilter(xfermodeNoBg);
988     canvas.drawSprite(bitmap, 0, 0, &paint);
989     canvas.readPixels(info, &pixel, 4, 0, 0);
990     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
991
992     paint.setImageFilter(xfermodeNoFgNoBg);
993     canvas.drawSprite(bitmap, 0, 0, &paint);
994     canvas.readPixels(info, &pixel, 4, 0, 0);
995     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
996 }
997
998 DEF_TEST(ImageFilterNestedSaveLayer, reporter) {
999     SkBitmap temp;
1000     temp.allocN32Pixels(50, 50);
1001     SkBitmapDevice device(temp);
1002     SkCanvas canvas(&device);
1003     canvas.clear(0x0);
1004
1005     SkBitmap bitmap;
1006     bitmap.allocN32Pixels(10, 10);
1007     bitmap.eraseColor(SK_ColorGREEN);
1008
1009     SkMatrix matrix;
1010     matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
1011     matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
1012     SkAutoTUnref<SkImageFilter> matrixFilter(
1013         SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel));
1014
1015     // Test that saveLayer() with a filter nested inside another saveLayer() applies the
1016     // correct offset to the filter matrix.
1017     SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
1018     canvas.saveLayer(&bounds1, NULL);
1019     SkPaint filterPaint;
1020     filterPaint.setImageFilter(matrixFilter);
1021     SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
1022     canvas.saveLayer(&bounds2, &filterPaint);
1023     SkPaint greenPaint;
1024     greenPaint.setColor(SK_ColorGREEN);
1025     canvas.drawRect(bounds2, greenPaint);
1026     canvas.restore();
1027     canvas.restore();
1028     SkPaint strokePaint;
1029     strokePaint.setStyle(SkPaint::kStroke_Style);
1030     strokePaint.setColor(SK_ColorRED);
1031
1032     SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
1033     uint32_t pixel;
1034     canvas.readPixels(info, &pixel, 4, 25, 25);
1035     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1036
1037     // Test that drawSprite() with a filter nested inside a saveLayer() applies the
1038     // correct offset to the filter matrix.
1039     canvas.clear(0x0);
1040     canvas.readPixels(info, &pixel, 4, 25, 25);
1041     canvas.saveLayer(&bounds1, NULL);
1042     canvas.drawSprite(bitmap, 20, 20, &filterPaint);
1043     canvas.restore();
1044
1045     canvas.readPixels(info, &pixel, 4, 25, 25);
1046     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1047 }
1048
1049 DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
1050     SkBitmap temp;
1051     temp.allocN32Pixels(100, 100);
1052     SkBitmapDevice device(temp);
1053     test_xfermode_cropped_input(&device, reporter);
1054 }
1055
1056 #if SK_SUPPORT_GPU
1057 const SkSurfaceProps gProps = SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
1058
1059 DEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) {
1060     GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
1061     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
1062                                                          SkImageInfo::MakeN32Premul(100, 100),
1063                                                          gProps,
1064                                                          0));
1065     test_crop_rects(device, reporter);
1066 }
1067
1068 DEF_GPUTEST(HugeBlurImageFilterGPU, reporter, factory) {
1069     GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
1070     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
1071                                                          SkImageInfo::MakeN32Premul(100, 100),
1072                                                          gProps,
1073                                                          0));
1074     test_huge_blur(device, reporter);
1075 }
1076
1077 DEF_GPUTEST(XfermodeImageFilterCroppedInputGPU, reporter, factory) {
1078     GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
1079     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
1080                                                          SkImageInfo::MakeN32Premul(1, 1),
1081                                                          gProps,
1082                                                          0));
1083     test_xfermode_cropped_input(device, reporter);
1084 }
1085
1086 DEF_GPUTEST(TestNegativeBlurSigmaGPU, reporter, factory) {
1087     GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
1088     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
1089                                                          SkImageInfo::MakeN32Premul(1, 1),
1090                                                          gProps,
1091                                                          0));
1092     test_negative_blur_sigma(device, reporter);
1093 }
1094 #endif