1194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org/*
2194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org * Copyright 2013 Google Inc.
3194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org *
4194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be
5194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org * found in the LICENSE file.
6194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org */
7194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
84b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org#include "SkBicubicImageFilter.h"
94b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org#include "SkBitmap.h"
104b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org#include "SkBitmapDevice.h"
114b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org#include "SkBitmapSource.h"
128f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkBlurImageFilter.h"
134b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org#include "SkCanvas.h"
14194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org#include "SkColorFilterImageFilter.h"
158f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkColorMatrixFilter.h"
164b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org#include "SkDeviceImageFilterProxy.h"
176776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkDisplacementMapEffect.h"
186776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkDropShadowImageFilter.h"
195251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org#include "SkFlattenableBuffers.h"
2097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org#include "SkFlattenableSerialization.h"
210a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org#include "SkGradientShader.h"
224b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org#include "SkLightingImageFilter.h"
238f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkMatrixConvolutionImageFilter.h"
24d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org#include "SkMatrixImageFilter.h"
256776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkMergeImageFilter.h"
266776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkMorphologyImageFilter.h"
276776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkOffsetImageFilter.h"
285251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org#include "SkPicture.h"
29910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org#include "SkPictureImageFilter.h"
30770963f23f4fc313db0fa3bac18b1b8aafb55f17robertphillips@google.com#include "SkPictureRecorder.h"
318f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkRect.h"
326776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkTileImageFilter.h"
336776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkXfermodeImageFilter.h"
348f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h"
35194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
36aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org#if SK_SUPPORT_GPU
37aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org#include "GrContextFactory.h"
38aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org#include "SkGpuDevice.h"
39aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org#endif
40aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
419f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.orgstatic const int kBitmapSize = 4;
429f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
435251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgnamespace {
445251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
455251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgclass MatrixTestImageFilter : public SkImageFilter {
465251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgpublic:
475251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
485251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org      : SkImageFilter(0), fReporter(reporter), fExpectedMatrix(expectedMatrix) {
495251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    }
505251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
514cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context& ctx,
520937335e6b051150e9a42fc685659bac570b0c51senorblanco@chromium.org                               SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE {
534cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
545251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org        return true;
555251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    }
565251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
575251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(MatrixTestImageFilter)
585251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
595251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgprotected:
605251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    explicit MatrixTestImageFilter(SkReadBuffer& buffer) : SkImageFilter(0) {
615251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org        fReporter = static_cast<skiatest::Reporter*>(buffer.readFunctionPtr());
625251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org        buffer.readMatrix(&fExpectedMatrix);
635251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    }
645251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
655251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
665251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org        buffer.writeFunctionPtr(fReporter);
675251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org        buffer.writeMatrix(fExpectedMatrix);
685251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    }
695251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
705251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgprivate:
715251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    skiatest::Reporter* fReporter;
725251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkMatrix fExpectedMatrix;
735251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org};
745251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
755251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org}
765251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
779f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.orgstatic void make_small_bitmap(SkBitmap& bitmap) {
78deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    bitmap.allocN32Pixels(kBitmapSize, kBitmapSize);
79deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    SkCanvas canvas(bitmap);
809f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    canvas.clear(0x00000000);
819f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkPaint darkPaint;
829f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    darkPaint.setColor(0xFF804020);
839f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkPaint lightPaint;
849f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    lightPaint.setColor(0xFF244484);
859f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    const int i = kBitmapSize / 4;
869f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    for (int y = 0; y < kBitmapSize; y += i) {
879f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        for (int x = 0; x < kBitmapSize; x += i) {
889f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            canvas.save();
899f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
909f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            canvas.drawRect(SkRect::MakeXYWH(0, 0,
919f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
929f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i)), darkPaint);
939f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
949f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             0,
959f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
969f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i)), lightPaint);
979f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            canvas.drawRect(SkRect::MakeXYWH(0,
989f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
999f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
1009f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i)), lightPaint);
1019f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
1029f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
1039f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
1049f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i)), darkPaint);
1059f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            canvas.restore();
1064b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org        }
1074b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org    }
1089f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org}
1099f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
1109f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.orgstatic SkImageFilter* make_scale(float amount, SkImageFilter* input = NULL) {
1119f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkScalar s = amount;
1129f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkScalar matrix[20] = { s, 0, 0, 0, 0,
1139f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                            0, s, 0, 0, 0,
1149f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                            0, 0, s, 0, 0,
1159f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                            0, 0, 0, s, 0 };
116727a352f7412753d2a3e4d30eab6500a1a4de135commit-bot@chromium.org    SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
1179f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    return SkColorFilterImageFilter::Create(filter, input);
1189f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org}
1199f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
1209f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.orgstatic SkImageFilter* make_grayscale(SkImageFilter* input = NULL, const SkImageFilter::CropRect* cropRect = NULL) {
1219f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkScalar matrix[20];
1229f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    memset(matrix, 0, 20 * sizeof(SkScalar));
1239f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    matrix[0] = matrix[5] = matrix[10] = 0.2126f;
1249f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    matrix[1] = matrix[6] = matrix[11] = 0.7152f;
1259f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    matrix[2] = matrix[7] = matrix[12] = 0.0722f;
1269f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    matrix[18] = 1.0f;
127727a352f7412753d2a3e4d30eab6500a1a4de135commit-bot@chromium.org    SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
1289f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    return SkColorFilterImageFilter::Create(filter, input, cropRect);
1299f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org}
1309f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
1319f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.orgDEF_TEST(ImageFilter, reporter) {
1329f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
1339f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // Check that two non-clipping color matrices concatenate into a single filter.
1349f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f));
1359f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        SkAutoTUnref<SkImageFilter> quarterBrightness(make_scale(0.5f, halfBrightness));
1369f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        REPORTER_ASSERT(reporter, NULL == quarterBrightness->getInput(0));
137194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
138194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
1399f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
1409f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // Check that a clipping color matrix followed by a grayscale does not concatenate into a single filter.
1419f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        SkAutoTUnref<SkImageFilter> doubleBrightness(make_scale(2.0f));
1429f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f, doubleBrightness));
1439f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        REPORTER_ASSERT(reporter, NULL != halfBrightness->getInput(0));
144194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
145194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
1469f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
1479f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // Check that a color filter image filter without a crop rect can be
1489f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // expressed as a color filter.
1499f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        SkAutoTUnref<SkImageFilter> gray(make_grayscale());
1509f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        REPORTER_ASSERT(reporter, true == gray->asColorFilter(NULL));
151194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
152194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
1539f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
1549f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // Check that a color filter image filter with a crop rect cannot
1559f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // be expressed as a color filter.
1569f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100));
1579f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        SkAutoTUnref<SkImageFilter> grayWithCrop(make_grayscale(NULL, &cropRect));
1589f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(NULL));
1599f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    }
160194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
1619f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
1629ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        // Check that two non-commutative matrices are concatenated in
1639ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        // the correct order.
1649ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkScalar blueToRedMatrix[20] = { 0 };
1659ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
1669ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkScalar redToGreenMatrix[20] = { 0 };
1679ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        redToGreenMatrix[5] = redToGreenMatrix[18] = SK_Scalar1;
1689ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix));
1699ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkAutoTUnref<SkImageFilter> filter1(SkColorFilterImageFilter::Create(blueToRed.get()));
1709ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkAutoTUnref<SkColorFilter> redToGreen(SkColorMatrixFilter::Create(redToGreenMatrix));
1719ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkAutoTUnref<SkImageFilter> filter2(SkColorFilterImageFilter::Create(redToGreen.get(), filter1.get()));
1729ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger
1739ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkBitmap result;
1749ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        result.allocN32Pixels(kBitmapSize, kBitmapSize);
1759ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger
1769ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkPaint paint;
1779ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        paint.setColor(SK_ColorBLUE);
1789ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        paint.setImageFilter(filter2.get());
1799ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkCanvas canvas(result);
1809ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        canvas.clear(0x0);
1819ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
1829ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        canvas.drawRect(rect, paint);
1839ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        uint32_t pixel = *result.getAddr32(0, 0);
1849ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        // The result here should be green, since we have effectively shifted blue to green.
1859ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger        REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1869ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger    }
1879ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger
1889ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger    {
1899f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // Tests pass by not asserting
1909f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        SkBitmap bitmap, result;
1919f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        make_small_bitmap(bitmap);
192deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org        result.allocN32Pixels(kBitmapSize, kBitmapSize);
193194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
194194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        {
1959f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // This tests for :
1969f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // 1 ) location at (0,0,1)
1979f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkPoint3 location(0, 0, SK_Scalar1);
1989f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // 2 ) location and target at same value
1999f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkPoint3 target(location.fX, location.fY, location.fZ);
2009f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // 3 ) large negative specular exponent value
2019f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkScalar specularExponent = -1000;
2029f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
203cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org            SkAutoTUnref<SkImageFilter> bmSrc(SkBitmapSource::Create(bitmap));
2049f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkPaint paint;
2059f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(
2069f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                    location, target, specularExponent, 180,
2079f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                    0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
2089f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                    bmSrc))->unref();
2099f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkCanvas canvas(result);
2109f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkRect r = SkRect::MakeWH(SkIntToScalar(kBitmapSize),
2119f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                      SkIntToScalar(kBitmapSize));
2129f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            canvas.drawRect(r, paint);
213194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        }
2144b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org
2154b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org        {
2169f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // This tests for scale bringing width to 0
2179f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkSize scale = SkSize::Make(-0.001f, SK_Scalar1);
218cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org            SkAutoTUnref<SkImageFilter> bmSrc(SkBitmapSource::Create(bitmap));
2199f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkAutoTUnref<SkBicubicImageFilter> bicubic(
2209f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                SkBicubicImageFilter::CreateMitchell(scale, bmSrc));
2219f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkBitmapDevice device(bitmap);
2229f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkDeviceImageFilterProxy proxy(&device);
2239f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkIPoint loc = SkIPoint::Make(0, 0);
2249f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // An empty input should early return and return false
225f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(2));
226f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeEmpty(), cache.get());
2279f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            REPORTER_ASSERT(reporter,
2284cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                            !bicubic->filterImage(&proxy, bitmap, ctx, &result, &loc));
2294b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org        }
230194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
231aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org}
2326776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org
233aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.orgstatic void test_crop_rects(SkBaseDevice* device, skiatest::Reporter* reporter) {
234aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    // Check that all filters offset to their absolute crop rect,
235aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    // unaffected by the input crop rect.
236aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    // Tests pass by not asserting.
237aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkBitmap bitmap;
238deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    bitmap.allocN32Pixels(100, 100);
239aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    bitmap.eraseARGB(0, 0, 0, 0);
240aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkDeviceImageFilterProxy proxy(device);
241aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
242aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
243aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
244aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkAutoTUnref<SkImageFilter> input(make_grayscale(NULL, &inputCropRect));
245aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
246aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
247aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkPoint3 location(0, 0, SK_Scalar1);
248aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
249aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkScalar kernel[9] = {
250aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
251aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
252aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
253aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    };
254aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkISize kernelSize = SkISize::Make(3, 3);
255aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkScalar gain = SK_Scalar1, bias = 0;
256aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
257aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkImageFilter* filters[] = {
258aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
259cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType,
260cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org                                        SkDisplacementMapEffect::kB_ChannelSelectorType,
261cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org                                        40.0f, input.get(), input.get(), &cropRect),
262cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
263cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkDropShadowImageFilter::Create(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input.get(), &cropRect),
264aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
265aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
266cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkMatrixConvolutionImageFilter::Create(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
267cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkMergeImageFilter::Create(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
268cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
269cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
270cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkDilateImageFilter::Create(3, 2, input.get(), &cropRect),
271cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkErodeImageFilter::Create(2, 3, input.get(), &cropRect),
272cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkTileImageFilter::Create(inputCropRect.rect(), cropRect.rect(), input.get()),
273cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org        SkXfermodeImageFilter::Create(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
274aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    };
275aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
276aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
277aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkImageFilter* filter = filters[i];
278aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkBitmap result;
279aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkIPoint offset;
280aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkString str;
281f4e1a7614da0cc3738077a1df5d8895a4df6d2f6senorblanco@chromium.org        str.printf("filter %d", static_cast<int>(i));
282f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(2));
283f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), cache.get());
284f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        REPORTER_ASSERT_MESSAGE(reporter, filter->filterImage(&proxy, bitmap, ctx,
285f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org                                &result, &offset), str.c_str());
286aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str());
287aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    }
2886776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org
289aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
290aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkSafeUnref(filters[i]);
2916776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    }
2929f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org}
293aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
2940a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.orgstatic SkBitmap make_gradient_circle(int width, int height) {
2950a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkBitmap bitmap;
2960a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkScalar x = SkIntToScalar(width / 2);
2970a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkScalar y = SkIntToScalar(height / 2);
2980a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkScalar radius = SkMinScalar(x, y) * 0.8f;
2990a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    bitmap.allocN32Pixels(width, height);
3000a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkCanvas canvas(bitmap);
3010a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    canvas.clear(0x00000000);
3020a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkColor colors[2];
3030a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    colors[0] = SK_ColorWHITE;
3040a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    colors[1] = SK_ColorBLACK;
3050a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkAutoTUnref<SkShader> shader(
3060a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, NULL, 2,
3070a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org                                       SkShader::kClamp_TileMode)
3080a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    );
3090a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkPaint paint;
3100a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    paint.setShader(shader);
3110a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    canvas.drawCircle(x, y, radius, paint);
3120a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    return bitmap;
3130a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org}
3140a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
3150a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.orgDEF_TEST(ImageFilterDrawTiled, reporter) {
3160a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    // Check that all filters when drawn tiled (with subsequent clip rects) exactly
3170a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    // match the same filters drawn with a single full-canvas bitmap draw.
3180a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    // Tests pass by not asserting.
3190a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
3200a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
3210a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkPoint3 location(0, 0, SK_Scalar1);
3220a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
3230a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkScalar kernel[9] = {
3240a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
3250a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
3260a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
3270a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    };
3280a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkISize kernelSize = SkISize::Make(3, 3);
3290a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkScalar gain = SK_Scalar1, bias = 0;
33029ac34ee526578fb0a01cd2d0c23c23e6a823d82senorblanco@chromium.org    SkScalar five = SkIntToScalar(5);
3310a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
3320a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkAutoTUnref<SkImageFilter> gradient_source(SkBitmapSource::Create(make_gradient_circle(64, 64)));
33329ac34ee526578fb0a01cd2d0c23c23e6a823d82senorblanco@chromium.org    SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(five, five));
334ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org    SkMatrix matrix;
33529ac34ee526578fb0a01cd2d0c23c23e6a823d82senorblanco@chromium.org
336ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org    matrix.setTranslate(SK_Scalar1, SK_Scalar1);
337ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org    matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
3380a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
339910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org    SkRTreeFactory factory;
340910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org    SkPictureRecorder recorder;
341910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org    SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0);
342910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org
343910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org    SkPaint greenPaint;
344910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org    greenPaint.setColor(SK_ColorGREEN);
345910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org    recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
346910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
347910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org    SkAutoTUnref<SkImageFilter> pictureFilter(SkPictureImageFilter::Create(picture.get()));
348910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org
3490a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    struct {
3500a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        const char*    fName;
3510a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        SkImageFilter* fFilter;
3520a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    } filters[] = {
3530a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "color filter", SkColorFilterImageFilter::Create(cf.get()) },
3540a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "displacement map", SkDisplacementMapEffect::Create(
3550a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org              SkDisplacementMapEffect::kR_ChannelSelectorType,
3560a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org              SkDisplacementMapEffect::kB_ChannelSelectorType,
357d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org              20.0f, gradient_source.get()) },
3580a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
3590a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "drop shadow", SkDropShadowImageFilter::Create(
3600a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org              SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN) },
3610a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse(
3620a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org              location, SK_ColorGREEN, 0, 0) },
3630a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "specular lighting",
3640a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org              SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) },
3650a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "matrix convolution",
3660a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org              SkMatrixConvolutionImageFilter::Create(
3670a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org                  kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
3680a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org                  SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) },
3690a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "merge", SkMergeImageFilter::Create(NULL, NULL, SkXfermode::kSrcOver_Mode) },
3700a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) },
3710a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "dilate", SkDilateImageFilter::Create(3, 2) },
3720a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "erode", SkErodeImageFilter::Create(2, 3) },
3730a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50),
3740a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org                                            SkRect::MakeXYWH(0, 0, 100, 100), NULL) },
375ba31f1d341bac57ca76a75d67f64434b4b371dc6senorblanco@chromium.org        { "matrix", SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel) },
37629ac34ee526578fb0a01cd2d0c23c23e6a823d82senorblanco@chromium.org        { "blur and offset", SkOffsetImageFilter::Create(five, five, blur.get()) },
377910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org        { "picture and blur", SkBlurImageFilter::Create(five, five, pictureFilter.get()) },
3780a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    };
3790a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
3800a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkBitmap untiledResult, tiledResult;
3810a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    int width = 64, height = 64;
3820a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    untiledResult.allocN32Pixels(width, height);
3830a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    tiledResult.allocN32Pixels(width, height);
3840a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkCanvas tiledCanvas(tiledResult);
3850a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkCanvas untiledCanvas(untiledResult);
386d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org    int tileSize = 8;
3870a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
388d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org    for (int scale = 1; scale <= 2; ++scale) {
389d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org        for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
390d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            tiledCanvas.clear(0);
391d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.clear(0);
392d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            SkPaint paint;
393d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            paint.setImageFilter(filters[i].fFilter);
394d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            paint.setTextSize(SkIntToScalar(height));
395d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            paint.setColor(SK_ColorWHITE);
396d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            SkString str;
397d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            const char* text = "ABC";
398d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            SkScalar ypos = SkIntToScalar(height);
399d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.save();
400d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
401d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
402d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.restore();
403d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            for (int y = 0; y < height; y += tileSize) {
404d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                for (int x = 0; x < width; x += tileSize) {
405d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.save();
406d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
407d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
408d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
409d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.restore();
410d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                }
4110a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org            }
412d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.flush();
413d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            tiledCanvas.flush();
414d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            for (int y = 0; y < height; y++) {
415d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
416d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
417d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                if (diffs) {
418d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    break;
419d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                }
4200a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org            }
4210a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        }
4220a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    }
4230a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
4240a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
4250a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        SkSafeUnref(filters[i].fFilter);
4260a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    }
4270a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org}
4280a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
4299195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.orgDEF_TEST(ImageFilterMatrixConvolution, reporter) {
4309195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    // Check that a 1x3 filter does not cause a spurious assert.
4319195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkScalar kernel[3] = {
4329195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org        SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
4339195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    };
4349195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkISize kernelSize = SkISize::Make(1, 3);
4359195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkScalar gain = SK_Scalar1, bias = 0;
4369195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkIPoint kernelOffset = SkIPoint::Make(0, 0);
4379195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org
4389195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkAutoTUnref<SkImageFilter> filter(
4399195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org        SkMatrixConvolutionImageFilter::Create(
4409195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org            kernelSize, kernel, gain, bias, kernelOffset,
4419195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org            SkMatrixConvolutionImageFilter::kRepeat_TileMode, false));
4429195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org
4439195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkBitmap result;
4449195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    int width = 16, height = 16;
4459195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    result.allocN32Pixels(width, height);
4469195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkCanvas canvas(result);
4479195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    canvas.clear(0);
4489195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org
4499195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkPaint paint;
4509195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    paint.setImageFilter(filter);
4519195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
4529195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    canvas.drawRect(rect, paint);
4539195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org}
4549195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org
4558c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.orgDEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
4568c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    // Check that a filter with borders outside the target bounds
4578c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    // does not crash.
4588c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkScalar kernel[3] = {
4598c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org        0, 0, 0,
4608c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    };
4618c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkISize kernelSize = SkISize::Make(3, 1);
4628c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkScalar gain = SK_Scalar1, bias = 0;
4638c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkIPoint kernelOffset = SkIPoint::Make(2, 0);
4648c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
4658c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkAutoTUnref<SkImageFilter> filter(
4668c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org        SkMatrixConvolutionImageFilter::Create(
4678c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org            kernelSize, kernel, gain, bias, kernelOffset,
4688c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org            SkMatrixConvolutionImageFilter::kClamp_TileMode, true));
4698c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
4708c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkBitmap result;
4718c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
4728c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    int width = 10, height = 10;
4738c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    result.allocN32Pixels(width, height);
4748c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkCanvas canvas(result);
4758c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    canvas.clear(0);
4768c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
4778c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkPaint filterPaint;
4788c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    filterPaint.setImageFilter(filter);
4798c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkRect bounds = SkRect::MakeWH(1, 10);
4808c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
4818c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkPaint rectPaint;
4828c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    canvas.saveLayer(&bounds, &filterPaint);
4838c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    canvas.drawRect(rect, rectPaint);
4848c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    canvas.restore();
4858c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org}
4868c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
487aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.orgDEF_TEST(ImageFilterCropRect, reporter) {
488aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkBitmap temp;
489deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    temp.allocN32Pixels(100, 100);
490aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkBitmapDevice device(temp);
491aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    test_crop_rects(&device, reporter);
492aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org}
493aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
4945251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgDEF_TEST(ImageFilterMatrixTest, reporter) {
4955251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkBitmap temp;
496deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    temp.allocN32Pixels(100, 100);
4975251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkBitmapDevice device(temp);
4985251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkCanvas canvas(&device);
4995251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
5005251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
5015251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkMatrix expectedMatrix = canvas.getTotalMatrix();
5025251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
5035fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkRTreeFactory factory;
5045fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkPictureRecorder recorder;
5055fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
5065251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
5075251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkPaint paint;
5085251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkAutoTUnref<MatrixTestImageFilter> imageFilter(
5095251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org        new MatrixTestImageFilter(reporter, expectedMatrix));
5105251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    paint.setImageFilter(imageFilter.get());
511091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org    recordingCanvas->saveLayer(NULL, &paint);
5125251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkPaint solidPaint;
5135251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    solidPaint.setColor(0xFFFFFFFF);
5145251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->save();
5155251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
5165251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
5175251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->restore(); // scale
5185251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->restore(); // saveLayer
51984b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
5205251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
5219b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(picture);
5225251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org}
5235251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
52497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.orgDEF_TEST(ImageFilterPictureImageFilterTest, reporter) {
52597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
52697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkRTreeFactory factory;
52797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPictureRecorder recorder;
52897f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
52997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
53097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // Create an SkPicture which simply draws a green 1x1 rectangle.
53197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPaint greenPaint;
53297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    greenPaint.setColor(SK_ColorGREEN);
53397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
53497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
53597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
53697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // Wrap that SkPicture in an SkPictureImageFilter.
53797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkAutoTUnref<SkImageFilter> imageFilter(
53897f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org        SkPictureImageFilter::Create(picture.get()));
53997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
54097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // Check that SkPictureImageFilter successfully serializes its contained
54197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // SkPicture when not in cross-process mode.
54297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPaint paint;
54397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    paint.setImageFilter(imageFilter.get());
54497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPictureRecorder outerRecorder;
54597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
54697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPaint redPaintWithFilter;
54797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    redPaintWithFilter.setColor(SK_ColorRED);
54897f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    redPaintWithFilter.setImageFilter(imageFilter.get());
54997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
55097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording());
55197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
55297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkBitmap bitmap;
55397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    bitmap.allocN32Pixels(1, 1);
55497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkBitmapDevice device(bitmap);
55597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkCanvas canvas(&device);
55697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
55797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // The result here should be green, since the filter replaces the primitive's red interior.
55897f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    canvas.clear(0x0);
5599b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(outerPicture);
56097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    uint32_t pixel = *bitmap.getAddr32(0, 0);
56197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
56297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
56397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // Check that, for now, SkPictureImageFilter does not serialize or
56497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // deserialize its contained picture when the filter is serialized
56597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
56697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
56797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
56897f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org        data->data(), data->size(), SkImageFilter::GetFlattenableType()));
56997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
57097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
57197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    redPaintWithFilter.setImageFilter(unflattenedFilter);
57297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPictureRecorder crossProcessRecorder;
57397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
57497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
57597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording());
57697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
57797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    canvas.clear(0x0);
5789b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(crossProcessPicture);
57997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    pixel = *bitmap.getAddr32(0, 0);
58097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // The result here should not be green, since the filter draws nothing.
58197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel != SK_ColorGREEN);
58297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org}
58397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
58468250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.orgDEF_TEST(ImageFilterEmptySaveLayerTest, reporter) {
58568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
58668250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    // Even when there's an empty saveLayer()/restore(), ensure that an image
58768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    // filter or color filter which affects transparent black still draws.
58868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
58968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkBitmap bitmap;
59068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    bitmap.allocN32Pixels(10, 10);
59168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkBitmapDevice device(bitmap);
59268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkCanvas canvas(&device);
59368250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
59468250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkRTreeFactory factory;
59568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkPictureRecorder recorder;
59668250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
59768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkAutoTUnref<SkColorFilter> green(
59868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org        SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode));
59968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkAutoTUnref<SkColorFilterImageFilter> imageFilter(
60068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org        SkColorFilterImageFilter::Create(green.get()));
60168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkPaint imageFilterPaint;
60268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    imageFilterPaint.setImageFilter(imageFilter.get());
60368250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkPaint colorFilterPaint;
60468250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    colorFilterPaint.setColorFilter(green.get());
60568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
60668250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkRect bounds = SkRect::MakeWH(10, 10);
60768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
60868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
60968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
61068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->restore();
61168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
61268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
61368250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    canvas.clear(0);
6149b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(picture);
61568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    uint32_t pixel = *bitmap.getAddr32(0, 0);
61668250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
61768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
61868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
61968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->saveLayer(NULL, &imageFilterPaint);
62068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->restore();
62168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkAutoTUnref<SkPicture> picture2(recorder.endRecording());
62268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
62368250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    canvas.clear(0);
6249b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(picture2);
62568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    pixel = *bitmap.getAddr32(0, 0);
62668250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
62768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
62868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
62968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
63068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->restore();
63168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkAutoTUnref<SkPicture> picture3(recorder.endRecording());
63268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
63368250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    canvas.clear(0);
6349b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(picture3);
63568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    pixel = *bitmap.getAddr32(0, 0);
63668250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
63768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org}
63868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
63928ae55de3c4ec93516901100df1170048f949dfbsenorblanco@chromium.orgstatic void test_huge_blur(SkBaseDevice* device, skiatest::Reporter* reporter) {
64009843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkCanvas canvas(device);
64109843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
64209843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkBitmap bitmap;
64309843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    bitmap.allocN32Pixels(100, 100);
64409843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    bitmap.eraseARGB(0, 0, 0, 0);
64509843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
64609843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    // Check that a blur with an insane radius does not crash or assert.
64709843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(SkIntToScalar(1<<30), SkIntToScalar(1<<30)));
64809843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
64909843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkPaint paint;
65009843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    paint.setImageFilter(blur);
65109843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    canvas.drawSprite(bitmap, 0, 0, &paint);
65209843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org}
65309843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
65409843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.orgDEF_TEST(HugeBlurImageFilter, reporter) {
65509843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkBitmap temp;
65609843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    temp.allocN32Pixels(100, 100);
65709843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkBitmapDevice device(temp);
65809843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    test_huge_blur(&device, reporter);
65909843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org}
66009843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
661ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.orgstatic void test_xfermode_cropped_input(SkBaseDevice* device, skiatest::Reporter* reporter) {
662ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkCanvas canvas(device);
663ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    canvas.clear(0);
664ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
665ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkBitmap bitmap;
666ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    bitmap.allocN32Pixels(1, 1);
667ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    bitmap.eraseARGB(255, 255, 255, 255);
668ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
669ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkAutoTUnref<SkColorFilter> green(
670ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org        SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode));
671ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkAutoTUnref<SkColorFilterImageFilter> greenFilter(
672ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org        SkColorFilterImageFilter::Create(green.get()));
673ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkImageFilter::CropRect cropRect(SkRect::MakeEmpty());
674ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkAutoTUnref<SkColorFilterImageFilter> croppedOut(
675ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org        SkColorFilterImageFilter::Create(green.get(), NULL, &cropRect));
676ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
677ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    // Check that an xfermode image filter whose input has been cropped out still draws the other
678ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
679ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode);
680ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkAutoTUnref<SkImageFilter> xfermodeNoFg(
681ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org        SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut));
682ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkAutoTUnref<SkImageFilter> xfermodeNoBg(
683ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org        SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter));
684ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg(
685ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org        SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut));
686ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
687ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkPaint paint;
688ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    paint.setImageFilter(xfermodeNoFg);
689ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    canvas.drawSprite(bitmap, 0, 0, &paint);
690ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
691ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    uint32_t pixel;
692ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
693ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    canvas.readPixels(info, &pixel, 4, 0, 0);
694ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
695ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
696ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    paint.setImageFilter(xfermodeNoBg);
697ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    canvas.drawSprite(bitmap, 0, 0, &paint);
698ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    canvas.readPixels(info, &pixel, 4, 0, 0);
699ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
700ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
701ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    paint.setImageFilter(xfermodeNoFgNoBg);
702ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    canvas.drawSprite(bitmap, 0, 0, &paint);
703ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    canvas.readPixels(info, &pixel, 4, 0, 0);
704ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
705ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org}
706ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
707d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.orgDEF_TEST(ImageFilterNestedSaveLayer, reporter) {
708d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkBitmap temp;
709d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    temp.allocN32Pixels(50, 50);
710d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkBitmapDevice device(temp);
711d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkCanvas canvas(&device);
712d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.clear(0x0);
713d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
714d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkBitmap bitmap;
715d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    bitmap.allocN32Pixels(10, 10);
716d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    bitmap.eraseColor(SK_ColorGREEN);
717d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
718d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkMatrix matrix;
719d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
720d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
721d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkAutoTUnref<SkImageFilter> matrixFilter(
722d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org        SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel));
723d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
724d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    // Test that saveLayer() with a filter nested inside another saveLayer() applies the
725d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    // correct offset to the filter matrix.
726d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
727d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.saveLayer(&bounds1, NULL);
728d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkPaint filterPaint;
729d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    filterPaint.setImageFilter(matrixFilter);
730d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
731d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.saveLayer(&bounds2, &filterPaint);
732d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkPaint greenPaint;
733d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    greenPaint.setColor(SK_ColorGREEN);
734d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.drawRect(bounds2, greenPaint);
735d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.restore();
736d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.restore();
737d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkPaint strokePaint;
738d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    strokePaint.setStyle(SkPaint::kStroke_Style);
739d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    strokePaint.setColor(SK_ColorRED);
740d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
741d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
742d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    uint32_t pixel;
743d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.readPixels(info, &pixel, 4, 25, 25);
744d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
745d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
746d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    // Test that drawSprite() with a filter nested inside a saveLayer() applies the
747d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    // correct offset to the filter matrix.
748d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.clear(0x0);
749d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.readPixels(info, &pixel, 4, 25, 25);
750d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.saveLayer(&bounds1, NULL);
751d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.drawSprite(bitmap, 20, 20, &filterPaint);
752d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.restore();
753d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
754d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.readPixels(info, &pixel, 4, 25, 25);
755d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
756d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org}
757d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
758ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.orgDEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
759ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkBitmap temp;
760ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    temp.allocN32Pixels(100, 100);
761ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkBitmapDevice device(temp);
762ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    test_xfermode_cropped_input(&device, reporter);
763ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org}
76409843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
76558d1466c7773984b7ce4bd75ebf7c97cd42f7d12senorblanco@chromium.org#if SK_SUPPORT_GPU
766aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.orgDEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) {
767aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
76815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
76915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                                                         SkImageInfo::MakeN32Premul(100, 100),
77015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                                                         0));
77115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    test_crop_rects(device, reporter);
772aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org}
77309843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
77409843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.orgDEF_GPUTEST(HugeBlurImageFilterGPU, reporter, factory) {
77509843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
77609843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
77709843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org                                                         SkImageInfo::MakeN32Premul(100, 100),
77809843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org                                                         0));
77909843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    test_huge_blur(device, reporter);
78009843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org}
781ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
782ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.orgDEF_GPUTEST(XfermodeImageFilterCroppedInputGPU, reporter, factory) {
783ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
784ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
785ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org                                                         SkImageInfo::MakeN32Premul(1, 1),
786ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org                                                         0));
787ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    test_xfermode_cropped_input(device, reporter);
788ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org}
78958d1466c7773984b7ce4bd75ebf7c97cd42f7d12senorblanco@chromium.org#endif
790