Home | History | Annotate | Download | only in tests
      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
   1095