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 "SkBitmap.h"
98f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkBlurImageFilter.h"
104b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org#include "SkCanvas.h"
11194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org#include "SkColorFilterImageFilter.h"
128f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkColorMatrixFilter.h"
135788faaa2ac4203827c68006b669e277d441e2e4ajuma#include "SkComposeImageFilter.h"
146776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkDisplacementMapEffect.h"
156776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkDropShadowImageFilter.h"
1697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org#include "SkFlattenableSerialization.h"
170a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org#include "SkGradientShader.h"
185598b63cd2443a608a74a222d0206bb2455383b7fmalita#include "SkImage.h"
19cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita#include "SkImageSource.h"
204b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org#include "SkLightingImageFilter.h"
218f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkMatrixConvolutionImageFilter.h"
226776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkMergeImageFilter.h"
236776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkMorphologyImageFilter.h"
246776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkOffsetImageFilter.h"
2577b6ba3b6e23b84a3a4f3a62812e4a9eb6de4c23ajuma#include "SkPaintImageFilter.h"
268f3937d9fcb28018ec14db6697d41b645716d589senorblanco#include "SkPerlinNoiseShader.h"
275251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org#include "SkPicture.h"
28910702b564048d77e36a68b0f8dda7cc48a8fcffsenorblanco@chromium.org#include "SkPictureImageFilter.h"
29770963f23f4fc313db0fa3bac18b1b8aafb55f17robertphillips@google.com#include "SkPictureRecorder.h"
303d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips#include "SkPoint3.h"
3197d2c0a216e8feae251a6af1e50579df3e026434halcanary#include "SkReadBuffer.h"
328f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkRect.h"
334418dbac3386f26c8da62ab242be9c178961eb18robertphillips#include "SkSpecialImage.h"
344418dbac3386f26c8da62ab242be9c178961eb18robertphillips#include "SkSpecialSurface.h"
35cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita#include "SkSurface.h"
360abdf766d395ed3b7059511425f431589eca05f6senorblanco#include "SkTableColorFilter.h"
376776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkTileImageFilter.h"
386776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org#include "SkXfermodeImageFilter.h"
398f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h"
40194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
41aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org#if SK_SUPPORT_GPU
421530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#include "GrContext.h"
43aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org#endif
44aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
459f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.orgstatic const int kBitmapSize = 4;
469f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
475251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgnamespace {
485251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
495251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgclass MatrixTestImageFilter : public SkImageFilter {
505251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgpublic:
5143c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips    static sk_sp<SkImageFilter> Make(skiatest::Reporter* reporter,
5243c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips                                     const SkMatrix& expectedMatrix) {
5343c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips        return sk_sp<SkImageFilter>(new MatrixTestImageFilter(reporter, expectedMatrix));
545251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    }
555251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
5643c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips    SK_TO_STRING_OVERRIDE()
5743c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(MatrixTestImageFilter)
5843c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips
5943c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillipsprotected:
604ba94e26106a4ecab4d3841d702b57487b82334erobertphillips    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context& ctx,
614ba94e26106a4ecab4d3841d702b57487b82334erobertphillips                                        SkIPoint* offset) const override {
624cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
634ba94e26106a4ecab4d3841d702b57487b82334erobertphillips        offset->fX = offset->fY = 0;
644ba94e26106a4ecab4d3841d702b57487b82334erobertphillips        return sk_ref_sp<SkSpecialImage>(source);
655251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    }
665251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
6736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer& buffer) const override {
6818f13f3673c20fec220a1594b3174f9dcab35c5dbrianosman        SkDEBUGFAIL("Should never get here");
695251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    }
705251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
715251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.orgprivate:
7243c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips    MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
7343c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips        : INHERITED(nullptr, 0, nullptr)
7443c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips        , fReporter(reporter)
7543c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips        , fExpectedMatrix(expectedMatrix) {
7643c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips    }
7743c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips
785251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    skiatest::Reporter* fReporter;
795251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkMatrix fExpectedMatrix;
803f3b3d003527861dc0bd89733857576408906431mtklein
819fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    typedef SkImageFilter INHERITED;
825251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org};
835251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
846a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblancoclass FailImageFilter : public SkImageFilter {
856a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblancopublic:
866b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips    FailImageFilter() : SkImageFilter(nullptr, 0, nullptr) { }
876a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
886a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source,
896a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco                                        const Context& ctx,
906a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco                                        SkIPoint* offset) const override {
916a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco        return nullptr;
926a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    }
936a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
946a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    SK_TO_STRING_OVERRIDE()
956a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(FailImageFilter)
966a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
976a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblancoprivate:
986a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    typedef SkImageFilter INHERITED;
996a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco};
1006a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
1016a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblancosk_sp<SkFlattenable> FailImageFilter::CreateProc(SkReadBuffer& buffer) {
1026a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
1036a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    return sk_sp<SkFlattenable>(new FailImageFilter());
1046a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco}
1056a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
1066a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco#ifndef SK_IGNORE_TO_STRING
1076a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblancovoid FailImageFilter::toString(SkString* str) const {
1086a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    str->appendf("FailImageFilter: (");
1096a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    str->append(")");
1106a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco}
1116a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco#endif
1126a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
113297f7ce2bb6184849adf0e5479e92f76764ec76asenorblancovoid draw_gradient_circle(SkCanvas* canvas, int width, int height) {
114297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    SkScalar x = SkIntToScalar(width / 2);
115297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    SkScalar y = SkIntToScalar(height / 2);
116297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    SkScalar radius = SkMinScalar(x, y) * 0.8f;
117297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    canvas->clear(0x00000000);
118297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    SkColor colors[2];
119297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    colors[0] = SK_ColorWHITE;
120297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    colors[1] = SK_ColorBLACK;
121297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    sk_sp<SkShader> shader(
122297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        SkGradientShader::MakeRadial(SkPoint::Make(x, y), radius, colors, nullptr, 2,
123297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco                                       SkShader::kClamp_TileMode)
124297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    );
125297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    SkPaint paint;
126297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    paint.setShader(shader);
127297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    canvas->drawCircle(x, y, radius, paint);
128297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco}
129297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco
130297f7ce2bb6184849adf0e5479e92f76764ec76asenorblancoSkBitmap make_gradient_circle(int width, int height) {
131297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    SkBitmap bitmap;
132297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    bitmap.allocN32Pixels(width, height);
133297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    SkCanvas canvas(bitmap);
134297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    draw_gradient_circle(&canvas, width, height);
135297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    return bitmap;
136297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco}
137297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco
138297f7ce2bb6184849adf0e5479e92f76764ec76asenorblancoclass FilterList {
139297f7ce2bb6184849adf0e5479e92f76764ec76asenorblancopublic:
140fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips    FilterList(sk_sp<SkImageFilter> input, const SkImageFilter::CropRect* cropRect = nullptr) {
141297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
142297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        const SkScalar five = SkIntToScalar(5);
143297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco
1446e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        {
1456e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            sk_sp<SkColorFilter> cf(SkColorFilter::MakeModeFilter(SK_ColorRED,
1467d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                                                                  SkBlendMode::kSrcIn));
147297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco
1486e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            this->addFilter("color filter",
14912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                SkColorFilterImageFilter::Make(std::move(cf), input, cropRect));
1506e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        }
151297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco
1526e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        {
1536e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            sk_sp<SkImage> gradientImage(SkImage::MakeFromBitmap(make_gradient_circle(64, 64)));
1546e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            sk_sp<SkImageFilter> gradientSource(SkImageSource::Make(std::move(gradientImage)));
1556e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
156bfebe22ed54d1e3a00888292f10ed8b9714135d3liyuqian            this->addFilter("displacement map",
157bfe11fc9a6e660f83a454b6a5f5945089a4800f3robertphillips                SkDisplacementMapEffect::Make(SkDisplacementMapEffect::kR_ChannelSelectorType,
158bfe11fc9a6e660f83a454b6a5f5945089a4800f3robertphillips                                              SkDisplacementMapEffect::kB_ChannelSelectorType,
159bfe11fc9a6e660f83a454b6a5f5945089a4800f3robertphillips                                              20.0f,
160bfe11fc9a6e660f83a454b6a5f5945089a4800f3robertphillips                                              std::move(gradientSource), input, cropRect));
1616e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        }
1626e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
1636e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        this->addFilter("blur", SkBlurImageFilter::Make(SK_Scalar1,
1646e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                        SK_Scalar1,
165fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips                                                        input,
16612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                        cropRect));
167c416912da4840af0c49bd8cdcf00044ed39500f6robertphillips        this->addFilter("drop shadow", SkDropShadowImageFilter::Make(
168297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco                  SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN,
169fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips                  SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
17012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                  input, cropRect));
17112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        this->addFilter("diffuse lighting",
17212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                  SkLightingImageFilter::MakePointLitDiffuse(location, SK_ColorGREEN, 0, 0,
17312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                             input, cropRect));
174297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        this->addFilter("specular lighting",
17512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                  SkLightingImageFilter::MakePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0,
17612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                              input, cropRect));
17712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        {
17812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            SkScalar kernel[9] = {
17912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                SkIntToScalar(1), SkIntToScalar(1), SkIntToScalar(1),
18012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                SkIntToScalar(1), SkIntToScalar(-7), SkIntToScalar(1),
18112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                SkIntToScalar(1), SkIntToScalar(1), SkIntToScalar(1),
18212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            };
18312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            const SkISize kernelSize = SkISize::Make(3, 3);
18412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            const SkScalar gain = SK_Scalar1, bias = 0;
18512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips
18612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            this->addFilter("matrix convolution",
187ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips                  SkMatrixConvolutionImageFilter::Make(
188297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco                      kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
189fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips                      SkMatrixConvolutionImageFilter::kRepeat_TileMode, false,
19012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                      input, cropRect));
19112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        }
19212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips
193fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips        this->addFilter("merge", SkMergeImageFilter::Make(input, input,
1947d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                                                          SkBlendMode::kSrcOver,
19512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                          cropRect));
19612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips
1976e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        {
1986e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            SkPaint greenColorShaderPaint;
1996e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            greenColorShaderPaint.setShader(SkShader::MakeColorShader(SK_ColorGREEN));
2006e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
2016e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            SkImageFilter::CropRect leftSideCropRect(SkRect::MakeXYWH(0, 0, 32, 64));
2026e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            sk_sp<SkImageFilter> paintFilterLeft(SkPaintImageFilter::Make(greenColorShaderPaint,
2036e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                                          &leftSideCropRect));
2046e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            SkImageFilter::CropRect rightSideCropRect(SkRect::MakeXYWH(32, 0, 32, 64));
2056e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            sk_sp<SkImageFilter> paintFilterRight(SkPaintImageFilter::Make(greenColorShaderPaint,
2066e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                                           &rightSideCropRect));
2076e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
2086e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
2096e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            this->addFilter("merge with disjoint inputs", SkMergeImageFilter::Make(
2102238c9dbca4b791edc512957728a18ce14d55912robertphillips                  std::move(paintFilterLeft), std::move(paintFilterRight),
2117d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                  SkBlendMode::kSrcOver, cropRect));
2126e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        }
2136e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
214297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        this->addFilter("offset",
215fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips                        SkOffsetImageFilter::Make(SK_Scalar1, SK_Scalar1, input,
21612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                  cropRect));
21712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        this->addFilter("dilate", SkDilateImageFilter::Make(3, 2, input, cropRect));
21812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        this->addFilter("erode", SkErodeImageFilter::Make(2, 3, input, cropRect));
219534c270465a9824893d5c9d6c5bacef7726cc389robertphillips        this->addFilter("tile", SkTileImageFilter::Make(
220534c270465a9824893d5c9d6c5bacef7726cc389robertphillips                                    SkRect::MakeXYWH(0, 0, 50, 50),
221534c270465a9824893d5c9d6c5bacef7726cc389robertphillips                                    cropRect ? cropRect->rect() : SkRect::MakeXYWH(0, 0, 100, 100),
222534c270465a9824893d5c9d6c5bacef7726cc389robertphillips                                    input));
22312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips
224297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        if (!cropRect) {
22512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            SkMatrix matrix;
22612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips
22712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            matrix.setTranslate(SK_Scalar1, SK_Scalar1);
22812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
22912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips
230ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips            this->addFilter("matrix",
23112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                SkImageFilter::MakeMatrixFilter(matrix, kLow_SkFilterQuality, input));
232297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        }
2336e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        {
234fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips            sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(five, five, input));
2356e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
2366e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            this->addFilter("blur and offset", SkOffsetImageFilter::Make(five, five,
2376e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                                         std::move(blur),
23812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                         cropRect));
2396e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        }
2406e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        {
2416e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            SkRTreeFactory factory;
2426e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            SkPictureRecorder recorder;
2436e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0);
2446e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
2456e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            SkPaint greenPaint;
2466e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            greenPaint.setColor(SK_ColorGREEN);
2476e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
2486e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
2496e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            sk_sp<SkImageFilter> pictureFilter(SkPictureImageFilter::Make(std::move(picture)));
2506e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
2516e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            this->addFilter("picture and blur", SkBlurImageFilter::Make(five, five,
2526e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                                        std::move(pictureFilter),
25312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                        cropRect));
2546e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        }
2556e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        {
2566e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            SkPaint paint;
2576e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            paint.setShader(SkPerlinNoiseShader::MakeTurbulence(SK_Scalar1, SK_Scalar1, 1, 0));
2586e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            sk_sp<SkImageFilter> paintFilter(SkPaintImageFilter::Make(paint));
2596e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
2606e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            this->addFilter("paint and blur", SkBlurImageFilter::Make(five, five,
2616e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                                      std::move(paintFilter),
26212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                      cropRect));
2636e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        }
264374772bd61951f01bf84fe17bf53d8867681c9aereed        this->addFilter("xfermode", SkXfermodeImageFilter::Make(SkBlendMode::kSrc, input, input,
265374772bd61951f01bf84fe17bf53d8867681c9aereed                                                                cropRect));
266297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    }
267297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    int count() const { return fFilters.count(); }
268297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    SkImageFilter* getFilter(int index) const { return fFilters[index].fFilter.get(); }
269297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    const char* getName(int index) const { return fFilters[index].fName; }
270297f7ce2bb6184849adf0e5479e92f76764ec76asenorblancoprivate:
271297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    struct Filter {
27212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        Filter() : fName(nullptr) {}
27312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        Filter(const char* name, sk_sp<SkImageFilter> filter)
27412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            : fName(name)
27512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            , fFilter(std::move(filter)) {
27612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        }
277297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        const char*                 fName;
278297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        sk_sp<SkImageFilter>        fFilter;
279297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    };
28012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    void addFilter(const char* name, sk_sp<SkImageFilter> filter) {
28112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        fFilters.push_back(Filter(name, std::move(filter)));
282297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    }
283297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco
284297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    SkTArray<Filter> fFilters;
285297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco};
286297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco
2875251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org}
2885251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
28960c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> MatrixTestImageFilter::CreateProc(SkReadBuffer& buffer) {
29018f13f3673c20fec220a1594b3174f9dcab35c5dbrianosman    SkDEBUGFAIL("Should never get here");
29118f13f3673c20fec220a1594b3174f9dcab35c5dbrianosman    return nullptr;
2929fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
2939fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
294f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING
295f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid MatrixTestImageFilter::toString(SkString* str) const {
296f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->appendf("MatrixTestImageFilter: (");
297f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->append(")");
298f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips}
299f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif
300f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips
3019ce9d6772df650ceb0511f275e1a83dffa78ff72reedstatic sk_sp<SkImage> make_small_image() {
302e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    auto surface(SkSurface::MakeRasterN32Premul(kBitmapSize, kBitmapSize));
3035598b63cd2443a608a74a222d0206bb2455383b7fmalita    SkCanvas* canvas = surface->getCanvas();
3045598b63cd2443a608a74a222d0206bb2455383b7fmalita    canvas->clear(0x00000000);
3059f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkPaint darkPaint;
3069f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    darkPaint.setColor(0xFF804020);
3079f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkPaint lightPaint;
3089f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    lightPaint.setColor(0xFF244484);
3099f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    const int i = kBitmapSize / 4;
3109f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    for (int y = 0; y < kBitmapSize; y += i) {
3119f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        for (int x = 0; x < kBitmapSize; x += i) {
3125598b63cd2443a608a74a222d0206bb2455383b7fmalita            canvas->save();
3135598b63cd2443a608a74a222d0206bb2455383b7fmalita            canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
3145598b63cd2443a608a74a222d0206bb2455383b7fmalita            canvas->drawRect(SkRect::MakeXYWH(0, 0,
3159f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
3169f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i)), darkPaint);
3175598b63cd2443a608a74a222d0206bb2455383b7fmalita            canvas->drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
3189f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             0,
3199f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
3209f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i)), lightPaint);
3215598b63cd2443a608a74a222d0206bb2455383b7fmalita            canvas->drawRect(SkRect::MakeXYWH(0,
3229f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
3239f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
3249f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i)), lightPaint);
3255598b63cd2443a608a74a222d0206bb2455383b7fmalita            canvas->drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
3269f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
3279f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i),
3289f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                             SkIntToScalar(i)), darkPaint);
3295598b63cd2443a608a74a222d0206bb2455383b7fmalita            canvas->restore();
3304b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org        }
3314b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org    }
3325598b63cd2443a608a74a222d0206bb2455383b7fmalita
3339ce9d6772df650ceb0511f275e1a83dffa78ff72reed    return surface->makeImageSnapshot();
3349f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org}
3359f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
3365605b56afa5bd89f3148b397318b616fccfd4004robertphillipsstatic sk_sp<SkImageFilter> make_scale(float amount, sk_sp<SkImageFilter> input) {
3379f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkScalar s = amount;
3389f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkScalar matrix[20] = { s, 0, 0, 0, 0,
3399f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                            0, s, 0, 0, 0,
3409f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                            0, 0, s, 0, 0,
3419f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                            0, 0, 0, s, 0 };
3425605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkColorFilter> filter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
3435605b56afa5bd89f3148b397318b616fccfd4004robertphillips    return SkColorFilterImageFilter::Make(std::move(filter), std::move(input));
3449f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org}
3459f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
3465605b56afa5bd89f3148b397318b616fccfd4004robertphillipsstatic sk_sp<SkImageFilter> make_grayscale(sk_sp<SkImageFilter> input,
3475605b56afa5bd89f3148b397318b616fccfd4004robertphillips                                           const SkImageFilter::CropRect* cropRect) {
3489f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    SkScalar matrix[20];
3499f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    memset(matrix, 0, 20 * sizeof(SkScalar));
3509f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    matrix[0] = matrix[5] = matrix[10] = 0.2126f;
3519f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    matrix[1] = matrix[6] = matrix[11] = 0.7152f;
3529f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    matrix[2] = matrix[7] = matrix[12] = 0.0722f;
3539f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    matrix[18] = 1.0f;
3545605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkColorFilter> filter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
3555605b56afa5bd89f3148b397318b616fccfd4004robertphillips    return SkColorFilterImageFilter::Make(std::move(filter), std::move(input), cropRect);
3569f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org}
3579f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
3585605b56afa5bd89f3148b397318b616fccfd4004robertphillipsstatic sk_sp<SkImageFilter> make_blue(sk_sp<SkImageFilter> input,
3595605b56afa5bd89f3148b397318b616fccfd4004robertphillips                                      const SkImageFilter::CropRect* cropRect) {
3605605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkColorFilter> filter(SkColorFilter::MakeModeFilter(SK_ColorBLUE,
3617d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                                                              SkBlendMode::kSrcIn));
3625605b56afa5bd89f3148b397318b616fccfd4004robertphillips    return SkColorFilterImageFilter::Make(std::move(filter), std::move(input), cropRect);
363cedc36f18b2254c5ee21f6348124886b6db4f4c2reed}
364cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
3653e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic sk_sp<SkSpecialSurface> create_empty_special_surface(GrContext* context, int widthHeight) {
366c91fd3447e1d3452d5e43e70e371896c80645b61robertphillips#if SK_SUPPORT_GPU
3674418dbac3386f26c8da62ab242be9c178961eb18robertphillips    if (context) {
3684df1656f0f728ed428c3ab8f7beb19703b27c28erobertphillips        return SkSpecialSurface::MakeRenderTarget(context,
3694df1656f0f728ed428c3ab8f7beb19703b27c28erobertphillips                                                  widthHeight, widthHeight,
370777b5633f599f2a99e2035fdb7ab600779ab95acBrian Osman                                                  kRGBA_8888_GrPixelConfig, nullptr);
371c91fd3447e1d3452d5e43e70e371896c80645b61robertphillips    } else
372c91fd3447e1d3452d5e43e70e371896c80645b61robertphillips#endif
373c91fd3447e1d3452d5e43e70e371896c80645b61robertphillips    {
3744418dbac3386f26c8da62ab242be9c178961eb18robertphillips        const SkImageInfo info = SkImageInfo::MakeN32(widthHeight, widthHeight,
3754418dbac3386f26c8da62ab242be9c178961eb18robertphillips                                                      kOpaque_SkAlphaType);
3763e302275b324172c845627cbd00cee8a06571bafrobertphillips        return SkSpecialSurface::MakeRaster(info);
3774418dbac3386f26c8da62ab242be9c178961eb18robertphillips    }
378bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco}
379bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
3805878dbdf1b5d86201d299c6e07d53e35048713c7senorblancostatic sk_sp<SkSurface> create_surface(GrContext* context, int width, int height) {
3815878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    const SkImageInfo info = SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType);
3825878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco#if SK_SUPPORT_GPU
3835878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    if (context) {
3845878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco        return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
3855878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    } else
3865878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco#endif
3875878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    {
3885878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco        return SkSurface::MakeRaster(info);
3895878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    }
3905878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco}
3915878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
3923e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic sk_sp<SkSpecialImage> create_empty_special_image(GrContext* context, int widthHeight) {
3933e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialSurface> surf(create_empty_special_surface(context, widthHeight));
3944418dbac3386f26c8da62ab242be9c178961eb18robertphillips
3954418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkASSERT(surf);
3964418dbac3386f26c8da62ab242be9c178961eb18robertphillips
3974418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkCanvas* canvas = surf->getCanvas();
3984418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkASSERT(canvas);
3994418dbac3386f26c8da62ab242be9c178961eb18robertphillips
4004418dbac3386f26c8da62ab242be9c178961eb18robertphillips    canvas->clear(0x0);
4014418dbac3386f26c8da62ab242be9c178961eb18robertphillips
40237bd7c3aca66697fff2db79c21771a0b3cbe3b4crobertphillips    return surf->makeImageSnapshot();
4034418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
4044418dbac3386f26c8da62ab242be9c178961eb18robertphillips
4054418dbac3386f26c8da62ab242be9c178961eb18robertphillips
4069f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.orgDEF_TEST(ImageFilter, reporter) {
4079f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
408cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        // Check that two non-clipping color-matrice-filters concatenate into a single filter.
4095605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> halfBrightness(make_scale(0.5f, nullptr));
4105605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> quarterBrightness(make_scale(0.5f, std::move(halfBrightness)));
41196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, nullptr == quarterBrightness->getInput(0));
412cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        SkColorFilter* cf;
413cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        REPORTER_ASSERT(reporter, quarterBrightness->asColorFilter(&cf));
41496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, cf->asColorMatrix(nullptr));
415cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        cf->unref();
416194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
417194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
4189f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
419cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        // Check that a clipping color-matrice-filter followed by a color-matrice-filters
420cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        // concatenates into a single filter, but not a matrixfilter (due to clamping).
4215605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> doubleBrightness(make_scale(2.0f, nullptr));
4225605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> halfBrightness(make_scale(0.5f, std::move(doubleBrightness)));
42396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, nullptr == halfBrightness->getInput(0));
424cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        SkColorFilter* cf;
425cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        REPORTER_ASSERT(reporter, halfBrightness->asColorFilter(&cf));
42696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, !cf->asColorMatrix(nullptr));
427cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        cf->unref();
428194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
429194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
4309f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
4319f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // Check that a color filter image filter without a crop rect can be
4329f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // expressed as a color filter.
4335605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
43496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
435cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
4362afbe23753bf97402a47408c83107042eea3c476mtklein
437cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    {
438cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        // Check that a colorfilterimage filter without a crop rect but with an input
439cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        // that is another colorfilterimage can be expressed as a colorfilter (composed).
4405605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> mode(make_blue(nullptr, nullptr));
4415605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> gray(make_grayscale(std::move(mode), nullptr));
44296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
443194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
4445c518a862264225f0a378e4728e037966ddf4cc2reed
4459f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
446cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        // Test that if we exceed the limit of what ComposeColorFilter can combine, we still
447cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        // can build the DAG and won't assert if we call asColorFilter.
4485605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> filter(make_blue(nullptr, nullptr));
449cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        const int kWayTooManyForComposeColorFilter = 100;
450cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        for (int i = 0; i < kWayTooManyForComposeColorFilter; ++i) {
4515605b56afa5bd89f3148b397318b616fccfd4004robertphillips            filter = make_blue(filter, nullptr);
452cedc36f18b2254c5ee21f6348124886b6db4f4c2reed            // the first few of these will succeed, but after we hit the internal limit,
453cedc36f18b2254c5ee21f6348124886b6db4f4c2reed            // it will then return false.
45496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            (void)filter->asColorFilter(nullptr);
455cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        }
456cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
457cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
458cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    {
4599f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // Check that a color filter image filter with a crop rect cannot
4609f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // be expressed as a color filter.
4619f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100));
4625605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> grayWithCrop(make_grayscale(nullptr, &cropRect));
46396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(nullptr));
4649f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    }
465194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
4669f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org    {
4673df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        // Check that two non-commutative matrices are concatenated in
4683df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        // the correct order.
4693df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        SkScalar blueToRedMatrix[20] = { 0 };
4703df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
4713df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        SkScalar redToGreenMatrix[20] = { 0 };
4723df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        redToGreenMatrix[5] = redToGreenMatrix[18] = SK_Scalar1;
4735605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkColorFilter> blueToRed(SkColorFilter::MakeMatrixFilterRowMajor255(blueToRedMatrix));
4745605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> filter1(SkColorFilterImageFilter::Make(std::move(blueToRed),
4755605b56afa5bd89f3148b397318b616fccfd4004robertphillips                                                                    nullptr));
4765605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkColorFilter> redToGreen(SkColorFilter::MakeMatrixFilterRowMajor255(redToGreenMatrix));
4775605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> filter2(SkColorFilterImageFilter::Make(std::move(redToGreen),
4785605b56afa5bd89f3148b397318b616fccfd4004robertphillips                                                                    std::move(filter1)));
4793df05015efce95c306fb79c21efc77c79f1ac1basenorblanco
4803df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        SkBitmap result;
4813df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        result.allocN32Pixels(kBitmapSize, kBitmapSize);
4823df05015efce95c306fb79c21efc77c79f1ac1basenorblanco
4833df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        SkPaint paint;
4843df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        paint.setColor(SK_ColorBLUE);
4855605b56afa5bd89f3148b397318b616fccfd4004robertphillips        paint.setImageFilter(std::move(filter2));
4863df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        SkCanvas canvas(result);
4873df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        canvas.clear(0x0);
4883df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
4893df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        canvas.drawRect(rect, paint);
4903df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        uint32_t pixel = *result.getAddr32(0, 0);
4913df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        // The result here should be green, since we have effectively shifted blue to green.
4923df05015efce95c306fb79c21efc77c79f1ac1basenorblanco        REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
4933df05015efce95c306fb79c21efc77c79f1ac1basenorblanco    }
4943df05015efce95c306fb79c21efc77c79f1ac1basenorblanco
4953df05015efce95c306fb79c21efc77c79f1ac1basenorblanco    {
4969f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org        // Tests pass by not asserting
4979ce9d6772df650ceb0511f275e1a83dffa78ff72reed        sk_sp<SkImage> image(make_small_image());
4985598b63cd2443a608a74a222d0206bb2455383b7fmalita        SkBitmap result;
499deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org        result.allocN32Pixels(kBitmapSize, kBitmapSize);
500194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
501194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        {
5029f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // This tests for :
5039f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // 1 ) location at (0,0,1)
5043d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips            SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
5059f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // 2 ) location and target at same value
5063d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips            SkPoint3 target = SkPoint3::Make(location.fX, location.fY, location.fZ);
5079f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            // 3 ) large negative specular exponent value
5089f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkScalar specularExponent = -1000;
5099f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org
510549c8991959333e5c0f53faebcbbd5d6bc8f6a56robertphillips            sk_sp<SkImageFilter> bmSrc(SkImageSource::Make(std::move(image)));
5119f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkPaint paint;
51212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            paint.setImageFilter(SkLightingImageFilter::MakeSpotLitSpecular(
5139f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                    location, target, specularExponent, 180,
5149f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                    0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
51512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                    std::move(bmSrc)));
5169f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkCanvas canvas(result);
5179f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            SkRect r = SkRect::MakeWH(SkIntToScalar(kBitmapSize),
5189f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org                                      SkIntToScalar(kBitmapSize));
5199f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org            canvas.drawRect(r, paint);
520194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org        }
521194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    }
522aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org}
5236776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org
5243e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_crop_rects(skiatest::Reporter* reporter,
5254418dbac3386f26c8da62ab242be9c178961eb18robertphillips                            GrContext* context) {
526aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    // Check that all filters offset to their absolute crop rect,
527aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    // unaffected by the input crop rect.
528aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    // Tests pass by not asserting.
5293e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 100));
5304418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkASSERT(srcImg);
531aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
532aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
533aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
534fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips    sk_sp<SkImageFilter> input(make_grayscale(nullptr, &inputCropRect));
535aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
536fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips    FilterList filters(input, &cropRect);
537aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
538297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco    for (int i = 0; i < filters.count(); ++i) {
539297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        SkImageFilter* filter = filters.getFilter(i);
540aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org        SkIPoint offset;
5412a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        SkImageFilter::OutputProperties noColorSpace(nullptr);
5422a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr, noColorSpace);
5432302de920e5434809bd0e85b871a6e002856dfdbrobertphillips        sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg.get(), ctx, &offset));
544297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        REPORTER_ASSERT_MESSAGE(reporter, resultImg, filters.getName(i));
545297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, filters.getName(i));
5466776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    }
5479f9d5829c29d8934fa0d4d348173d5ae39bed4e9tfarina@chromium.org}
548aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
5493e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_negative_blur_sigma(skiatest::Reporter* reporter,
5504418dbac3386f26c8da62ab242be9c178961eb18robertphillips                                     GrContext* context) {
55132673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco    // Check that SkBlurImageFilter will accept a negative sigma, either in
55232673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco    // the given arguments or after CTM application.
5535ea95df02de9cd774d0b84d1341599bbd9c0d8dbreed    const int width = 32, height = 32;
5545ea95df02de9cd774d0b84d1341599bbd9c0d8dbreed    const SkScalar five = SkIntToScalar(5);
55532673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco
5566e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> positiveFilter(SkBlurImageFilter::Make(five, five, nullptr));
5576e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> negativeFilter(SkBlurImageFilter::Make(-five, five, nullptr));
55832673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco
55932673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco    SkBitmap gradient = make_gradient_circle(width, height);
5603e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> imgSrc(SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(width, height),
56137bd7c3aca66697fff2db79c21771a0b3cbe3b4crobertphillips                                                                gradient));
5624418dbac3386f26c8da62ab242be9c178961eb18robertphillips
56332673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco    SkIPoint offset;
5642a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::OutputProperties noColorSpace(nullptr);
5652a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr, noColorSpace);
5664418dbac3386f26c8da62ab242be9c178961eb18robertphillips
5672302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> positiveResult1(positiveFilter->filterImage(imgSrc.get(), ctx, &offset));
5684418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, positiveResult1);
5694418dbac3386f26c8da62ab242be9c178961eb18robertphillips
5702302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> negativeResult1(negativeFilter->filterImage(imgSrc.get(), ctx, &offset));
5714418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, negativeResult1);
5724418dbac3386f26c8da62ab242be9c178961eb18robertphillips
57332673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco    SkMatrix negativeScale;
57432673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco    negativeScale.setScale(-SK_Scalar1, SK_Scalar1);
5752a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context negativeCTX(negativeScale, SkIRect::MakeWH(32, 32), nullptr,
5762a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                                       noColorSpace);
5774418dbac3386f26c8da62ab242be9c178961eb18robertphillips
5782302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> negativeResult2(positiveFilter->filterImage(imgSrc.get(),
5792302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                                                      negativeCTX,
5802302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                                                      &offset));
5814418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, negativeResult2);
5824418dbac3386f26c8da62ab242be9c178961eb18robertphillips
5832302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> positiveResult2(negativeFilter->filterImage(imgSrc.get(),
5842302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                                                      negativeCTX,
5852302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                                                      &offset));
5864418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, positiveResult2);
5874418dbac3386f26c8da62ab242be9c178961eb18robertphillips
5884418dbac3386f26c8da62ab242be9c178961eb18robertphillips
5894418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkBitmap positiveResultBM1, positiveResultBM2;
5904418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkBitmap negativeResultBM1, negativeResultBM2;
5914418dbac3386f26c8da62ab242be9c178961eb18robertphillips
592646125114b42b24e5ada3c9f8fac53a85f9ad2a0robertphillips    REPORTER_ASSERT(reporter, positiveResult1->getROPixels(&positiveResultBM1));
593646125114b42b24e5ada3c9f8fac53a85f9ad2a0robertphillips    REPORTER_ASSERT(reporter, positiveResult2->getROPixels(&positiveResultBM2));
594646125114b42b24e5ada3c9f8fac53a85f9ad2a0robertphillips    REPORTER_ASSERT(reporter, negativeResult1->getROPixels(&negativeResultBM1));
595646125114b42b24e5ada3c9f8fac53a85f9ad2a0robertphillips    REPORTER_ASSERT(reporter, negativeResult2->getROPixels(&negativeResultBM2));
5964418dbac3386f26c8da62ab242be9c178961eb18robertphillips
5974418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkAutoLockPixels lockP1(positiveResultBM1);
5984418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkAutoLockPixels lockP2(positiveResultBM2);
5994418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkAutoLockPixels lockN1(negativeResultBM1);
6004418dbac3386f26c8da62ab242be9c178961eb18robertphillips    SkAutoLockPixels lockN2(negativeResultBM2);
60132673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco    for (int y = 0; y < height; y++) {
6024418dbac3386f26c8da62ab242be9c178961eb18robertphillips        int diffs = memcmp(positiveResultBM1.getAddr32(0, y),
6034418dbac3386f26c8da62ab242be9c178961eb18robertphillips                           negativeResultBM1.getAddr32(0, y),
6044418dbac3386f26c8da62ab242be9c178961eb18robertphillips                           positiveResultBM1.rowBytes());
60532673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco        REPORTER_ASSERT(reporter, !diffs);
60632673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco        if (diffs) {
60732673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco            break;
60832673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco        }
6094418dbac3386f26c8da62ab242be9c178961eb18robertphillips        diffs = memcmp(positiveResultBM1.getAddr32(0, y),
6104418dbac3386f26c8da62ab242be9c178961eb18robertphillips                       negativeResultBM2.getAddr32(0, y),
6114418dbac3386f26c8da62ab242be9c178961eb18robertphillips                       positiveResultBM1.rowBytes());
61232673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco        REPORTER_ASSERT(reporter, !diffs);
61332673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco        if (diffs) {
61432673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco            break;
61532673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco        }
6164418dbac3386f26c8da62ab242be9c178961eb18robertphillips        diffs = memcmp(positiveResultBM1.getAddr32(0, y),
6174418dbac3386f26c8da62ab242be9c178961eb18robertphillips                       positiveResultBM2.getAddr32(0, y),
6184418dbac3386f26c8da62ab242be9c178961eb18robertphillips                       positiveResultBM1.rowBytes());
61932673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco        REPORTER_ASSERT(reporter, !diffs);
62032673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco        if (diffs) {
62132673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco            break;
62232673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco        }
62332673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco    }
62432673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco}
62532673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco
62621a465d7f4c5e639044e79971aeaa1194fc73078senorblancoDEF_TEST(ImageFilterNegativeBlurSigma, reporter) {
6273e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_negative_blur_sigma(reporter, nullptr);
6284418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
6294418dbac3386f26c8da62ab242be9c178961eb18robertphillips
6304418dbac3386f26c8da62ab242be9c178961eb18robertphillips#if SK_SUPPORT_GPU
63168d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterNegativeBlurSigma_Gpu, reporter, ctxInfo) {
6328b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_negative_blur_sigma(reporter, ctxInfo.grContext());
63332673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco}
6344418dbac3386f26c8da62ab242be9c178961eb18robertphillips#endif
63532673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco
6363e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_zero_blur_sigma(skiatest::Reporter* reporter, GrContext* context) {
637bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    // Check that SkBlurImageFilter with a zero sigma and a non-zero srcOffset works correctly.
638bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    SkImageFilter::CropRect cropRect(SkRect::Make(SkIRect::MakeXYWH(5, 0, 5, 10)));
63951a315eff9b86bd60e7884240c4efc199129d37arobertphillips    sk_sp<SkImageFilter> input(SkOffsetImageFilter::Make(0, 0, nullptr, &cropRect));
6406e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> filter(SkBlurImageFilter::Make(0, 0, std::move(input), &cropRect));
641bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
6423e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialSurface> surf(create_empty_special_surface(context, 10));
643bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    surf->getCanvas()->clear(SK_ColorGREEN);
64437bd7c3aca66697fff2db79c21771a0b3cbe3b4crobertphillips    sk_sp<SkSpecialImage> image(surf->makeImageSnapshot());
645bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
646bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    SkIPoint offset;
6472a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::OutputProperties noColorSpace(nullptr);
6482a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr, noColorSpace);
649bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
6502302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> result(filter->filterImage(image.get(), ctx, &offset));
651bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    REPORTER_ASSERT(reporter, offset.fX == 5 && offset.fY == 0);
652bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    REPORTER_ASSERT(reporter, result);
653bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    REPORTER_ASSERT(reporter, result->width() == 5 && result->height() == 10);
654bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
655bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    SkBitmap resultBM;
656bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
657646125114b42b24e5ada3c9f8fac53a85f9ad2a0robertphillips    REPORTER_ASSERT(reporter, result->getROPixels(&resultBM));
658bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
659bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    SkAutoLockPixels lock(resultBM);
660bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    for (int y = 0; y < resultBM.height(); y++) {
661bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco        for (int x = 0; x < resultBM.width(); x++) {
662bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco            bool diff = *resultBM.getAddr32(x, y) != SK_ColorGREEN;
663bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco            REPORTER_ASSERT(reporter, !diff);
664bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco            if (diff) {
665bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco                break;
666bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco            }
667bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco        }
668bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco    }
669bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco}
670bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
67121a465d7f4c5e639044e79971aeaa1194fc73078senorblancoDEF_TEST(ImageFilterZeroBlurSigma, reporter) {
6723e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_zero_blur_sigma(reporter, nullptr);
673bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco}
674bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
675bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco#if SK_SUPPORT_GPU
67668d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterZeroBlurSigma_Gpu, reporter, ctxInfo) {
6778b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_zero_blur_sigma(reporter, ctxInfo.grContext());
678bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco}
679bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco#endif
680bf680c30a280d4d7b3b8d5fedf23defff348cb50senorblanco
6816a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
6826a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco// Tests that, even when an upstream filter has returned null (due to failure or clipping), a
6836a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco// downstream filter that affects transparent black still does so even with a nullptr input.
6843e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_fail_affects_transparent_black(skiatest::Reporter* reporter, GrContext* context) {
6856a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    sk_sp<FailImageFilter> failFilter(new FailImageFilter());
6863e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> source(create_empty_special_image(context, 5));
6872a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::OutputProperties noColorSpace(nullptr);
6882a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(0, 0, 1, 1), nullptr, noColorSpace);
6897d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    sk_sp<SkColorFilter> green(SkColorFilter::MakeModeFilter(SK_ColorGREEN, SkBlendMode::kSrc));
6906a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    SkASSERT(green->affectsTransparentBlack());
6915605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkImageFilter> greenFilter(SkColorFilterImageFilter::Make(std::move(green),
6925605b56afa5bd89f3148b397318b616fccfd4004robertphillips                                                                    std::move(failFilter)));
6936a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    SkIPoint offset;
6946a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    sk_sp<SkSpecialImage> result(greenFilter->filterImage(source.get(), ctx, &offset));
6956a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    REPORTER_ASSERT(reporter, nullptr != result.get());
6966a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    if (result.get()) {
6976a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco        SkBitmap resultBM;
698646125114b42b24e5ada3c9f8fac53a85f9ad2a0robertphillips        REPORTER_ASSERT(reporter, result->getROPixels(&resultBM));
6996a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco        SkAutoLockPixels lock(resultBM);
7006a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco        REPORTER_ASSERT(reporter, *resultBM.getAddr32(0, 0) == SK_ColorGREEN);
7016a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco    }
7026a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco}
7036a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
7046a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblancoDEF_TEST(ImageFilterFailAffectsTransparentBlack, reporter) {
7053e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_fail_affects_transparent_black(reporter, nullptr);
7066a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco}
7076a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
7086a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco#if SK_SUPPORT_GPU
70968d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterFailAffectsTransparentBlack_Gpu, reporter, ctxInfo) {
7108b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_fail_affects_transparent_black(reporter, ctxInfo.grContext());
7116a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco}
7126a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco#endif
7136a93fa1a4526ba14782f7f17a73479ca5a4a8e3asenorblanco
7140a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.orgDEF_TEST(ImageFilterDrawTiled, reporter) {
7150a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    // Check that all filters when drawn tiled (with subsequent clip rects) exactly
7160a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    // match the same filters drawn with a single full-canvas bitmap draw.
7170a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    // Tests pass by not asserting.
7180a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
719fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips    FilterList filters(nullptr);
7200a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
7210a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkBitmap untiledResult, tiledResult;
7225ea95df02de9cd774d0b84d1341599bbd9c0d8dbreed    const int width = 64, height = 64;
7230a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    untiledResult.allocN32Pixels(width, height);
7240a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    tiledResult.allocN32Pixels(width, height);
7250a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkCanvas tiledCanvas(tiledResult);
7260a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    SkCanvas untiledCanvas(untiledResult);
727d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org    int tileSize = 8;
7280a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
729d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org    for (int scale = 1; scale <= 2; ++scale) {
730297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco        for (int i = 0; i < filters.count(); ++i) {
731d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            tiledCanvas.clear(0);
732d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.clear(0);
733d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            SkPaint paint;
7345e25717ab6313b011ec54eac0109c414aa8ffc17Mike Reed            paint.setImageFilter(sk_ref_sp(filters.getFilter(i)));
735d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            paint.setTextSize(SkIntToScalar(height));
736d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            paint.setColor(SK_ColorWHITE);
737d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            SkString str;
738d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            const char* text = "ABC";
739d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            SkScalar ypos = SkIntToScalar(height);
740d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.save();
741d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
742d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
743d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.restore();
744d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            for (int y = 0; y < height; y += tileSize) {
745d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                for (int x = 0; x < width; x += tileSize) {
746d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.save();
747d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
748d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
749d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
750d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    tiledCanvas.restore();
751d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                }
7520a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org            }
753d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            untiledCanvas.flush();
754d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            tiledCanvas.flush();
755d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org            for (int y = 0; y < height; y++) {
756d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
757297f7ce2bb6184849adf0e5479e92f76764ec76asenorblanco                REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters.getName(i));
758d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                if (diffs) {
759d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                    break;
760d4db657bf54ae5346cb142fed2f83ea88544a733senorblanco@chromium.org                }
7610a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org            }
7620a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org        }
7630a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org    }
7640a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org}
7650a5c233e3b911232c0d6f9a88ded99ecf88b8a97senorblanco@chromium.org
7663f3b3d003527861dc0bd89733857576408906431mtkleinstatic void draw_saveLayer_picture(int width, int height, int tileSize,
767a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                   SkBBHFactory* factory, SkBitmap* result) {
768d910f544439fffa6c2bcc5181b79b2811a4c130amtklein
769d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    SkMatrix matrix;
770d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    matrix.setTranslate(SkIntToScalar(50), 0);
771d910f544439fffa6c2bcc5181b79b2811a4c130amtklein
7727d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    sk_sp<SkColorFilter> cf(SkColorFilter::MakeModeFilter(SK_ColorWHITE, SkBlendMode::kSrc));
7735605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkImageFilter> cfif(SkColorFilterImageFilter::Make(std::move(cf), nullptr));
774ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips    sk_sp<SkImageFilter> imageFilter(SkImageFilter::MakeMatrixFilter(matrix,
775ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips                                                                     kNone_SkFilterQuality,
776ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips                                                                     std::move(cfif)));
777d910f544439fffa6c2bcc5181b79b2811a4c130amtklein
778d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    SkPaint paint;
7795605b56afa5bd89f3148b397318b616fccfd4004robertphillips    paint.setImageFilter(std::move(imageFilter));
780d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    SkPictureRecorder recorder;
781d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50));
7823f3b3d003527861dc0bd89733857576408906431mtklein    SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width),
7833f3b3d003527861dc0bd89733857576408906431mtklein                                                        SkIntToScalar(height),
784a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                        factory, 0);
785d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    recordingCanvas->translate(-55, 0);
786d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    recordingCanvas->saveLayer(&bounds, &paint);
787d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    recordingCanvas->restore();
788ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> picture1(recorder.finishRecordingAsPicture());
789d910f544439fffa6c2bcc5181b79b2811a4c130amtklein
790d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    result->allocN32Pixels(width, height);
791d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    SkCanvas canvas(*result);
792d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    canvas.clear(0);
793d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize)));
794d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    canvas.drawPicture(picture1.get());
795d910f544439fffa6c2bcc5181b79b2811a4c130amtklein}
796d910f544439fffa6c2bcc5181b79b2811a4c130amtklein
797d910f544439fffa6c2bcc5181b79b2811a4c130amtkleinDEF_TEST(ImageFilterDrawMatrixBBH, reporter) {
798d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    // Check that matrix filter when drawn tiled with BBH exactly
799d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    // matches the same thing drawn without BBH.
800d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    // Tests pass by not asserting.
801d910f544439fffa6c2bcc5181b79b2811a4c130amtklein
802d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    const int width = 200, height = 200;
803d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    const int tileSize = 100;
804d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    SkBitmap result1, result2;
805d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    SkRTreeFactory factory;
806d910f544439fffa6c2bcc5181b79b2811a4c130amtklein
807a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    draw_saveLayer_picture(width, height, tileSize, &factory, &result1);
80896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    draw_saveLayer_picture(width, height, tileSize, nullptr, &result2);
809d910f544439fffa6c2bcc5181b79b2811a4c130amtklein
810d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    for (int y = 0; y < height; y++) {
811d910f544439fffa6c2bcc5181b79b2811a4c130amtklein        int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
812d910f544439fffa6c2bcc5181b79b2811a4c130amtklein        REPORTER_ASSERT(reporter, !diffs);
813d910f544439fffa6c2bcc5181b79b2811a4c130amtklein        if (diffs) {
814d910f544439fffa6c2bcc5181b79b2811a4c130amtklein            break;
815d910f544439fffa6c2bcc5181b79b2811a4c130amtklein        }
816d910f544439fffa6c2bcc5181b79b2811a4c130amtklein    }
817d910f544439fffa6c2bcc5181b79b2811a4c130amtklein}
818d910f544439fffa6c2bcc5181b79b2811a4c130amtklein
8196e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillipsstatic sk_sp<SkImageFilter> make_blur(sk_sp<SkImageFilter> input) {
8206e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    return SkBlurImageFilter::Make(SK_Scalar1, SK_Scalar1, std::move(input));
8211150a6d151571fb6ee816dadec844ae7ab53948asenorblanco}
8221150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8236e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillipsstatic sk_sp<SkImageFilter> make_drop_shadow(sk_sp<SkImageFilter> input) {
824c416912da4840af0c49bd8cdcf00044ed39500f6robertphillips    return SkDropShadowImageFilter::Make(
8251150a6d151571fb6ee816dadec844ae7ab53948asenorblanco        SkIntToScalar(100), SkIntToScalar(100),
8261150a6d151571fb6ee816dadec844ae7ab53948asenorblanco        SkIntToScalar(10), SkIntToScalar(10),
827234f036b3e731e06e616c5291157d3bb4fbfdee2sugoi        SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
828c416912da4840af0c49bd8cdcf00044ed39500f6robertphillips        std::move(input));
8291150a6d151571fb6ee816dadec844ae7ab53948asenorblanco}
8301150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8311150a6d151571fb6ee816dadec844ae7ab53948asenorblancoDEF_TEST(ImageFilterBlurThenShadowBounds, reporter) {
8326e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> filter1(make_blur(nullptr));
8336e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> filter2(make_drop_shadow(std::move(filter1)));
8341150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8351150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
8361150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
837e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    bounds = filter2->filterBounds(bounds, SkMatrix::I());
8381150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8391150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    REPORTER_ASSERT(reporter, bounds == expectedBounds);
8401150a6d151571fb6ee816dadec844ae7ab53948asenorblanco}
8411150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8421150a6d151571fb6ee816dadec844ae7ab53948asenorblancoDEF_TEST(ImageFilterShadowThenBlurBounds, reporter) {
8436e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> filter1(make_drop_shadow(nullptr));
8446e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> filter2(make_blur(std::move(filter1)));
8451150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8461150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
8471150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
848e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    bounds = filter2->filterBounds(bounds, SkMatrix::I());
8491150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8501150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    REPORTER_ASSERT(reporter, bounds == expectedBounds);
8511150a6d151571fb6ee816dadec844ae7ab53948asenorblanco}
8521150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8531150a6d151571fb6ee816dadec844ae7ab53948asenorblancoDEF_TEST(ImageFilterDilateThenBlurBounds, reporter) {
854fc11b0afe0ca922a42767d4a656ed640008da1bbrobertphillips    sk_sp<SkImageFilter> filter1(SkDilateImageFilter::Make(2, 2, nullptr));
8556e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> filter2(make_drop_shadow(std::move(filter1)));
8561150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8571150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
8581150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    SkIRect expectedBounds = SkIRect::MakeXYWH(-132, -132, 234, 234);
859e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    bounds = filter2->filterBounds(bounds, SkMatrix::I());
8601150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
8611150a6d151571fb6ee816dadec844ae7ab53948asenorblanco    REPORTER_ASSERT(reporter, bounds == expectedBounds);
8621150a6d151571fb6ee816dadec844ae7ab53948asenorblanco}
8631150a6d151571fb6ee816dadec844ae7ab53948asenorblanco
864203a993c77ea146e0a4e7f1e0c079cc79fd09167jbromanDEF_TEST(ImageFilterScaledBlurRadius, reporter) {
865203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman    // Each blur should spread 3*sigma, so 3 for the blur and 30 for the shadow
866203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman    // (before the CTM). Bounds should be computed correctly in the presence of
867203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman    // a (possibly negative) scale.
868203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman    sk_sp<SkImageFilter> blur(make_blur(nullptr));
869203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman    sk_sp<SkImageFilter> dropShadow(make_drop_shadow(nullptr));
870203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman    {
871203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        // Uniform scale by 2.
872203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkMatrix scaleMatrix;
873203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        scaleMatrix.setScale(2, 2);
874203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect bounds = SkIRect::MakeLTRB(0, 0, 200, 200);
875203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman
876203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect expectedBlurBounds = SkIRect::MakeLTRB(-6, -6, 206, 206);
877203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect blurBounds = blur->filterBounds(
878203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            bounds, scaleMatrix, SkImageFilter::kForward_MapDirection);
879203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        REPORTER_ASSERT(reporter, blurBounds == expectedBlurBounds);
880203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect reverseBlurBounds = blur->filterBounds(
881203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection);
882203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        REPORTER_ASSERT(reporter, reverseBlurBounds == expectedBlurBounds);
883203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman
884203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect expectedShadowBounds = SkIRect::MakeLTRB(0, 0, 460, 460);
885203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect shadowBounds = dropShadow->filterBounds(
886203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            bounds, scaleMatrix, SkImageFilter::kForward_MapDirection);
887203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        REPORTER_ASSERT(reporter, shadowBounds == expectedShadowBounds);
888203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect expectedReverseShadowBounds =
889203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            SkIRect::MakeLTRB(-260, -260, 200, 200);
890203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect reverseShadowBounds = dropShadow->filterBounds(
891203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection);
892203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        REPORTER_ASSERT(reporter,
893203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            reverseShadowBounds == expectedReverseShadowBounds);
894203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman    }
895203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman    {
896203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        // Vertical flip.
897203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkMatrix scaleMatrix;
898203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        scaleMatrix.setScale(1, -1);
899203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect bounds = SkIRect::MakeLTRB(0, -100, 100, 0);
900203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman
901203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect expectedBlurBounds = SkIRect::MakeLTRB(-3, -103, 103, 3);
902203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect blurBounds = blur->filterBounds(
903203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            bounds, scaleMatrix, SkImageFilter::kForward_MapDirection);
904203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        REPORTER_ASSERT(reporter, blurBounds == expectedBlurBounds);
905203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect reverseBlurBounds = blur->filterBounds(
906203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection);
907203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        REPORTER_ASSERT(reporter, reverseBlurBounds == expectedBlurBounds);
908203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman
909203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect expectedShadowBounds = SkIRect::MakeLTRB(0, -230, 230, 0);
910203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect shadowBounds = dropShadow->filterBounds(
911203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            bounds, scaleMatrix, SkImageFilter::kForward_MapDirection);
912203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        REPORTER_ASSERT(reporter, shadowBounds == expectedShadowBounds);
913203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect expectedReverseShadowBounds =
914203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            SkIRect::MakeLTRB(-130, -100, 100, 130);
915203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        SkIRect reverseShadowBounds = dropShadow->filterBounds(
916203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            bounds, scaleMatrix, SkImageFilter::kReverse_MapDirection);
917203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman        REPORTER_ASSERT(reporter,
918203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman            reverseShadowBounds == expectedReverseShadowBounds);
919203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman    }
920203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman}
921203a993c77ea146e0a4e7f1e0c079cc79fd09167jbroman
9225788faaa2ac4203827c68006b669e277d441e2e4ajumaDEF_TEST(ImageFilterComposedBlurFastBounds, reporter) {
9236e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> filter1(make_blur(nullptr));
9246e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> filter2(make_blur(nullptr));
925491fb17cab07574a9d5656c1c97ad0acc3af5c70robertphillips    sk_sp<SkImageFilter> composedFilter(SkComposeImageFilter::Make(std::move(filter1),
926491fb17cab07574a9d5656c1c97ad0acc3af5c70robertphillips                                                                   std::move(filter2)));
9275788faaa2ac4203827c68006b669e277d441e2e4ajuma
9285788faaa2ac4203827c68006b669e277d441e2e4ajuma    SkRect boundsSrc = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
9295788faaa2ac4203827c68006b669e277d441e2e4ajuma    SkRect expectedBounds = SkRect::MakeXYWH(
9305788faaa2ac4203827c68006b669e277d441e2e4ajuma        SkIntToScalar(-6), SkIntToScalar(-6), SkIntToScalar(112), SkIntToScalar(112));
931e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    SkRect boundsDst = composedFilter->computeFastBounds(boundsSrc);
9325788faaa2ac4203827c68006b669e277d441e2e4ajuma
9335788faaa2ac4203827c68006b669e277d441e2e4ajuma    REPORTER_ASSERT(reporter, boundsDst == expectedBounds);
9345788faaa2ac4203827c68006b669e277d441e2e4ajuma}
9355788faaa2ac4203827c68006b669e277d441e2e4ajuma
9360e3129d734212089f872f0e7de8f2537861a3f89jbromanDEF_TEST(ImageFilterUnionBounds, reporter) {
93751a315eff9b86bd60e7884240c4efc199129d37arobertphillips    sk_sp<SkImageFilter> offset(SkOffsetImageFilter::Make(50, 0, nullptr));
9380e3129d734212089f872f0e7de8f2537861a3f89jbroman    // Regardless of which order they appear in, the image filter bounds should
9390e3129d734212089f872f0e7de8f2537861a3f89jbroman    // be combined correctly.
9400e3129d734212089f872f0e7de8f2537861a3f89jbroman    {
941374772bd61951f01bf84fe17bf53d8867681c9aereed        sk_sp<SkImageFilter> composite(SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver, offset));
9420e3129d734212089f872f0e7de8f2537861a3f89jbroman        SkRect bounds = SkRect::MakeWH(100, 100);
9430e3129d734212089f872f0e7de8f2537861a3f89jbroman        // Intentionally aliasing here, as that's what the real callers do.
944e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco        bounds = composite->computeFastBounds(bounds);
9450e3129d734212089f872f0e7de8f2537861a3f89jbroman        REPORTER_ASSERT(reporter, bounds == SkRect::MakeWH(150, 100));
9460e3129d734212089f872f0e7de8f2537861a3f89jbroman    }
9470e3129d734212089f872f0e7de8f2537861a3f89jbroman    {
948374772bd61951f01bf84fe17bf53d8867681c9aereed        sk_sp<SkImageFilter> composite(SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver, nullptr,
9498c0326df5f600da43a054dad3b354221dd6b790frobertphillips                                                                   offset, nullptr));
9500e3129d734212089f872f0e7de8f2537861a3f89jbroman        SkRect bounds = SkRect::MakeWH(100, 100);
9510e3129d734212089f872f0e7de8f2537861a3f89jbroman        // Intentionally aliasing here, as that's what the real callers do.
952e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco        bounds = composite->computeFastBounds(bounds);
9530e3129d734212089f872f0e7de8f2537861a3f89jbroman        REPORTER_ASSERT(reporter, bounds == SkRect::MakeWH(150, 100));
9540e3129d734212089f872f0e7de8f2537861a3f89jbroman    }
9550e3129d734212089f872f0e7de8f2537861a3f89jbroman}
9560e3129d734212089f872f0e7de8f2537861a3f89jbroman
9573e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_imagefilter_merge_result_size(skiatest::Reporter* reporter, GrContext* context) {
9584a24398391536f7b176b44a8c45dc288655b4adbsenorblanco    SkBitmap greenBM;
9594a24398391536f7b176b44a8c45dc288655b4adbsenorblanco    greenBM.allocN32Pixels(20, 20);
9604a24398391536f7b176b44a8c45dc288655b4adbsenorblanco    greenBM.eraseColor(SK_ColorGREEN);
9619ce9d6772df650ceb0511f275e1a83dffa78ff72reed    sk_sp<SkImage> greenImage(SkImage::MakeFromBitmap(greenBM));
962549c8991959333e5c0f53faebcbbd5d6bc8f6a56robertphillips    sk_sp<SkImageFilter> source(SkImageSource::Make(std::move(greenImage)));
9637d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    sk_sp<SkImageFilter> merge(SkMergeImageFilter::Make(source, source, SkBlendMode::kSrcOver));
9644a24398391536f7b176b44a8c45dc288655b4adbsenorblanco
9653e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 1));
9664418dbac3386f26c8da62ab242be9c178961eb18robertphillips
9672a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::OutputProperties noColorSpace(nullptr);
9682a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(0, 0, 100, 100), nullptr,
9692a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                               noColorSpace);
9704a24398391536f7b176b44a8c45dc288655b4adbsenorblanco    SkIPoint offset;
9714418dbac3386f26c8da62ab242be9c178961eb18robertphillips
9722302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> resultImg(merge->filterImage(srcImg.get(), ctx, &offset));
9734418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, resultImg);
9744418dbac3386f26c8da62ab242be9c178961eb18robertphillips
9754418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, resultImg->width() == 20 && resultImg->height() == 20);
9764418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
9774418dbac3386f26c8da62ab242be9c178961eb18robertphillips
9784418dbac3386f26c8da62ab242be9c178961eb18robertphillipsDEF_TEST(ImageFilterMergeResultSize, reporter) {
9793e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_imagefilter_merge_result_size(reporter, nullptr);
9804418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
9814418dbac3386f26c8da62ab242be9c178961eb18robertphillips
9824418dbac3386f26c8da62ab242be9c178961eb18robertphillips#if SK_SUPPORT_GPU
983ab527a5bbfb1eae4f99a1435d349a44d00477d82egdanielDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterMergeResultSize_Gpu, reporter, ctxInfo) {
9848b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_imagefilter_merge_result_size(reporter, ctxInfo.grContext());
9854a24398391536f7b176b44a8c45dc288655b4adbsenorblanco}
9864418dbac3386f26c8da62ab242be9c178961eb18robertphillips#endif
9874a24398391536f7b176b44a8c45dc288655b4adbsenorblanco
988a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillipsstatic void draw_blurred_rect(SkCanvas* canvas) {
989837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    SkPaint filterPaint;
990837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    filterPaint.setColor(SK_ColorWHITE);
9916e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    filterPaint.setImageFilter(SkBlurImageFilter::Make(SkIntToScalar(8), 0, nullptr));
99296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    canvas->saveLayer(nullptr, &filterPaint);
993837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    SkPaint whitePaint;
994837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    whitePaint.setColor(SK_ColorWHITE);
995837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
996837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    canvas->restore();
997837f5321a409228a27fc710eb71c87866b820cfbsenorblanco}
998837f5321a409228a27fc710eb71c87866b820cfbsenorblanco
999a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillipsstatic void draw_picture_clipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
1000837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    canvas->save();
1001837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    canvas->clipRect(clipRect);
1002837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    canvas->drawPicture(picture);
1003837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    canvas->restore();
1004837f5321a409228a27fc710eb71c87866b820cfbsenorblanco}
1005837f5321a409228a27fc710eb71c87866b820cfbsenorblanco
1006837f5321a409228a27fc710eb71c87866b820cfbsenorblancoDEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) {
1007837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    // Check that the blur filter when recorded with RTree acceleration,
1008837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    // and drawn tiled (with subsequent clip rects) exactly
1009837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    // matches the same filter drawn with without RTree acceleration.
1010837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    // This tests that the "bleed" from the blur into the otherwise-blank
1011837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    // tiles is correctly rendered.
1012837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    // Tests pass by not asserting.
1013837f5321a409228a27fc710eb71c87866b820cfbsenorblanco
1014837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    int width = 16, height = 8;
1015837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    SkBitmap result1, result2;
1016837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    result1.allocN32Pixels(width, height);
1017837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    result2.allocN32Pixels(width, height);
1018837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    SkCanvas canvas1(result1);
1019837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    SkCanvas canvas2(result2);
1020837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    int tileSize = 8;
1021837f5321a409228a27fc710eb71c87866b820cfbsenorblanco
1022837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    canvas1.clear(0);
1023837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    canvas2.clear(0);
1024837f5321a409228a27fc710eb71c87866b820cfbsenorblanco
1025837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    SkRTreeFactory factory;
1026837f5321a409228a27fc710eb71c87866b820cfbsenorblanco
1027837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    SkPictureRecorder recorder1, recorder2;
1028837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    // The only difference between these two pictures is that one has RTree aceleration.
10293f3b3d003527861dc0bd89733857576408906431mtklein    SkCanvas* recordingCanvas1 = recorder1.beginRecording(SkIntToScalar(width),
10303f3b3d003527861dc0bd89733857576408906431mtklein                                                          SkIntToScalar(height),
103196fcdcc219d2a0d3579719b84b28bede76efba64halcanary                                                          nullptr, 0);
10323f3b3d003527861dc0bd89733857576408906431mtklein    SkCanvas* recordingCanvas2 = recorder2.beginRecording(SkIntToScalar(width),
10333f3b3d003527861dc0bd89733857576408906431mtklein                                                          SkIntToScalar(height),
1034a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                          &factory, 0);
1035a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    draw_blurred_rect(recordingCanvas1);
1036a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    draw_blurred_rect(recordingCanvas2);
1037ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> picture1(recorder1.finishRecordingAsPicture());
1038ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> picture2(recorder2.finishRecordingAsPicture());
1039837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    for (int y = 0; y < height; y += tileSize) {
1040837f5321a409228a27fc710eb71c87866b820cfbsenorblanco        for (int x = 0; x < width; x += tileSize) {
1041837f5321a409228a27fc710eb71c87866b820cfbsenorblanco            SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
1042ca2622ba051829fed5f30facd74c5b41cd4b931creed            draw_picture_clipped(&canvas1, tileRect, picture1.get());
1043ca2622ba051829fed5f30facd74c5b41cd4b931creed            draw_picture_clipped(&canvas2, tileRect, picture2.get());
1044837f5321a409228a27fc710eb71c87866b820cfbsenorblanco        }
1045837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    }
1046837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    for (int y = 0; y < height; y++) {
1047837f5321a409228a27fc710eb71c87866b820cfbsenorblanco        int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
1048837f5321a409228a27fc710eb71c87866b820cfbsenorblanco        REPORTER_ASSERT(reporter, !diffs);
1049837f5321a409228a27fc710eb71c87866b820cfbsenorblanco        if (diffs) {
1050837f5321a409228a27fc710eb71c87866b820cfbsenorblanco            break;
1051837f5321a409228a27fc710eb71c87866b820cfbsenorblanco        }
1052837f5321a409228a27fc710eb71c87866b820cfbsenorblanco    }
1053837f5321a409228a27fc710eb71c87866b820cfbsenorblanco}
1054837f5321a409228a27fc710eb71c87866b820cfbsenorblanco
10559195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.orgDEF_TEST(ImageFilterMatrixConvolution, reporter) {
10569195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    // Check that a 1x3 filter does not cause a spurious assert.
10579195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkScalar kernel[3] = {
10589195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org        SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
10599195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    };
10609195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkISize kernelSize = SkISize::Make(1, 3);
10619195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkScalar gain = SK_Scalar1, bias = 0;
10629195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkIPoint kernelOffset = SkIPoint::Make(0, 0);
10639195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org
1064ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips    sk_sp<SkImageFilter> filter(SkMatrixConvolutionImageFilter::Make(
1065ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips                                            kernelSize, kernel,
1066ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips                                            gain, bias, kernelOffset,
1067ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips                                            SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1068ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips                                            false, nullptr));
10699195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org
10709195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkBitmap result;
10719195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    int width = 16, height = 16;
10729195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    result.allocN32Pixels(width, height);
10739195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkCanvas canvas(result);
10749195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    canvas.clear(0);
10759195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org
10769195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkPaint paint;
1077ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips    paint.setImageFilter(std::move(filter));
10789195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
10799195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org    canvas.drawRect(rect, paint);
10809195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org}
10819195743aac79a4fa82059ab614b9795f215475f7senorblanco@chromium.org
10828c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.orgDEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
10838c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    // Check that a filter with borders outside the target bounds
10848c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    // does not crash.
10858c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkScalar kernel[3] = {
10868c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org        0, 0, 0,
10878c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    };
10888c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkISize kernelSize = SkISize::Make(3, 1);
10898c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkScalar gain = SK_Scalar1, bias = 0;
10908c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkIPoint kernelOffset = SkIPoint::Make(2, 0);
10918c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
1092ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips    sk_sp<SkImageFilter> filter(SkMatrixConvolutionImageFilter::Make(
1093ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips                                            kernelSize, kernel, gain, bias, kernelOffset,
1094ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips                                            SkMatrixConvolutionImageFilter::kClamp_TileMode,
1095ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips                                            true, nullptr));
10968c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
10978c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkBitmap result;
10988c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
10998c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    int width = 10, height = 10;
11008c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    result.allocN32Pixels(width, height);
11018c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkCanvas canvas(result);
11028c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    canvas.clear(0);
11038c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
11048c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkPaint filterPaint;
1105ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips    filterPaint.setImageFilter(std::move(filter));
11068c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkRect bounds = SkRect::MakeWH(1, 10);
11078c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
11088c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    SkPaint rectPaint;
11098c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    canvas.saveLayer(&bounds, &filterPaint);
11108c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    canvas.drawRect(rect, rectPaint);
11118c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org    canvas.restore();
11128c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org}
11138c7372bbe8949f2864bd3d9df00d85c5669a74b1senorblanco@chromium.org
11143e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_big_kernel(skiatest::Reporter* reporter, GrContext* context) {
1115dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    // Check that a kernel that is too big for the GPU still works
1116dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    SkScalar identityKernel[49] = {
1117dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips        0, 0, 0, 0, 0, 0, 0,
1118dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips        0, 0, 0, 0, 0, 0, 0,
1119dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips        0, 0, 0, 0, 0, 0, 0,
1120dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips        0, 0, 0, 1, 0, 0, 0,
1121dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips        0, 0, 0, 0, 0, 0, 0,
1122dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips        0, 0, 0, 0, 0, 0, 0,
1123dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips        0, 0, 0, 0, 0, 0, 0
1124dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    };
1125dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    SkISize kernelSize = SkISize::Make(7, 7);
1126dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    SkScalar gain = SK_Scalar1, bias = 0;
1127dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    SkIPoint kernelOffset = SkIPoint::Make(0, 0);
1128dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips
1129dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    sk_sp<SkImageFilter> filter(SkMatrixConvolutionImageFilter::Make(
1130dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips                                        kernelSize, identityKernel, gain, bias, kernelOffset,
1131dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips                                        SkMatrixConvolutionImageFilter::kClamp_TileMode,
1132dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips                                        true, nullptr));
1133dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips
11343e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 100));
1135dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    SkASSERT(srcImg);
1136dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips
1137dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    SkIPoint offset;
11382a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::OutputProperties noColorSpace(nullptr);
11392a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr, noColorSpace);
1140dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg.get(), ctx, &offset));
1141dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    REPORTER_ASSERT(reporter, resultImg);
1142dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    REPORTER_ASSERT(reporter, SkToBool(context) == resultImg->isTextureBacked());
1143dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    REPORTER_ASSERT(reporter, resultImg->width() == 100 && resultImg->height() == 100);
1144dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips    REPORTER_ASSERT(reporter, offset.fX == 0 && offset.fY == 0);
1145dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips}
1146dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips
1147dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillipsDEF_TEST(ImageFilterMatrixConvolutionBigKernel, reporter) {
11483e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_big_kernel(reporter, nullptr);
1149dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips}
1150dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips
1151dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips#if SK_SUPPORT_GPU
1152ab527a5bbfb1eae4f99a1435d349a44d00477d82egdanielDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterMatrixConvolutionBigKernel_Gpu,
1153ab527a5bbfb1eae4f99a1435d349a44d00477d82egdaniel                                   reporter, ctxInfo) {
11548b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_big_kernel(reporter, ctxInfo.grContext());
1155dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips}
1156dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips#endif
1157dada4dd9cf03e42369ca5b38086dba77f01a68e6robertphillips
1158aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.orgDEF_TEST(ImageFilterCropRect, reporter) {
11593e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_crop_rects(reporter, nullptr);
11604418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
11619a53fd7c41554630124522f4b6eedc16912abbb7robertphillips
11624418dbac3386f26c8da62ab242be9c178961eb18robertphillips#if SK_SUPPORT_GPU
116368d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCropRect_Gpu, reporter, ctxInfo) {
11648b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_crop_rects(reporter, ctxInfo.grContext());
1165aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org}
11664418dbac3386f26c8da62ab242be9c178961eb18robertphillips#endif
1167aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org
11689ea53f93e79ba312c4b3943923450a8b4aa57c82tfarinaDEF_TEST(ImageFilterMatrix, reporter) {
11695251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkBitmap temp;
1170deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    temp.allocN32Pixels(100, 100);
11719a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    SkCanvas canvas(temp);
11725251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
11735251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
11745251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkMatrix expectedMatrix = canvas.getTotalMatrix();
11755251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
11765fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkRTreeFactory factory;
11775fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkPictureRecorder recorder;
11785fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
11795251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
11805251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkPaint paint;
118143c2ad4e8f9ed84f46caa57e0b471f7393f1280arobertphillips    paint.setImageFilter(MatrixTestImageFilter::Make(reporter, expectedMatrix));
118296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    recordingCanvas->saveLayer(nullptr, &paint);
11835251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    SkPaint solidPaint;
11845251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    solidPaint.setColor(0xFFFFFFFF);
11855251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->save();
11865251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
11875251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
11885251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->restore(); // scale
11895251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org    recordingCanvas->restore(); // saveLayer
11905251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
1191ca2622ba051829fed5f30facd74c5b41cd4b931creed    canvas.drawPicture(recorder.finishRecordingAsPicture());
11925251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org}
11935251e2b91ac976f61e6252d931c1a0e746d2290asenorblanco@chromium.org
11943d822c29d4272a6749e59801b202b1ed6d611be8senorblancoDEF_TEST(ImageFilterCrossProcessPictureImageFilter, reporter) {
119597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkRTreeFactory factory;
119697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPictureRecorder recorder;
119797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
119897f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
119997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // Create an SkPicture which simply draws a green 1x1 rectangle.
120097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPaint greenPaint;
120197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    greenPaint.setColor(SK_ColorGREEN);
120297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
1203ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
120497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
120597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // Wrap that SkPicture in an SkPictureImageFilter.
12065ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips    sk_sp<SkImageFilter> imageFilter(SkPictureImageFilter::Make(picture));
120797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
120897f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // Check that SkPictureImageFilter successfully serializes its contained
120997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // SkPicture when not in cross-process mode.
121097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPaint paint;
12115ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips    paint.setImageFilter(imageFilter);
121297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPictureRecorder outerRecorder;
121397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
121497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPaint redPaintWithFilter;
121597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    redPaintWithFilter.setColor(SK_ColorRED);
12165ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips    redPaintWithFilter.setImageFilter(imageFilter);
121797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
1218ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> outerPicture(outerRecorder.finishRecordingAsPicture());
121997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
122097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkBitmap bitmap;
122197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    bitmap.allocN32Pixels(1, 1);
12229a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    SkCanvas canvas(bitmap);
122397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
122497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // The result here should be green, since the filter replaces the primitive's red interior.
122597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    canvas.clear(0x0);
12269b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(outerPicture);
122797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    uint32_t pixel = *bitmap.getAddr32(0, 0);
122897f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
122997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
123097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // Check that, for now, SkPictureImageFilter does not serialize or
123197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // deserialize its contained picture when the filter is serialized
123297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
123312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    sk_sp<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
12345e25717ab6313b011ec54eac0109c414aa8ffc17Mike Reed    sk_sp<SkImageFilter> unflattenedFilter = SkValidatingDeserializeImageFilter(data->data(),
12355e25717ab6313b011ec54eac0109c414aa8ffc17Mike Reed                                                                                data->size());
123697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
123797f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    redPaintWithFilter.setImageFilter(unflattenedFilter);
123897f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkPictureRecorder crossProcessRecorder;
123997f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
124097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
1241ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> crossProcessPicture(crossProcessRecorder.finishRecordingAsPicture());
124297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
124397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    canvas.clear(0x0);
12449b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(crossProcessPicture);
124597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org    pixel = *bitmap.getAddr32(0, 0);
1246446ee67fda73b11281b8e28a68edec811347c0c5hendrikw    // If the security precautions are enabled, the result here should not be green, since the
1247446ee67fda73b11281b8e28a68edec811347c0c5hendrikw    // filter draws nothing.
12482afbe23753bf97402a47408c83107042eea3c476mtklein    REPORTER_ASSERT(reporter, SkPicture::PictureIOSecurityPrecautionsEnabled()
1249446ee67fda73b11281b8e28a68edec811347c0c5hendrikw        ? pixel != SK_ColorGREEN : pixel == SK_ColorGREEN);
125097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org}
125197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org
12523e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_clipped_picture_imagefilter(skiatest::Reporter* reporter, GrContext* context) {
1253ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> picture;
12543d822c29d4272a6749e59801b202b1ed6d611be8senorblanco
12554418dbac3386f26c8da62ab242be9c178961eb18robertphillips    {
12564418dbac3386f26c8da62ab242be9c178961eb18robertphillips        SkRTreeFactory factory;
12574418dbac3386f26c8da62ab242be9c178961eb18robertphillips        SkPictureRecorder recorder;
12584418dbac3386f26c8da62ab242be9c178961eb18robertphillips        SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
12594418dbac3386f26c8da62ab242be9c178961eb18robertphillips
12604418dbac3386f26c8da62ab242be9c178961eb18robertphillips        // Create an SkPicture which simply draws a green 1x1 rectangle.
12614418dbac3386f26c8da62ab242be9c178961eb18robertphillips        SkPaint greenPaint;
12624418dbac3386f26c8da62ab242be9c178961eb18robertphillips        greenPaint.setColor(SK_ColorGREEN);
12634418dbac3386f26c8da62ab242be9c178961eb18robertphillips        recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
1264ca2622ba051829fed5f30facd74c5b41cd4b931creed        picture = recorder.finishRecordingAsPicture();
12654418dbac3386f26c8da62ab242be9c178961eb18robertphillips    }
12664418dbac3386f26c8da62ab242be9c178961eb18robertphillips
12673e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 2));
12683d822c29d4272a6749e59801b202b1ed6d611be8senorblanco
12695ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips    sk_sp<SkImageFilter> imageFilter(SkPictureImageFilter::Make(picture));
12703d822c29d4272a6749e59801b202b1ed6d611be8senorblanco
12713d822c29d4272a6749e59801b202b1ed6d611be8senorblanco    SkIPoint offset;
12722a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::OutputProperties noColorSpace(nullptr);
12732a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(1, 1, 1, 1), nullptr, noColorSpace);
12744418dbac3386f26c8da62ab242be9c178961eb18robertphillips
12752302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> resultImage(imageFilter->filterImage(srcImg.get(), ctx, &offset));
12764418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, !resultImage);
12774418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
12784418dbac3386f26c8da62ab242be9c178961eb18robertphillips
12794418dbac3386f26c8da62ab242be9c178961eb18robertphillipsDEF_TEST(ImageFilterClippedPictureImageFilter, reporter) {
12803e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_clipped_picture_imagefilter(reporter, nullptr);
12814418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
12824418dbac3386f26c8da62ab242be9c178961eb18robertphillips
12834418dbac3386f26c8da62ab242be9c178961eb18robertphillips#if SK_SUPPORT_GPU
128468d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterClippedPictureImageFilter_Gpu, reporter, ctxInfo) {
12858b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_clipped_picture_imagefilter(reporter, ctxInfo.grContext());
12863d822c29d4272a6749e59801b202b1ed6d611be8senorblanco}
12874418dbac3386f26c8da62ab242be9c178961eb18robertphillips#endif
12883d822c29d4272a6749e59801b202b1ed6d611be8senorblanco
12899ea53f93e79ba312c4b3943923450a8b4aa57c82tfarinaDEF_TEST(ImageFilterEmptySaveLayer, reporter) {
129068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    // Even when there's an empty saveLayer()/restore(), ensure that an image
129168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    // filter or color filter which affects transparent black still draws.
129268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
129368250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkBitmap bitmap;
129468250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    bitmap.allocN32Pixels(10, 10);
12959a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    SkCanvas canvas(bitmap);
129668250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
129768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkRTreeFactory factory;
129868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkPictureRecorder recorder;
129968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
13005605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkColorFilter> green(SkColorFilter::MakeModeFilter(SK_ColorGREEN,
13017d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                                                             SkBlendMode::kSrc));
13025605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkImageFilter> imageFilter(SkColorFilterImageFilter::Make(green, nullptr));
130368250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkPaint imageFilterPaint;
13045605b56afa5bd89f3148b397318b616fccfd4004robertphillips    imageFilterPaint.setImageFilter(std::move(imageFilter));
130568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkPaint colorFilterPaint;
1306d053ce9c54d4e5937a142278359e5a4cde18095ereed    colorFilterPaint.setColorFilter(green);
130768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
130868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkRect bounds = SkRect::MakeWH(10, 10);
130968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
131068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
131168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
131268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->restore();
1313ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
131468250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
131568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    canvas.clear(0);
13169b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(picture);
131768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    uint32_t pixel = *bitmap.getAddr32(0, 0);
131868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
131968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
132068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
132196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    recordingCanvas->saveLayer(nullptr, &imageFilterPaint);
132268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->restore();
1323ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> picture2(recorder.finishRecordingAsPicture());
132468250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
132568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    canvas.clear(0);
13269b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(picture2);
132768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    pixel = *bitmap.getAddr32(0, 0);
132868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
132968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
133068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
133168250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
133268250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    recordingCanvas->restore();
1333ca2622ba051829fed5f30facd74c5b41cd4b931creed    sk_sp<SkPicture> picture3(recorder.finishRecordingAsPicture());
133468250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
133568250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    canvas.clear(0);
13369b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(picture3);
133768250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    pixel = *bitmap.getAddr32(0, 0);
133868250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
133968250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org}
134068250c8e7c2bf5d669397c849259c3bcad40237esenorblanco@chromium.org
13419a53fd7c41554630124522f4b6eedc16912abbb7robertphillipsstatic void test_huge_blur(SkCanvas* canvas, skiatest::Reporter* reporter) {
134209843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkBitmap bitmap;
134309843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    bitmap.allocN32Pixels(100, 100);
134409843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    bitmap.eraseARGB(0, 0, 0, 0);
134509843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
134609843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    // Check that a blur with an insane radius does not crash or assert.
134709843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkPaint paint;
13486e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    paint.setImageFilter(SkBlurImageFilter::Make(SkIntToScalar(1<<30),
13496e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                 SkIntToScalar(1<<30),
13506e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                 nullptr));
1351da420b976e61071cfe5de10556b4b23e519091d6reed    canvas->drawBitmap(bitmap, 0, 0, &paint);
135209843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org}
135309843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
135409843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.orgDEF_TEST(HugeBlurImageFilter, reporter) {
135509843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    SkBitmap temp;
135609843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org    temp.allocN32Pixels(100, 100);
13579a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    SkCanvas canvas(temp);
13589a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    test_huge_blur(&canvas, reporter);
135909843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org}
136009843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
136121a465d7f4c5e639044e79971aeaa1194fc73078senorblancoDEF_TEST(ImageFilterMatrixConvolutionSanityTest, reporter) {
13623a49520696b2eca69e57884657d23fd2402ccfd1senorblanco    SkScalar kernel[1] = { 0 };
13633a49520696b2eca69e57884657d23fd2402ccfd1senorblanco    SkScalar gain = SK_Scalar1, bias = 0;
13643a49520696b2eca69e57884657d23fd2402ccfd1senorblanco    SkIPoint kernelOffset = SkIPoint::Make(1, 1);
13653a49520696b2eca69e57884657d23fd2402ccfd1senorblanco
136696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    // Check that an enormous (non-allocatable) kernel gives a nullptr filter.
1367ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips    sk_sp<SkImageFilter> conv(SkMatrixConvolutionImageFilter::Make(
13683a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        SkISize::Make(1<<30, 1<<30),
13693a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        kernel,
13703a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        gain,
13713a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        bias,
13723a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        kernelOffset,
13733a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1374ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips        false,
1375ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips        nullptr));
13763a49520696b2eca69e57884657d23fd2402ccfd1senorblanco
137796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, nullptr == conv.get());
13783a49520696b2eca69e57884657d23fd2402ccfd1senorblanco
137996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    // Check that a nullptr kernel gives a nullptr filter.
1380ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips    conv = SkMatrixConvolutionImageFilter::Make(
13813a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        SkISize::Make(1, 1),
138296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        nullptr,
13833a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        gain,
13843a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        bias,
13853a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        kernelOffset,
13863a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1387ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips        false,
1388ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips        nullptr);
13893a49520696b2eca69e57884657d23fd2402ccfd1senorblanco
139096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, nullptr == conv.get());
13913a49520696b2eca69e57884657d23fd2402ccfd1senorblanco
139296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    // Check that a kernel width < 1 gives a nullptr filter.
1393ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips    conv = SkMatrixConvolutionImageFilter::Make(
13943a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        SkISize::Make(0, 1),
13953a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        kernel,
13963a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        gain,
13973a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        bias,
13983a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        kernelOffset,
13993a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1400ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips        false,
1401ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips        nullptr);
14023a49520696b2eca69e57884657d23fd2402ccfd1senorblanco
140396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, nullptr == conv.get());
14043a49520696b2eca69e57884657d23fd2402ccfd1senorblanco
140596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    // Check that kernel height < 1 gives a nullptr filter.
1406ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips    conv = SkMatrixConvolutionImageFilter::Make(
14073a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        SkISize::Make(1, -1),
14083a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        kernel,
14093a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        gain,
14103a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        bias,
14113a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        kernelOffset,
14123a49520696b2eca69e57884657d23fd2402ccfd1senorblanco        SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1413ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips        false,
1414ef6a47b4af1ebf621682b3398916fefb90fc912erobertphillips        nullptr);
14153a49520696b2eca69e57884657d23fd2402ccfd1senorblanco
141696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, nullptr == conv.get());
14173a49520696b2eca69e57884657d23fd2402ccfd1senorblanco}
14183a49520696b2eca69e57884657d23fd2402ccfd1senorblanco
14199a53fd7c41554630124522f4b6eedc16912abbb7robertphillipsstatic void test_xfermode_cropped_input(SkCanvas* canvas, skiatest::Reporter* reporter) {
14209a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    canvas->clear(0);
1421ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
1422ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkBitmap bitmap;
1423ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    bitmap.allocN32Pixels(1, 1);
1424ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    bitmap.eraseARGB(255, 255, 255, 255);
1425ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
14265605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkColorFilter> green(SkColorFilter::MakeModeFilter(SK_ColorGREEN,
14277d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                                                             SkBlendMode::kSrcIn));
14285605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkImageFilter> greenFilter(SkColorFilterImageFilter::Make(green, nullptr));
1429ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkImageFilter::CropRect cropRect(SkRect::MakeEmpty());
14305605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkImageFilter> croppedOut(SkColorFilterImageFilter::Make(green, nullptr, &cropRect));
1431ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
1432ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    // Check that an xfermode image filter whose input has been cropped out still draws the other
1433ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
1434374772bd61951f01bf84fe17bf53d8867681c9aereed    SkBlendMode mode = SkBlendMode::kSrcOver;
14358c0326df5f600da43a054dad3b354221dd6b790frobertphillips    sk_sp<SkImageFilter> xfermodeNoFg(SkXfermodeImageFilter::Make(mode, greenFilter,
14368c0326df5f600da43a054dad3b354221dd6b790frobertphillips                                                                  croppedOut, nullptr));
14378c0326df5f600da43a054dad3b354221dd6b790frobertphillips    sk_sp<SkImageFilter> xfermodeNoBg(SkXfermodeImageFilter::Make(mode, croppedOut,
14388c0326df5f600da43a054dad3b354221dd6b790frobertphillips                                                                  greenFilter, nullptr));
14398c0326df5f600da43a054dad3b354221dd6b790frobertphillips    sk_sp<SkImageFilter> xfermodeNoFgNoBg(SkXfermodeImageFilter::Make(mode, croppedOut,
14408c0326df5f600da43a054dad3b354221dd6b790frobertphillips                                                                      croppedOut, nullptr));
1441ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
1442ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkPaint paint;
14438c0326df5f600da43a054dad3b354221dd6b790frobertphillips    paint.setImageFilter(std::move(xfermodeNoFg));
1444da420b976e61071cfe5de10556b4b23e519091d6reed    canvas->drawBitmap(bitmap, 0, 0, &paint);   // drawSprite
1445ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
1446ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    uint32_t pixel;
1447a9d9a392380952006303d83c35a63a32dffd0b36kkinnunen    SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
14489a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    canvas->readPixels(info, &pixel, 4, 0, 0);
1449ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1450ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
14518c0326df5f600da43a054dad3b354221dd6b790frobertphillips    paint.setImageFilter(std::move(xfermodeNoBg));
1452da420b976e61071cfe5de10556b4b23e519091d6reed    canvas->drawBitmap(bitmap, 0, 0, &paint);   // drawSprite
14539a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    canvas->readPixels(info, &pixel, 4, 0, 0);
1454ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1455ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
14568c0326df5f600da43a054dad3b354221dd6b790frobertphillips    paint.setImageFilter(std::move(xfermodeNoFgNoBg));
1457da420b976e61071cfe5de10556b4b23e519091d6reed    canvas->drawBitmap(bitmap, 0, 0, &paint);   // drawSprite
14589a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    canvas->readPixels(info, &pixel, 4, 0, 0);
1459ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1460ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org}
1461ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
1462d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.orgDEF_TEST(ImageFilterNestedSaveLayer, reporter) {
1463d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkBitmap temp;
1464d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    temp.allocN32Pixels(50, 50);
14659a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    SkCanvas canvas(temp);
1466d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.clear(0x0);
1467d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
1468d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkBitmap bitmap;
1469d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    bitmap.allocN32Pixels(10, 10);
1470d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    bitmap.eraseColor(SK_ColorGREEN);
1471d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
1472d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkMatrix matrix;
1473d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
1474d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
1475ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips    sk_sp<SkImageFilter> matrixFilter(
1476ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips        SkImageFilter::MakeMatrixFilter(matrix, kLow_SkFilterQuality, nullptr));
1477d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
1478d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    // Test that saveLayer() with a filter nested inside another saveLayer() applies the
1479d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    // correct offset to the filter matrix.
1480d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
148196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    canvas.saveLayer(&bounds1, nullptr);
1482d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkPaint filterPaint;
1483ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips    filterPaint.setImageFilter(std::move(matrixFilter));
1484d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
1485d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.saveLayer(&bounds2, &filterPaint);
1486d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkPaint greenPaint;
1487d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    greenPaint.setColor(SK_ColorGREEN);
1488d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.drawRect(bounds2, greenPaint);
1489d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.restore();
1490d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.restore();
1491d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    SkPaint strokePaint;
1492d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    strokePaint.setStyle(SkPaint::kStroke_Style);
1493d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    strokePaint.setColor(SK_ColorRED);
1494d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
1495a9d9a392380952006303d83c35a63a32dffd0b36kkinnunen    SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
1496d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    uint32_t pixel;
1497d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.readPixels(info, &pixel, 4, 25, 25);
1498d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1499d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
1500d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    // Test that drawSprite() with a filter nested inside a saveLayer() applies the
1501d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    // correct offset to the filter matrix.
1502d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.clear(0x0);
1503d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.readPixels(info, &pixel, 4, 25, 25);
150496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    canvas.saveLayer(&bounds1, nullptr);
1505da420b976e61071cfe5de10556b4b23e519091d6reed    canvas.drawBitmap(bitmap, 20, 20, &filterPaint);    // drawSprite
1506d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.restore();
1507d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
1508d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    canvas.readPixels(info, &pixel, 4, 25, 25);
1509d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org    REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1510d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org}
1511d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org
1512ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.orgDEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
1513ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    SkBitmap temp;
1514ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org    temp.allocN32Pixels(100, 100);
15159a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    SkCanvas canvas(temp);
15169a53fd7c41554630124522f4b6eedc16912abbb7robertphillips    test_xfermode_cropped_input(&canvas, reporter);
1517ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org}
151809843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org
15193e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_composed_imagefilter_offset(skiatest::Reporter* reporter, GrContext* context) {
15203e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 100));
15215788faaa2ac4203827c68006b669e277d441e2e4ajuma
15225788faaa2ac4203827c68006b669e277d441e2e4ajuma    SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(1, 0, 20, 20));
152351a315eff9b86bd60e7884240c4efc199129d37arobertphillips    sk_sp<SkImageFilter> offsetFilter(SkOffsetImageFilter::Make(0, 0, nullptr, &cropRect));
15246e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> blurFilter(SkBlurImageFilter::Make(SK_Scalar1, SK_Scalar1,
15256e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                            nullptr, &cropRect));
1526491fb17cab07574a9d5656c1c97ad0acc3af5c70robertphillips    sk_sp<SkImageFilter> composedFilter(SkComposeImageFilter::Make(std::move(blurFilter),
1527491fb17cab07574a9d5656c1c97ad0acc3af5c70robertphillips                                                                   std::move(offsetFilter)));
15285788faaa2ac4203827c68006b669e277d441e2e4ajuma    SkIPoint offset;
15292a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::OutputProperties noColorSpace(nullptr);
15302a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr, noColorSpace);
15314418dbac3386f26c8da62ab242be9c178961eb18robertphillips
15322302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> resultImg(composedFilter->filterImage(srcImg.get(), ctx, &offset));
15334418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, resultImg);
15345788faaa2ac4203827c68006b669e277d441e2e4ajuma    REPORTER_ASSERT(reporter, offset.fX == 1 && offset.fY == 0);
15355788faaa2ac4203827c68006b669e277d441e2e4ajuma}
15365788faaa2ac4203827c68006b669e277d441e2e4ajuma
15374418dbac3386f26c8da62ab242be9c178961eb18robertphillipsDEF_TEST(ComposedImageFilterOffset, reporter) {
15383e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_composed_imagefilter_offset(reporter, nullptr);
15394418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
15404418dbac3386f26c8da62ab242be9c178961eb18robertphillips
15414418dbac3386f26c8da62ab242be9c178961eb18robertphillips#if SK_SUPPORT_GPU
154268d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ComposedImageFilterOffset_Gpu, reporter, ctxInfo) {
15438b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_composed_imagefilter_offset(reporter, ctxInfo.grContext());
15444418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
15454418dbac3386f26c8da62ab242be9c178961eb18robertphillips#endif
15464418dbac3386f26c8da62ab242be9c178961eb18robertphillips
15473e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_composed_imagefilter_bounds(skiatest::Reporter* reporter, GrContext* context) {
154817a652017a0243c57c954662e08a7976b9990feejbroman    // The bounds passed to the inner filter must be filtered by the outer
154917a652017a0243c57c954662e08a7976b9990feejbroman    // filter, so that the inner filter produces the pixels that the outer
155017a652017a0243c57c954662e08a7976b9990feejbroman    // filter requires as input. This matters if the outer filter moves pixels.
155117a652017a0243c57c954662e08a7976b9990feejbroman    // Here, accounting for the outer offset is necessary so that the green
155217a652017a0243c57c954662e08a7976b9990feejbroman    // pixels of the picture are not clipped.
155317a652017a0243c57c954662e08a7976b9990feejbroman
155417a652017a0243c57c954662e08a7976b9990feejbroman    SkPictureRecorder recorder;
155517a652017a0243c57c954662e08a7976b9990feejbroman    SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeWH(200, 100));
155617a652017a0243c57c954662e08a7976b9990feejbroman    recordingCanvas->clipRect(SkRect::MakeXYWH(100, 0, 100, 100));
155717a652017a0243c57c954662e08a7976b9990feejbroman    recordingCanvas->clear(SK_ColorGREEN);
1558491fb17cab07574a9d5656c1c97ad0acc3af5c70robertphillips    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
15595ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips    sk_sp<SkImageFilter> pictureFilter(SkPictureImageFilter::Make(picture));
156017a652017a0243c57c954662e08a7976b9990feejbroman    SkImageFilter::CropRect cropRect(SkRect::MakeWH(100, 100));
156151a315eff9b86bd60e7884240c4efc199129d37arobertphillips    sk_sp<SkImageFilter> offsetFilter(SkOffsetImageFilter::Make(-100, 0, nullptr, &cropRect));
1562491fb17cab07574a9d5656c1c97ad0acc3af5c70robertphillips    sk_sp<SkImageFilter> composedFilter(SkComposeImageFilter::Make(std::move(offsetFilter),
1563491fb17cab07574a9d5656c1c97ad0acc3af5c70robertphillips                                                                   std::move(pictureFilter)));
156417a652017a0243c57c954662e08a7976b9990feejbroman
15653e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> sourceImage(create_empty_special_image(context, 100));
15662a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::OutputProperties noColorSpace(nullptr);
15672a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr, noColorSpace);
156817a652017a0243c57c954662e08a7976b9990feejbroman    SkIPoint offset;
156917a652017a0243c57c954662e08a7976b9990feejbroman    sk_sp<SkSpecialImage> result(composedFilter->filterImage(sourceImage.get(), ctx, &offset));
157017a652017a0243c57c954662e08a7976b9990feejbroman    REPORTER_ASSERT(reporter, offset.isZero());
157117a652017a0243c57c954662e08a7976b9990feejbroman    REPORTER_ASSERT(reporter, result);
157217a652017a0243c57c954662e08a7976b9990feejbroman    REPORTER_ASSERT(reporter, result->subset().size() == SkISize::Make(100, 100));
157317a652017a0243c57c954662e08a7976b9990feejbroman
157417a652017a0243c57c954662e08a7976b9990feejbroman    SkBitmap resultBM;
1575646125114b42b24e5ada3c9f8fac53a85f9ad2a0robertphillips    REPORTER_ASSERT(reporter, result->getROPixels(&resultBM));
157617a652017a0243c57c954662e08a7976b9990feejbroman    SkAutoLockPixels lock(resultBM);
157717a652017a0243c57c954662e08a7976b9990feejbroman    REPORTER_ASSERT(reporter, resultBM.getColor(50, 50) == SK_ColorGREEN);
157817a652017a0243c57c954662e08a7976b9990feejbroman}
157917a652017a0243c57c954662e08a7976b9990feejbroman
158017a652017a0243c57c954662e08a7976b9990feejbromanDEF_TEST(ComposedImageFilterBounds, reporter) {
15813e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_composed_imagefilter_bounds(reporter, nullptr);
158217a652017a0243c57c954662e08a7976b9990feejbroman}
158317a652017a0243c57c954662e08a7976b9990feejbroman
158417a652017a0243c57c954662e08a7976b9990feejbroman#if SK_SUPPORT_GPU
1585ab527a5bbfb1eae4f99a1435d349a44d00477d82egdanielDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ComposedImageFilterBounds_Gpu, reporter, ctxInfo) {
15868b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_composed_imagefilter_bounds(reporter, ctxInfo.grContext());
158717a652017a0243c57c954662e08a7976b9990feejbroman}
158817a652017a0243c57c954662e08a7976b9990feejbroman#endif
158917a652017a0243c57c954662e08a7976b9990feejbroman
15903e302275b324172c845627cbd00cee8a06571bafrobertphillipsstatic void test_partial_crop_rect(skiatest::Reporter* reporter, GrContext* context) {
15913e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> srcImg(create_empty_special_image(context, 100));
159224d2a7b463d585f9300ceac946431e822531d504senorblanco
159324d2a7b463d585f9300ceac946431e822531d504senorblanco    SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(100, 0, 20, 30),
1594ed7cf273226ca5818a9d58b0f9183d665bb1ff58senorblanco        SkImageFilter::CropRect::kHasWidth_CropEdge | SkImageFilter::CropRect::kHasHeight_CropEdge);
15955605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkImageFilter> filter(make_grayscale(nullptr, &cropRect));
159624d2a7b463d585f9300ceac946431e822531d504senorblanco    SkIPoint offset;
15972a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::OutputProperties noColorSpace(nullptr);
15982a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr, noColorSpace);
15994418dbac3386f26c8da62ab242be9c178961eb18robertphillips
16002302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg.get(), ctx, &offset));
16014418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, resultImg);
16024418dbac3386f26c8da62ab242be9c178961eb18robertphillips
160324d2a7b463d585f9300ceac946431e822531d504senorblanco    REPORTER_ASSERT(reporter, offset.fX == 0);
160424d2a7b463d585f9300ceac946431e822531d504senorblanco    REPORTER_ASSERT(reporter, offset.fY == 0);
16054418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, resultImg->width() == 20);
16064418dbac3386f26c8da62ab242be9c178961eb18robertphillips    REPORTER_ASSERT(reporter, resultImg->height() == 30);
16074418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
16084418dbac3386f26c8da62ab242be9c178961eb18robertphillips
160921a465d7f4c5e639044e79971aeaa1194fc73078senorblancoDEF_TEST(ImageFilterPartialCropRect, reporter) {
16103e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_partial_crop_rect(reporter, nullptr);
161124d2a7b463d585f9300ceac946431e822531d504senorblanco}
161224d2a7b463d585f9300ceac946431e822531d504senorblanco
16134418dbac3386f26c8da62ab242be9c178961eb18robertphillips#if SK_SUPPORT_GPU
161468d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterPartialCropRect_Gpu, reporter, ctxInfo) {
16158b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    test_partial_crop_rect(reporter, ctxInfo.grContext());
16164418dbac3386f26c8da62ab242be9c178961eb18robertphillips}
16174418dbac3386f26c8da62ab242be9c178961eb18robertphillips#endif
16184418dbac3386f26c8da62ab242be9c178961eb18robertphillips
16190abdf766d395ed3b7059511425f431589eca05f6senorblancoDEF_TEST(ImageFilterCanComputeFastBounds, reporter) {
16200abdf766d395ed3b7059511425f431589eca05f6senorblanco
162112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    {
162212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
162312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        sk_sp<SkImageFilter> lighting(SkLightingImageFilter::MakePointLitDiffuse(location,
162412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                                 SK_ColorGREEN,
162512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                                 0, 0, nullptr));
162612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        REPORTER_ASSERT(reporter, !lighting->canComputeFastBounds());
162712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    }
16280abdf766d395ed3b7059511425f431589eca05f6senorblanco
16290abdf766d395ed3b7059511425f431589eca05f6senorblanco    {
16306e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        sk_sp<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
16316e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
16326e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        {
16336e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            SkColorFilter* grayCF;
16346e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            REPORTER_ASSERT(reporter, gray->asAColorFilter(&grayCF));
16356e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            REPORTER_ASSERT(reporter, !grayCF->affectsTransparentBlack());
16366e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips            grayCF->unref();
16376e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        }
16386e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
16390abdf766d395ed3b7059511425f431589eca05f6senorblanco
16406e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        sk_sp<SkImageFilter> grayBlur(SkBlurImageFilter::Make(SK_Scalar1, SK_Scalar1,
16416e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                              std::move(gray)));
16426e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        REPORTER_ASSERT(reporter, grayBlur->canComputeFastBounds());
16436e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    }
16440abdf766d395ed3b7059511425f431589eca05f6senorblanco
16456e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    {
16466e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        SkScalar greenMatrix[20] = { 0, 0, 0, 0, 0,
16476e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                     0, 0, 0, 0, 1,
16486e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                     0, 0, 0, 0, 0,
16496e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                     0, 0, 0, 0, 1 };
16506e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        sk_sp<SkColorFilter> greenCF(SkColorFilter::MakeMatrixFilterRowMajor255(greenMatrix));
16515605b56afa5bd89f3148b397318b616fccfd4004robertphillips        sk_sp<SkImageFilter> green(SkColorFilterImageFilter::Make(greenCF, nullptr));
16526e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
16536e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        REPORTER_ASSERT(reporter, greenCF->affectsTransparentBlack());
16546e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        REPORTER_ASSERT(reporter, !green->canComputeFastBounds());
16556e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips
16566e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        sk_sp<SkImageFilter> greenBlur(SkBlurImageFilter::Make(SK_Scalar1, SK_Scalar1,
16576e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips                                                               std::move(green)));
16586e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips        REPORTER_ASSERT(reporter, !greenBlur->canComputeFastBounds());
16596e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    }
16600abdf766d395ed3b7059511425f431589eca05f6senorblanco
16610abdf766d395ed3b7059511425f431589eca05f6senorblanco    uint8_t allOne[256], identity[256];
16620abdf766d395ed3b7059511425f431589eca05f6senorblanco    for (int i = 0; i < 256; ++i) {
16630abdf766d395ed3b7059511425f431589eca05f6senorblanco        identity[i] = i;
16640abdf766d395ed3b7059511425f431589eca05f6senorblanco        allOne[i] = 255;
16650abdf766d395ed3b7059511425f431589eca05f6senorblanco    }
16660abdf766d395ed3b7059511425f431589eca05f6senorblanco
16675605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkColorFilter> identityCF(SkTableColorFilter::MakeARGB(identity, identity,
16685605b56afa5bd89f3148b397318b616fccfd4004robertphillips                                                                 identity, allOne));
16695605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkImageFilter> identityFilter(SkColorFilterImageFilter::Make(identityCF, nullptr));
16700abdf766d395ed3b7059511425f431589eca05f6senorblanco    REPORTER_ASSERT(reporter, !identityCF->affectsTransparentBlack());
16710abdf766d395ed3b7059511425f431589eca05f6senorblanco    REPORTER_ASSERT(reporter, identityFilter->canComputeFastBounds());
16720abdf766d395ed3b7059511425f431589eca05f6senorblanco
16735605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkColorFilter> forceOpaqueCF(SkTableColorFilter::MakeARGB(allOne, identity,
16745605b56afa5bd89f3148b397318b616fccfd4004robertphillips                                                                    identity, identity));
16755605b56afa5bd89f3148b397318b616fccfd4004robertphillips    sk_sp<SkImageFilter> forceOpaque(SkColorFilterImageFilter::Make(forceOpaqueCF, nullptr));
16760abdf766d395ed3b7059511425f431589eca05f6senorblanco    REPORTER_ASSERT(reporter, forceOpaqueCF->affectsTransparentBlack());
16770abdf766d395ed3b7059511425f431589eca05f6senorblanco    REPORTER_ASSERT(reporter, !forceOpaque->canComputeFastBounds());
16780abdf766d395ed3b7059511425f431589eca05f6senorblanco}
16790abdf766d395ed3b7059511425f431589eca05f6senorblanco
1680cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita// Verify that SkImageSource survives serialization
1681cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalitaDEF_TEST(ImageFilterImageSourceSerialization, reporter) {
1682e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    auto surface(SkSurface::MakeRasterN32Premul(10, 10));
1683cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    surface->getCanvas()->clear(SK_ColorGREEN);
16849ce9d6772df650ceb0511f275e1a83dffa78ff72reed    sk_sp<SkImage> image(surface->makeImageSnapshot());
1685549c8991959333e5c0f53faebcbbd5d6bc8f6a56robertphillips    sk_sp<SkImageFilter> filter(SkImageSource::Make(std::move(image)));
1686cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita
1687549c8991959333e5c0f53faebcbbd5d6bc8f6a56robertphillips    sk_sp<SkData> data(SkValidatingSerializeFlattenable(filter.get()));
16885e25717ab6313b011ec54eac0109c414aa8ffc17Mike Reed    sk_sp<SkImageFilter> unflattenedFilter = SkValidatingDeserializeImageFilter(data->data(),
16895e25717ab6313b011ec54eac0109c414aa8ffc17Mike Reed                                                                                data->size());
1690cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    REPORTER_ASSERT(reporter, unflattenedFilter);
1691cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita
1692cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    SkBitmap bm;
1693cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    bm.allocN32Pixels(10, 10);
169423cb88c52cd8bb7a0de80e2c85280375425c5189fmalita    bm.eraseColor(SK_ColorBLUE);
1695cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    SkPaint paint;
1696cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    paint.setColor(SK_ColorRED);
1697cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    paint.setImageFilter(unflattenedFilter);
1698cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita
1699cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    SkCanvas canvas(bm);
1700cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    canvas.drawRect(SkRect::MakeWH(10, 10), paint);
1701cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita    REPORTER_ASSERT(reporter, *bm.getAddr32(0, 0) == SkPreMultiplyColor(SK_ColorGREEN));
1702cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita}
1703cd56f812e09fdd8f8322c5c28cbc4423a74b9a0afmalita
170445eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomonstatic void test_large_blur_input(skiatest::Reporter* reporter, SkCanvas* canvas) {
170545eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    SkBitmap largeBmp;
170645eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    int largeW = 5000;
170745eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    int largeH = 5000;
170845eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon#if SK_SUPPORT_GPU
170945eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    // If we're GPU-backed make the bitmap too large to be converted into a texture.
171045eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    if (GrContext* ctx = canvas->getGrContext()) {
171145eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon        largeW = ctx->caps()->maxTextureSize() + 1;
171245eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    }
171345eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon#endif
171445eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon
171545eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    largeBmp.allocN32Pixels(largeW, largeH);
17162afbe23753bf97402a47408c83107042eea3c476mtklein    largeBmp.eraseColor(0);
171745eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    if (!largeBmp.getPixels()) {
171845eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon        ERRORF(reporter, "Failed to allocate large bmp.");
171945eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon        return;
172045eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    }
172145eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon
17229ce9d6772df650ceb0511f275e1a83dffa78ff72reed    sk_sp<SkImage> largeImage(SkImage::MakeFromBitmap(largeBmp));
172345eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    if (!largeImage) {
172445eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon        ERRORF(reporter, "Failed to create large image.");
172545eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon        return;
172645eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    }
172745eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon
1728549c8991959333e5c0f53faebcbbd5d6bc8f6a56robertphillips    sk_sp<SkImageFilter> largeSource(SkImageSource::Make(std::move(largeImage)));
172945eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    if (!largeSource) {
173045eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon        ERRORF(reporter, "Failed to create large SkImageSource.");
173145eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon        return;
173245eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    }
173345eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon
17346e7025ab13dfc4f0037233e67b4b8e18d6dfd1e1robertphillips    sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(10.f, 10.f, std::move(largeSource)));
173545eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    if (!blur) {
173645eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon        ERRORF(reporter, "Failed to create SkBlurImageFilter.");
173745eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon        return;
173845eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    }
173945eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon
174045eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    SkPaint paint;
1741549c8991959333e5c0f53faebcbbd5d6bc8f6a56robertphillips    paint.setImageFilter(std::move(blur));
174245eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon
174345eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    // This should not crash (http://crbug.com/570479).
174445eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    canvas->drawRect(SkRect::MakeIWH(largeW, largeH), paint);
174545eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon}
174645eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon
174721a465d7f4c5e639044e79971aeaa1194fc73078senorblancoDEF_TEST(ImageFilterBlurLargeImage, reporter) {
1748e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    auto surface(SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(100, 100)));
174945eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    test_large_blur_input(reporter, surface->getCanvas());
175045eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon}
175145eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon
17525878dbdf1b5d86201d299c6e07d53e35048713c7senorblancostatic void test_make_with_filter(skiatest::Reporter* reporter, GrContext* context) {
1753a5fdc974a996dca79be8388e61db68043001760bRobert Phillips    sk_sp<SkSurface> surface(create_surface(context, 192, 128));
17545878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    surface->getCanvas()->clear(SK_ColorRED);
17555878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    SkPaint bluePaint;
17565878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    bluePaint.setColor(SK_ColorBLUE);
17575878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    SkIRect subset = SkIRect::MakeXYWH(25, 20, 50, 50);
17585878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    surface->getCanvas()->drawRect(SkRect::Make(subset), bluePaint);
17595878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    sk_sp<SkImage> sourceImage = surface->makeImageSnapshot();
17605878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17615878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    sk_sp<SkImageFilter> filter = make_grayscale(nullptr, nullptr);
17625878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    SkIRect clipBounds = SkIRect::MakeXYWH(30, 35, 100, 100);
17635878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    SkIRect outSubset;
17645878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    SkIPoint offset;
17655878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    sk_sp<SkImage> result;
17665878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17675878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    result = sourceImage->makeWithFilter(nullptr, subset, clipBounds, &outSubset, &offset);
17685878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, !result);
17695878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17705878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    result = sourceImage->makeWithFilter(filter.get(), subset, clipBounds, nullptr, &offset);
17715878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, !result);
17725878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17735878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    result = sourceImage->makeWithFilter(filter.get(), subset, clipBounds, &outSubset, nullptr);
17745878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, !result);
17755878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17765878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    SkIRect bigSubset = SkIRect::MakeXYWH(-10000, -10000, 20000, 20000);
17775878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    result = sourceImage->makeWithFilter(filter.get(), bigSubset, clipBounds, &outSubset, &offset);
17785878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, !result);
17795878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17805878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    SkIRect empty = SkIRect::MakeEmpty();
17815878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    result = sourceImage->makeWithFilter(filter.get(), empty, clipBounds, &outSubset, &offset);
17825878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, !result);
17835878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17845878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    result = sourceImage->makeWithFilter(filter.get(), subset, empty, &outSubset, &offset);
17855878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, !result);
17865878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17875878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    SkIRect leftField = SkIRect::MakeXYWH(-1000, 0, 100, 100);
17885878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    result = sourceImage->makeWithFilter(filter.get(), subset, leftField, &outSubset, &offset);
17895878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, !result);
17905878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17915878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    result = sourceImage->makeWithFilter(filter.get(), subset, clipBounds, &outSubset, &offset);
17925878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
17935878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, result);
17945878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, result->bounds().contains(outSubset));
17955878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    SkIRect destRect = SkIRect::MakeXYWH(offset.x(), offset.y(),
17965878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco                                          outSubset.width(), outSubset.height());
17975878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    REPORTER_ASSERT(reporter, clipBounds.contains(destRect));
1798a5fdc974a996dca79be8388e61db68043001760bRobert Phillips
1799a5fdc974a996dca79be8388e61db68043001760bRobert Phillips    // In GPU-mode, this case creates a special image with a backing size that differs from
1800a5fdc974a996dca79be8388e61db68043001760bRobert Phillips    // the content size
1801a5fdc974a996dca79be8388e61db68043001760bRobert Phillips    {
1802a5fdc974a996dca79be8388e61db68043001760bRobert Phillips        clipBounds.setXYWH(0, 0, 170, 100);
1803a5fdc974a996dca79be8388e61db68043001760bRobert Phillips        subset.setXYWH(0, 0, 160, 90);
1804a5fdc974a996dca79be8388e61db68043001760bRobert Phillips
1805a5fdc974a996dca79be8388e61db68043001760bRobert Phillips        filter = SkXfermodeImageFilter::Make(SkBlendMode::kSrc, nullptr);
1806a5fdc974a996dca79be8388e61db68043001760bRobert Phillips        result = sourceImage->makeWithFilter(filter.get(), subset, clipBounds, &outSubset, &offset);
1807a5fdc974a996dca79be8388e61db68043001760bRobert Phillips        REPORTER_ASSERT(reporter, result);
1808a5fdc974a996dca79be8388e61db68043001760bRobert Phillips    }
18095878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco}
18105878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
18115878dbdf1b5d86201d299c6e07d53e35048713c7senorblancoDEF_TEST(ImageFilterMakeWithFilter, reporter) {
18125878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    test_make_with_filter(reporter, nullptr);
18135878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco}
18145878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
18155878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco#if SK_SUPPORT_GPU
18165878dbdf1b5d86201d299c6e07d53e35048713c7senorblancoDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterMakeWithFilter_Gpu, reporter, ctxInfo) {
18175878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco    test_make_with_filter(reporter, ctxInfo.grContext());
18185878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco}
18195878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco#endif
18205878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco
182158d1466c7773984b7ce4bd75ebf7c97cd42f7d12senorblanco@chromium.org#if SK_SUPPORT_GPU
18224a8126e7f81384526629b1e21bf89b632ea13cd9reed
182368d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterHugeBlur_Gpu, reporter, ctxInfo) {
1824efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips
18258b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(ctxInfo.grContext(),
18263e302275b324172c845627cbd00cee8a06571bafrobertphillips                                                      SkBudgeted::kNo,
18273e302275b324172c845627cbd00cee8a06571bafrobertphillips                                                      SkImageInfo::MakeN32Premul(100, 100)));
18289a53fd7c41554630124522f4b6eedc16912abbb7robertphillips
18293e302275b324172c845627cbd00cee8a06571bafrobertphillips
18303e302275b324172c845627cbd00cee8a06571bafrobertphillips    SkCanvas* canvas = surf->getCanvas();
18313e302275b324172c845627cbd00cee8a06571bafrobertphillips
18323e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_huge_blur(canvas, reporter);
183309843fd5c15e84e9b14ab511a04d9d639149fa75senorblanco@chromium.org}
1834ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org
1835ab527a5bbfb1eae4f99a1435d349a44d00477d82egdanielDEF_GPUTEST_FOR_RENDERING_CONTEXTS(XfermodeImageFilterCroppedInput_Gpu, reporter, ctxInfo) {
1836efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips
18378b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(ctxInfo.grContext(),
18383e302275b324172c845627cbd00cee8a06571bafrobertphillips                                                      SkBudgeted::kNo,
18393e302275b324172c845627cbd00cee8a06571bafrobertphillips                                                      SkImageInfo::MakeN32Premul(1, 1)));
18409a53fd7c41554630124522f4b6eedc16912abbb7robertphillips
18413e302275b324172c845627cbd00cee8a06571bafrobertphillips
18423e302275b324172c845627cbd00cee8a06571bafrobertphillips    SkCanvas* canvas = surf->getCanvas();
18433e302275b324172c845627cbd00cee8a06571bafrobertphillips
18443e302275b324172c845627cbd00cee8a06571bafrobertphillips    test_xfermode_cropped_input(canvas, reporter);
1845ee845ae4940779280a853269d7d797dc9eb89201senorblanco@chromium.org}
184632673b99a4fb5d798206eb7665b730ed0b4597a0senorblanco
1847ab527a5bbfb1eae4f99a1435d349a44d00477d82egdanielDEF_GPUTEST_FOR_ALL_CONTEXTS(ImageFilterBlurLargeImage_Gpu, reporter, ctxInfo) {
18488b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    auto surface(SkSurface::MakeRenderTarget(ctxInfo.grContext(), SkBudgeted::kYes,
1849e8f3062a36d3682f4019309a32b5b84dc9eddf8creed                                             SkImageInfo::MakeN32Premul(100, 100)));
185045eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon    test_large_blur_input(reporter, surface->getCanvas());
185145eefcfec26ee48c0b2ee1d316aae3c3dc529145bsalomon}
185258d1466c7773984b7ce4bd75ebf7c97cd42f7d12senorblanco@chromium.org#endif
1853bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed
1854bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed/*
1855bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed *  Test that colorfilterimagefilter does not require its CTM to be decomposed when it has more
1856bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed *  than just scale/translate, but that other filters do.
1857bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed */
185896a04f329926099f0002f97883242793ff04f61creedDEF_TEST(ImageFilterComplexCTM, reporter) {
1859bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed    // just need a colorfilter to exercise the corresponding imagefilter
18607d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    sk_sp<SkColorFilter> cf = SkColorFilter::MakeModeFilter(SK_ColorRED, SkBlendMode::kSrcATop);
186196a04f329926099f0002f97883242793ff04f61creed    sk_sp<SkImageFilter> cfif = SkColorFilterImageFilter::Make(cf, nullptr);    // can handle
186296a04f329926099f0002f97883242793ff04f61creed    sk_sp<SkImageFilter> blif = SkBlurImageFilter::Make(3, 3, nullptr);         // cannot handle
1863bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed
1864bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed    struct {
1865bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed        sk_sp<SkImageFilter> fFilter;
1866bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed        bool                 fExpectCanHandle;
1867bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed    } recs[] = {
1868bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed        { cfif,                                     true  },
1869bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed        { SkColorFilterImageFilter::Make(cf, cfif), true  },
18707d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        { SkMergeImageFilter::Make(cfif, cfif, SkBlendMode::kSrcOver),     true  },
187196a04f329926099f0002f97883242793ff04f61creed        { SkComposeImageFilter::Make(cfif, cfif),   true  },
187296a04f329926099f0002f97883242793ff04f61creed
1873bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed        { blif,                                     false },
187496a04f329926099f0002f97883242793ff04f61creed        { SkBlurImageFilter::Make(3, 3, cfif),      false },
1875bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed        { SkColorFilterImageFilter::Make(cf, blif), false },
18767d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        { SkMergeImageFilter::Make(cfif, blif, SkBlendMode::kSrcOver),     false },
187796a04f329926099f0002f97883242793ff04f61creed        { SkComposeImageFilter::Make(blif, cfif),   false },
1878bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed    };
1879bfebe22ed54d1e3a00888292f10ed8b9714135d3liyuqian
1880bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed    for (const auto& rec : recs) {
188196a04f329926099f0002f97883242793ff04f61creed        const bool canHandle = rec.fFilter->canHandleComplexCTM();
1882bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed        REPORTER_ASSERT(reporter, canHandle == rec.fExpectCanHandle);
1883bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed    }
1884bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed}
1885