blob: c4e431f4ed3053d7ab9f5eb4d2514096ca92f891 [file] [log] [blame]
bsalomon86100022016-02-01 12:09:07 -08001
senorblanco@chromium.org194d7752013-07-24 22:19:24 +00002/*
3 * Copyright 2013 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +00009#include "SkBitmap.h"
10#include "SkBitmapDevice.h"
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000011#include "SkBlurImageFilter.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000012#include "SkCanvas.h"
13#include "SkColorFilterImageFilter.h"
14#include "SkColorMatrixFilter.h"
ajuma5788faa2015-02-13 09:05:47 -080015#include "SkComposeImageFilter.h"
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000016#include "SkDisplacementMapEffect.h"
17#include "SkDropShadowImageFilter.h"
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +000018#include "SkFlattenableSerialization.h"
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +000019#include "SkGradientShader.h"
fmalita5598b632015-09-15 11:26:13 -070020#include "SkImage.h"
fmalitacd56f812015-09-14 13:31:18 -070021#include "SkImageSource.h"
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +000022#include "SkLightingImageFilter.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000023#include "SkMatrixConvolutionImageFilter.h"
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000024#include "SkMergeImageFilter.h"
25#include "SkMorphologyImageFilter.h"
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000026#include "SkOffsetImageFilter.h"
ajuma77b6ba32016-01-08 14:58:35 -080027#include "SkPaintImageFilter.h"
senorblanco8f3937d2014-10-29 12:36:32 -070028#include "SkPerlinNoiseShader.h"
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000029#include "SkPicture.h"
senorblanco@chromium.org910702b2014-05-30 20:36:15 +000030#include "SkPictureImageFilter.h"
robertphillips@google.com770963f2014-04-18 18:04:41 +000031#include "SkPictureRecorder.h"
robertphillips3d32d762015-07-13 13:16:44 -070032#include "SkPoint3.h"
halcanary97d2c0a2014-08-19 06:27:53 -070033#include "SkReadBuffer.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000034#include "SkRect.h"
fmalitacd56f812015-09-14 13:31:18 -070035#include "SkSurface.h"
senorblanco0abdf762015-08-20 11:10:41 -070036#include "SkTableColorFilter.h"
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000037#include "SkTileImageFilter.h"
38#include "SkXfermodeImageFilter.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000039#include "Test.h"
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000040
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +000041#if SK_SUPPORT_GPU
kkinnunen15302832015-12-01 04:35:26 -080042#include "GrContext.h"
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +000043#include "SkGpuDevice.h"
44#endif
45
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +000046static const int kBitmapSize = 4;
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +000047
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000048namespace {
49
50class MatrixTestImageFilter : public SkImageFilter {
51public:
52 MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
halcanary96fcdcc2015-08-27 07:41:13 -070053 : SkImageFilter(0, nullptr), fReporter(reporter), fExpectedMatrix(expectedMatrix) {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000054 }
55
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000056 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context& ctx,
mtklein36352bf2015-03-25 18:17:31 -070057 SkBitmap* result, SkIPoint* offset) const override {
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000058 REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000059 return true;
60 }
61
robertphillipsf3f5bad2014-12-19 13:49:15 -080062 SK_TO_STRING_OVERRIDE()
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000063 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(MatrixTestImageFilter)
64
65protected:
mtklein36352bf2015-03-25 18:17:31 -070066 void flatten(SkWriteBuffer& buffer) const override {
reed9fa60da2014-08-21 07:59:51 -070067 this->INHERITED::flatten(buffer);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000068 buffer.writeFunctionPtr(fReporter);
69 buffer.writeMatrix(fExpectedMatrix);
70 }
71
72private:
73 skiatest::Reporter* fReporter;
74 SkMatrix fExpectedMatrix;
mtklein3f3b3d02014-12-01 11:47:08 -080075
reed9fa60da2014-08-21 07:59:51 -070076 typedef SkImageFilter INHERITED;
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000077};
78
79}
80
reed9fa60da2014-08-21 07:59:51 -070081SkFlattenable* MatrixTestImageFilter::CreateProc(SkReadBuffer& buffer) {
82 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
83 skiatest::Reporter* reporter = (skiatest::Reporter*)buffer.readFunctionPtr();
84 SkMatrix matrix;
85 buffer.readMatrix(&matrix);
halcanary385fe4d2015-08-26 13:07:48 -070086 return new MatrixTestImageFilter(reporter, matrix);
reed9fa60da2014-08-21 07:59:51 -070087}
88
robertphillipsf3f5bad2014-12-19 13:49:15 -080089#ifndef SK_IGNORE_TO_STRING
90void MatrixTestImageFilter::toString(SkString* str) const {
91 str->appendf("MatrixTestImageFilter: (");
92 str->append(")");
93}
94#endif
95
fmalita5598b632015-09-15 11:26:13 -070096static SkImage* make_small_image() {
97 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(kBitmapSize, kBitmapSize));
98 SkCanvas* canvas = surface->getCanvas();
99 canvas->clear(0x00000000);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000100 SkPaint darkPaint;
101 darkPaint.setColor(0xFF804020);
102 SkPaint lightPaint;
103 lightPaint.setColor(0xFF244484);
104 const int i = kBitmapSize / 4;
105 for (int y = 0; y < kBitmapSize; y += i) {
106 for (int x = 0; x < kBitmapSize; x += i) {
fmalita5598b632015-09-15 11:26:13 -0700107 canvas->save();
108 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
109 canvas->drawRect(SkRect::MakeXYWH(0, 0,
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000110 SkIntToScalar(i),
111 SkIntToScalar(i)), darkPaint);
fmalita5598b632015-09-15 11:26:13 -0700112 canvas->drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000113 0,
114 SkIntToScalar(i),
115 SkIntToScalar(i)), lightPaint);
fmalita5598b632015-09-15 11:26:13 -0700116 canvas->drawRect(SkRect::MakeXYWH(0,
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000117 SkIntToScalar(i),
118 SkIntToScalar(i),
119 SkIntToScalar(i)), lightPaint);
fmalita5598b632015-09-15 11:26:13 -0700120 canvas->drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000121 SkIntToScalar(i),
122 SkIntToScalar(i),
123 SkIntToScalar(i)), darkPaint);
fmalita5598b632015-09-15 11:26:13 -0700124 canvas->restore();
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +0000125 }
126 }
fmalita5598b632015-09-15 11:26:13 -0700127
128 return surface->newImageSnapshot();
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000129}
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000130
halcanary96fcdcc2015-08-27 07:41:13 -0700131static SkImageFilter* make_scale(float amount, SkImageFilter* input = nullptr) {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000132 SkScalar s = amount;
133 SkScalar matrix[20] = { s, 0, 0, 0, 0,
134 0, s, 0, 0, 0,
135 0, 0, s, 0, 0,
136 0, 0, 0, s, 0 };
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000137 SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000138 return SkColorFilterImageFilter::Create(filter, input);
139}
140
reedcedc36f2015-03-08 04:42:52 -0700141static SkImageFilter* make_grayscale(SkImageFilter* input, const SkImageFilter::CropRect* cropRect) {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000142 SkScalar matrix[20];
143 memset(matrix, 0, 20 * sizeof(SkScalar));
144 matrix[0] = matrix[5] = matrix[10] = 0.2126f;
145 matrix[1] = matrix[6] = matrix[11] = 0.7152f;
146 matrix[2] = matrix[7] = matrix[12] = 0.0722f;
147 matrix[18] = 1.0f;
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000148 SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000149 return SkColorFilterImageFilter::Create(filter, input, cropRect);
150}
151
reedcedc36f2015-03-08 04:42:52 -0700152static SkImageFilter* make_blue(SkImageFilter* input, const SkImageFilter::CropRect* cropRect) {
153 SkAutoTUnref<SkColorFilter> filter(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
154 SkXfermode::kSrcIn_Mode));
155 return SkColorFilterImageFilter::Create(filter, input, cropRect);
156}
157
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000158DEF_TEST(ImageFilter, reporter) {
159 {
reedcedc36f2015-03-08 04:42:52 -0700160 // Check that two non-clipping color-matrice-filters concatenate into a single filter.
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000161 SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f));
162 SkAutoTUnref<SkImageFilter> quarterBrightness(make_scale(0.5f, halfBrightness));
halcanary96fcdcc2015-08-27 07:41:13 -0700163 REPORTER_ASSERT(reporter, nullptr == quarterBrightness->getInput(0));
reedcedc36f2015-03-08 04:42:52 -0700164 SkColorFilter* cf;
165 REPORTER_ASSERT(reporter, quarterBrightness->asColorFilter(&cf));
halcanary96fcdcc2015-08-27 07:41:13 -0700166 REPORTER_ASSERT(reporter, cf->asColorMatrix(nullptr));
reedcedc36f2015-03-08 04:42:52 -0700167 cf->unref();
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000168 }
169
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000170 {
reedcedc36f2015-03-08 04:42:52 -0700171 // Check that a clipping color-matrice-filter followed by a color-matrice-filters
172 // concatenates into a single filter, but not a matrixfilter (due to clamping).
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000173 SkAutoTUnref<SkImageFilter> doubleBrightness(make_scale(2.0f));
174 SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f, doubleBrightness));
halcanary96fcdcc2015-08-27 07:41:13 -0700175 REPORTER_ASSERT(reporter, nullptr == halfBrightness->getInput(0));
reedcedc36f2015-03-08 04:42:52 -0700176 SkColorFilter* cf;
177 REPORTER_ASSERT(reporter, halfBrightness->asColorFilter(&cf));
halcanary96fcdcc2015-08-27 07:41:13 -0700178 REPORTER_ASSERT(reporter, !cf->asColorMatrix(nullptr));
reedcedc36f2015-03-08 04:42:52 -0700179 cf->unref();
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000180 }
181
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000182 {
183 // Check that a color filter image filter without a crop rect can be
184 // expressed as a color filter.
halcanary96fcdcc2015-08-27 07:41:13 -0700185 SkAutoTUnref<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
186 REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000187 }
mtklein2afbe232016-02-07 12:23:10 -0800188
reedcedc36f2015-03-08 04:42:52 -0700189 {
190 // Check that a colorfilterimage filter without a crop rect but with an input
191 // that is another colorfilterimage can be expressed as a colorfilter (composed).
halcanary96fcdcc2015-08-27 07:41:13 -0700192 SkAutoTUnref<SkImageFilter> mode(make_blue(nullptr, nullptr));
193 SkAutoTUnref<SkImageFilter> gray(make_grayscale(mode, nullptr));
194 REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
reedcedc36f2015-03-08 04:42:52 -0700195 }
196
197 {
198 // Test that if we exceed the limit of what ComposeColorFilter can combine, we still
199 // can build the DAG and won't assert if we call asColorFilter.
halcanary96fcdcc2015-08-27 07:41:13 -0700200 SkAutoTUnref<SkImageFilter> filter(make_blue(nullptr, nullptr));
reedcedc36f2015-03-08 04:42:52 -0700201 const int kWayTooManyForComposeColorFilter = 100;
202 for (int i = 0; i < kWayTooManyForComposeColorFilter; ++i) {
halcanary96fcdcc2015-08-27 07:41:13 -0700203 filter.reset(make_blue(filter, nullptr));
reedcedc36f2015-03-08 04:42:52 -0700204 // the first few of these will succeed, but after we hit the internal limit,
205 // it will then return false.
halcanary96fcdcc2015-08-27 07:41:13 -0700206 (void)filter->asColorFilter(nullptr);
reedcedc36f2015-03-08 04:42:52 -0700207 }
208 }
reed5c518a82015-03-05 14:47:29 -0800209
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000210 {
211 // Check that a color filter image filter with a crop rect cannot
212 // be expressed as a color filter.
213 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100));
halcanary96fcdcc2015-08-27 07:41:13 -0700214 SkAutoTUnref<SkImageFilter> grayWithCrop(make_grayscale(nullptr, &cropRect));
215 REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(nullptr));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000216 }
217
218 {
senorblanco3df05012014-07-03 11:13:09 -0700219 // Check that two non-commutative matrices are concatenated in
220 // the correct order.
221 SkScalar blueToRedMatrix[20] = { 0 };
222 blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
223 SkScalar redToGreenMatrix[20] = { 0 };
224 redToGreenMatrix[5] = redToGreenMatrix[18] = SK_Scalar1;
225 SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix));
226 SkAutoTUnref<SkImageFilter> filter1(SkColorFilterImageFilter::Create(blueToRed.get()));
227 SkAutoTUnref<SkColorFilter> redToGreen(SkColorMatrixFilter::Create(redToGreenMatrix));
228 SkAutoTUnref<SkImageFilter> filter2(SkColorFilterImageFilter::Create(redToGreen.get(), filter1.get()));
229
230 SkBitmap result;
231 result.allocN32Pixels(kBitmapSize, kBitmapSize);
232
233 SkPaint paint;
234 paint.setColor(SK_ColorBLUE);
235 paint.setImageFilter(filter2.get());
236 SkCanvas canvas(result);
237 canvas.clear(0x0);
238 SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
239 canvas.drawRect(rect, paint);
240 uint32_t pixel = *result.getAddr32(0, 0);
241 // The result here should be green, since we have effectively shifted blue to green.
242 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
243 }
244
245 {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000246 // Tests pass by not asserting
fmalita5598b632015-09-15 11:26:13 -0700247 SkAutoTUnref<SkImage> image(make_small_image());
248 SkBitmap result;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000249 result.allocN32Pixels(kBitmapSize, kBitmapSize);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000250
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000251 {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000252 // This tests for :
253 // 1 ) location at (0,0,1)
robertphillips3d32d762015-07-13 13:16:44 -0700254 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000255 // 2 ) location and target at same value
robertphillips3d32d762015-07-13 13:16:44 -0700256 SkPoint3 target = SkPoint3::Make(location.fX, location.fY, location.fZ);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000257 // 3 ) large negative specular exponent value
258 SkScalar specularExponent = -1000;
259
fmalita5598b632015-09-15 11:26:13 -0700260 SkAutoTUnref<SkImageFilter> bmSrc(SkImageSource::Create(image));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000261 SkPaint paint;
262 paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(
263 location, target, specularExponent, 180,
264 0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
265 bmSrc))->unref();
266 SkCanvas canvas(result);
267 SkRect r = SkRect::MakeWH(SkIntToScalar(kBitmapSize),
268 SkIntToScalar(kBitmapSize));
269 canvas.drawRect(r, paint);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000270 }
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000271 }
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000272}
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000273
robertphillips9a53fd72015-06-22 09:46:59 -0700274static void test_crop_rects(SkImageFilter::Proxy* proxy, skiatest::Reporter* reporter) {
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000275 // Check that all filters offset to their absolute crop rect,
276 // unaffected by the input crop rect.
277 // Tests pass by not asserting.
278 SkBitmap bitmap;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000279 bitmap.allocN32Pixels(100, 100);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000280 bitmap.eraseARGB(0, 0, 0, 0);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000281
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000282 SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
283 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
halcanary96fcdcc2015-08-27 07:41:13 -0700284 SkAutoTUnref<SkImageFilter> input(make_grayscale(nullptr, &inputCropRect));
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000285
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000286 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
robertphillips3d32d762015-07-13 13:16:44 -0700287 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000288 SkScalar kernel[9] = {
289 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
290 SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
291 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
292 };
293 SkISize kernelSize = SkISize::Make(3, 3);
294 SkScalar gain = SK_Scalar1, bias = 0;
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000295
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000296 SkImageFilter* filters[] = {
297 SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000298 SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType,
299 SkDisplacementMapEffect::kB_ChannelSelectorType,
300 40.0f, input.get(), input.get(), &cropRect),
301 SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
sugoi234f0362014-10-23 13:59:52 -0700302 SkDropShadowImageFilter::Create(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1,
303 SK_ColorGREEN, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
senorblanco24e06d52015-03-18 12:11:33 -0700304 input.get(), &cropRect),
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000305 SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
306 SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000307 SkMatrixConvolutionImageFilter::Create(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
308 SkMergeImageFilter::Create(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
309 SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
310 SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
311 SkDilateImageFilter::Create(3, 2, input.get(), &cropRect),
312 SkErodeImageFilter::Create(2, 3, input.get(), &cropRect),
313 SkTileImageFilter::Create(inputCropRect.rect(), cropRect.rect(), input.get()),
314 SkXfermodeImageFilter::Create(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000315 };
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000316
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000317 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
318 SkImageFilter* filter = filters[i];
319 SkBitmap result;
320 SkIPoint offset;
321 SkString str;
senorblanco@chromium.orgf4e1a762014-02-04 00:28:46 +0000322 str.printf("filter %d", static_cast<int>(i));
reed4e23cda2016-01-11 10:56:59 -0800323 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr);
robertphillips9a53fd72015-06-22 09:46:59 -0700324 REPORTER_ASSERT_MESSAGE(reporter, filter->filterImage(proxy, bitmap, ctx,
commit-bot@chromium.orgf7efa502014-04-11 18:57:00 +0000325 &result, &offset), str.c_str());
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000326 REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str());
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000327 }
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000328
329 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
330 SkSafeUnref(filters[i]);
331 }
332}
333
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000334static SkBitmap make_gradient_circle(int width, int height) {
335 SkBitmap bitmap;
336 SkScalar x = SkIntToScalar(width / 2);
337 SkScalar y = SkIntToScalar(height / 2);
338 SkScalar radius = SkMinScalar(x, y) * 0.8f;
339 bitmap.allocN32Pixels(width, height);
340 SkCanvas canvas(bitmap);
341 canvas.clear(0x00000000);
342 SkColor colors[2];
343 colors[0] = SK_ColorWHITE;
344 colors[1] = SK_ColorBLACK;
345 SkAutoTUnref<SkShader> shader(
halcanary96fcdcc2015-08-27 07:41:13 -0700346 SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, nullptr, 2,
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000347 SkShader::kClamp_TileMode)
348 );
349 SkPaint paint;
350 paint.setShader(shader);
351 canvas.drawCircle(x, y, radius, paint);
352 return bitmap;
353}
354
robertphillips9a53fd72015-06-22 09:46:59 -0700355static void test_negative_blur_sigma(SkImageFilter::Proxy* proxy, skiatest::Reporter* reporter) {
senorblanco32673b92014-09-09 09:15:04 -0700356 // Check that SkBlurImageFilter will accept a negative sigma, either in
357 // the given arguments or after CTM application.
reed5ea95df2015-10-06 14:05:32 -0700358 const int width = 32, height = 32;
359 const SkScalar five = SkIntToScalar(5);
senorblanco32673b92014-09-09 09:15:04 -0700360
reed5ea95df2015-10-06 14:05:32 -0700361 SkAutoTUnref<SkImageFilter> positiveFilter(SkBlurImageFilter::Create(five, five));
362 SkAutoTUnref<SkImageFilter> negativeFilter(SkBlurImageFilter::Create(-five, five));
senorblanco32673b92014-09-09 09:15:04 -0700363
364 SkBitmap gradient = make_gradient_circle(width, height);
365 SkBitmap positiveResult1, negativeResult1;
366 SkBitmap positiveResult2, negativeResult2;
367 SkIPoint offset;
reed4e23cda2016-01-11 10:56:59 -0800368 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr);
senorblanco84449132015-11-25 10:32:18 -0800369 REPORTER_ASSERT(reporter, positiveFilter->filterImage(proxy, gradient, ctx, &positiveResult1, &offset));
370 REPORTER_ASSERT(reporter, negativeFilter->filterImage(proxy, gradient, ctx, &negativeResult1, &offset));
senorblanco32673b92014-09-09 09:15:04 -0700371 SkMatrix negativeScale;
372 negativeScale.setScale(-SK_Scalar1, SK_Scalar1);
reed4e23cda2016-01-11 10:56:59 -0800373 SkImageFilter::Context negativeCTX(negativeScale, SkIRect::MakeWH(32, 32), nullptr);
senorblanco84449132015-11-25 10:32:18 -0800374 REPORTER_ASSERT(reporter, positiveFilter->filterImage(proxy, gradient, negativeCTX, &negativeResult2, &offset));
375 REPORTER_ASSERT(reporter, negativeFilter->filterImage(proxy, gradient, negativeCTX, &positiveResult2, &offset));
senorblanco32673b92014-09-09 09:15:04 -0700376 SkAutoLockPixels lockP1(positiveResult1);
377 SkAutoLockPixels lockP2(positiveResult2);
378 SkAutoLockPixels lockN1(negativeResult1);
379 SkAutoLockPixels lockN2(negativeResult2);
380 for (int y = 0; y < height; y++) {
381 int diffs = memcmp(positiveResult1.getAddr32(0, y), negativeResult1.getAddr32(0, y), positiveResult1.rowBytes());
382 REPORTER_ASSERT(reporter, !diffs);
383 if (diffs) {
384 break;
385 }
386 diffs = memcmp(positiveResult1.getAddr32(0, y), negativeResult2.getAddr32(0, y), positiveResult1.rowBytes());
387 REPORTER_ASSERT(reporter, !diffs);
388 if (diffs) {
389 break;
390 }
391 diffs = memcmp(positiveResult1.getAddr32(0, y), positiveResult2.getAddr32(0, y), positiveResult1.rowBytes());
392 REPORTER_ASSERT(reporter, !diffs);
393 if (diffs) {
394 break;
395 }
396 }
397}
398
399DEF_TEST(TestNegativeBlurSigma, reporter) {
robertphillips9a53fd72015-06-22 09:46:59 -0700400 const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
401 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
402
403 SkAutoTUnref<SkBaseDevice> device(SkBitmapDevice::Create(info, props));
reed88d064d2015-10-12 11:30:02 -0700404 SkImageFilter::DeviceProxy proxy(device);
robertphillips9a53fd72015-06-22 09:46:59 -0700405
406 test_negative_blur_sigma(&proxy, reporter);
senorblanco32673b92014-09-09 09:15:04 -0700407}
408
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000409DEF_TEST(ImageFilterDrawTiled, reporter) {
410 // Check that all filters when drawn tiled (with subsequent clip rects) exactly
411 // match the same filters drawn with a single full-canvas bitmap draw.
412 // Tests pass by not asserting.
413
414 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
robertphillips3d32d762015-07-13 13:16:44 -0700415 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000416 SkScalar kernel[9] = {
417 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
418 SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
419 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
420 };
reed5ea95df2015-10-06 14:05:32 -0700421 const SkISize kernelSize = SkISize::Make(3, 3);
422 const SkScalar gain = SK_Scalar1, bias = 0;
423 const SkScalar five = SkIntToScalar(5);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000424
fmalita5598b632015-09-15 11:26:13 -0700425 SkAutoTUnref<SkImage> gradientImage(SkImage::NewFromBitmap(make_gradient_circle(64, 64)));
426 SkAutoTUnref<SkImageFilter> gradientSource(SkImageSource::Create(gradientImage));
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000427 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(five, five));
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000428 SkMatrix matrix;
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000429
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000430 matrix.setTranslate(SK_Scalar1, SK_Scalar1);
431 matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000432
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000433 SkRTreeFactory factory;
434 SkPictureRecorder recorder;
435 SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0);
436
437 SkPaint greenPaint;
438 greenPaint.setColor(SK_ColorGREEN);
439 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
440 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
441 SkAutoTUnref<SkImageFilter> pictureFilter(SkPictureImageFilter::Create(picture.get()));
senorblanco8f3937d2014-10-29 12:36:32 -0700442 SkAutoTUnref<SkShader> shader(SkPerlinNoiseShader::CreateTurbulence(SK_Scalar1, SK_Scalar1, 1, 0));
ajuma77b6ba32016-01-08 14:58:35 -0800443 SkPaint noisePaint;
444 noisePaint.setShader(shader);
senorblanco8f3937d2014-10-29 12:36:32 -0700445
ajuma77b6ba32016-01-08 14:58:35 -0800446 SkAutoTUnref<SkImageFilter> paintFilter(SkPaintImageFilter::Create(noisePaint));
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000447
fsd8b57712015-05-20 00:52:17 -0700448 SkImageFilter::CropRect leftSideCropRect(SkRect::MakeXYWH(0, 0, 32, 64));
ajuma77b6ba32016-01-08 14:58:35 -0800449 SkAutoTUnref<SkImageFilter> paintFilterLeft(SkPaintImageFilter::Create(greenPaint, &leftSideCropRect));
fsd8b57712015-05-20 00:52:17 -0700450 SkImageFilter::CropRect rightSideCropRect(SkRect::MakeXYWH(32, 0, 32, 64));
ajuma77b6ba32016-01-08 14:58:35 -0800451 SkAutoTUnref<SkImageFilter> paintFilterRight(SkPaintImageFilter::Create(greenPaint, &rightSideCropRect));
fsd8b57712015-05-20 00:52:17 -0700452
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000453 struct {
454 const char* fName;
455 SkImageFilter* fFilter;
456 } filters[] = {
457 { "color filter", SkColorFilterImageFilter::Create(cf.get()) },
458 { "displacement map", SkDisplacementMapEffect::Create(
459 SkDisplacementMapEffect::kR_ChannelSelectorType,
460 SkDisplacementMapEffect::kB_ChannelSelectorType,
fmalita5598b632015-09-15 11:26:13 -0700461 20.0f, gradientSource.get()) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000462 { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
463 { "drop shadow", SkDropShadowImageFilter::Create(
sugoi234f0362014-10-23 13:59:52 -0700464 SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN,
465 SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000466 { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse(
467 location, SK_ColorGREEN, 0, 0) },
468 { "specular lighting",
469 SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) },
470 { "matrix convolution",
471 SkMatrixConvolutionImageFilter::Create(
472 kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
473 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) },
halcanary96fcdcc2015-08-27 07:41:13 -0700474 { "merge", SkMergeImageFilter::Create(nullptr, nullptr, SkXfermode::kSrcOver_Mode) },
fsd8b57712015-05-20 00:52:17 -0700475 { "merge with disjoint inputs", SkMergeImageFilter::Create(
ajuma77b6ba32016-01-08 14:58:35 -0800476 paintFilterLeft, paintFilterRight, SkXfermode::kSrcOver_Mode) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000477 { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) },
478 { "dilate", SkDilateImageFilter::Create(3, 2) },
479 { "erode", SkErodeImageFilter::Create(2, 3) },
480 { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50),
halcanary96fcdcc2015-08-27 07:41:13 -0700481 SkRect::MakeXYWH(0, 0, 100, 100), nullptr) },
senorblanco8c874ee2015-03-20 06:38:17 -0700482 { "matrix", SkImageFilter::CreateMatrixFilter(matrix, kLow_SkFilterQuality) },
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000483 { "blur and offset", SkOffsetImageFilter::Create(five, five, blur.get()) },
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000484 { "picture and blur", SkBlurImageFilter::Create(five, five, pictureFilter.get()) },
ajuma77b6ba32016-01-08 14:58:35 -0800485 { "paint and blur", SkBlurImageFilter::Create(five, five, paintFilter.get()) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000486 };
487
488 SkBitmap untiledResult, tiledResult;
reed5ea95df2015-10-06 14:05:32 -0700489 const int width = 64, height = 64;
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000490 untiledResult.allocN32Pixels(width, height);
491 tiledResult.allocN32Pixels(width, height);
492 SkCanvas tiledCanvas(tiledResult);
493 SkCanvas untiledCanvas(untiledResult);
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000494 int tileSize = 8;
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000495
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000496 for (int scale = 1; scale <= 2; ++scale) {
497 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
498 tiledCanvas.clear(0);
499 untiledCanvas.clear(0);
500 SkPaint paint;
501 paint.setImageFilter(filters[i].fFilter);
502 paint.setTextSize(SkIntToScalar(height));
503 paint.setColor(SK_ColorWHITE);
504 SkString str;
505 const char* text = "ABC";
506 SkScalar ypos = SkIntToScalar(height);
507 untiledCanvas.save();
508 untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
509 untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
510 untiledCanvas.restore();
511 for (int y = 0; y < height; y += tileSize) {
512 for (int x = 0; x < width; x += tileSize) {
513 tiledCanvas.save();
514 tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
515 tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
516 tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
517 tiledCanvas.restore();
518 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000519 }
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000520 untiledCanvas.flush();
521 tiledCanvas.flush();
522 for (int y = 0; y < height; y++) {
523 int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
524 REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
525 if (diffs) {
526 break;
527 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000528 }
529 }
530 }
531
532 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
533 SkSafeUnref(filters[i].fFilter);
534 }
535}
536
mtklein3f3b3d02014-12-01 11:47:08 -0800537static void draw_saveLayer_picture(int width, int height, int tileSize,
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700538 SkBBHFactory* factory, SkBitmap* result) {
mtkleind910f542014-08-22 09:06:34 -0700539
540 SkMatrix matrix;
541 matrix.setTranslate(SkIntToScalar(50), 0);
542
543 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorWHITE, SkXfermode::kSrc_Mode));
544 SkAutoTUnref<SkImageFilter> cfif(SkColorFilterImageFilter::Create(cf.get()));
senorblanco8c874ee2015-03-20 06:38:17 -0700545 SkAutoTUnref<SkImageFilter> imageFilter(SkImageFilter::CreateMatrixFilter(matrix, kNone_SkFilterQuality, cfif.get()));
mtkleind910f542014-08-22 09:06:34 -0700546
547 SkPaint paint;
548 paint.setImageFilter(imageFilter.get());
549 SkPictureRecorder recorder;
550 SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50));
mtklein3f3b3d02014-12-01 11:47:08 -0800551 SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width),
552 SkIntToScalar(height),
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700553 factory, 0);
mtkleind910f542014-08-22 09:06:34 -0700554 recordingCanvas->translate(-55, 0);
555 recordingCanvas->saveLayer(&bounds, &paint);
556 recordingCanvas->restore();
557 SkAutoTUnref<SkPicture> picture1(recorder.endRecording());
558
559 result->allocN32Pixels(width, height);
560 SkCanvas canvas(*result);
561 canvas.clear(0);
562 canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize)));
563 canvas.drawPicture(picture1.get());
564}
565
566DEF_TEST(ImageFilterDrawMatrixBBH, reporter) {
567 // Check that matrix filter when drawn tiled with BBH exactly
568 // matches the same thing drawn without BBH.
569 // Tests pass by not asserting.
570
571 const int width = 200, height = 200;
572 const int tileSize = 100;
573 SkBitmap result1, result2;
574 SkRTreeFactory factory;
575
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700576 draw_saveLayer_picture(width, height, tileSize, &factory, &result1);
halcanary96fcdcc2015-08-27 07:41:13 -0700577 draw_saveLayer_picture(width, height, tileSize, nullptr, &result2);
mtkleind910f542014-08-22 09:06:34 -0700578
579 for (int y = 0; y < height; y++) {
580 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
581 REPORTER_ASSERT(reporter, !diffs);
582 if (diffs) {
583 break;
584 }
585 }
586}
587
halcanary96fcdcc2015-08-27 07:41:13 -0700588static SkImageFilter* makeBlur(SkImageFilter* input = nullptr) {
senorblanco1150a6d2014-08-25 12:46:58 -0700589 return SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input);
590}
591
halcanary96fcdcc2015-08-27 07:41:13 -0700592static SkImageFilter* makeDropShadow(SkImageFilter* input = nullptr) {
senorblanco1150a6d2014-08-25 12:46:58 -0700593 return SkDropShadowImageFilter::Create(
594 SkIntToScalar(100), SkIntToScalar(100),
595 SkIntToScalar(10), SkIntToScalar(10),
sugoi234f0362014-10-23 13:59:52 -0700596 SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
halcanary96fcdcc2015-08-27 07:41:13 -0700597 input, nullptr);
senorblanco1150a6d2014-08-25 12:46:58 -0700598}
599
600DEF_TEST(ImageFilterBlurThenShadowBounds, reporter) {
601 SkAutoTUnref<SkImageFilter> filter1(makeBlur());
602 SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get()));
603
604 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
605 SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
606 filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
607
608 REPORTER_ASSERT(reporter, bounds == expectedBounds);
609}
610
611DEF_TEST(ImageFilterShadowThenBlurBounds, reporter) {
612 SkAutoTUnref<SkImageFilter> filter1(makeDropShadow());
613 SkAutoTUnref<SkImageFilter> filter2(makeBlur(filter1.get()));
614
615 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
616 SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
617 filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
618
619 REPORTER_ASSERT(reporter, bounds == expectedBounds);
620}
621
622DEF_TEST(ImageFilterDilateThenBlurBounds, reporter) {
623 SkAutoTUnref<SkImageFilter> filter1(SkDilateImageFilter::Create(2, 2));
624 SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get()));
625
626 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
627 SkIRect expectedBounds = SkIRect::MakeXYWH(-132, -132, 234, 234);
628 filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
629
630 REPORTER_ASSERT(reporter, bounds == expectedBounds);
631}
632
ajuma5788faa2015-02-13 09:05:47 -0800633DEF_TEST(ImageFilterComposedBlurFastBounds, reporter) {
634 SkAutoTUnref<SkImageFilter> filter1(makeBlur());
635 SkAutoTUnref<SkImageFilter> filter2(makeBlur());
636 SkAutoTUnref<SkImageFilter> composedFilter(SkComposeImageFilter::Create(filter1.get(), filter2.get()));
637
638 SkRect boundsSrc = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
639 SkRect expectedBounds = SkRect::MakeXYWH(
640 SkIntToScalar(-6), SkIntToScalar(-6), SkIntToScalar(112), SkIntToScalar(112));
641 SkRect boundsDst = SkRect::MakeEmpty();
642 composedFilter->computeFastBounds(boundsSrc, &boundsDst);
643
644 REPORTER_ASSERT(reporter, boundsDst == expectedBounds);
645}
646
senorblanco4a243982015-11-25 07:06:55 -0800647DEF_TEST(ImageFilterMergeResultSize, reporter) {
648 SkBitmap greenBM;
649 greenBM.allocN32Pixels(20, 20);
650 greenBM.eraseColor(SK_ColorGREEN);
651 SkAutoTUnref<SkImage> greenImage(SkImage::NewFromBitmap(greenBM));
652 SkAutoTUnref<SkImageFilter> source(SkImageSource::Create(greenImage.get()));
653 SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(source.get(), source.get()));
654
655 SkBitmap bitmap;
656 bitmap.allocN32Pixels(1, 1);
657 bitmap.eraseColor(0);
658 const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
659 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
660 SkAutoTUnref<SkBaseDevice> device(SkBitmapDevice::Create(info, props));
661 SkImageFilter::DeviceProxy proxy(device);
reed4e23cda2016-01-11 10:56:59 -0800662 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(0, 0, 100, 100), nullptr);
senorblanco4a243982015-11-25 07:06:55 -0800663 SkBitmap result;
664 SkIPoint offset;
665 REPORTER_ASSERT(reporter, merge->filterImage(&proxy, bitmap, ctx, &result, &offset));
666 REPORTER_ASSERT(reporter, result.width() == 20 && result.height() == 20);
667}
668
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700669static void draw_blurred_rect(SkCanvas* canvas) {
senorblanco837f5322014-07-14 10:19:54 -0700670 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0));
671 SkPaint filterPaint;
672 filterPaint.setColor(SK_ColorWHITE);
673 filterPaint.setImageFilter(filter);
halcanary96fcdcc2015-08-27 07:41:13 -0700674 canvas->saveLayer(nullptr, &filterPaint);
senorblanco837f5322014-07-14 10:19:54 -0700675 SkPaint whitePaint;
676 whitePaint.setColor(SK_ColorWHITE);
677 canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
678 canvas->restore();
679}
680
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700681static void draw_picture_clipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
senorblanco837f5322014-07-14 10:19:54 -0700682 canvas->save();
683 canvas->clipRect(clipRect);
684 canvas->drawPicture(picture);
685 canvas->restore();
686}
687
688DEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) {
689 // Check that the blur filter when recorded with RTree acceleration,
690 // and drawn tiled (with subsequent clip rects) exactly
691 // matches the same filter drawn with without RTree acceleration.
692 // This tests that the "bleed" from the blur into the otherwise-blank
693 // tiles is correctly rendered.
694 // Tests pass by not asserting.
695
696 int width = 16, height = 8;
697 SkBitmap result1, result2;
698 result1.allocN32Pixels(width, height);
699 result2.allocN32Pixels(width, height);
700 SkCanvas canvas1(result1);
701 SkCanvas canvas2(result2);
702 int tileSize = 8;
703
704 canvas1.clear(0);
705 canvas2.clear(0);
706
707 SkRTreeFactory factory;
708
709 SkPictureRecorder recorder1, recorder2;
710 // The only difference between these two pictures is that one has RTree aceleration.
mtklein3f3b3d02014-12-01 11:47:08 -0800711 SkCanvas* recordingCanvas1 = recorder1.beginRecording(SkIntToScalar(width),
712 SkIntToScalar(height),
halcanary96fcdcc2015-08-27 07:41:13 -0700713 nullptr, 0);
mtklein3f3b3d02014-12-01 11:47:08 -0800714 SkCanvas* recordingCanvas2 = recorder2.beginRecording(SkIntToScalar(width),
715 SkIntToScalar(height),
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700716 &factory, 0);
717 draw_blurred_rect(recordingCanvas1);
718 draw_blurred_rect(recordingCanvas2);
senorblanco837f5322014-07-14 10:19:54 -0700719 SkAutoTUnref<SkPicture> picture1(recorder1.endRecording());
720 SkAutoTUnref<SkPicture> picture2(recorder2.endRecording());
721 for (int y = 0; y < height; y += tileSize) {
722 for (int x = 0; x < width; x += tileSize) {
723 SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700724 draw_picture_clipped(&canvas1, tileRect, picture1);
725 draw_picture_clipped(&canvas2, tileRect, picture2);
senorblanco837f5322014-07-14 10:19:54 -0700726 }
727 }
728 for (int y = 0; y < height; y++) {
729 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
730 REPORTER_ASSERT(reporter, !diffs);
731 if (diffs) {
732 break;
733 }
734 }
735}
736
senorblanco@chromium.org91957432014-05-01 14:03:41 +0000737DEF_TEST(ImageFilterMatrixConvolution, reporter) {
738 // Check that a 1x3 filter does not cause a spurious assert.
739 SkScalar kernel[3] = {
740 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
741 };
742 SkISize kernelSize = SkISize::Make(1, 3);
743 SkScalar gain = SK_Scalar1, bias = 0;
744 SkIPoint kernelOffset = SkIPoint::Make(0, 0);
745
746 SkAutoTUnref<SkImageFilter> filter(
747 SkMatrixConvolutionImageFilter::Create(
748 kernelSize, kernel, gain, bias, kernelOffset,
749 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false));
750
751 SkBitmap result;
752 int width = 16, height = 16;
753 result.allocN32Pixels(width, height);
754 SkCanvas canvas(result);
755 canvas.clear(0);
756
757 SkPaint paint;
758 paint.setImageFilter(filter);
759 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
760 canvas.drawRect(rect, paint);
761}
762
senorblanco@chromium.org8c7372b2014-05-02 19:13:11 +0000763DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
764 // Check that a filter with borders outside the target bounds
765 // does not crash.
766 SkScalar kernel[3] = {
767 0, 0, 0,
768 };
769 SkISize kernelSize = SkISize::Make(3, 1);
770 SkScalar gain = SK_Scalar1, bias = 0;
771 SkIPoint kernelOffset = SkIPoint::Make(2, 0);
772
773 SkAutoTUnref<SkImageFilter> filter(
774 SkMatrixConvolutionImageFilter::Create(
775 kernelSize, kernel, gain, bias, kernelOffset,
776 SkMatrixConvolutionImageFilter::kClamp_TileMode, true));
777
778 SkBitmap result;
779
780 int width = 10, height = 10;
781 result.allocN32Pixels(width, height);
782 SkCanvas canvas(result);
783 canvas.clear(0);
784
785 SkPaint filterPaint;
786 filterPaint.setImageFilter(filter);
787 SkRect bounds = SkRect::MakeWH(1, 10);
788 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
789 SkPaint rectPaint;
790 canvas.saveLayer(&bounds, &filterPaint);
791 canvas.drawRect(rect, rectPaint);
792 canvas.restore();
793}
794
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000795DEF_TEST(ImageFilterCropRect, reporter) {
robertphillips9a53fd72015-06-22 09:46:59 -0700796 const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
797 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
798
799 SkAutoTUnref<SkBaseDevice> device(SkBitmapDevice::Create(info, props));
reed88d064d2015-10-12 11:30:02 -0700800 SkImageFilter::DeviceProxy proxy(device);
robertphillips9a53fd72015-06-22 09:46:59 -0700801
802 test_crop_rects(&proxy, reporter);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000803}
804
tfarina9ea53f92014-06-24 06:50:39 -0700805DEF_TEST(ImageFilterMatrix, reporter) {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000806 SkBitmap temp;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000807 temp.allocN32Pixels(100, 100);
robertphillips9a53fd72015-06-22 09:46:59 -0700808 SkCanvas canvas(temp);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000809 canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
810
811 SkMatrix expectedMatrix = canvas.getTotalMatrix();
812
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000813 SkRTreeFactory factory;
814 SkPictureRecorder recorder;
815 SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000816
817 SkPaint paint;
818 SkAutoTUnref<MatrixTestImageFilter> imageFilter(
819 new MatrixTestImageFilter(reporter, expectedMatrix));
820 paint.setImageFilter(imageFilter.get());
halcanary96fcdcc2015-08-27 07:41:13 -0700821 recordingCanvas->saveLayer(nullptr, &paint);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000822 SkPaint solidPaint;
823 solidPaint.setColor(0xFFFFFFFF);
824 recordingCanvas->save();
825 recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
826 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
827 recordingCanvas->restore(); // scale
828 recordingCanvas->restore(); // saveLayer
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000829 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000830
robertphillips9b14f262014-06-04 05:40:44 -0700831 canvas.drawPicture(picture);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000832}
833
senorblanco3d822c22014-07-30 14:49:31 -0700834DEF_TEST(ImageFilterCrossProcessPictureImageFilter, reporter) {
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000835 SkRTreeFactory factory;
836 SkPictureRecorder recorder;
837 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
838
839 // Create an SkPicture which simply draws a green 1x1 rectangle.
840 SkPaint greenPaint;
841 greenPaint.setColor(SK_ColorGREEN);
842 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
843 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
844
845 // Wrap that SkPicture in an SkPictureImageFilter.
846 SkAutoTUnref<SkImageFilter> imageFilter(
847 SkPictureImageFilter::Create(picture.get()));
848
849 // Check that SkPictureImageFilter successfully serializes its contained
850 // SkPicture when not in cross-process mode.
851 SkPaint paint;
852 paint.setImageFilter(imageFilter.get());
853 SkPictureRecorder outerRecorder;
854 SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
855 SkPaint redPaintWithFilter;
856 redPaintWithFilter.setColor(SK_ColorRED);
857 redPaintWithFilter.setImageFilter(imageFilter.get());
858 outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
859 SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording());
860
861 SkBitmap bitmap;
862 bitmap.allocN32Pixels(1, 1);
robertphillips9a53fd72015-06-22 09:46:59 -0700863 SkCanvas canvas(bitmap);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000864
865 // The result here should be green, since the filter replaces the primitive's red interior.
866 canvas.clear(0x0);
robertphillips9b14f262014-06-04 05:40:44 -0700867 canvas.drawPicture(outerPicture);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000868 uint32_t pixel = *bitmap.getAddr32(0, 0);
869 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
870
871 // Check that, for now, SkPictureImageFilter does not serialize or
872 // deserialize its contained picture when the filter is serialized
873 // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
874 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
875 SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
876 data->data(), data->size(), SkImageFilter::GetFlattenableType()));
877 SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
878
879 redPaintWithFilter.setImageFilter(unflattenedFilter);
880 SkPictureRecorder crossProcessRecorder;
881 SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
882 crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
883 SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording());
884
885 canvas.clear(0x0);
robertphillips9b14f262014-06-04 05:40:44 -0700886 canvas.drawPicture(crossProcessPicture);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000887 pixel = *bitmap.getAddr32(0, 0);
hendrikw446ee672015-06-16 09:28:37 -0700888 // If the security precautions are enabled, the result here should not be green, since the
889 // filter draws nothing.
mtklein2afbe232016-02-07 12:23:10 -0800890 REPORTER_ASSERT(reporter, SkPicture::PictureIOSecurityPrecautionsEnabled()
hendrikw446ee672015-06-16 09:28:37 -0700891 ? pixel != SK_ColorGREEN : pixel == SK_ColorGREEN);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000892}
893
senorblanco3d822c22014-07-30 14:49:31 -0700894DEF_TEST(ImageFilterClippedPictureImageFilter, reporter) {
895 SkRTreeFactory factory;
896 SkPictureRecorder recorder;
897 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
898
899 // Create an SkPicture which simply draws a green 1x1 rectangle.
900 SkPaint greenPaint;
901 greenPaint.setColor(SK_ColorGREEN);
902 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
903 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
904
robertphillips9a53fd72015-06-22 09:46:59 -0700905 SkAutoTUnref<SkImageFilter> imageFilter(SkPictureImageFilter::Create(picture.get()));
senorblanco3d822c22014-07-30 14:49:31 -0700906
907 SkBitmap result;
908 SkIPoint offset;
reed4e23cda2016-01-11 10:56:59 -0800909 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(1, 1, 1, 1), nullptr);
senorblanco3d822c22014-07-30 14:49:31 -0700910 SkBitmap bitmap;
911 bitmap.allocN32Pixels(2, 2);
robertphillipsefbffed2015-06-22 12:06:08 -0700912 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
913 SkBitmapDevice device(bitmap, props);
reed88d064d2015-10-12 11:30:02 -0700914 SkImageFilter::DeviceProxy proxy(&device);
senorblanco3d822c22014-07-30 14:49:31 -0700915 REPORTER_ASSERT(reporter, !imageFilter->filterImage(&proxy, bitmap, ctx, &result, &offset));
916}
917
tfarina9ea53f92014-06-24 06:50:39 -0700918DEF_TEST(ImageFilterEmptySaveLayer, reporter) {
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000919 // Even when there's an empty saveLayer()/restore(), ensure that an image
920 // filter or color filter which affects transparent black still draws.
921
922 SkBitmap bitmap;
923 bitmap.allocN32Pixels(10, 10);
robertphillips9a53fd72015-06-22 09:46:59 -0700924 SkCanvas canvas(bitmap);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000925
926 SkRTreeFactory factory;
927 SkPictureRecorder recorder;
928
929 SkAutoTUnref<SkColorFilter> green(
930 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode));
reedf0280032015-10-12 11:10:10 -0700931 SkAutoTUnref<SkImageFilter> imageFilter(
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000932 SkColorFilterImageFilter::Create(green.get()));
933 SkPaint imageFilterPaint;
934 imageFilterPaint.setImageFilter(imageFilter.get());
935 SkPaint colorFilterPaint;
936 colorFilterPaint.setColorFilter(green.get());
937
938 SkRect bounds = SkRect::MakeWH(10, 10);
939
940 SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
941 recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
942 recordingCanvas->restore();
943 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
944
945 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -0700946 canvas.drawPicture(picture);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000947 uint32_t pixel = *bitmap.getAddr32(0, 0);
948 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
949
950 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
halcanary96fcdcc2015-08-27 07:41:13 -0700951 recordingCanvas->saveLayer(nullptr, &imageFilterPaint);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000952 recordingCanvas->restore();
953 SkAutoTUnref<SkPicture> picture2(recorder.endRecording());
954
955 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -0700956 canvas.drawPicture(picture2);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000957 pixel = *bitmap.getAddr32(0, 0);
958 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
959
960 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
961 recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
962 recordingCanvas->restore();
963 SkAutoTUnref<SkPicture> picture3(recorder.endRecording());
964
965 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -0700966 canvas.drawPicture(picture3);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000967 pixel = *bitmap.getAddr32(0, 0);
968 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
969}
970
robertphillips9a53fd72015-06-22 09:46:59 -0700971static void test_huge_blur(SkCanvas* canvas, skiatest::Reporter* reporter) {
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000972 SkBitmap bitmap;
973 bitmap.allocN32Pixels(100, 100);
974 bitmap.eraseARGB(0, 0, 0, 0);
975
976 // Check that a blur with an insane radius does not crash or assert.
977 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(SkIntToScalar(1<<30), SkIntToScalar(1<<30)));
978
979 SkPaint paint;
980 paint.setImageFilter(blur);
reedda420b92015-12-16 08:38:15 -0800981 canvas->drawBitmap(bitmap, 0, 0, &paint);
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000982}
983
984DEF_TEST(HugeBlurImageFilter, reporter) {
985 SkBitmap temp;
986 temp.allocN32Pixels(100, 100);
robertphillips9a53fd72015-06-22 09:46:59 -0700987 SkCanvas canvas(temp);
988 test_huge_blur(&canvas, reporter);
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000989}
990
senorblanco3a495202014-09-29 07:57:20 -0700991DEF_TEST(MatrixConvolutionSanityTest, reporter) {
992 SkScalar kernel[1] = { 0 };
993 SkScalar gain = SK_Scalar1, bias = 0;
994 SkIPoint kernelOffset = SkIPoint::Make(1, 1);
995
halcanary96fcdcc2015-08-27 07:41:13 -0700996 // Check that an enormous (non-allocatable) kernel gives a nullptr filter.
senorblanco3a495202014-09-29 07:57:20 -0700997 SkAutoTUnref<SkImageFilter> conv(SkMatrixConvolutionImageFilter::Create(
998 SkISize::Make(1<<30, 1<<30),
999 kernel,
1000 gain,
1001 bias,
1002 kernelOffset,
1003 SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1004 false));
1005
halcanary96fcdcc2015-08-27 07:41:13 -07001006 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001007
halcanary96fcdcc2015-08-27 07:41:13 -07001008 // Check that a nullptr kernel gives a nullptr filter.
senorblanco3a495202014-09-29 07:57:20 -07001009 conv.reset(SkMatrixConvolutionImageFilter::Create(
1010 SkISize::Make(1, 1),
halcanary96fcdcc2015-08-27 07:41:13 -07001011 nullptr,
senorblanco3a495202014-09-29 07:57:20 -07001012 gain,
1013 bias,
1014 kernelOffset,
1015 SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1016 false));
1017
halcanary96fcdcc2015-08-27 07:41:13 -07001018 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001019
halcanary96fcdcc2015-08-27 07:41:13 -07001020 // Check that a kernel width < 1 gives a nullptr filter.
senorblanco3a495202014-09-29 07:57:20 -07001021 conv.reset(SkMatrixConvolutionImageFilter::Create(
1022 SkISize::Make(0, 1),
1023 kernel,
1024 gain,
1025 bias,
1026 kernelOffset,
1027 SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1028 false));
1029
halcanary96fcdcc2015-08-27 07:41:13 -07001030 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001031
halcanary96fcdcc2015-08-27 07:41:13 -07001032 // Check that kernel height < 1 gives a nullptr filter.
senorblanco3a495202014-09-29 07:57:20 -07001033 conv.reset(SkMatrixConvolutionImageFilter::Create(
1034 SkISize::Make(1, -1),
1035 kernel,
1036 gain,
1037 bias,
1038 kernelOffset,
1039 SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1040 false));
1041
halcanary96fcdcc2015-08-27 07:41:13 -07001042 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001043}
1044
robertphillips9a53fd72015-06-22 09:46:59 -07001045static void test_xfermode_cropped_input(SkCanvas* canvas, skiatest::Reporter* reporter) {
1046 canvas->clear(0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001047
1048 SkBitmap bitmap;
1049 bitmap.allocN32Pixels(1, 1);
1050 bitmap.eraseARGB(255, 255, 255, 255);
1051
1052 SkAutoTUnref<SkColorFilter> green(
1053 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode));
reedf0280032015-10-12 11:10:10 -07001054 SkAutoTUnref<SkImageFilter> greenFilter(SkColorFilterImageFilter::Create(green.get()));
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001055 SkImageFilter::CropRect cropRect(SkRect::MakeEmpty());
reedf0280032015-10-12 11:10:10 -07001056 SkAutoTUnref<SkImageFilter> croppedOut(
halcanary96fcdcc2015-08-27 07:41:13 -07001057 SkColorFilterImageFilter::Create(green.get(), nullptr, &cropRect));
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001058
1059 // Check that an xfermode image filter whose input has been cropped out still draws the other
1060 // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
1061 SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode);
1062 SkAutoTUnref<SkImageFilter> xfermodeNoFg(
1063 SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut));
1064 SkAutoTUnref<SkImageFilter> xfermodeNoBg(
1065 SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter));
1066 SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg(
1067 SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut));
1068
1069 SkPaint paint;
1070 paint.setImageFilter(xfermodeNoFg);
reedda420b92015-12-16 08:38:15 -08001071 canvas->drawBitmap(bitmap, 0, 0, &paint); // drawSprite
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001072
1073 uint32_t pixel;
kkinnunena9d9a392015-03-06 07:16:00 -08001074 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
robertphillips9a53fd72015-06-22 09:46:59 -07001075 canvas->readPixels(info, &pixel, 4, 0, 0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001076 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1077
1078 paint.setImageFilter(xfermodeNoBg);
reedda420b92015-12-16 08:38:15 -08001079 canvas->drawBitmap(bitmap, 0, 0, &paint); // drawSprite
robertphillips9a53fd72015-06-22 09:46:59 -07001080 canvas->readPixels(info, &pixel, 4, 0, 0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001081 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1082
1083 paint.setImageFilter(xfermodeNoFgNoBg);
reedda420b92015-12-16 08:38:15 -08001084 canvas->drawBitmap(bitmap, 0, 0, &paint); // drawSprite
robertphillips9a53fd72015-06-22 09:46:59 -07001085 canvas->readPixels(info, &pixel, 4, 0, 0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001086 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1087}
1088
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001089DEF_TEST(ImageFilterNestedSaveLayer, reporter) {
1090 SkBitmap temp;
1091 temp.allocN32Pixels(50, 50);
robertphillips9a53fd72015-06-22 09:46:59 -07001092 SkCanvas canvas(temp);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001093 canvas.clear(0x0);
1094
1095 SkBitmap bitmap;
1096 bitmap.allocN32Pixels(10, 10);
1097 bitmap.eraseColor(SK_ColorGREEN);
1098
1099 SkMatrix matrix;
1100 matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
1101 matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
1102 SkAutoTUnref<SkImageFilter> matrixFilter(
senorblanco8c874ee2015-03-20 06:38:17 -07001103 SkImageFilter::CreateMatrixFilter(matrix, kLow_SkFilterQuality));
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001104
1105 // Test that saveLayer() with a filter nested inside another saveLayer() applies the
1106 // correct offset to the filter matrix.
1107 SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
halcanary96fcdcc2015-08-27 07:41:13 -07001108 canvas.saveLayer(&bounds1, nullptr);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001109 SkPaint filterPaint;
1110 filterPaint.setImageFilter(matrixFilter);
1111 SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
1112 canvas.saveLayer(&bounds2, &filterPaint);
1113 SkPaint greenPaint;
1114 greenPaint.setColor(SK_ColorGREEN);
1115 canvas.drawRect(bounds2, greenPaint);
1116 canvas.restore();
1117 canvas.restore();
1118 SkPaint strokePaint;
1119 strokePaint.setStyle(SkPaint::kStroke_Style);
1120 strokePaint.setColor(SK_ColorRED);
1121
kkinnunena9d9a392015-03-06 07:16:00 -08001122 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001123 uint32_t pixel;
1124 canvas.readPixels(info, &pixel, 4, 25, 25);
1125 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1126
1127 // Test that drawSprite() with a filter nested inside a saveLayer() applies the
1128 // correct offset to the filter matrix.
1129 canvas.clear(0x0);
1130 canvas.readPixels(info, &pixel, 4, 25, 25);
halcanary96fcdcc2015-08-27 07:41:13 -07001131 canvas.saveLayer(&bounds1, nullptr);
reedda420b92015-12-16 08:38:15 -08001132 canvas.drawBitmap(bitmap, 20, 20, &filterPaint); // drawSprite
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001133 canvas.restore();
1134
1135 canvas.readPixels(info, &pixel, 4, 25, 25);
1136 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1137}
1138
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001139DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
1140 SkBitmap temp;
1141 temp.allocN32Pixels(100, 100);
robertphillips9a53fd72015-06-22 09:46:59 -07001142 SkCanvas canvas(temp);
1143 test_xfermode_cropped_input(&canvas, reporter);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001144}
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001145
ajuma5788faa2015-02-13 09:05:47 -08001146DEF_TEST(ComposedImageFilterOffset, reporter) {
1147 SkBitmap bitmap;
1148 bitmap.allocN32Pixels(100, 100);
1149 bitmap.eraseARGB(0, 0, 0, 0);
robertphillipsefbffed2015-06-22 12:06:08 -07001150 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1151 SkBitmapDevice device(bitmap, props);
reed88d064d2015-10-12 11:30:02 -07001152 SkImageFilter::DeviceProxy proxy(&device);
ajuma5788faa2015-02-13 09:05:47 -08001153
1154 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(1, 0, 20, 20));
halcanary96fcdcc2015-08-27 07:41:13 -07001155 SkAutoTUnref<SkImageFilter> offsetFilter(SkOffsetImageFilter::Create(0, 0, nullptr, &cropRect));
senorblancodb64af32015-12-09 10:11:43 -08001156 SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1,
1157 nullptr, &cropRect));
1158 SkAutoTUnref<SkImageFilter> composedFilter(SkComposeImageFilter::Create(blurFilter,
1159 offsetFilter.get()));
ajuma5788faa2015-02-13 09:05:47 -08001160 SkBitmap result;
1161 SkIPoint offset;
reed4e23cda2016-01-11 10:56:59 -08001162 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr);
ajuma5788faa2015-02-13 09:05:47 -08001163 REPORTER_ASSERT(reporter, composedFilter->filterImage(&proxy, bitmap, ctx, &result, &offset));
1164 REPORTER_ASSERT(reporter, offset.fX == 1 && offset.fY == 0);
1165}
1166
senorblanco24d2a7b2015-07-13 10:27:05 -07001167DEF_TEST(PartialCropRect, reporter) {
1168 SkBitmap bitmap;
1169 bitmap.allocN32Pixels(100, 100);
1170 bitmap.eraseARGB(0, 0, 0, 0);
1171 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1172 SkBitmapDevice device(bitmap, props);
reed88d064d2015-10-12 11:30:02 -07001173 SkImageFilter::DeviceProxy proxy(&device);
senorblanco24d2a7b2015-07-13 10:27:05 -07001174
1175 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(100, 0, 20, 30),
senorblancoed7cf272015-07-16 15:19:11 -07001176 SkImageFilter::CropRect::kHasWidth_CropEdge | SkImageFilter::CropRect::kHasHeight_CropEdge);
halcanary96fcdcc2015-08-27 07:41:13 -07001177 SkAutoTUnref<SkImageFilter> filter(make_grayscale(nullptr, &cropRect));
senorblanco24d2a7b2015-07-13 10:27:05 -07001178 SkBitmap result;
1179 SkIPoint offset;
reed4e23cda2016-01-11 10:56:59 -08001180 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr);
senorblanco24d2a7b2015-07-13 10:27:05 -07001181 REPORTER_ASSERT(reporter, filter->filterImage(&proxy, bitmap, ctx, &result, &offset));
1182 REPORTER_ASSERT(reporter, offset.fX == 0);
1183 REPORTER_ASSERT(reporter, offset.fY == 0);
1184 REPORTER_ASSERT(reporter, result.width() == 20);
1185 REPORTER_ASSERT(reporter, result.height() == 30);
1186}
1187
senorblanco0abdf762015-08-20 11:10:41 -07001188DEF_TEST(ImageFilterCanComputeFastBounds, reporter) {
1189
1190 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
1191 SkAutoTUnref<SkImageFilter> lighting(SkLightingImageFilter::CreatePointLitDiffuse(
1192 location, SK_ColorGREEN, 0, 0));
1193 REPORTER_ASSERT(reporter, !lighting->canComputeFastBounds());
1194
1195 SkAutoTUnref<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
1196 REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1197 {
1198 SkColorFilter* grayCF;
1199 REPORTER_ASSERT(reporter, gray->asAColorFilter(&grayCF));
1200 REPORTER_ASSERT(reporter, !grayCF->affectsTransparentBlack());
1201 grayCF->unref();
1202 }
1203 REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1204
1205 SkAutoTUnref<SkImageFilter> grayBlur(SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, gray.get()));
1206 REPORTER_ASSERT(reporter, grayBlur->canComputeFastBounds());
1207
1208 SkScalar greenMatrix[20] = { 0, 0, 0, 0, 0,
1209 0, 0, 0, 0, 1,
1210 0, 0, 0, 0, 0,
1211 0, 0, 0, 0, 1 };
1212 SkAutoTUnref<SkColorFilter> greenCF(SkColorMatrixFilter::Create(greenMatrix));
1213 SkAutoTUnref<SkImageFilter> green(SkColorFilterImageFilter::Create(greenCF));
1214
1215 REPORTER_ASSERT(reporter, greenCF->affectsTransparentBlack());
1216 REPORTER_ASSERT(reporter, !green->canComputeFastBounds());
1217
1218 SkAutoTUnref<SkImageFilter> greenBlur(SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, green.get()));
1219 REPORTER_ASSERT(reporter, !greenBlur->canComputeFastBounds());
1220
1221 uint8_t allOne[256], identity[256];
1222 for (int i = 0; i < 256; ++i) {
1223 identity[i] = i;
1224 allOne[i] = 255;
1225 }
1226
1227 SkAutoTUnref<SkColorFilter> identityCF(
1228 SkTableColorFilter::CreateARGB(identity, identity, identity, allOne));
1229 SkAutoTUnref<SkImageFilter> identityFilter(SkColorFilterImageFilter::Create(identityCF.get()));
1230 REPORTER_ASSERT(reporter, !identityCF->affectsTransparentBlack());
1231 REPORTER_ASSERT(reporter, identityFilter->canComputeFastBounds());
1232
1233 SkAutoTUnref<SkColorFilter> forceOpaqueCF(
1234 SkTableColorFilter::CreateARGB(allOne, identity, identity, identity));
1235 SkAutoTUnref<SkImageFilter> forceOpaque(SkColorFilterImageFilter::Create(forceOpaqueCF.get()));
1236 REPORTER_ASSERT(reporter, forceOpaqueCF->affectsTransparentBlack());
1237 REPORTER_ASSERT(reporter, !forceOpaque->canComputeFastBounds());
1238}
1239
fmalitacd56f812015-09-14 13:31:18 -07001240// Verify that SkImageSource survives serialization
1241DEF_TEST(ImageFilterImageSourceSerialization, reporter) {
1242 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(10, 10));
1243 surface->getCanvas()->clear(SK_ColorGREEN);
1244 SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
1245 SkAutoTUnref<SkImageFilter> filter(SkImageSource::Create(image));
1246
1247 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(filter));
1248 SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
1249 data->data(), data->size(), SkImageFilter::GetFlattenableType()));
1250 SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
1251 REPORTER_ASSERT(reporter, unflattenedFilter);
1252
1253 SkBitmap bm;
1254 bm.allocN32Pixels(10, 10);
fmalita23cb88c2015-09-15 06:56:23 -07001255 bm.eraseColor(SK_ColorBLUE);
fmalitacd56f812015-09-14 13:31:18 -07001256 SkPaint paint;
1257 paint.setColor(SK_ColorRED);
1258 paint.setImageFilter(unflattenedFilter);
1259
1260 SkCanvas canvas(bm);
1261 canvas.drawRect(SkRect::MakeWH(10, 10), paint);
1262 REPORTER_ASSERT(reporter, *bm.getAddr32(0, 0) == SkPreMultiplyColor(SK_ColorGREEN));
1263}
1264
bsalomon45eefcf2016-01-05 08:39:28 -08001265static void test_large_blur_input(skiatest::Reporter* reporter, SkCanvas* canvas) {
1266 SkBitmap largeBmp;
1267 int largeW = 5000;
1268 int largeH = 5000;
1269#if SK_SUPPORT_GPU
1270 // If we're GPU-backed make the bitmap too large to be converted into a texture.
1271 if (GrContext* ctx = canvas->getGrContext()) {
1272 largeW = ctx->caps()->maxTextureSize() + 1;
1273 }
1274#endif
1275
1276 largeBmp.allocN32Pixels(largeW, largeH);
mtklein2afbe232016-02-07 12:23:10 -08001277 largeBmp.eraseColor(0);
bsalomon45eefcf2016-01-05 08:39:28 -08001278 if (!largeBmp.getPixels()) {
1279 ERRORF(reporter, "Failed to allocate large bmp.");
1280 return;
1281 }
1282
1283 SkAutoTUnref<SkImage> largeImage(SkImage::NewFromBitmap(largeBmp));
1284 if (!largeImage) {
1285 ERRORF(reporter, "Failed to create large image.");
1286 return;
1287 }
1288
1289 SkAutoTUnref<SkImageFilter> largeSource(SkImageSource::Create(largeImage));
1290 if (!largeSource) {
1291 ERRORF(reporter, "Failed to create large SkImageSource.");
1292 return;
1293 }
1294
1295 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(10.f, 10.f, largeSource));
1296 if (!blur) {
1297 ERRORF(reporter, "Failed to create SkBlurImageFilter.");
1298 return;
1299 }
1300
1301 SkPaint paint;
1302 paint.setImageFilter(blur);
1303
1304 // This should not crash (http://crbug.com/570479).
1305 canvas->drawRect(SkRect::MakeIWH(largeW, largeH), paint);
1306}
1307
1308DEF_TEST(BlurLargeImage, reporter) {
1309 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(SkImageInfo::MakeN32Premul(100, 100)));
1310 test_large_blur_input(reporter, surface->getCanvas());
1311}
1312
senorblanco@chromium.org58d14662014-02-03 22:36:39 +00001313#if SK_SUPPORT_GPU
reed4a8126e2014-09-22 07:29:03 -07001314
kkinnunen15302832015-12-01 04:35:26 -08001315DEF_GPUTEST_FOR_NATIVE_CONTEXT(ImageFilterCropRect_Gpu, reporter, context) {
robertphillipsefbffed2015-06-22 12:06:08 -07001316 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1317
commit-bot@chromium.org15a14052014-02-16 00:59:25 +00001318 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
bsalomonafe30052015-01-16 07:32:33 -08001319 SkSurface::kNo_Budgeted,
commit-bot@chromium.org15a14052014-02-16 00:59:25 +00001320 SkImageInfo::MakeN32Premul(100, 100),
bsalomonafe30052015-01-16 07:32:33 -08001321 0,
bsalomon74f681d2015-06-23 14:38:48 -07001322 &props,
1323 SkGpuDevice::kUninit_InitContents));
reed88d064d2015-10-12 11:30:02 -07001324 SkImageFilter::DeviceProxy proxy(device);
robertphillips9a53fd72015-06-22 09:46:59 -07001325
1326 test_crop_rects(&proxy, reporter);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +00001327}
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001328
kkinnunen15302832015-12-01 04:35:26 -08001329DEF_GPUTEST_FOR_NATIVE_CONTEXT(HugeBlurImageFilter_Gpu, reporter, context) {
robertphillipsefbffed2015-06-22 12:06:08 -07001330 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1331
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001332 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
bsalomonafe30052015-01-16 07:32:33 -08001333 SkSurface::kNo_Budgeted,
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001334 SkImageInfo::MakeN32Premul(100, 100),
bsalomonafe30052015-01-16 07:32:33 -08001335 0,
bsalomon74f681d2015-06-23 14:38:48 -07001336 &props,
1337 SkGpuDevice::kUninit_InitContents));
robertphillips9a53fd72015-06-22 09:46:59 -07001338 SkCanvas canvas(device);
1339
1340 test_huge_blur(&canvas, reporter);
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001341}
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001342
kkinnunen15302832015-12-01 04:35:26 -08001343DEF_GPUTEST_FOR_NATIVE_CONTEXT(XfermodeImageFilterCroppedInput_Gpu, reporter, context) {
robertphillipsefbffed2015-06-22 12:06:08 -07001344 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1345
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001346 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
bsalomonafe30052015-01-16 07:32:33 -08001347 SkSurface::kNo_Budgeted,
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001348 SkImageInfo::MakeN32Premul(1, 1),
bsalomonafe30052015-01-16 07:32:33 -08001349 0,
bsalomon74f681d2015-06-23 14:38:48 -07001350 &props,
1351 SkGpuDevice::kUninit_InitContents));
robertphillips9a53fd72015-06-22 09:46:59 -07001352 SkCanvas canvas(device);
1353
1354 test_xfermode_cropped_input(&canvas, reporter);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001355}
senorblanco32673b92014-09-09 09:15:04 -07001356
kkinnunen15302832015-12-01 04:35:26 -08001357DEF_GPUTEST_FOR_NATIVE_CONTEXT(TestNegativeBlurSigma_Gpu, reporter, context) {
robertphillipsefbffed2015-06-22 12:06:08 -07001358 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1359
senorblanco32673b92014-09-09 09:15:04 -07001360 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
bsalomonafe30052015-01-16 07:32:33 -08001361 SkSurface::kNo_Budgeted,
senorblanco32673b92014-09-09 09:15:04 -07001362 SkImageInfo::MakeN32Premul(1, 1),
bsalomonafe30052015-01-16 07:32:33 -08001363 0,
bsalomon74f681d2015-06-23 14:38:48 -07001364 &props,
1365 SkGpuDevice::kUninit_InitContents));
reed88d064d2015-10-12 11:30:02 -07001366 SkImageFilter::DeviceProxy proxy(device);
robertphillips9a53fd72015-06-22 09:46:59 -07001367
1368 test_negative_blur_sigma(&proxy, reporter);
senorblanco32673b92014-09-09 09:15:04 -07001369}
bsalomon45eefcf2016-01-05 08:39:28 -08001370
1371DEF_GPUTEST_FOR_ALL_CONTEXTS(BlurLargeImage_Gpu, reporter, context) {
1372 SkAutoTUnref<SkSurface> surface(
1373 SkSurface::NewRenderTarget(context, SkSurface::kYes_Budgeted,
1374 SkImageInfo::MakeN32Premul(100, 100)));
1375 test_large_blur_input(reporter, surface->getCanvas());
1376}
senorblanco@chromium.org58d14662014-02-03 22:36:39 +00001377#endif