blob: 3def8f5cca82134f36ef733f9e20d38f7381bb22 [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"
robertphillips4418dba2016-03-07 12:45:14 -080035#include "SkSpecialImage.h"
36#include "SkSpecialSurface.h"
fmalitacd56f812015-09-14 13:31:18 -070037#include "SkSurface.h"
senorblanco0abdf762015-08-20 11:10:41 -070038#include "SkTableColorFilter.h"
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000039#include "SkTileImageFilter.h"
40#include "SkXfermodeImageFilter.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000041#include "Test.h"
robertphillips4418dba2016-03-07 12:45:14 -080042#include "TestingSpecialImageAccess.h"
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000043
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +000044#if SK_SUPPORT_GPU
kkinnunen15302832015-12-01 04:35:26 -080045#include "GrContext.h"
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +000046#include "SkGpuDevice.h"
47#endif
48
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +000049static const int kBitmapSize = 4;
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +000050
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000051namespace {
52
53class MatrixTestImageFilter : public SkImageFilter {
54public:
55 MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
halcanary96fcdcc2015-08-27 07:41:13 -070056 : SkImageFilter(0, nullptr), fReporter(reporter), fExpectedMatrix(expectedMatrix) {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000057 }
58
robertphillips48e78462016-02-17 13:57:16 -080059 bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context& ctx,
60 SkBitmap* result, SkIPoint* offset) const override {
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000061 REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000062 return true;
63 }
64
robertphillipsf3f5bad2014-12-19 13:49:15 -080065 SK_TO_STRING_OVERRIDE()
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000066 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(MatrixTestImageFilter)
67
68protected:
mtklein36352bf2015-03-25 18:17:31 -070069 void flatten(SkWriteBuffer& buffer) const override {
reed9fa60da2014-08-21 07:59:51 -070070 this->INHERITED::flatten(buffer);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000071 buffer.writeFunctionPtr(fReporter);
72 buffer.writeMatrix(fExpectedMatrix);
73 }
74
75private:
76 skiatest::Reporter* fReporter;
77 SkMatrix fExpectedMatrix;
mtklein3f3b3d02014-12-01 11:47:08 -080078
reed9fa60da2014-08-21 07:59:51 -070079 typedef SkImageFilter INHERITED;
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000080};
81
82}
83
reed9fa60da2014-08-21 07:59:51 -070084SkFlattenable* MatrixTestImageFilter::CreateProc(SkReadBuffer& buffer) {
85 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
86 skiatest::Reporter* reporter = (skiatest::Reporter*)buffer.readFunctionPtr();
87 SkMatrix matrix;
88 buffer.readMatrix(&matrix);
halcanary385fe4d2015-08-26 13:07:48 -070089 return new MatrixTestImageFilter(reporter, matrix);
reed9fa60da2014-08-21 07:59:51 -070090}
91
robertphillipsf3f5bad2014-12-19 13:49:15 -080092#ifndef SK_IGNORE_TO_STRING
93void MatrixTestImageFilter::toString(SkString* str) const {
94 str->appendf("MatrixTestImageFilter: (");
95 str->append(")");
96}
97#endif
98
fmalita5598b632015-09-15 11:26:13 -070099static SkImage* make_small_image() {
100 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(kBitmapSize, kBitmapSize));
101 SkCanvas* canvas = surface->getCanvas();
102 canvas->clear(0x00000000);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000103 SkPaint darkPaint;
104 darkPaint.setColor(0xFF804020);
105 SkPaint lightPaint;
106 lightPaint.setColor(0xFF244484);
107 const int i = kBitmapSize / 4;
108 for (int y = 0; y < kBitmapSize; y += i) {
109 for (int x = 0; x < kBitmapSize; x += i) {
fmalita5598b632015-09-15 11:26:13 -0700110 canvas->save();
111 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
112 canvas->drawRect(SkRect::MakeXYWH(0, 0,
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000113 SkIntToScalar(i),
114 SkIntToScalar(i)), darkPaint);
fmalita5598b632015-09-15 11:26:13 -0700115 canvas->drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000116 0,
117 SkIntToScalar(i),
118 SkIntToScalar(i)), lightPaint);
fmalita5598b632015-09-15 11:26:13 -0700119 canvas->drawRect(SkRect::MakeXYWH(0,
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000120 SkIntToScalar(i),
121 SkIntToScalar(i),
122 SkIntToScalar(i)), lightPaint);
fmalita5598b632015-09-15 11:26:13 -0700123 canvas->drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000124 SkIntToScalar(i),
125 SkIntToScalar(i),
126 SkIntToScalar(i)), darkPaint);
fmalita5598b632015-09-15 11:26:13 -0700127 canvas->restore();
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +0000128 }
129 }
fmalita5598b632015-09-15 11:26:13 -0700130
131 return surface->newImageSnapshot();
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000132}
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000133
halcanary96fcdcc2015-08-27 07:41:13 -0700134static SkImageFilter* make_scale(float amount, SkImageFilter* input = nullptr) {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000135 SkScalar s = amount;
136 SkScalar matrix[20] = { s, 0, 0, 0, 0,
137 0, s, 0, 0, 0,
138 0, 0, s, 0, 0,
139 0, 0, 0, s, 0 };
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000140 SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000141 return SkColorFilterImageFilter::Create(filter, input);
142}
143
reedcedc36f2015-03-08 04:42:52 -0700144static SkImageFilter* make_grayscale(SkImageFilter* input, const SkImageFilter::CropRect* cropRect) {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000145 SkScalar matrix[20];
146 memset(matrix, 0, 20 * sizeof(SkScalar));
147 matrix[0] = matrix[5] = matrix[10] = 0.2126f;
148 matrix[1] = matrix[6] = matrix[11] = 0.7152f;
149 matrix[2] = matrix[7] = matrix[12] = 0.0722f;
150 matrix[18] = 1.0f;
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000151 SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000152 return SkColorFilterImageFilter::Create(filter, input, cropRect);
153}
154
reedcedc36f2015-03-08 04:42:52 -0700155static SkImageFilter* make_blue(SkImageFilter* input, const SkImageFilter::CropRect* cropRect) {
156 SkAutoTUnref<SkColorFilter> filter(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
157 SkXfermode::kSrcIn_Mode));
158 return SkColorFilterImageFilter::Create(filter, input, cropRect);
159}
160
robertphillips4418dba2016-03-07 12:45:14 -0800161static SkSpecialImage* create_empty_special_image(GrContext* context,
162 SkImageFilter::Proxy* proxy,
163 int widthHeight) {
164 SkAutoTUnref<SkSpecialSurface> surf;
165
166 if (context) {
167 GrSurfaceDesc desc;
168 desc.fConfig = kSkia8888_GrPixelConfig;
169 desc.fFlags = kRenderTarget_GrSurfaceFlag;
170 desc.fWidth = widthHeight;
171 desc.fHeight = widthHeight;
172 surf.reset(SkSpecialSurface::NewRenderTarget(proxy, context, desc));
173 } else {
174 const SkImageInfo info = SkImageInfo::MakeN32(widthHeight, widthHeight,
175 kOpaque_SkAlphaType);
176 surf.reset(SkSpecialSurface::NewRaster(proxy, info));
177 }
178
179 SkASSERT(surf);
180
181 SkCanvas* canvas = surf->getCanvas();
182 SkASSERT(canvas);
183
184 canvas->clear(0x0);
185
186 return surf->newImageSnapshot();
187}
188
189
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000190DEF_TEST(ImageFilter, reporter) {
191 {
reedcedc36f2015-03-08 04:42:52 -0700192 // Check that two non-clipping color-matrice-filters concatenate into a single filter.
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000193 SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f));
194 SkAutoTUnref<SkImageFilter> quarterBrightness(make_scale(0.5f, halfBrightness));
halcanary96fcdcc2015-08-27 07:41:13 -0700195 REPORTER_ASSERT(reporter, nullptr == quarterBrightness->getInput(0));
reedcedc36f2015-03-08 04:42:52 -0700196 SkColorFilter* cf;
197 REPORTER_ASSERT(reporter, quarterBrightness->asColorFilter(&cf));
halcanary96fcdcc2015-08-27 07:41:13 -0700198 REPORTER_ASSERT(reporter, cf->asColorMatrix(nullptr));
reedcedc36f2015-03-08 04:42:52 -0700199 cf->unref();
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000200 }
201
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000202 {
reedcedc36f2015-03-08 04:42:52 -0700203 // Check that a clipping color-matrice-filter followed by a color-matrice-filters
204 // concatenates into a single filter, but not a matrixfilter (due to clamping).
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000205 SkAutoTUnref<SkImageFilter> doubleBrightness(make_scale(2.0f));
206 SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f, doubleBrightness));
halcanary96fcdcc2015-08-27 07:41:13 -0700207 REPORTER_ASSERT(reporter, nullptr == halfBrightness->getInput(0));
reedcedc36f2015-03-08 04:42:52 -0700208 SkColorFilter* cf;
209 REPORTER_ASSERT(reporter, halfBrightness->asColorFilter(&cf));
halcanary96fcdcc2015-08-27 07:41:13 -0700210 REPORTER_ASSERT(reporter, !cf->asColorMatrix(nullptr));
reedcedc36f2015-03-08 04:42:52 -0700211 cf->unref();
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000212 }
213
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000214 {
215 // Check that a color filter image filter without a crop rect can be
216 // expressed as a color filter.
halcanary96fcdcc2015-08-27 07:41:13 -0700217 SkAutoTUnref<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
218 REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000219 }
mtklein2afbe232016-02-07 12:23:10 -0800220
reedcedc36f2015-03-08 04:42:52 -0700221 {
222 // Check that a colorfilterimage filter without a crop rect but with an input
223 // that is another colorfilterimage can be expressed as a colorfilter (composed).
halcanary96fcdcc2015-08-27 07:41:13 -0700224 SkAutoTUnref<SkImageFilter> mode(make_blue(nullptr, nullptr));
225 SkAutoTUnref<SkImageFilter> gray(make_grayscale(mode, nullptr));
226 REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
reedcedc36f2015-03-08 04:42:52 -0700227 }
228
229 {
230 // Test that if we exceed the limit of what ComposeColorFilter can combine, we still
231 // can build the DAG and won't assert if we call asColorFilter.
halcanary96fcdcc2015-08-27 07:41:13 -0700232 SkAutoTUnref<SkImageFilter> filter(make_blue(nullptr, nullptr));
reedcedc36f2015-03-08 04:42:52 -0700233 const int kWayTooManyForComposeColorFilter = 100;
234 for (int i = 0; i < kWayTooManyForComposeColorFilter; ++i) {
halcanary96fcdcc2015-08-27 07:41:13 -0700235 filter.reset(make_blue(filter, nullptr));
reedcedc36f2015-03-08 04:42:52 -0700236 // the first few of these will succeed, but after we hit the internal limit,
237 // it will then return false.
halcanary96fcdcc2015-08-27 07:41:13 -0700238 (void)filter->asColorFilter(nullptr);
reedcedc36f2015-03-08 04:42:52 -0700239 }
240 }
reed5c518a82015-03-05 14:47:29 -0800241
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000242 {
243 // Check that a color filter image filter with a crop rect cannot
244 // be expressed as a color filter.
245 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100));
halcanary96fcdcc2015-08-27 07:41:13 -0700246 SkAutoTUnref<SkImageFilter> grayWithCrop(make_grayscale(nullptr, &cropRect));
247 REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(nullptr));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000248 }
249
250 {
senorblanco3df05012014-07-03 11:13:09 -0700251 // Check that two non-commutative matrices are concatenated in
252 // the correct order.
253 SkScalar blueToRedMatrix[20] = { 0 };
254 blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
255 SkScalar redToGreenMatrix[20] = { 0 };
256 redToGreenMatrix[5] = redToGreenMatrix[18] = SK_Scalar1;
257 SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix));
258 SkAutoTUnref<SkImageFilter> filter1(SkColorFilterImageFilter::Create(blueToRed.get()));
259 SkAutoTUnref<SkColorFilter> redToGreen(SkColorMatrixFilter::Create(redToGreenMatrix));
260 SkAutoTUnref<SkImageFilter> filter2(SkColorFilterImageFilter::Create(redToGreen.get(), filter1.get()));
261
262 SkBitmap result;
263 result.allocN32Pixels(kBitmapSize, kBitmapSize);
264
265 SkPaint paint;
266 paint.setColor(SK_ColorBLUE);
267 paint.setImageFilter(filter2.get());
268 SkCanvas canvas(result);
269 canvas.clear(0x0);
270 SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
271 canvas.drawRect(rect, paint);
272 uint32_t pixel = *result.getAddr32(0, 0);
273 // The result here should be green, since we have effectively shifted blue to green.
274 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
275 }
276
277 {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000278 // Tests pass by not asserting
fmalita5598b632015-09-15 11:26:13 -0700279 SkAutoTUnref<SkImage> image(make_small_image());
280 SkBitmap result;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000281 result.allocN32Pixels(kBitmapSize, kBitmapSize);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000282
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000283 {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000284 // This tests for :
285 // 1 ) location at (0,0,1)
robertphillips3d32d762015-07-13 13:16:44 -0700286 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000287 // 2 ) location and target at same value
robertphillips3d32d762015-07-13 13:16:44 -0700288 SkPoint3 target = SkPoint3::Make(location.fX, location.fY, location.fZ);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000289 // 3 ) large negative specular exponent value
290 SkScalar specularExponent = -1000;
291
fmalita5598b632015-09-15 11:26:13 -0700292 SkAutoTUnref<SkImageFilter> bmSrc(SkImageSource::Create(image));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000293 SkPaint paint;
294 paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(
295 location, target, specularExponent, 180,
296 0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
297 bmSrc))->unref();
298 SkCanvas canvas(result);
299 SkRect r = SkRect::MakeWH(SkIntToScalar(kBitmapSize),
300 SkIntToScalar(kBitmapSize));
301 canvas.drawRect(r, paint);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000302 }
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000303 }
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000304}
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000305
robertphillips4418dba2016-03-07 12:45:14 -0800306static void test_crop_rects(SkImageFilter::Proxy* proxy,
307 skiatest::Reporter* reporter,
308 GrContext* context) {
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000309 // Check that all filters offset to their absolute crop rect,
310 // unaffected by the input crop rect.
311 // Tests pass by not asserting.
robertphillips4418dba2016-03-07 12:45:14 -0800312 SkAutoTUnref<SkSpecialImage> srcImg(create_empty_special_image(context, proxy, 100));
313 SkASSERT(srcImg);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000314
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000315 SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
316 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
halcanary96fcdcc2015-08-27 07:41:13 -0700317 SkAutoTUnref<SkImageFilter> input(make_grayscale(nullptr, &inputCropRect));
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000318
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000319 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
robertphillips3d32d762015-07-13 13:16:44 -0700320 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000321 SkScalar kernel[9] = {
322 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
323 SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
324 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
325 };
326 SkISize kernelSize = SkISize::Make(3, 3);
327 SkScalar gain = SK_Scalar1, bias = 0;
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000328
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000329 SkImageFilter* filters[] = {
330 SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000331 SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType,
332 SkDisplacementMapEffect::kB_ChannelSelectorType,
333 40.0f, input.get(), input.get(), &cropRect),
334 SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
sugoi234f0362014-10-23 13:59:52 -0700335 SkDropShadowImageFilter::Create(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1,
336 SK_ColorGREEN, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
senorblanco24e06d52015-03-18 12:11:33 -0700337 input.get(), &cropRect),
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000338 SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
339 SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000340 SkMatrixConvolutionImageFilter::Create(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
341 SkMergeImageFilter::Create(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
342 SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
343 SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
344 SkDilateImageFilter::Create(3, 2, input.get(), &cropRect),
345 SkErodeImageFilter::Create(2, 3, input.get(), &cropRect),
346 SkTileImageFilter::Create(inputCropRect.rect(), cropRect.rect(), input.get()),
347 SkXfermodeImageFilter::Create(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000348 };
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000349
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000350 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
351 SkImageFilter* filter = filters[i];
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000352 SkIPoint offset;
353 SkString str;
senorblanco@chromium.orgf4e1a762014-02-04 00:28:46 +0000354 str.printf("filter %d", static_cast<int>(i));
reed4e23cda2016-01-11 10:56:59 -0800355 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr);
robertphillips4418dba2016-03-07 12:45:14 -0800356 SkAutoTUnref<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset));
357 REPORTER_ASSERT_MESSAGE(reporter, resultImg, str.c_str());
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000358 REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str());
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000359 }
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000360
361 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
362 SkSafeUnref(filters[i]);
363 }
364}
365
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000366static SkBitmap make_gradient_circle(int width, int height) {
367 SkBitmap bitmap;
368 SkScalar x = SkIntToScalar(width / 2);
369 SkScalar y = SkIntToScalar(height / 2);
370 SkScalar radius = SkMinScalar(x, y) * 0.8f;
371 bitmap.allocN32Pixels(width, height);
372 SkCanvas canvas(bitmap);
373 canvas.clear(0x00000000);
374 SkColor colors[2];
375 colors[0] = SK_ColorWHITE;
376 colors[1] = SK_ColorBLACK;
377 SkAutoTUnref<SkShader> shader(
halcanary96fcdcc2015-08-27 07:41:13 -0700378 SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, nullptr, 2,
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000379 SkShader::kClamp_TileMode)
380 );
381 SkPaint paint;
382 paint.setShader(shader);
383 canvas.drawCircle(x, y, radius, paint);
384 return bitmap;
385}
386
robertphillips4418dba2016-03-07 12:45:14 -0800387
388
389static void test_negative_blur_sigma(SkImageFilter::Proxy* proxy,
390 skiatest::Reporter* reporter,
391 GrContext* context) {
senorblanco32673b92014-09-09 09:15:04 -0700392 // Check that SkBlurImageFilter will accept a negative sigma, either in
393 // the given arguments or after CTM application.
reed5ea95df2015-10-06 14:05:32 -0700394 const int width = 32, height = 32;
395 const SkScalar five = SkIntToScalar(5);
senorblanco32673b92014-09-09 09:15:04 -0700396
reed5ea95df2015-10-06 14:05:32 -0700397 SkAutoTUnref<SkImageFilter> positiveFilter(SkBlurImageFilter::Create(five, five));
398 SkAutoTUnref<SkImageFilter> negativeFilter(SkBlurImageFilter::Create(-five, five));
senorblanco32673b92014-09-09 09:15:04 -0700399
400 SkBitmap gradient = make_gradient_circle(width, height);
robertphillips4418dba2016-03-07 12:45:14 -0800401 SkAutoTUnref<SkSpecialImage> imgSrc(SkSpecialImage::NewFromRaster(proxy,
402 SkIRect::MakeWH(width,
403 height),
404 gradient));
405
senorblanco32673b92014-09-09 09:15:04 -0700406 SkIPoint offset;
reed4e23cda2016-01-11 10:56:59 -0800407 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(32, 32), nullptr);
robertphillips4418dba2016-03-07 12:45:14 -0800408
409 SkAutoTUnref<SkSpecialImage> positiveResult1(positiveFilter->filterImage(imgSrc, ctx, &offset));
410 REPORTER_ASSERT(reporter, positiveResult1);
411
412 SkAutoTUnref<SkSpecialImage> negativeResult1(negativeFilter->filterImage(imgSrc, ctx, &offset));
413 REPORTER_ASSERT(reporter, negativeResult1);
414
senorblanco32673b92014-09-09 09:15:04 -0700415 SkMatrix negativeScale;
416 negativeScale.setScale(-SK_Scalar1, SK_Scalar1);
reed4e23cda2016-01-11 10:56:59 -0800417 SkImageFilter::Context negativeCTX(negativeScale, SkIRect::MakeWH(32, 32), nullptr);
robertphillips4418dba2016-03-07 12:45:14 -0800418
419 SkAutoTUnref<SkSpecialImage> negativeResult2(positiveFilter->filterImage(imgSrc,
420 negativeCTX,
421 &offset));
422 REPORTER_ASSERT(reporter, negativeResult2);
423
424 SkAutoTUnref<SkSpecialImage> positiveResult2(negativeFilter->filterImage(imgSrc,
425 negativeCTX,
426 &offset));
427 REPORTER_ASSERT(reporter, positiveResult2);
428
429
430 SkBitmap positiveResultBM1, positiveResultBM2;
431 SkBitmap negativeResultBM1, negativeResultBM2;
432
433 TestingSpecialImageAccess::GetROPixels(positiveResult1, &positiveResultBM1);
434 TestingSpecialImageAccess::GetROPixels(positiveResult2, &positiveResultBM2);
435 TestingSpecialImageAccess::GetROPixels(negativeResult1, &negativeResultBM1);
436 TestingSpecialImageAccess::GetROPixels(negativeResult2, &negativeResultBM2);
437
438 SkAutoLockPixels lockP1(positiveResultBM1);
439 SkAutoLockPixels lockP2(positiveResultBM2);
440 SkAutoLockPixels lockN1(negativeResultBM1);
441 SkAutoLockPixels lockN2(negativeResultBM2);
senorblanco32673b92014-09-09 09:15:04 -0700442 for (int y = 0; y < height; y++) {
robertphillips4418dba2016-03-07 12:45:14 -0800443 int diffs = memcmp(positiveResultBM1.getAddr32(0, y),
444 negativeResultBM1.getAddr32(0, y),
445 positiveResultBM1.rowBytes());
senorblanco32673b92014-09-09 09:15:04 -0700446 REPORTER_ASSERT(reporter, !diffs);
447 if (diffs) {
448 break;
449 }
robertphillips4418dba2016-03-07 12:45:14 -0800450 diffs = memcmp(positiveResultBM1.getAddr32(0, y),
451 negativeResultBM2.getAddr32(0, y),
452 positiveResultBM1.rowBytes());
senorblanco32673b92014-09-09 09:15:04 -0700453 REPORTER_ASSERT(reporter, !diffs);
454 if (diffs) {
455 break;
456 }
robertphillips4418dba2016-03-07 12:45:14 -0800457 diffs = memcmp(positiveResultBM1.getAddr32(0, y),
458 positiveResultBM2.getAddr32(0, y),
459 positiveResultBM1.rowBytes());
senorblanco32673b92014-09-09 09:15:04 -0700460 REPORTER_ASSERT(reporter, !diffs);
461 if (diffs) {
462 break;
463 }
464 }
465}
466
robertphillips4418dba2016-03-07 12:45:14 -0800467typedef void (*PFTest)(SkImageFilter::Proxy* proxy,
468 skiatest::Reporter* reporter,
469 GrContext* context);
470
471static void run_raster_test(skiatest::Reporter* reporter,
472 int widthHeight,
473 PFTest test) {
robertphillips9a53fd72015-06-22 09:46:59 -0700474 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
475
robertphillips4418dba2016-03-07 12:45:14 -0800476 const SkImageInfo info = SkImageInfo::MakeN32Premul(widthHeight, widthHeight);
477
robertphillips9a53fd72015-06-22 09:46:59 -0700478 SkAutoTUnref<SkBaseDevice> device(SkBitmapDevice::Create(info, props));
reed88d064d2015-10-12 11:30:02 -0700479 SkImageFilter::DeviceProxy proxy(device);
robertphillips9a53fd72015-06-22 09:46:59 -0700480
robertphillips4418dba2016-03-07 12:45:14 -0800481 (*test)(&proxy, reporter, nullptr);
senorblanco32673b92014-09-09 09:15:04 -0700482}
483
robertphillips4418dba2016-03-07 12:45:14 -0800484#if SK_SUPPORT_GPU
485static void run_gpu_test(skiatest::Reporter* reporter,
486 GrContext* context,
487 int widthHeight,
488 PFTest test) {
489 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
490
491 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
492 SkBudgeted::kNo,
493 SkImageInfo::MakeN32Premul(widthHeight,
494 widthHeight),
495 0,
496 &props,
497 SkGpuDevice::kUninit_InitContents));
498 SkImageFilter::DeviceProxy proxy(device);
499
500 (*test)(&proxy, reporter, context);
501}
502#endif
503
504DEF_TEST(TestNegativeBlurSigma, reporter) {
505 run_raster_test(reporter, 100, test_negative_blur_sigma);
506}
507
508#if SK_SUPPORT_GPU
509DEF_GPUTEST_FOR_NATIVE_CONTEXT(TestNegativeBlurSigma_Gpu, reporter, context) {
510 run_gpu_test(reporter, context, 100, test_negative_blur_sigma);
511}
512#endif
513
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000514DEF_TEST(ImageFilterDrawTiled, reporter) {
515 // Check that all filters when drawn tiled (with subsequent clip rects) exactly
516 // match the same filters drawn with a single full-canvas bitmap draw.
517 // Tests pass by not asserting.
518
519 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
robertphillips3d32d762015-07-13 13:16:44 -0700520 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000521 SkScalar kernel[9] = {
522 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
523 SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
524 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
525 };
reed5ea95df2015-10-06 14:05:32 -0700526 const SkISize kernelSize = SkISize::Make(3, 3);
527 const SkScalar gain = SK_Scalar1, bias = 0;
528 const SkScalar five = SkIntToScalar(5);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000529
fmalita5598b632015-09-15 11:26:13 -0700530 SkAutoTUnref<SkImage> gradientImage(SkImage::NewFromBitmap(make_gradient_circle(64, 64)));
531 SkAutoTUnref<SkImageFilter> gradientSource(SkImageSource::Create(gradientImage));
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000532 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(five, five));
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000533 SkMatrix matrix;
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000534
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000535 matrix.setTranslate(SK_Scalar1, SK_Scalar1);
536 matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000537
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000538 SkRTreeFactory factory;
539 SkPictureRecorder recorder;
540 SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0);
541
542 SkPaint greenPaint;
543 greenPaint.setColor(SK_ColorGREEN);
544 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
545 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
546 SkAutoTUnref<SkImageFilter> pictureFilter(SkPictureImageFilter::Create(picture.get()));
senorblanco8f3937d2014-10-29 12:36:32 -0700547 SkAutoTUnref<SkShader> shader(SkPerlinNoiseShader::CreateTurbulence(SK_Scalar1, SK_Scalar1, 1, 0));
ajuma77b6ba32016-01-08 14:58:35 -0800548 SkPaint noisePaint;
549 noisePaint.setShader(shader);
senorblanco8f3937d2014-10-29 12:36:32 -0700550
ajuma77b6ba32016-01-08 14:58:35 -0800551 SkAutoTUnref<SkImageFilter> paintFilter(SkPaintImageFilter::Create(noisePaint));
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000552
fsd8b57712015-05-20 00:52:17 -0700553 SkImageFilter::CropRect leftSideCropRect(SkRect::MakeXYWH(0, 0, 32, 64));
ajuma77b6ba32016-01-08 14:58:35 -0800554 SkAutoTUnref<SkImageFilter> paintFilterLeft(SkPaintImageFilter::Create(greenPaint, &leftSideCropRect));
fsd8b57712015-05-20 00:52:17 -0700555 SkImageFilter::CropRect rightSideCropRect(SkRect::MakeXYWH(32, 0, 32, 64));
ajuma77b6ba32016-01-08 14:58:35 -0800556 SkAutoTUnref<SkImageFilter> paintFilterRight(SkPaintImageFilter::Create(greenPaint, &rightSideCropRect));
fsd8b57712015-05-20 00:52:17 -0700557
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000558 struct {
559 const char* fName;
560 SkImageFilter* fFilter;
561 } filters[] = {
562 { "color filter", SkColorFilterImageFilter::Create(cf.get()) },
563 { "displacement map", SkDisplacementMapEffect::Create(
564 SkDisplacementMapEffect::kR_ChannelSelectorType,
565 SkDisplacementMapEffect::kB_ChannelSelectorType,
fmalita5598b632015-09-15 11:26:13 -0700566 20.0f, gradientSource.get()) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000567 { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
568 { "drop shadow", SkDropShadowImageFilter::Create(
sugoi234f0362014-10-23 13:59:52 -0700569 SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN,
570 SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000571 { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse(
572 location, SK_ColorGREEN, 0, 0) },
573 { "specular lighting",
574 SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) },
575 { "matrix convolution",
576 SkMatrixConvolutionImageFilter::Create(
577 kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
578 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) },
halcanary96fcdcc2015-08-27 07:41:13 -0700579 { "merge", SkMergeImageFilter::Create(nullptr, nullptr, SkXfermode::kSrcOver_Mode) },
fsd8b57712015-05-20 00:52:17 -0700580 { "merge with disjoint inputs", SkMergeImageFilter::Create(
ajuma77b6ba32016-01-08 14:58:35 -0800581 paintFilterLeft, paintFilterRight, SkXfermode::kSrcOver_Mode) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000582 { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) },
583 { "dilate", SkDilateImageFilter::Create(3, 2) },
584 { "erode", SkErodeImageFilter::Create(2, 3) },
585 { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50),
halcanary96fcdcc2015-08-27 07:41:13 -0700586 SkRect::MakeXYWH(0, 0, 100, 100), nullptr) },
senorblanco8c874ee2015-03-20 06:38:17 -0700587 { "matrix", SkImageFilter::CreateMatrixFilter(matrix, kLow_SkFilterQuality) },
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000588 { "blur and offset", SkOffsetImageFilter::Create(five, five, blur.get()) },
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000589 { "picture and blur", SkBlurImageFilter::Create(five, five, pictureFilter.get()) },
ajuma77b6ba32016-01-08 14:58:35 -0800590 { "paint and blur", SkBlurImageFilter::Create(five, five, paintFilter.get()) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000591 };
592
593 SkBitmap untiledResult, tiledResult;
reed5ea95df2015-10-06 14:05:32 -0700594 const int width = 64, height = 64;
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000595 untiledResult.allocN32Pixels(width, height);
596 tiledResult.allocN32Pixels(width, height);
597 SkCanvas tiledCanvas(tiledResult);
598 SkCanvas untiledCanvas(untiledResult);
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000599 int tileSize = 8;
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000600
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000601 for (int scale = 1; scale <= 2; ++scale) {
602 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
603 tiledCanvas.clear(0);
604 untiledCanvas.clear(0);
605 SkPaint paint;
606 paint.setImageFilter(filters[i].fFilter);
607 paint.setTextSize(SkIntToScalar(height));
608 paint.setColor(SK_ColorWHITE);
609 SkString str;
610 const char* text = "ABC";
611 SkScalar ypos = SkIntToScalar(height);
612 untiledCanvas.save();
613 untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
614 untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
615 untiledCanvas.restore();
616 for (int y = 0; y < height; y += tileSize) {
617 for (int x = 0; x < width; x += tileSize) {
618 tiledCanvas.save();
619 tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
620 tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
621 tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
622 tiledCanvas.restore();
623 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000624 }
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000625 untiledCanvas.flush();
626 tiledCanvas.flush();
627 for (int y = 0; y < height; y++) {
628 int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
629 REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
630 if (diffs) {
631 break;
632 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000633 }
634 }
635 }
636
637 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
638 SkSafeUnref(filters[i].fFilter);
639 }
640}
641
mtklein3f3b3d02014-12-01 11:47:08 -0800642static void draw_saveLayer_picture(int width, int height, int tileSize,
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700643 SkBBHFactory* factory, SkBitmap* result) {
mtkleind910f542014-08-22 09:06:34 -0700644
645 SkMatrix matrix;
646 matrix.setTranslate(SkIntToScalar(50), 0);
647
648 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorWHITE, SkXfermode::kSrc_Mode));
649 SkAutoTUnref<SkImageFilter> cfif(SkColorFilterImageFilter::Create(cf.get()));
senorblanco8c874ee2015-03-20 06:38:17 -0700650 SkAutoTUnref<SkImageFilter> imageFilter(SkImageFilter::CreateMatrixFilter(matrix, kNone_SkFilterQuality, cfif.get()));
mtkleind910f542014-08-22 09:06:34 -0700651
652 SkPaint paint;
653 paint.setImageFilter(imageFilter.get());
654 SkPictureRecorder recorder;
655 SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50));
mtklein3f3b3d02014-12-01 11:47:08 -0800656 SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width),
657 SkIntToScalar(height),
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700658 factory, 0);
mtkleind910f542014-08-22 09:06:34 -0700659 recordingCanvas->translate(-55, 0);
660 recordingCanvas->saveLayer(&bounds, &paint);
661 recordingCanvas->restore();
662 SkAutoTUnref<SkPicture> picture1(recorder.endRecording());
663
664 result->allocN32Pixels(width, height);
665 SkCanvas canvas(*result);
666 canvas.clear(0);
667 canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize)));
668 canvas.drawPicture(picture1.get());
669}
670
671DEF_TEST(ImageFilterDrawMatrixBBH, reporter) {
672 // Check that matrix filter when drawn tiled with BBH exactly
673 // matches the same thing drawn without BBH.
674 // Tests pass by not asserting.
675
676 const int width = 200, height = 200;
677 const int tileSize = 100;
678 SkBitmap result1, result2;
679 SkRTreeFactory factory;
680
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700681 draw_saveLayer_picture(width, height, tileSize, &factory, &result1);
halcanary96fcdcc2015-08-27 07:41:13 -0700682 draw_saveLayer_picture(width, height, tileSize, nullptr, &result2);
mtkleind910f542014-08-22 09:06:34 -0700683
684 for (int y = 0; y < height; y++) {
685 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
686 REPORTER_ASSERT(reporter, !diffs);
687 if (diffs) {
688 break;
689 }
690 }
691}
692
halcanary96fcdcc2015-08-27 07:41:13 -0700693static SkImageFilter* makeBlur(SkImageFilter* input = nullptr) {
senorblanco1150a6d2014-08-25 12:46:58 -0700694 return SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input);
695}
696
halcanary96fcdcc2015-08-27 07:41:13 -0700697static SkImageFilter* makeDropShadow(SkImageFilter* input = nullptr) {
senorblanco1150a6d2014-08-25 12:46:58 -0700698 return SkDropShadowImageFilter::Create(
699 SkIntToScalar(100), SkIntToScalar(100),
700 SkIntToScalar(10), SkIntToScalar(10),
sugoi234f0362014-10-23 13:59:52 -0700701 SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
halcanary96fcdcc2015-08-27 07:41:13 -0700702 input, nullptr);
senorblanco1150a6d2014-08-25 12:46:58 -0700703}
704
705DEF_TEST(ImageFilterBlurThenShadowBounds, reporter) {
706 SkAutoTUnref<SkImageFilter> filter1(makeBlur());
707 SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get()));
708
709 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
710 SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
711 filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
712
713 REPORTER_ASSERT(reporter, bounds == expectedBounds);
714}
715
716DEF_TEST(ImageFilterShadowThenBlurBounds, reporter) {
717 SkAutoTUnref<SkImageFilter> filter1(makeDropShadow());
718 SkAutoTUnref<SkImageFilter> filter2(makeBlur(filter1.get()));
719
720 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
721 SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236);
722 filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
723
724 REPORTER_ASSERT(reporter, bounds == expectedBounds);
725}
726
727DEF_TEST(ImageFilterDilateThenBlurBounds, reporter) {
728 SkAutoTUnref<SkImageFilter> filter1(SkDilateImageFilter::Create(2, 2));
729 SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get()));
730
731 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100);
732 SkIRect expectedBounds = SkIRect::MakeXYWH(-132, -132, 234, 234);
733 filter2->filterBounds(bounds, SkMatrix::I(), &bounds);
734
735 REPORTER_ASSERT(reporter, bounds == expectedBounds);
736}
737
ajuma5788faa2015-02-13 09:05:47 -0800738DEF_TEST(ImageFilterComposedBlurFastBounds, reporter) {
739 SkAutoTUnref<SkImageFilter> filter1(makeBlur());
740 SkAutoTUnref<SkImageFilter> filter2(makeBlur());
741 SkAutoTUnref<SkImageFilter> composedFilter(SkComposeImageFilter::Create(filter1.get(), filter2.get()));
742
743 SkRect boundsSrc = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
744 SkRect expectedBounds = SkRect::MakeXYWH(
745 SkIntToScalar(-6), SkIntToScalar(-6), SkIntToScalar(112), SkIntToScalar(112));
746 SkRect boundsDst = SkRect::MakeEmpty();
747 composedFilter->computeFastBounds(boundsSrc, &boundsDst);
748
749 REPORTER_ASSERT(reporter, boundsDst == expectedBounds);
750}
751
robertphillips4418dba2016-03-07 12:45:14 -0800752static void test_imagefilter_merge_result_size(SkImageFilter::Proxy* proxy,
753 skiatest::Reporter* reporter,
754 GrContext* context) {
senorblanco4a243982015-11-25 07:06:55 -0800755 SkBitmap greenBM;
756 greenBM.allocN32Pixels(20, 20);
757 greenBM.eraseColor(SK_ColorGREEN);
758 SkAutoTUnref<SkImage> greenImage(SkImage::NewFromBitmap(greenBM));
759 SkAutoTUnref<SkImageFilter> source(SkImageSource::Create(greenImage.get()));
760 SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(source.get(), source.get()));
761
robertphillips4418dba2016-03-07 12:45:14 -0800762 SkAutoTUnref<SkSpecialImage> srcImg(create_empty_special_image(context, proxy, 1));
763
reed4e23cda2016-01-11 10:56:59 -0800764 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(0, 0, 100, 100), nullptr);
senorblanco4a243982015-11-25 07:06:55 -0800765 SkIPoint offset;
robertphillips4418dba2016-03-07 12:45:14 -0800766
767 SkAutoTUnref<SkSpecialImage> resultImg(merge->filterImage(srcImg, ctx, &offset));
768 REPORTER_ASSERT(reporter, resultImg);
769
770 REPORTER_ASSERT(reporter, resultImg->width() == 20 && resultImg->height() == 20);
senorblanco4a243982015-11-25 07:06:55 -0800771}
772
robertphillips4418dba2016-03-07 12:45:14 -0800773DEF_TEST(ImageFilterMergeResultSize, reporter) {
774 run_raster_test(reporter, 100, test_imagefilter_merge_result_size);
775}
776
777#if SK_SUPPORT_GPU
778DEF_GPUTEST_FOR_NATIVE_CONTEXT(ImageFilterMergeResultSize_Gpu, reporter, context) {
779 run_gpu_test(reporter, context, 100, test_imagefilter_merge_result_size);
780}
781#endif
782
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700783static void draw_blurred_rect(SkCanvas* canvas) {
senorblanco837f5322014-07-14 10:19:54 -0700784 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0));
785 SkPaint filterPaint;
786 filterPaint.setColor(SK_ColorWHITE);
787 filterPaint.setImageFilter(filter);
halcanary96fcdcc2015-08-27 07:41:13 -0700788 canvas->saveLayer(nullptr, &filterPaint);
senorblanco837f5322014-07-14 10:19:54 -0700789 SkPaint whitePaint;
790 whitePaint.setColor(SK_ColorWHITE);
791 canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
792 canvas->restore();
793}
794
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700795static void draw_picture_clipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
senorblanco837f5322014-07-14 10:19:54 -0700796 canvas->save();
797 canvas->clipRect(clipRect);
798 canvas->drawPicture(picture);
799 canvas->restore();
800}
801
802DEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) {
803 // Check that the blur filter when recorded with RTree acceleration,
804 // and drawn tiled (with subsequent clip rects) exactly
805 // matches the same filter drawn with without RTree acceleration.
806 // This tests that the "bleed" from the blur into the otherwise-blank
807 // tiles is correctly rendered.
808 // Tests pass by not asserting.
809
810 int width = 16, height = 8;
811 SkBitmap result1, result2;
812 result1.allocN32Pixels(width, height);
813 result2.allocN32Pixels(width, height);
814 SkCanvas canvas1(result1);
815 SkCanvas canvas2(result2);
816 int tileSize = 8;
817
818 canvas1.clear(0);
819 canvas2.clear(0);
820
821 SkRTreeFactory factory;
822
823 SkPictureRecorder recorder1, recorder2;
824 // The only difference between these two pictures is that one has RTree aceleration.
mtklein3f3b3d02014-12-01 11:47:08 -0800825 SkCanvas* recordingCanvas1 = recorder1.beginRecording(SkIntToScalar(width),
826 SkIntToScalar(height),
halcanary96fcdcc2015-08-27 07:41:13 -0700827 nullptr, 0);
mtklein3f3b3d02014-12-01 11:47:08 -0800828 SkCanvas* recordingCanvas2 = recorder2.beginRecording(SkIntToScalar(width),
829 SkIntToScalar(height),
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700830 &factory, 0);
831 draw_blurred_rect(recordingCanvas1);
832 draw_blurred_rect(recordingCanvas2);
senorblanco837f5322014-07-14 10:19:54 -0700833 SkAutoTUnref<SkPicture> picture1(recorder1.endRecording());
834 SkAutoTUnref<SkPicture> picture2(recorder2.endRecording());
835 for (int y = 0; y < height; y += tileSize) {
836 for (int x = 0; x < width; x += tileSize) {
837 SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700838 draw_picture_clipped(&canvas1, tileRect, picture1);
839 draw_picture_clipped(&canvas2, tileRect, picture2);
senorblanco837f5322014-07-14 10:19:54 -0700840 }
841 }
842 for (int y = 0; y < height; y++) {
843 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
844 REPORTER_ASSERT(reporter, !diffs);
845 if (diffs) {
846 break;
847 }
848 }
849}
850
senorblanco@chromium.org91957432014-05-01 14:03:41 +0000851DEF_TEST(ImageFilterMatrixConvolution, reporter) {
852 // Check that a 1x3 filter does not cause a spurious assert.
853 SkScalar kernel[3] = {
854 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
855 };
856 SkISize kernelSize = SkISize::Make(1, 3);
857 SkScalar gain = SK_Scalar1, bias = 0;
858 SkIPoint kernelOffset = SkIPoint::Make(0, 0);
859
860 SkAutoTUnref<SkImageFilter> filter(
861 SkMatrixConvolutionImageFilter::Create(
862 kernelSize, kernel, gain, bias, kernelOffset,
863 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false));
864
865 SkBitmap result;
866 int width = 16, height = 16;
867 result.allocN32Pixels(width, height);
868 SkCanvas canvas(result);
869 canvas.clear(0);
870
871 SkPaint paint;
872 paint.setImageFilter(filter);
873 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
874 canvas.drawRect(rect, paint);
875}
876
senorblanco@chromium.org8c7372b2014-05-02 19:13:11 +0000877DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
878 // Check that a filter with borders outside the target bounds
879 // does not crash.
880 SkScalar kernel[3] = {
881 0, 0, 0,
882 };
883 SkISize kernelSize = SkISize::Make(3, 1);
884 SkScalar gain = SK_Scalar1, bias = 0;
885 SkIPoint kernelOffset = SkIPoint::Make(2, 0);
886
887 SkAutoTUnref<SkImageFilter> filter(
888 SkMatrixConvolutionImageFilter::Create(
889 kernelSize, kernel, gain, bias, kernelOffset,
890 SkMatrixConvolutionImageFilter::kClamp_TileMode, true));
891
892 SkBitmap result;
893
894 int width = 10, height = 10;
895 result.allocN32Pixels(width, height);
896 SkCanvas canvas(result);
897 canvas.clear(0);
898
899 SkPaint filterPaint;
900 filterPaint.setImageFilter(filter);
901 SkRect bounds = SkRect::MakeWH(1, 10);
902 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
903 SkPaint rectPaint;
904 canvas.saveLayer(&bounds, &filterPaint);
905 canvas.drawRect(rect, rectPaint);
906 canvas.restore();
907}
908
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000909DEF_TEST(ImageFilterCropRect, reporter) {
robertphillips4418dba2016-03-07 12:45:14 -0800910 run_raster_test(reporter, 100, test_crop_rects);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000911}
912
robertphillips4418dba2016-03-07 12:45:14 -0800913#if SK_SUPPORT_GPU
914DEF_GPUTEST_FOR_NATIVE_CONTEXT(ImageFilterCropRect_Gpu, reporter, context) {
915 run_gpu_test(reporter, context, 100, test_crop_rects);
916}
917#endif
918
tfarina9ea53f92014-06-24 06:50:39 -0700919DEF_TEST(ImageFilterMatrix, reporter) {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000920 SkBitmap temp;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000921 temp.allocN32Pixels(100, 100);
robertphillips9a53fd72015-06-22 09:46:59 -0700922 SkCanvas canvas(temp);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000923 canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
924
925 SkMatrix expectedMatrix = canvas.getTotalMatrix();
926
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000927 SkRTreeFactory factory;
928 SkPictureRecorder recorder;
929 SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000930
931 SkPaint paint;
932 SkAutoTUnref<MatrixTestImageFilter> imageFilter(
933 new MatrixTestImageFilter(reporter, expectedMatrix));
934 paint.setImageFilter(imageFilter.get());
halcanary96fcdcc2015-08-27 07:41:13 -0700935 recordingCanvas->saveLayer(nullptr, &paint);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000936 SkPaint solidPaint;
937 solidPaint.setColor(0xFFFFFFFF);
938 recordingCanvas->save();
939 recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
940 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
941 recordingCanvas->restore(); // scale
942 recordingCanvas->restore(); // saveLayer
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000943 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000944
robertphillips9b14f262014-06-04 05:40:44 -0700945 canvas.drawPicture(picture);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000946}
947
senorblanco3d822c22014-07-30 14:49:31 -0700948DEF_TEST(ImageFilterCrossProcessPictureImageFilter, reporter) {
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000949 SkRTreeFactory factory;
950 SkPictureRecorder recorder;
951 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
952
953 // Create an SkPicture which simply draws a green 1x1 rectangle.
954 SkPaint greenPaint;
955 greenPaint.setColor(SK_ColorGREEN);
956 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
957 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
958
959 // Wrap that SkPicture in an SkPictureImageFilter.
960 SkAutoTUnref<SkImageFilter> imageFilter(
961 SkPictureImageFilter::Create(picture.get()));
962
963 // Check that SkPictureImageFilter successfully serializes its contained
964 // SkPicture when not in cross-process mode.
965 SkPaint paint;
966 paint.setImageFilter(imageFilter.get());
967 SkPictureRecorder outerRecorder;
968 SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
969 SkPaint redPaintWithFilter;
970 redPaintWithFilter.setColor(SK_ColorRED);
971 redPaintWithFilter.setImageFilter(imageFilter.get());
972 outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
973 SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording());
974
975 SkBitmap bitmap;
976 bitmap.allocN32Pixels(1, 1);
robertphillips9a53fd72015-06-22 09:46:59 -0700977 SkCanvas canvas(bitmap);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000978
979 // The result here should be green, since the filter replaces the primitive's red interior.
980 canvas.clear(0x0);
robertphillips9b14f262014-06-04 05:40:44 -0700981 canvas.drawPicture(outerPicture);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000982 uint32_t pixel = *bitmap.getAddr32(0, 0);
983 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
984
985 // Check that, for now, SkPictureImageFilter does not serialize or
986 // deserialize its contained picture when the filter is serialized
987 // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
988 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
989 SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
990 data->data(), data->size(), SkImageFilter::GetFlattenableType()));
991 SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
992
993 redPaintWithFilter.setImageFilter(unflattenedFilter);
994 SkPictureRecorder crossProcessRecorder;
995 SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
996 crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
997 SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording());
998
999 canvas.clear(0x0);
robertphillips9b14f262014-06-04 05:40:44 -07001000 canvas.drawPicture(crossProcessPicture);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +00001001 pixel = *bitmap.getAddr32(0, 0);
hendrikw446ee672015-06-16 09:28:37 -07001002 // If the security precautions are enabled, the result here should not be green, since the
1003 // filter draws nothing.
mtklein2afbe232016-02-07 12:23:10 -08001004 REPORTER_ASSERT(reporter, SkPicture::PictureIOSecurityPrecautionsEnabled()
hendrikw446ee672015-06-16 09:28:37 -07001005 ? pixel != SK_ColorGREEN : pixel == SK_ColorGREEN);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +00001006}
1007
robertphillips4418dba2016-03-07 12:45:14 -08001008static void test_clipped_picture_imagefilter(SkImageFilter::Proxy* proxy,
1009 skiatest::Reporter* reporter,
1010 GrContext* context) {
1011 SkAutoTUnref<SkPicture> picture;
senorblanco3d822c22014-07-30 14:49:31 -07001012
robertphillips4418dba2016-03-07 12:45:14 -08001013 {
1014 SkRTreeFactory factory;
1015 SkPictureRecorder recorder;
1016 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
1017
1018 // Create an SkPicture which simply draws a green 1x1 rectangle.
1019 SkPaint greenPaint;
1020 greenPaint.setColor(SK_ColorGREEN);
1021 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
1022 picture.reset(recorder.endRecording());
1023 }
1024
1025 SkAutoTUnref<SkSpecialImage> srcImg(create_empty_special_image(context, proxy, 2));
senorblanco3d822c22014-07-30 14:49:31 -07001026
robertphillips9a53fd72015-06-22 09:46:59 -07001027 SkAutoTUnref<SkImageFilter> imageFilter(SkPictureImageFilter::Create(picture.get()));
senorblanco3d822c22014-07-30 14:49:31 -07001028
senorblanco3d822c22014-07-30 14:49:31 -07001029 SkIPoint offset;
reed4e23cda2016-01-11 10:56:59 -08001030 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(1, 1, 1, 1), nullptr);
robertphillips4418dba2016-03-07 12:45:14 -08001031
1032 SkAutoTUnref<SkSpecialImage> resultImage(imageFilter->filterImage(srcImg, ctx, &offset));
1033 REPORTER_ASSERT(reporter, !resultImage);
senorblanco3d822c22014-07-30 14:49:31 -07001034}
1035
robertphillips4418dba2016-03-07 12:45:14 -08001036DEF_TEST(ImageFilterClippedPictureImageFilter, reporter) {
1037 run_raster_test(reporter, 2, test_clipped_picture_imagefilter);
1038}
1039
1040#if SK_SUPPORT_GPU
1041DEF_GPUTEST_FOR_NATIVE_CONTEXT(ImageFilterClippedPictureImageFilter_Gpu, reporter, context) {
1042 run_gpu_test(reporter, context, 2, test_clipped_picture_imagefilter);
1043}
1044#endif
1045
tfarina9ea53f92014-06-24 06:50:39 -07001046DEF_TEST(ImageFilterEmptySaveLayer, reporter) {
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001047 // Even when there's an empty saveLayer()/restore(), ensure that an image
1048 // filter or color filter which affects transparent black still draws.
1049
1050 SkBitmap bitmap;
1051 bitmap.allocN32Pixels(10, 10);
robertphillips9a53fd72015-06-22 09:46:59 -07001052 SkCanvas canvas(bitmap);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001053
1054 SkRTreeFactory factory;
1055 SkPictureRecorder recorder;
1056
1057 SkAutoTUnref<SkColorFilter> green(
1058 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode));
reedf0280032015-10-12 11:10:10 -07001059 SkAutoTUnref<SkImageFilter> imageFilter(
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001060 SkColorFilterImageFilter::Create(green.get()));
1061 SkPaint imageFilterPaint;
1062 imageFilterPaint.setImageFilter(imageFilter.get());
1063 SkPaint colorFilterPaint;
1064 colorFilterPaint.setColorFilter(green.get());
1065
1066 SkRect bounds = SkRect::MakeWH(10, 10);
1067
1068 SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
1069 recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
1070 recordingCanvas->restore();
1071 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
1072
1073 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -07001074 canvas.drawPicture(picture);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001075 uint32_t pixel = *bitmap.getAddr32(0, 0);
1076 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1077
1078 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
halcanary96fcdcc2015-08-27 07:41:13 -07001079 recordingCanvas->saveLayer(nullptr, &imageFilterPaint);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001080 recordingCanvas->restore();
1081 SkAutoTUnref<SkPicture> picture2(recorder.endRecording());
1082
1083 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -07001084 canvas.drawPicture(picture2);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001085 pixel = *bitmap.getAddr32(0, 0);
1086 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1087
1088 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
1089 recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
1090 recordingCanvas->restore();
1091 SkAutoTUnref<SkPicture> picture3(recorder.endRecording());
1092
1093 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -07001094 canvas.drawPicture(picture3);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +00001095 pixel = *bitmap.getAddr32(0, 0);
1096 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1097}
1098
robertphillips9a53fd72015-06-22 09:46:59 -07001099static void test_huge_blur(SkCanvas* canvas, skiatest::Reporter* reporter) {
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001100 SkBitmap bitmap;
1101 bitmap.allocN32Pixels(100, 100);
1102 bitmap.eraseARGB(0, 0, 0, 0);
1103
1104 // Check that a blur with an insane radius does not crash or assert.
1105 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(SkIntToScalar(1<<30), SkIntToScalar(1<<30)));
1106
1107 SkPaint paint;
1108 paint.setImageFilter(blur);
reedda420b92015-12-16 08:38:15 -08001109 canvas->drawBitmap(bitmap, 0, 0, &paint);
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001110}
1111
1112DEF_TEST(HugeBlurImageFilter, reporter) {
1113 SkBitmap temp;
1114 temp.allocN32Pixels(100, 100);
robertphillips9a53fd72015-06-22 09:46:59 -07001115 SkCanvas canvas(temp);
1116 test_huge_blur(&canvas, reporter);
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001117}
1118
senorblanco3a495202014-09-29 07:57:20 -07001119DEF_TEST(MatrixConvolutionSanityTest, reporter) {
1120 SkScalar kernel[1] = { 0 };
1121 SkScalar gain = SK_Scalar1, bias = 0;
1122 SkIPoint kernelOffset = SkIPoint::Make(1, 1);
1123
halcanary96fcdcc2015-08-27 07:41:13 -07001124 // Check that an enormous (non-allocatable) kernel gives a nullptr filter.
senorblanco3a495202014-09-29 07:57:20 -07001125 SkAutoTUnref<SkImageFilter> conv(SkMatrixConvolutionImageFilter::Create(
1126 SkISize::Make(1<<30, 1<<30),
1127 kernel,
1128 gain,
1129 bias,
1130 kernelOffset,
1131 SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1132 false));
1133
halcanary96fcdcc2015-08-27 07:41:13 -07001134 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001135
halcanary96fcdcc2015-08-27 07:41:13 -07001136 // Check that a nullptr kernel gives a nullptr filter.
senorblanco3a495202014-09-29 07:57:20 -07001137 conv.reset(SkMatrixConvolutionImageFilter::Create(
1138 SkISize::Make(1, 1),
halcanary96fcdcc2015-08-27 07:41:13 -07001139 nullptr,
senorblanco3a495202014-09-29 07:57:20 -07001140 gain,
1141 bias,
1142 kernelOffset,
1143 SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1144 false));
1145
halcanary96fcdcc2015-08-27 07:41:13 -07001146 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001147
halcanary96fcdcc2015-08-27 07:41:13 -07001148 // Check that a kernel width < 1 gives a nullptr filter.
senorblanco3a495202014-09-29 07:57:20 -07001149 conv.reset(SkMatrixConvolutionImageFilter::Create(
1150 SkISize::Make(0, 1),
1151 kernel,
1152 gain,
1153 bias,
1154 kernelOffset,
1155 SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1156 false));
1157
halcanary96fcdcc2015-08-27 07:41:13 -07001158 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001159
halcanary96fcdcc2015-08-27 07:41:13 -07001160 // Check that kernel height < 1 gives a nullptr filter.
senorblanco3a495202014-09-29 07:57:20 -07001161 conv.reset(SkMatrixConvolutionImageFilter::Create(
1162 SkISize::Make(1, -1),
1163 kernel,
1164 gain,
1165 bias,
1166 kernelOffset,
1167 SkMatrixConvolutionImageFilter::kRepeat_TileMode,
1168 false));
1169
halcanary96fcdcc2015-08-27 07:41:13 -07001170 REPORTER_ASSERT(reporter, nullptr == conv.get());
senorblanco3a495202014-09-29 07:57:20 -07001171}
1172
robertphillips9a53fd72015-06-22 09:46:59 -07001173static void test_xfermode_cropped_input(SkCanvas* canvas, skiatest::Reporter* reporter) {
1174 canvas->clear(0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001175
1176 SkBitmap bitmap;
1177 bitmap.allocN32Pixels(1, 1);
1178 bitmap.eraseARGB(255, 255, 255, 255);
1179
1180 SkAutoTUnref<SkColorFilter> green(
1181 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode));
reedf0280032015-10-12 11:10:10 -07001182 SkAutoTUnref<SkImageFilter> greenFilter(SkColorFilterImageFilter::Create(green.get()));
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001183 SkImageFilter::CropRect cropRect(SkRect::MakeEmpty());
reedf0280032015-10-12 11:10:10 -07001184 SkAutoTUnref<SkImageFilter> croppedOut(
halcanary96fcdcc2015-08-27 07:41:13 -07001185 SkColorFilterImageFilter::Create(green.get(), nullptr, &cropRect));
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001186
1187 // Check that an xfermode image filter whose input has been cropped out still draws the other
1188 // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
1189 SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode);
1190 SkAutoTUnref<SkImageFilter> xfermodeNoFg(
1191 SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut));
1192 SkAutoTUnref<SkImageFilter> xfermodeNoBg(
1193 SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter));
1194 SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg(
1195 SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut));
1196
1197 SkPaint paint;
1198 paint.setImageFilter(xfermodeNoFg);
reedda420b92015-12-16 08:38:15 -08001199 canvas->drawBitmap(bitmap, 0, 0, &paint); // drawSprite
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001200
1201 uint32_t pixel;
kkinnunena9d9a392015-03-06 07:16:00 -08001202 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
robertphillips9a53fd72015-06-22 09:46:59 -07001203 canvas->readPixels(info, &pixel, 4, 0, 0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001204 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1205
1206 paint.setImageFilter(xfermodeNoBg);
reedda420b92015-12-16 08:38:15 -08001207 canvas->drawBitmap(bitmap, 0, 0, &paint); // drawSprite
robertphillips9a53fd72015-06-22 09:46:59 -07001208 canvas->readPixels(info, &pixel, 4, 0, 0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001209 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1210
1211 paint.setImageFilter(xfermodeNoFgNoBg);
reedda420b92015-12-16 08:38:15 -08001212 canvas->drawBitmap(bitmap, 0, 0, &paint); // drawSprite
robertphillips9a53fd72015-06-22 09:46:59 -07001213 canvas->readPixels(info, &pixel, 4, 0, 0);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001214 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1215}
1216
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001217DEF_TEST(ImageFilterNestedSaveLayer, reporter) {
1218 SkBitmap temp;
1219 temp.allocN32Pixels(50, 50);
robertphillips9a53fd72015-06-22 09:46:59 -07001220 SkCanvas canvas(temp);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001221 canvas.clear(0x0);
1222
1223 SkBitmap bitmap;
1224 bitmap.allocN32Pixels(10, 10);
1225 bitmap.eraseColor(SK_ColorGREEN);
1226
1227 SkMatrix matrix;
1228 matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
1229 matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
1230 SkAutoTUnref<SkImageFilter> matrixFilter(
senorblanco8c874ee2015-03-20 06:38:17 -07001231 SkImageFilter::CreateMatrixFilter(matrix, kLow_SkFilterQuality));
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001232
1233 // Test that saveLayer() with a filter nested inside another saveLayer() applies the
1234 // correct offset to the filter matrix.
1235 SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
halcanary96fcdcc2015-08-27 07:41:13 -07001236 canvas.saveLayer(&bounds1, nullptr);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001237 SkPaint filterPaint;
1238 filterPaint.setImageFilter(matrixFilter);
1239 SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
1240 canvas.saveLayer(&bounds2, &filterPaint);
1241 SkPaint greenPaint;
1242 greenPaint.setColor(SK_ColorGREEN);
1243 canvas.drawRect(bounds2, greenPaint);
1244 canvas.restore();
1245 canvas.restore();
1246 SkPaint strokePaint;
1247 strokePaint.setStyle(SkPaint::kStroke_Style);
1248 strokePaint.setColor(SK_ColorRED);
1249
kkinnunena9d9a392015-03-06 07:16:00 -08001250 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001251 uint32_t pixel;
1252 canvas.readPixels(info, &pixel, 4, 25, 25);
1253 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1254
1255 // Test that drawSprite() with a filter nested inside a saveLayer() applies the
1256 // correct offset to the filter matrix.
1257 canvas.clear(0x0);
1258 canvas.readPixels(info, &pixel, 4, 25, 25);
halcanary96fcdcc2015-08-27 07:41:13 -07001259 canvas.saveLayer(&bounds1, nullptr);
reedda420b92015-12-16 08:38:15 -08001260 canvas.drawBitmap(bitmap, 20, 20, &filterPaint); // drawSprite
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +00001261 canvas.restore();
1262
1263 canvas.readPixels(info, &pixel, 4, 25, 25);
1264 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
1265}
1266
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001267DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
1268 SkBitmap temp;
1269 temp.allocN32Pixels(100, 100);
robertphillips9a53fd72015-06-22 09:46:59 -07001270 SkCanvas canvas(temp);
1271 test_xfermode_cropped_input(&canvas, reporter);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001272}
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001273
robertphillips4418dba2016-03-07 12:45:14 -08001274static void test_composed_imagefilter_offset(SkImageFilter::Proxy* proxy,
1275 skiatest::Reporter* reporter,
1276 GrContext* context) {
1277 SkAutoTUnref<SkSpecialImage> srcImg(create_empty_special_image(context, proxy, 100));
ajuma5788faa2015-02-13 09:05:47 -08001278
1279 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(1, 0, 20, 20));
halcanary96fcdcc2015-08-27 07:41:13 -07001280 SkAutoTUnref<SkImageFilter> offsetFilter(SkOffsetImageFilter::Create(0, 0, nullptr, &cropRect));
senorblancodb64af32015-12-09 10:11:43 -08001281 SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1,
1282 nullptr, &cropRect));
1283 SkAutoTUnref<SkImageFilter> composedFilter(SkComposeImageFilter::Create(blurFilter,
1284 offsetFilter.get()));
ajuma5788faa2015-02-13 09:05:47 -08001285 SkIPoint offset;
reed4e23cda2016-01-11 10:56:59 -08001286 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr);
robertphillips4418dba2016-03-07 12:45:14 -08001287
1288 SkAutoTUnref<SkSpecialImage> resultImg(composedFilter->filterImage(srcImg, ctx, &offset));
1289 REPORTER_ASSERT(reporter, resultImg);
ajuma5788faa2015-02-13 09:05:47 -08001290 REPORTER_ASSERT(reporter, offset.fX == 1 && offset.fY == 0);
1291}
1292
robertphillips4418dba2016-03-07 12:45:14 -08001293DEF_TEST(ComposedImageFilterOffset, reporter) {
1294 run_raster_test(reporter, 100, test_composed_imagefilter_offset);
1295}
1296
1297#if SK_SUPPORT_GPU
1298DEF_GPUTEST_FOR_NATIVE_CONTEXT(ComposedImageFilterOffset_Gpu, reporter, context) {
1299 run_gpu_test(reporter, context, 100, test_composed_imagefilter_offset);
1300}
1301#endif
1302
1303static void test_partial_crop_rect(SkImageFilter::Proxy* proxy,
1304 skiatest::Reporter* reporter,
1305 GrContext* context) {
1306 SkAutoTUnref<SkSpecialImage> srcImg(create_empty_special_image(context, proxy, 100));
senorblanco24d2a7b2015-07-13 10:27:05 -07001307
1308 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(100, 0, 20, 30),
senorblancoed7cf272015-07-16 15:19:11 -07001309 SkImageFilter::CropRect::kHasWidth_CropEdge | SkImageFilter::CropRect::kHasHeight_CropEdge);
halcanary96fcdcc2015-08-27 07:41:13 -07001310 SkAutoTUnref<SkImageFilter> filter(make_grayscale(nullptr, &cropRect));
senorblanco24d2a7b2015-07-13 10:27:05 -07001311 SkIPoint offset;
reed4e23cda2016-01-11 10:56:59 -08001312 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeWH(100, 100), nullptr);
robertphillips4418dba2016-03-07 12:45:14 -08001313
1314 SkAutoTUnref<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset));
1315 REPORTER_ASSERT(reporter, resultImg);
1316
senorblanco24d2a7b2015-07-13 10:27:05 -07001317 REPORTER_ASSERT(reporter, offset.fX == 0);
1318 REPORTER_ASSERT(reporter, offset.fY == 0);
robertphillips4418dba2016-03-07 12:45:14 -08001319 REPORTER_ASSERT(reporter, resultImg->width() == 20);
1320 REPORTER_ASSERT(reporter, resultImg->height() == 30);
senorblanco24d2a7b2015-07-13 10:27:05 -07001321}
1322
robertphillips4418dba2016-03-07 12:45:14 -08001323DEF_TEST(PartialCropRect, reporter) {
1324 run_raster_test(reporter, 100, test_partial_crop_rect);
1325}
1326
1327#if SK_SUPPORT_GPU
1328DEF_GPUTEST_FOR_NATIVE_CONTEXT(PartialCropRect_Gpu, reporter, context) {
1329 run_gpu_test(reporter, context, 100, test_partial_crop_rect);
1330}
1331#endif
1332
senorblanco0abdf762015-08-20 11:10:41 -07001333DEF_TEST(ImageFilterCanComputeFastBounds, reporter) {
1334
1335 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
1336 SkAutoTUnref<SkImageFilter> lighting(SkLightingImageFilter::CreatePointLitDiffuse(
1337 location, SK_ColorGREEN, 0, 0));
1338 REPORTER_ASSERT(reporter, !lighting->canComputeFastBounds());
1339
1340 SkAutoTUnref<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
1341 REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1342 {
1343 SkColorFilter* grayCF;
1344 REPORTER_ASSERT(reporter, gray->asAColorFilter(&grayCF));
1345 REPORTER_ASSERT(reporter, !grayCF->affectsTransparentBlack());
1346 grayCF->unref();
1347 }
1348 REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1349
1350 SkAutoTUnref<SkImageFilter> grayBlur(SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, gray.get()));
1351 REPORTER_ASSERT(reporter, grayBlur->canComputeFastBounds());
1352
1353 SkScalar greenMatrix[20] = { 0, 0, 0, 0, 0,
1354 0, 0, 0, 0, 1,
1355 0, 0, 0, 0, 0,
1356 0, 0, 0, 0, 1 };
1357 SkAutoTUnref<SkColorFilter> greenCF(SkColorMatrixFilter::Create(greenMatrix));
1358 SkAutoTUnref<SkImageFilter> green(SkColorFilterImageFilter::Create(greenCF));
1359
1360 REPORTER_ASSERT(reporter, greenCF->affectsTransparentBlack());
1361 REPORTER_ASSERT(reporter, !green->canComputeFastBounds());
1362
1363 SkAutoTUnref<SkImageFilter> greenBlur(SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, green.get()));
1364 REPORTER_ASSERT(reporter, !greenBlur->canComputeFastBounds());
1365
1366 uint8_t allOne[256], identity[256];
1367 for (int i = 0; i < 256; ++i) {
1368 identity[i] = i;
1369 allOne[i] = 255;
1370 }
1371
1372 SkAutoTUnref<SkColorFilter> identityCF(
1373 SkTableColorFilter::CreateARGB(identity, identity, identity, allOne));
1374 SkAutoTUnref<SkImageFilter> identityFilter(SkColorFilterImageFilter::Create(identityCF.get()));
1375 REPORTER_ASSERT(reporter, !identityCF->affectsTransparentBlack());
1376 REPORTER_ASSERT(reporter, identityFilter->canComputeFastBounds());
1377
1378 SkAutoTUnref<SkColorFilter> forceOpaqueCF(
1379 SkTableColorFilter::CreateARGB(allOne, identity, identity, identity));
1380 SkAutoTUnref<SkImageFilter> forceOpaque(SkColorFilterImageFilter::Create(forceOpaqueCF.get()));
1381 REPORTER_ASSERT(reporter, forceOpaqueCF->affectsTransparentBlack());
1382 REPORTER_ASSERT(reporter, !forceOpaque->canComputeFastBounds());
1383}
1384
fmalitacd56f812015-09-14 13:31:18 -07001385// Verify that SkImageSource survives serialization
1386DEF_TEST(ImageFilterImageSourceSerialization, reporter) {
1387 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(10, 10));
1388 surface->getCanvas()->clear(SK_ColorGREEN);
1389 SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
1390 SkAutoTUnref<SkImageFilter> filter(SkImageSource::Create(image));
1391
1392 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(filter));
1393 SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
1394 data->data(), data->size(), SkImageFilter::GetFlattenableType()));
1395 SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
1396 REPORTER_ASSERT(reporter, unflattenedFilter);
1397
1398 SkBitmap bm;
1399 bm.allocN32Pixels(10, 10);
fmalita23cb88c2015-09-15 06:56:23 -07001400 bm.eraseColor(SK_ColorBLUE);
fmalitacd56f812015-09-14 13:31:18 -07001401 SkPaint paint;
1402 paint.setColor(SK_ColorRED);
1403 paint.setImageFilter(unflattenedFilter);
1404
1405 SkCanvas canvas(bm);
1406 canvas.drawRect(SkRect::MakeWH(10, 10), paint);
1407 REPORTER_ASSERT(reporter, *bm.getAddr32(0, 0) == SkPreMultiplyColor(SK_ColorGREEN));
1408}
1409
bsalomon45eefcf2016-01-05 08:39:28 -08001410static void test_large_blur_input(skiatest::Reporter* reporter, SkCanvas* canvas) {
1411 SkBitmap largeBmp;
1412 int largeW = 5000;
1413 int largeH = 5000;
1414#if SK_SUPPORT_GPU
1415 // If we're GPU-backed make the bitmap too large to be converted into a texture.
1416 if (GrContext* ctx = canvas->getGrContext()) {
1417 largeW = ctx->caps()->maxTextureSize() + 1;
1418 }
1419#endif
1420
1421 largeBmp.allocN32Pixels(largeW, largeH);
mtklein2afbe232016-02-07 12:23:10 -08001422 largeBmp.eraseColor(0);
bsalomon45eefcf2016-01-05 08:39:28 -08001423 if (!largeBmp.getPixels()) {
1424 ERRORF(reporter, "Failed to allocate large bmp.");
1425 return;
1426 }
1427
1428 SkAutoTUnref<SkImage> largeImage(SkImage::NewFromBitmap(largeBmp));
1429 if (!largeImage) {
1430 ERRORF(reporter, "Failed to create large image.");
1431 return;
1432 }
1433
1434 SkAutoTUnref<SkImageFilter> largeSource(SkImageSource::Create(largeImage));
1435 if (!largeSource) {
1436 ERRORF(reporter, "Failed to create large SkImageSource.");
1437 return;
1438 }
1439
1440 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(10.f, 10.f, largeSource));
1441 if (!blur) {
1442 ERRORF(reporter, "Failed to create SkBlurImageFilter.");
1443 return;
1444 }
1445
1446 SkPaint paint;
1447 paint.setImageFilter(blur);
1448
1449 // This should not crash (http://crbug.com/570479).
1450 canvas->drawRect(SkRect::MakeIWH(largeW, largeH), paint);
1451}
1452
1453DEF_TEST(BlurLargeImage, reporter) {
1454 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(SkImageInfo::MakeN32Premul(100, 100)));
1455 test_large_blur_input(reporter, surface->getCanvas());
1456}
1457
senorblanco@chromium.org58d14662014-02-03 22:36:39 +00001458#if SK_SUPPORT_GPU
reed4a8126e2014-09-22 07:29:03 -07001459
kkinnunen15302832015-12-01 04:35:26 -08001460DEF_GPUTEST_FOR_NATIVE_CONTEXT(HugeBlurImageFilter_Gpu, reporter, context) {
robertphillipsefbffed2015-06-22 12:06:08 -07001461 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1462
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001463 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
bsalomon5ec26ae2016-02-25 08:33:02 -08001464 SkBudgeted::kNo,
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001465 SkImageInfo::MakeN32Premul(100, 100),
bsalomonafe30052015-01-16 07:32:33 -08001466 0,
bsalomon74f681d2015-06-23 14:38:48 -07001467 &props,
1468 SkGpuDevice::kUninit_InitContents));
robertphillips9a53fd72015-06-22 09:46:59 -07001469 SkCanvas canvas(device);
1470
1471 test_huge_blur(&canvas, reporter);
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +00001472}
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001473
kkinnunen15302832015-12-01 04:35:26 -08001474DEF_GPUTEST_FOR_NATIVE_CONTEXT(XfermodeImageFilterCroppedInput_Gpu, reporter, context) {
robertphillipsefbffed2015-06-22 12:06:08 -07001475 const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
1476
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001477 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
bsalomon5ec26ae2016-02-25 08:33:02 -08001478 SkBudgeted::kNo,
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001479 SkImageInfo::MakeN32Premul(1, 1),
bsalomonafe30052015-01-16 07:32:33 -08001480 0,
bsalomon74f681d2015-06-23 14:38:48 -07001481 &props,
1482 SkGpuDevice::kUninit_InitContents));
robertphillips9a53fd72015-06-22 09:46:59 -07001483 SkCanvas canvas(device);
1484
1485 test_xfermode_cropped_input(&canvas, reporter);
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +00001486}
senorblanco32673b92014-09-09 09:15:04 -07001487
bsalomon45eefcf2016-01-05 08:39:28 -08001488DEF_GPUTEST_FOR_ALL_CONTEXTS(BlurLargeImage_Gpu, reporter, context) {
1489 SkAutoTUnref<SkSurface> surface(
bsalomon5ec26ae2016-02-25 08:33:02 -08001490 SkSurface::NewRenderTarget(context, SkBudgeted::kYes,
bsalomon45eefcf2016-01-05 08:39:28 -08001491 SkImageInfo::MakeN32Premul(100, 100)));
1492 test_large_blur_input(reporter, surface->getCanvas());
1493}
senorblanco@chromium.org58d14662014-02-03 22:36:39 +00001494#endif