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 "SkBicubicImageFilter.h"
      9 #include "SkBitmap.h"
     10 #include "SkBitmapDevice.h"
     11 #include "SkBitmapSource.h"
     12 #include "SkBlurImageFilter.h"
     13 #include "SkCanvas.h"
     14 #include "SkColorFilterImageFilter.h"
     15 #include "SkColorMatrixFilter.h"
     16 #include "SkDeviceImageFilterProxy.h"
     17 #include "SkDisplacementMapEffect.h"
     18 #include "SkDropShadowImageFilter.h"
     19 #include "SkFlattenableBuffers.h"
     20 #include "SkFlattenableSerialization.h"
     21 #include "SkGradientShader.h"
     22 #include "SkLightingImageFilter.h"
     23 #include "SkMatrixConvolutionImageFilter.h"
     24 #include "SkMatrixImageFilter.h"
     25 #include "SkMergeImageFilter.h"
     26 #include "SkMorphologyImageFilter.h"
     27 #include "SkOffsetImageFilter.h"
     28 #include "SkPicture.h"
     29 #include "SkPictureImageFilter.h"
     30 #include "SkPictureRecorder.h"
     31 #include "SkRect.h"
     32 #include "SkTileImageFilter.h"
     33 #include "SkXfermodeImageFilter.h"
     34 #include "Test.h"
     35 
     36 #if SK_SUPPORT_GPU
     37 #include "GrContextFactory.h"
     38 #include "SkGpuDevice.h"
     39 #endif
     40 
     41 static const int kBitmapSize = 4;
     42 
     43 namespace {
     44 
     45 class MatrixTestImageFilter : public SkImageFilter {
     46 public:
     47     MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
     48       : SkImageFilter(0), fReporter(reporter), fExpectedMatrix(expectedMatrix) {
     49     }
     50 
     51     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context& ctx,
     52                                SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE {
     53         REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
     54         return true;
     55     }
     56 
     57     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(MatrixTestImageFilter)
     58 
     59 protected:
     60     explicit MatrixTestImageFilter(SkReadBuffer& buffer) : SkImageFilter(0) {
     61         fReporter = static_cast<skiatest::Reporter*>(buffer.readFunctionPtr());
     62         buffer.readMatrix(&fExpectedMatrix);
     63     }
     64 
     65     virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
     66         buffer.writeFunctionPtr(fReporter);
     67         buffer.writeMatrix(fExpectedMatrix);
     68     }
     69 
     70 private:
     71     skiatest::Reporter* fReporter;
     72     SkMatrix fExpectedMatrix;
     73 };
     74 
     75 }
     76 
     77 static void make_small_bitmap(SkBitmap& bitmap) {
     78     bitmap.allocN32Pixels(kBitmapSize, kBitmapSize);
     79     SkCanvas canvas(bitmap);
     80     canvas.clear(0x00000000);
     81     SkPaint darkPaint;
     82     darkPaint.setColor(0xFF804020);
     83     SkPaint lightPaint;
     84     lightPaint.setColor(0xFF244484);
     85     const int i = kBitmapSize / 4;
     86     for (int y = 0; y < kBitmapSize; y += i) {
     87         for (int x = 0; x < kBitmapSize; x += i) {
     88             canvas.save();
     89             canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
     90             canvas.drawRect(SkRect::MakeXYWH(0, 0,
     91                                              SkIntToScalar(i),
     92                                              SkIntToScalar(i)), darkPaint);
     93             canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
     94                                              0,
     95                                              SkIntToScalar(i),
     96                                              SkIntToScalar(i)), lightPaint);
     97             canvas.drawRect(SkRect::MakeXYWH(0,
     98                                              SkIntToScalar(i),
     99                                              SkIntToScalar(i),
    100                                              SkIntToScalar(i)), lightPaint);
    101             canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
    102                                              SkIntToScalar(i),
    103                                              SkIntToScalar(i),
    104                                              SkIntToScalar(i)), darkPaint);
    105             canvas.restore();
    106         }
    107     }
    108 }
    109 
    110 static SkImageFilter* make_scale(float amount, SkImageFilter* input = NULL) {
    111     SkScalar s = amount;
    112     SkScalar matrix[20] = { s, 0, 0, 0, 0,
    113                             0, s, 0, 0, 0,
    114                             0, 0, s, 0, 0,
    115                             0, 0, 0, s, 0 };
    116     SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
    117     return SkColorFilterImageFilter::Create(filter, input);
    118 }
    119 
    120 static SkImageFilter* make_grayscale(SkImageFilter* input = NULL, const SkImageFilter::CropRect* cropRect = NULL) {
    121     SkScalar matrix[20];
    122     memset(matrix, 0, 20 * sizeof(SkScalar));
    123     matrix[0] = matrix[5] = matrix[10] = 0.2126f;
    124     matrix[1] = matrix[6] = matrix[11] = 0.7152f;
    125     matrix[2] = matrix[7] = matrix[12] = 0.0722f;
    126     matrix[18] = 1.0f;
    127     SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
    128     return SkColorFilterImageFilter::Create(filter, input, cropRect);
    129 }
    130 
    131 DEF_TEST(ImageFilter, reporter) {
    132     {
    133         // Check that two non-clipping color matrices concatenate into a single filter.
    134         SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f));
    135         SkAutoTUnref<SkImageFilter> quarterBrightness(make_scale(0.5f, halfBrightness));
    136         REPORTER_ASSERT(reporter, NULL == quarterBrightness->getInput(0));
    137     }
    138 
    139     {
    140         // Check that a clipping color matrix followed by a grayscale does not concatenate into a single filter.
    141         SkAutoTUnref<SkImageFilter> doubleBrightness(make_scale(2.0f));
    142         SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f, doubleBrightness));
    143         REPORTER_ASSERT(reporter, NULL != halfBrightness->getInput(0));
    144     }
    145 
    146     {
    147         // Check that a color filter image filter without a crop rect can be
    148         // expressed as a color filter.
    149         SkAutoTUnref<SkImageFilter> gray(make_grayscale());
    150         REPORTER_ASSERT(reporter, true == gray->asColorFilter(NULL));
    151     }
    152 
    153     {
    154         // Check that a color filter image filter with a crop rect cannot
    155         // be expressed as a color filter.
    156         SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100));
    157         SkAutoTUnref<SkImageFilter> grayWithCrop(make_grayscale(NULL, &cropRect));
    158         REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(NULL));
    159     }
    160 
    161     {
    162         // Check that two non-commutative matrices are concatenated in
    163         // the correct order.
    164         SkScalar blueToRedMatrix[20] = { 0 };
    165         blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
    166         SkScalar redToGreenMatrix[20] = { 0 };
    167         redToGreenMatrix[5] = redToGreenMatrix[18] = SK_Scalar1;
    168         SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix));
    169         SkAutoTUnref<SkImageFilter> filter1(SkColorFilterImageFilter::Create(blueToRed.get()));
    170         SkAutoTUnref<SkColorFilter> redToGreen(SkColorMatrixFilter::Create(redToGreenMatrix));
    171         SkAutoTUnref<SkImageFilter> filter2(SkColorFilterImageFilter::Create(redToGreen.get(), filter1.get()));
    172 
    173         SkBitmap result;
    174         result.allocN32Pixels(kBitmapSize, kBitmapSize);
    175 
    176         SkPaint paint;
    177         paint.setColor(SK_ColorBLUE);
    178         paint.setImageFilter(filter2.get());
    179         SkCanvas canvas(result);
    180         canvas.clear(0x0);
    181         SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
    182         canvas.drawRect(rect, paint);
    183         uint32_t pixel = *result.getAddr32(0, 0);
    184         // The result here should be green, since we have effectively shifted blue to green.
    185         REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    186     }
    187 
    188     {
    189         // Tests pass by not asserting
    190         SkBitmap bitmap, result;
    191         make_small_bitmap(bitmap);
    192         result.allocN32Pixels(kBitmapSize, kBitmapSize);
    193 
    194         {
    195             // This tests for :
    196             // 1 ) location at (0,0,1)
    197             SkPoint3 location(0, 0, SK_Scalar1);
    198             // 2 ) location and target at same value
    199             SkPoint3 target(location.fX, location.fY, location.fZ);
    200             // 3 ) large negative specular exponent value
    201             SkScalar specularExponent = -1000;
    202 
    203             SkAutoTUnref<SkImageFilter> bmSrc(SkBitmapSource::Create(bitmap));
    204             SkPaint paint;
    205             paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(
    206                     location, target, specularExponent, 180,
    207                     0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
    208                     bmSrc))->unref();
    209             SkCanvas canvas(result);
    210             SkRect r = SkRect::MakeWH(SkIntToScalar(kBitmapSize),
    211                                       SkIntToScalar(kBitmapSize));
    212             canvas.drawRect(r, paint);
    213         }
    214 
    215         {
    216             // This tests for scale bringing width to 0
    217             SkSize scale = SkSize::Make(-0.001f, SK_Scalar1);
    218             SkAutoTUnref<SkImageFilter> bmSrc(SkBitmapSource::Create(bitmap));
    219             SkAutoTUnref<SkBicubicImageFilter> bicubic(
    220                 SkBicubicImageFilter::CreateMitchell(scale, bmSrc));
    221             SkBitmapDevice device(bitmap);
    222             SkDeviceImageFilterProxy proxy(&device);
    223             SkIPoint loc = SkIPoint::Make(0, 0);
    224             // An empty input should early return and return false
    225             SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(2));
    226             SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeEmpty(), cache.get());
    227             REPORTER_ASSERT(reporter,
    228                             !bicubic->filterImage(&proxy, bitmap, ctx, &result, &loc));
    229         }
    230     }
    231 }
    232 
    233 static void test_crop_rects(SkBaseDevice* device, skiatest::Reporter* reporter) {
    234     // Check that all filters offset to their absolute crop rect,
    235     // unaffected by the input crop rect.
    236     // Tests pass by not asserting.
    237     SkBitmap bitmap;
    238     bitmap.allocN32Pixels(100, 100);
    239     bitmap.eraseARGB(0, 0, 0, 0);
    240     SkDeviceImageFilterProxy proxy(device);
    241 
    242     SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
    243     SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
    244     SkAutoTUnref<SkImageFilter> input(make_grayscale(NULL, &inputCropRect));
    245 
    246     SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
    247     SkPoint3 location(0, 0, SK_Scalar1);
    248     SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
    249     SkScalar kernel[9] = {
    250         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
    251         SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
    252         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
    253     };
    254     SkISize kernelSize = SkISize::Make(3, 3);
    255     SkScalar gain = SK_Scalar1, bias = 0;
    256 
    257     SkImageFilter* filters[] = {
    258         SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
    259         SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType,
    260                                         SkDisplacementMapEffect::kB_ChannelSelectorType,
    261                                         40.0f, input.get(), input.get(), &cropRect),
    262         SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
    263         SkDropShadowImageFilter::Create(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input.get(), &cropRect),
    264         SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
    265         SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
    266         SkMatrixConvolutionImageFilter::Create(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
    267         SkMergeImageFilter::Create(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
    268         SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
    269         SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
    270         SkDilateImageFilter::Create(3, 2, input.get(), &cropRect),
    271         SkErodeImageFilter::Create(2, 3, input.get(), &cropRect),
    272         SkTileImageFilter::Create(inputCropRect.rect(), cropRect.rect(), input.get()),
    273         SkXfermodeImageFilter::Create(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
    274     };
    275 
    276     for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
    277         SkImageFilter* filter = filters[i];
    278         SkBitmap result;
    279         SkIPoint offset;
    280         SkString str;
    281         str.printf("filter %d", static_cast<int>(i));
    282         SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(2));
    283         SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), cache.get());
    284         REPORTER_ASSERT_MESSAGE(reporter, filter->filterImage(&proxy, bitmap, ctx,
    285                                 &result, &offset), str.c_str());
    286         REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str());
    287     }
    288 
    289     for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
    290         SkSafeUnref(filters[i]);
    291     }
    292 }
    293 
    294 static SkBitmap make_gradient_circle(int width, int height) {
    295     SkBitmap bitmap;
    296     SkScalar x = SkIntToScalar(width / 2);
    297     SkScalar y = SkIntToScalar(height / 2);
    298     SkScalar radius = SkMinScalar(x, y) * 0.8f;
    299     bitmap.allocN32Pixels(width, height);
    300     SkCanvas canvas(bitmap);
    301     canvas.clear(0x00000000);
    302     SkColor colors[2];
    303     colors[0] = SK_ColorWHITE;
    304     colors[1] = SK_ColorBLACK;
    305     SkAutoTUnref<SkShader> shader(
    306         SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, NULL, 2,
    307                                        SkShader::kClamp_TileMode)
    308     );
    309     SkPaint paint;
    310     paint.setShader(shader);
    311     canvas.drawCircle(x, y, radius, paint);
    312     return bitmap;
    313 }
    314 
    315 DEF_TEST(ImageFilterDrawTiled, reporter) {
    316     // Check that all filters when drawn tiled (with subsequent clip rects) exactly
    317     // match the same filters drawn with a single full-canvas bitmap draw.
    318     // Tests pass by not asserting.
    319 
    320     SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
    321     SkPoint3 location(0, 0, SK_Scalar1);
    322     SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
    323     SkScalar kernel[9] = {
    324         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
    325         SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
    326         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
    327     };
    328     SkISize kernelSize = SkISize::Make(3, 3);
    329     SkScalar gain = SK_Scalar1, bias = 0;
    330     SkScalar five = SkIntToScalar(5);
    331 
    332     SkAutoTUnref<SkImageFilter> gradient_source(SkBitmapSource::Create(make_gradient_circle(64, 64)));
    333     SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(five, five));
    334     SkMatrix matrix;
    335 
    336     matrix.setTranslate(SK_Scalar1, SK_Scalar1);
    337     matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
    338 
    339     SkRTreeFactory factory;
    340     SkPictureRecorder recorder;
    341     SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0);
    342 
    343     SkPaint greenPaint;
    344     greenPaint.setColor(SK_ColorGREEN);
    345     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
    346     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    347     SkAutoTUnref<SkImageFilter> pictureFilter(SkPictureImageFilter::Create(picture.get()));
    348 
    349     struct {
    350         const char*    fName;
    351         SkImageFilter* fFilter;
    352     } filters[] = {
    353         { "color filter", SkColorFilterImageFilter::Create(cf.get()) },
    354         { "displacement map", SkDisplacementMapEffect::Create(
    355               SkDisplacementMapEffect::kR_ChannelSelectorType,
    356               SkDisplacementMapEffect::kB_ChannelSelectorType,
    357               20.0f, gradient_source.get()) },
    358         { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
    359         { "drop shadow", SkDropShadowImageFilter::Create(
    360               SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN) },
    361         { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse(
    362               location, SK_ColorGREEN, 0, 0) },
    363         { "specular lighting",
    364               SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) },
    365         { "matrix convolution",
    366               SkMatrixConvolutionImageFilter::Create(
    367                   kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
    368                   SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) },
    369         { "merge", SkMergeImageFilter::Create(NULL, NULL, SkXfermode::kSrcOver_Mode) },
    370         { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) },
    371         { "dilate", SkDilateImageFilter::Create(3, 2) },
    372         { "erode", SkErodeImageFilter::Create(2, 3) },
    373         { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50),
    374                                             SkRect::MakeXYWH(0, 0, 100, 100), NULL) },
    375         { "matrix", SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel) },
    376         { "blur and offset", SkOffsetImageFilter::Create(five, five, blur.get()) },
    377         { "picture and blur", SkBlurImageFilter::Create(five, five, pictureFilter.get()) },
    378     };
    379 
    380     SkBitmap untiledResult, tiledResult;
    381     int width = 64, height = 64;
    382     untiledResult.allocN32Pixels(width, height);
    383     tiledResult.allocN32Pixels(width, height);
    384     SkCanvas tiledCanvas(tiledResult);
    385     SkCanvas untiledCanvas(untiledResult);
    386     int tileSize = 8;
    387 
    388     for (int scale = 1; scale <= 2; ++scale) {
    389         for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
    390             tiledCanvas.clear(0);
    391             untiledCanvas.clear(0);
    392             SkPaint paint;
    393             paint.setImageFilter(filters[i].fFilter);
    394             paint.setTextSize(SkIntToScalar(height));
    395             paint.setColor(SK_ColorWHITE);
    396             SkString str;
    397             const char* text = "ABC";
    398             SkScalar ypos = SkIntToScalar(height);
    399             untiledCanvas.save();
    400             untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
    401             untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
    402             untiledCanvas.restore();
    403             for (int y = 0; y < height; y += tileSize) {
    404                 for (int x = 0; x < width; x += tileSize) {
    405                     tiledCanvas.save();
    406                     tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
    407                     tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
    408                     tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
    409                     tiledCanvas.restore();
    410                 }
    411             }
    412             untiledCanvas.flush();
    413             tiledCanvas.flush();
    414             for (int y = 0; y < height; y++) {
    415                 int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
    416                 REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
    417                 if (diffs) {
    418                     break;
    419                 }
    420             }
    421         }
    422     }
    423 
    424     for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
    425         SkSafeUnref(filters[i].fFilter);
    426     }
    427 }
    428 
    429 DEF_TEST(ImageFilterMatrixConvolution, reporter) {
    430     // Check that a 1x3 filter does not cause a spurious assert.
    431     SkScalar kernel[3] = {
    432         SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
    433     };
    434     SkISize kernelSize = SkISize::Make(1, 3);
    435     SkScalar gain = SK_Scalar1, bias = 0;
    436     SkIPoint kernelOffset = SkIPoint::Make(0, 0);
    437 
    438     SkAutoTUnref<SkImageFilter> filter(
    439         SkMatrixConvolutionImageFilter::Create(
    440             kernelSize, kernel, gain, bias, kernelOffset,
    441             SkMatrixConvolutionImageFilter::kRepeat_TileMode, false));
    442 
    443     SkBitmap result;
    444     int width = 16, height = 16;
    445     result.allocN32Pixels(width, height);
    446     SkCanvas canvas(result);
    447     canvas.clear(0);
    448 
    449     SkPaint paint;
    450     paint.setImageFilter(filter);
    451     SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
    452     canvas.drawRect(rect, paint);
    453 }
    454 
    455 DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
    456     // Check that a filter with borders outside the target bounds
    457     // does not crash.
    458     SkScalar kernel[3] = {
    459         0, 0, 0,
    460     };
    461     SkISize kernelSize = SkISize::Make(3, 1);
    462     SkScalar gain = SK_Scalar1, bias = 0;
    463     SkIPoint kernelOffset = SkIPoint::Make(2, 0);
    464 
    465     SkAutoTUnref<SkImageFilter> filter(
    466         SkMatrixConvolutionImageFilter::Create(
    467             kernelSize, kernel, gain, bias, kernelOffset,
    468             SkMatrixConvolutionImageFilter::kClamp_TileMode, true));
    469 
    470     SkBitmap result;
    471 
    472     int width = 10, height = 10;
    473     result.allocN32Pixels(width, height);
    474     SkCanvas canvas(result);
    475     canvas.clear(0);
    476 
    477     SkPaint filterPaint;
    478     filterPaint.setImageFilter(filter);
    479     SkRect bounds = SkRect::MakeWH(1, 10);
    480     SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
    481     SkPaint rectPaint;
    482     canvas.saveLayer(&bounds, &filterPaint);
    483     canvas.drawRect(rect, rectPaint);
    484     canvas.restore();
    485 }
    486 
    487 DEF_TEST(ImageFilterCropRect, reporter) {
    488     SkBitmap temp;
    489     temp.allocN32Pixels(100, 100);
    490     SkBitmapDevice device(temp);
    491     test_crop_rects(&device, reporter);
    492 }
    493 
    494 DEF_TEST(ImageFilterMatrixTest, reporter) {
    495     SkBitmap temp;
    496     temp.allocN32Pixels(100, 100);
    497     SkBitmapDevice device(temp);
    498     SkCanvas canvas(&device);
    499     canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
    500 
    501     SkMatrix expectedMatrix = canvas.getTotalMatrix();
    502 
    503     SkRTreeFactory factory;
    504     SkPictureRecorder recorder;
    505     SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
    506 
    507     SkPaint paint;
    508     SkAutoTUnref<MatrixTestImageFilter> imageFilter(
    509         new MatrixTestImageFilter(reporter, expectedMatrix));
    510     paint.setImageFilter(imageFilter.get());
    511     recordingCanvas->saveLayer(NULL, &paint);
    512     SkPaint solidPaint;
    513     solidPaint.setColor(0xFFFFFFFF);
    514     recordingCanvas->save();
    515     recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
    516     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
    517     recordingCanvas->restore(); // scale
    518     recordingCanvas->restore(); // saveLayer
    519     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    520 
    521     canvas.drawPicture(picture);
    522 }
    523 
    524 DEF_TEST(ImageFilterPictureImageFilterTest, reporter) {
    525 
    526     SkRTreeFactory factory;
    527     SkPictureRecorder recorder;
    528     SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
    529 
    530     // Create an SkPicture which simply draws a green 1x1 rectangle.
    531     SkPaint greenPaint;
    532     greenPaint.setColor(SK_ColorGREEN);
    533     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
    534     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    535 
    536     // Wrap that SkPicture in an SkPictureImageFilter.
    537     SkAutoTUnref<SkImageFilter> imageFilter(
    538         SkPictureImageFilter::Create(picture.get()));
    539 
    540     // Check that SkPictureImageFilter successfully serializes its contained
    541     // SkPicture when not in cross-process mode.
    542     SkPaint paint;
    543     paint.setImageFilter(imageFilter.get());
    544     SkPictureRecorder outerRecorder;
    545     SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
    546     SkPaint redPaintWithFilter;
    547     redPaintWithFilter.setColor(SK_ColorRED);
    548     redPaintWithFilter.setImageFilter(imageFilter.get());
    549     outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
    550     SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording());
    551 
    552     SkBitmap bitmap;
    553     bitmap.allocN32Pixels(1, 1);
    554     SkBitmapDevice device(bitmap);
    555     SkCanvas canvas(&device);
    556 
    557     // The result here should be green, since the filter replaces the primitive's red interior.
    558     canvas.clear(0x0);
    559     canvas.drawPicture(outerPicture);
    560     uint32_t pixel = *bitmap.getAddr32(0, 0);
    561     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    562 
    563     // Check that, for now, SkPictureImageFilter does not serialize or
    564     // deserialize its contained picture when the filter is serialized
    565     // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
    566     SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
    567     SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
    568         data->data(), data->size(), SkImageFilter::GetFlattenableType()));
    569     SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
    570 
    571     redPaintWithFilter.setImageFilter(unflattenedFilter);
    572     SkPictureRecorder crossProcessRecorder;
    573     SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
    574     crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
    575     SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording());
    576 
    577     canvas.clear(0x0);
    578     canvas.drawPicture(crossProcessPicture);
    579     pixel = *bitmap.getAddr32(0, 0);
    580     // The result here should not be green, since the filter draws nothing.
    581     REPORTER_ASSERT(reporter, pixel != SK_ColorGREEN);
    582 }
    583 
    584 DEF_TEST(ImageFilterEmptySaveLayerTest, reporter) {
    585 
    586     // Even when there's an empty saveLayer()/restore(), ensure that an image
    587     // filter or color filter which affects transparent black still draws.
    588 
    589     SkBitmap bitmap;
    590     bitmap.allocN32Pixels(10, 10);
    591     SkBitmapDevice device(bitmap);
    592     SkCanvas canvas(&device);
    593 
    594     SkRTreeFactory factory;
    595     SkPictureRecorder recorder;
    596 
    597     SkAutoTUnref<SkColorFilter> green(
    598         SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode));
    599     SkAutoTUnref<SkColorFilterImageFilter> imageFilter(
    600         SkColorFilterImageFilter::Create(green.get()));
    601     SkPaint imageFilterPaint;
    602     imageFilterPaint.setImageFilter(imageFilter.get());
    603     SkPaint colorFilterPaint;
    604     colorFilterPaint.setColorFilter(green.get());
    605 
    606     SkRect bounds = SkRect::MakeWH(10, 10);
    607 
    608     SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
    609     recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
    610     recordingCanvas->restore();
    611     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
    612 
    613     canvas.clear(0);
    614     canvas.drawPicture(picture);
    615     uint32_t pixel = *bitmap.getAddr32(0, 0);
    616     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    617 
    618     recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
    619     recordingCanvas->saveLayer(NULL, &imageFilterPaint);
    620     recordingCanvas->restore();
    621     SkAutoTUnref<SkPicture> picture2(recorder.endRecording());
    622 
    623     canvas.clear(0);
    624     canvas.drawPicture(picture2);
    625     pixel = *bitmap.getAddr32(0, 0);
    626     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    627 
    628     recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
    629     recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
    630     recordingCanvas->restore();
    631     SkAutoTUnref<SkPicture> picture3(recorder.endRecording());
    632 
    633     canvas.clear(0);
    634     canvas.drawPicture(picture3);
    635     pixel = *bitmap.getAddr32(0, 0);
    636     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    637 }
    638 
    639 static void test_huge_blur(SkBaseDevice* device, skiatest::Reporter* reporter) {
    640     SkCanvas canvas(device);
    641 
    642     SkBitmap bitmap;
    643     bitmap.allocN32Pixels(100, 100);
    644     bitmap.eraseARGB(0, 0, 0, 0);
    645 
    646     // Check that a blur with an insane radius does not crash or assert.
    647     SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(SkIntToScalar(1<<30), SkIntToScalar(1<<30)));
    648 
    649     SkPaint paint;
    650     paint.setImageFilter(blur);
    651     canvas.drawSprite(bitmap, 0, 0, &paint);
    652 }
    653 
    654 DEF_TEST(HugeBlurImageFilter, reporter) {
    655     SkBitmap temp;
    656     temp.allocN32Pixels(100, 100);
    657     SkBitmapDevice device(temp);
    658     test_huge_blur(&device, reporter);
    659 }
    660 
    661 static void test_xfermode_cropped_input(SkBaseDevice* device, skiatest::Reporter* reporter) {
    662     SkCanvas canvas(device);
    663     canvas.clear(0);
    664 
    665     SkBitmap bitmap;
    666     bitmap.allocN32Pixels(1, 1);
    667     bitmap.eraseARGB(255, 255, 255, 255);
    668 
    669     SkAutoTUnref<SkColorFilter> green(
    670         SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode));
    671     SkAutoTUnref<SkColorFilterImageFilter> greenFilter(
    672         SkColorFilterImageFilter::Create(green.get()));
    673     SkImageFilter::CropRect cropRect(SkRect::MakeEmpty());
    674     SkAutoTUnref<SkColorFilterImageFilter> croppedOut(
    675         SkColorFilterImageFilter::Create(green.get(), NULL, &cropRect));
    676 
    677     // Check that an xfermode image filter whose input has been cropped out still draws the other
    678     // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
    679     SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode);
    680     SkAutoTUnref<SkImageFilter> xfermodeNoFg(
    681         SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut));
    682     SkAutoTUnref<SkImageFilter> xfermodeNoBg(
    683         SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter));
    684     SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg(
    685         SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut));
    686 
    687     SkPaint paint;
    688     paint.setImageFilter(xfermodeNoFg);
    689     canvas.drawSprite(bitmap, 0, 0, &paint);
    690 
    691     uint32_t pixel;
    692     SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
    693     canvas.readPixels(info, &pixel, 4, 0, 0);
    694     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    695 
    696     paint.setImageFilter(xfermodeNoBg);
    697     canvas.drawSprite(bitmap, 0, 0, &paint);
    698     canvas.readPixels(info, &pixel, 4, 0, 0);
    699     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    700 
    701     paint.setImageFilter(xfermodeNoFgNoBg);
    702     canvas.drawSprite(bitmap, 0, 0, &paint);
    703     canvas.readPixels(info, &pixel, 4, 0, 0);
    704     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    705 }
    706 
    707 DEF_TEST(ImageFilterNestedSaveLayer, reporter) {
    708     SkBitmap temp;
    709     temp.allocN32Pixels(50, 50);
    710     SkBitmapDevice device(temp);
    711     SkCanvas canvas(&device);
    712     canvas.clear(0x0);
    713 
    714     SkBitmap bitmap;
    715     bitmap.allocN32Pixels(10, 10);
    716     bitmap.eraseColor(SK_ColorGREEN);
    717 
    718     SkMatrix matrix;
    719     matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
    720     matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
    721     SkAutoTUnref<SkImageFilter> matrixFilter(
    722         SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel));
    723 
    724     // Test that saveLayer() with a filter nested inside another saveLayer() applies the
    725     // correct offset to the filter matrix.
    726     SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
    727     canvas.saveLayer(&bounds1, NULL);
    728     SkPaint filterPaint;
    729     filterPaint.setImageFilter(matrixFilter);
    730     SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
    731     canvas.saveLayer(&bounds2, &filterPaint);
    732     SkPaint greenPaint;
    733     greenPaint.setColor(SK_ColorGREEN);
    734     canvas.drawRect(bounds2, greenPaint);
    735     canvas.restore();
    736     canvas.restore();
    737     SkPaint strokePaint;
    738     strokePaint.setStyle(SkPaint::kStroke_Style);
    739     strokePaint.setColor(SK_ColorRED);
    740 
    741     SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
    742     uint32_t pixel;
    743     canvas.readPixels(info, &pixel, 4, 25, 25);
    744     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    745 
    746     // Test that drawSprite() with a filter nested inside a saveLayer() applies the
    747     // correct offset to the filter matrix.
    748     canvas.clear(0x0);
    749     canvas.readPixels(info, &pixel, 4, 25, 25);
    750     canvas.saveLayer(&bounds1, NULL);
    751     canvas.drawSprite(bitmap, 20, 20, &filterPaint);
    752     canvas.restore();
    753 
    754     canvas.readPixels(info, &pixel, 4, 25, 25);
    755     REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
    756 }
    757 
    758 DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
    759     SkBitmap temp;
    760     temp.allocN32Pixels(100, 100);
    761     SkBitmapDevice device(temp);
    762     test_xfermode_cropped_input(&device, reporter);
    763 }
    764 
    765 #if SK_SUPPORT_GPU
    766 DEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) {
    767     GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
    768     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
    769                                                          SkImageInfo::MakeN32Premul(100, 100),
    770                                                          0));
    771     test_crop_rects(device, reporter);
    772 }
    773 
    774 DEF_GPUTEST(HugeBlurImageFilterGPU, reporter, factory) {
    775     GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
    776     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
    777                                                          SkImageInfo::MakeN32Premul(100, 100),
    778                                                          0));
    779     test_huge_blur(device, reporter);
    780 }
    781 
    782 DEF_GPUTEST(XfermodeImageFilterCroppedInputGPU, reporter, factory) {
    783     GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
    784     SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
    785                                                          SkImageInfo::MakeN32Premul(1, 1),
    786                                                          0));
    787     test_xfermode_cropped_input(device, reporter);
    788 }
    789 #endif
    790