blob: ee3de50c48108a36fbe47fe35761f98bcc890537 [file] [log] [blame]
senorblanco@chromium.org194d7752013-07-24 22:19:24 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +00008#include "SkBitmap.h"
9#include "SkBitmapDevice.h"
10#include "SkBitmapSource.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"
15#include "SkDeviceImageFilterProxy.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"
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +000020#include "SkLightingImageFilter.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000021#include "SkMatrixConvolutionImageFilter.h"
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +000022#include "SkMatrixImageFilter.h"
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000023#include "SkMergeImageFilter.h"
24#include "SkMorphologyImageFilter.h"
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000025#include "SkOffsetImageFilter.h"
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000026#include "SkPicture.h"
senorblanco@chromium.org910702b2014-05-30 20:36:15 +000027#include "SkPictureImageFilter.h"
robertphillips@google.com770963f2014-04-18 18:04:41 +000028#include "SkPictureRecorder.h"
halcanary97d2c0a2014-08-19 06:27:53 -070029#include "SkReadBuffer.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000030#include "SkRect.h"
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000031#include "SkTileImageFilter.h"
32#include "SkXfermodeImageFilter.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000033#include "Test.h"
senorblanco@chromium.org194d7752013-07-24 22:19:24 +000034
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +000035#if SK_SUPPORT_GPU
36#include "GrContextFactory.h"
37#include "SkGpuDevice.h"
38#endif
39
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +000040static const int kBitmapSize = 4;
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +000041
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000042namespace {
43
44class MatrixTestImageFilter : public SkImageFilter {
45public:
46 MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix)
senorblanco9ea3d572014-07-08 09:16:22 -070047 : SkImageFilter(0, NULL), fReporter(reporter), fExpectedMatrix(expectedMatrix) {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000048 }
49
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000050 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context& ctx,
senorblanco@chromium.org09373352014-02-05 23:04:28 +000051 SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE {
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000052 REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000053 return true;
54 }
55
56 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(MatrixTestImageFilter)
57
58protected:
senorblanco9ea3d572014-07-08 09:16:22 -070059 explicit MatrixTestImageFilter(SkReadBuffer& buffer) : SkImageFilter(0, NULL) {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000060 fReporter = static_cast<skiatest::Reporter*>(buffer.readFunctionPtr());
61 buffer.readMatrix(&fExpectedMatrix);
62 }
63
64 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
65 buffer.writeFunctionPtr(fReporter);
66 buffer.writeMatrix(fExpectedMatrix);
67 }
68
69private:
70 skiatest::Reporter* fReporter;
71 SkMatrix fExpectedMatrix;
72};
73
74}
75
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +000076static void make_small_bitmap(SkBitmap& bitmap) {
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +000077 bitmap.allocN32Pixels(kBitmapSize, kBitmapSize);
78 SkCanvas canvas(bitmap);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +000079 canvas.clear(0x00000000);
80 SkPaint darkPaint;
81 darkPaint.setColor(0xFF804020);
82 SkPaint lightPaint;
83 lightPaint.setColor(0xFF244484);
84 const int i = kBitmapSize / 4;
85 for (int y = 0; y < kBitmapSize; y += i) {
86 for (int x = 0; x < kBitmapSize; x += i) {
87 canvas.save();
88 canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
89 canvas.drawRect(SkRect::MakeXYWH(0, 0,
90 SkIntToScalar(i),
91 SkIntToScalar(i)), darkPaint);
92 canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
93 0,
94 SkIntToScalar(i),
95 SkIntToScalar(i)), lightPaint);
96 canvas.drawRect(SkRect::MakeXYWH(0,
97 SkIntToScalar(i),
98 SkIntToScalar(i),
99 SkIntToScalar(i)), lightPaint);
100 canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i),
101 SkIntToScalar(i),
102 SkIntToScalar(i),
103 SkIntToScalar(i)), darkPaint);
104 canvas.restore();
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +0000105 }
106 }
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000107}
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000108
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000109static SkImageFilter* make_scale(float amount, SkImageFilter* input = NULL) {
110 SkScalar s = amount;
111 SkScalar matrix[20] = { s, 0, 0, 0, 0,
112 0, s, 0, 0, 0,
113 0, 0, s, 0, 0,
114 0, 0, 0, s, 0 };
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000115 SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000116 return SkColorFilterImageFilter::Create(filter, input);
117}
118
119static SkImageFilter* make_grayscale(SkImageFilter* input = NULL, const SkImageFilter::CropRect* cropRect = NULL) {
120 SkScalar matrix[20];
121 memset(matrix, 0, 20 * sizeof(SkScalar));
122 matrix[0] = matrix[5] = matrix[10] = 0.2126f;
123 matrix[1] = matrix[6] = matrix[11] = 0.7152f;
124 matrix[2] = matrix[7] = matrix[12] = 0.0722f;
125 matrix[18] = 1.0f;
commit-bot@chromium.org727a3522014-02-21 18:46:30 +0000126 SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000127 return SkColorFilterImageFilter::Create(filter, input, cropRect);
128}
129
130DEF_TEST(ImageFilter, reporter) {
131 {
132 // Check that two non-clipping color matrices concatenate into a single filter.
133 SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f));
134 SkAutoTUnref<SkImageFilter> quarterBrightness(make_scale(0.5f, halfBrightness));
135 REPORTER_ASSERT(reporter, NULL == quarterBrightness->getInput(0));
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000136 }
137
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000138 {
139 // Check that a clipping color matrix followed by a grayscale does not concatenate into a single filter.
140 SkAutoTUnref<SkImageFilter> doubleBrightness(make_scale(2.0f));
141 SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f, doubleBrightness));
142 REPORTER_ASSERT(reporter, NULL != halfBrightness->getInput(0));
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000143 }
144
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000145 {
146 // Check that a color filter image filter without a crop rect can be
147 // expressed as a color filter.
148 SkAutoTUnref<SkImageFilter> gray(make_grayscale());
149 REPORTER_ASSERT(reporter, true == gray->asColorFilter(NULL));
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000150 }
151
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000152 {
153 // Check that a color filter image filter with a crop rect cannot
154 // be expressed as a color filter.
155 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100));
156 SkAutoTUnref<SkImageFilter> grayWithCrop(make_grayscale(NULL, &cropRect));
157 REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(NULL));
158 }
159
160 {
senorblanco3df05012014-07-03 11:13:09 -0700161 // Check that two non-commutative matrices are concatenated in
162 // the correct order.
163 SkScalar blueToRedMatrix[20] = { 0 };
164 blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1;
165 SkScalar redToGreenMatrix[20] = { 0 };
166 redToGreenMatrix[5] = redToGreenMatrix[18] = SK_Scalar1;
167 SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix));
168 SkAutoTUnref<SkImageFilter> filter1(SkColorFilterImageFilter::Create(blueToRed.get()));
169 SkAutoTUnref<SkColorFilter> redToGreen(SkColorMatrixFilter::Create(redToGreenMatrix));
170 SkAutoTUnref<SkImageFilter> filter2(SkColorFilterImageFilter::Create(redToGreen.get(), filter1.get()));
171
172 SkBitmap result;
173 result.allocN32Pixels(kBitmapSize, kBitmapSize);
174
175 SkPaint paint;
176 paint.setColor(SK_ColorBLUE);
177 paint.setImageFilter(filter2.get());
178 SkCanvas canvas(result);
179 canvas.clear(0x0);
180 SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize));
181 canvas.drawRect(rect, paint);
182 uint32_t pixel = *result.getAddr32(0, 0);
183 // The result here should be green, since we have effectively shifted blue to green.
184 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
185 }
186
187 {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000188 // Tests pass by not asserting
189 SkBitmap bitmap, result;
190 make_small_bitmap(bitmap);
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000191 result.allocN32Pixels(kBitmapSize, kBitmapSize);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000192
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000193 {
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000194 // This tests for :
195 // 1 ) location at (0,0,1)
196 SkPoint3 location(0, 0, SK_Scalar1);
197 // 2 ) location and target at same value
198 SkPoint3 target(location.fX, location.fY, location.fZ);
199 // 3 ) large negative specular exponent value
200 SkScalar specularExponent = -1000;
201
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000202 SkAutoTUnref<SkImageFilter> bmSrc(SkBitmapSource::Create(bitmap));
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000203 SkPaint paint;
204 paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(
205 location, target, specularExponent, 180,
206 0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
207 bmSrc))->unref();
208 SkCanvas canvas(result);
209 SkRect r = SkRect::MakeWH(SkIntToScalar(kBitmapSize),
210 SkIntToScalar(kBitmapSize));
211 canvas.drawRect(r, paint);
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000212 }
senorblanco@chromium.org194d7752013-07-24 22:19:24 +0000213 }
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000214}
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000215
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000216static void test_crop_rects(SkBaseDevice* device, skiatest::Reporter* reporter) {
217 // Check that all filters offset to their absolute crop rect,
218 // unaffected by the input crop rect.
219 // Tests pass by not asserting.
220 SkBitmap bitmap;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000221 bitmap.allocN32Pixels(100, 100);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000222 bitmap.eraseARGB(0, 0, 0, 0);
223 SkDeviceImageFilterProxy proxy(device);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000224
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000225 SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
226 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
227 SkAutoTUnref<SkImageFilter> input(make_grayscale(NULL, &inputCropRect));
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000228
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000229 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
230 SkPoint3 location(0, 0, SK_Scalar1);
231 SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
232 SkScalar kernel[9] = {
233 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
234 SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
235 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
236 };
237 SkISize kernelSize = SkISize::Make(3, 3);
238 SkScalar gain = SK_Scalar1, bias = 0;
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000239
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000240 SkImageFilter* filters[] = {
241 SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000242 SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType,
243 SkDisplacementMapEffect::kB_ChannelSelectorType,
244 40.0f, input.get(), input.get(), &cropRect),
245 SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
246 SkDropShadowImageFilter::Create(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input.get(), &cropRect),
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000247 SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
248 SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +0000249 SkMatrixConvolutionImageFilter::Create(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
250 SkMergeImageFilter::Create(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
251 SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
252 SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
253 SkDilateImageFilter::Create(3, 2, input.get(), &cropRect),
254 SkErodeImageFilter::Create(2, 3, input.get(), &cropRect),
255 SkTileImageFilter::Create(inputCropRect.rect(), cropRect.rect(), input.get()),
256 SkXfermodeImageFilter::Create(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000257 };
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000258
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000259 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
260 SkImageFilter* filter = filters[i];
261 SkBitmap result;
262 SkIPoint offset;
263 SkString str;
senorblanco@chromium.orgf4e1a762014-02-04 00:28:46 +0000264 str.printf("filter %d", static_cast<int>(i));
senorblanco55b6d8b2014-07-30 11:26:46 -0700265 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), NULL);
commit-bot@chromium.orgf7efa502014-04-11 18:57:00 +0000266 REPORTER_ASSERT_MESSAGE(reporter, filter->filterImage(&proxy, bitmap, ctx,
267 &result, &offset), str.c_str());
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000268 REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str());
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000269 }
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000270
271 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
272 SkSafeUnref(filters[i]);
273 }
274}
275
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000276static SkBitmap make_gradient_circle(int width, int height) {
277 SkBitmap bitmap;
278 SkScalar x = SkIntToScalar(width / 2);
279 SkScalar y = SkIntToScalar(height / 2);
280 SkScalar radius = SkMinScalar(x, y) * 0.8f;
281 bitmap.allocN32Pixels(width, height);
282 SkCanvas canvas(bitmap);
283 canvas.clear(0x00000000);
284 SkColor colors[2];
285 colors[0] = SK_ColorWHITE;
286 colors[1] = SK_ColorBLACK;
287 SkAutoTUnref<SkShader> shader(
288 SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, NULL, 2,
289 SkShader::kClamp_TileMode)
290 );
291 SkPaint paint;
292 paint.setShader(shader);
293 canvas.drawCircle(x, y, radius, paint);
294 return bitmap;
295}
296
297DEF_TEST(ImageFilterDrawTiled, reporter) {
298 // Check that all filters when drawn tiled (with subsequent clip rects) exactly
299 // match the same filters drawn with a single full-canvas bitmap draw.
300 // Tests pass by not asserting.
301
302 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
303 SkPoint3 location(0, 0, SK_Scalar1);
304 SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
305 SkScalar kernel[9] = {
306 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
307 SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
308 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
309 };
310 SkISize kernelSize = SkISize::Make(3, 3);
311 SkScalar gain = SK_Scalar1, bias = 0;
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000312 SkScalar five = SkIntToScalar(5);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000313
314 SkAutoTUnref<SkImageFilter> gradient_source(SkBitmapSource::Create(make_gradient_circle(64, 64)));
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000315 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(five, five));
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000316 SkMatrix matrix;
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000317
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000318 matrix.setTranslate(SK_Scalar1, SK_Scalar1);
319 matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000320
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000321 SkRTreeFactory factory;
322 SkPictureRecorder recorder;
323 SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0);
324
325 SkPaint greenPaint;
326 greenPaint.setColor(SK_ColorGREEN);
327 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
328 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
329 SkAutoTUnref<SkImageFilter> pictureFilter(SkPictureImageFilter::Create(picture.get()));
330
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000331 struct {
332 const char* fName;
333 SkImageFilter* fFilter;
334 } filters[] = {
335 { "color filter", SkColorFilterImageFilter::Create(cf.get()) },
336 { "displacement map", SkDisplacementMapEffect::Create(
337 SkDisplacementMapEffect::kR_ChannelSelectorType,
338 SkDisplacementMapEffect::kB_ChannelSelectorType,
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000339 20.0f, gradient_source.get()) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000340 { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
341 { "drop shadow", SkDropShadowImageFilter::Create(
342 SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN) },
343 { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse(
344 location, SK_ColorGREEN, 0, 0) },
345 { "specular lighting",
346 SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) },
347 { "matrix convolution",
348 SkMatrixConvolutionImageFilter::Create(
349 kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
350 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) },
351 { "merge", SkMergeImageFilter::Create(NULL, NULL, SkXfermode::kSrcOver_Mode) },
352 { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) },
353 { "dilate", SkDilateImageFilter::Create(3, 2) },
354 { "erode", SkErodeImageFilter::Create(2, 3) },
355 { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50),
356 SkRect::MakeXYWH(0, 0, 100, 100), NULL) },
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000357 { "matrix", SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel) },
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000358 { "blur and offset", SkOffsetImageFilter::Create(five, five, blur.get()) },
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000359 { "picture and blur", SkBlurImageFilter::Create(five, five, pictureFilter.get()) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000360 };
361
362 SkBitmap untiledResult, tiledResult;
363 int width = 64, height = 64;
364 untiledResult.allocN32Pixels(width, height);
365 tiledResult.allocN32Pixels(width, height);
366 SkCanvas tiledCanvas(tiledResult);
367 SkCanvas untiledCanvas(untiledResult);
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000368 int tileSize = 8;
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000369
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000370 for (int scale = 1; scale <= 2; ++scale) {
371 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
372 tiledCanvas.clear(0);
373 untiledCanvas.clear(0);
374 SkPaint paint;
375 paint.setImageFilter(filters[i].fFilter);
376 paint.setTextSize(SkIntToScalar(height));
377 paint.setColor(SK_ColorWHITE);
378 SkString str;
379 const char* text = "ABC";
380 SkScalar ypos = SkIntToScalar(height);
381 untiledCanvas.save();
382 untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
383 untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
384 untiledCanvas.restore();
385 for (int y = 0; y < height; y += tileSize) {
386 for (int x = 0; x < width; x += tileSize) {
387 tiledCanvas.save();
388 tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
389 tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
390 tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
391 tiledCanvas.restore();
392 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000393 }
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000394 untiledCanvas.flush();
395 tiledCanvas.flush();
396 for (int y = 0; y < height; y++) {
397 int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
398 REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
399 if (diffs) {
400 break;
401 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000402 }
403 }
404 }
405
406 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
407 SkSafeUnref(filters[i].fFilter);
408 }
409}
410
senorblanco837f5322014-07-14 10:19:54 -0700411static void drawBlurredRect(SkCanvas* canvas) {
412 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0));
413 SkPaint filterPaint;
414 filterPaint.setColor(SK_ColorWHITE);
415 filterPaint.setImageFilter(filter);
416 canvas->saveLayer(NULL, &filterPaint);
417 SkPaint whitePaint;
418 whitePaint.setColor(SK_ColorWHITE);
419 canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
420 canvas->restore();
421}
422
423static void drawPictureClipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
424 canvas->save();
425 canvas->clipRect(clipRect);
426 canvas->drawPicture(picture);
427 canvas->restore();
428}
429
430DEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) {
431 // Check that the blur filter when recorded with RTree acceleration,
432 // and drawn tiled (with subsequent clip rects) exactly
433 // matches the same filter drawn with without RTree acceleration.
434 // This tests that the "bleed" from the blur into the otherwise-blank
435 // tiles is correctly rendered.
436 // Tests pass by not asserting.
437
438 int width = 16, height = 8;
439 SkBitmap result1, result2;
440 result1.allocN32Pixels(width, height);
441 result2.allocN32Pixels(width, height);
442 SkCanvas canvas1(result1);
443 SkCanvas canvas2(result2);
444 int tileSize = 8;
445
446 canvas1.clear(0);
447 canvas2.clear(0);
448
449 SkRTreeFactory factory;
450
451 SkPictureRecorder recorder1, recorder2;
452 // The only difference between these two pictures is that one has RTree aceleration.
453 SkCanvas* recordingCanvas1 = recorder1.beginRecording(width, height, NULL, 0);
454 SkCanvas* recordingCanvas2 = recorder2.beginRecording(width, height, &factory, 0);
455 drawBlurredRect(recordingCanvas1);
456 drawBlurredRect(recordingCanvas2);
457 SkAutoTUnref<SkPicture> picture1(recorder1.endRecording());
458 SkAutoTUnref<SkPicture> picture2(recorder2.endRecording());
459 for (int y = 0; y < height; y += tileSize) {
460 for (int x = 0; x < width; x += tileSize) {
461 SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
462 drawPictureClipped(&canvas1, tileRect, picture1);
463 drawPictureClipped(&canvas2, tileRect, picture2);
464 }
465 }
466 for (int y = 0; y < height; y++) {
467 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
468 REPORTER_ASSERT(reporter, !diffs);
469 if (diffs) {
470 break;
471 }
472 }
473}
474
senorblanco@chromium.org91957432014-05-01 14:03:41 +0000475DEF_TEST(ImageFilterMatrixConvolution, reporter) {
476 // Check that a 1x3 filter does not cause a spurious assert.
477 SkScalar kernel[3] = {
478 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
479 };
480 SkISize kernelSize = SkISize::Make(1, 3);
481 SkScalar gain = SK_Scalar1, bias = 0;
482 SkIPoint kernelOffset = SkIPoint::Make(0, 0);
483
484 SkAutoTUnref<SkImageFilter> filter(
485 SkMatrixConvolutionImageFilter::Create(
486 kernelSize, kernel, gain, bias, kernelOffset,
487 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false));
488
489 SkBitmap result;
490 int width = 16, height = 16;
491 result.allocN32Pixels(width, height);
492 SkCanvas canvas(result);
493 canvas.clear(0);
494
495 SkPaint paint;
496 paint.setImageFilter(filter);
497 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
498 canvas.drawRect(rect, paint);
499}
500
senorblanco@chromium.org8c7372b2014-05-02 19:13:11 +0000501DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
502 // Check that a filter with borders outside the target bounds
503 // does not crash.
504 SkScalar kernel[3] = {
505 0, 0, 0,
506 };
507 SkISize kernelSize = SkISize::Make(3, 1);
508 SkScalar gain = SK_Scalar1, bias = 0;
509 SkIPoint kernelOffset = SkIPoint::Make(2, 0);
510
511 SkAutoTUnref<SkImageFilter> filter(
512 SkMatrixConvolutionImageFilter::Create(
513 kernelSize, kernel, gain, bias, kernelOffset,
514 SkMatrixConvolutionImageFilter::kClamp_TileMode, true));
515
516 SkBitmap result;
517
518 int width = 10, height = 10;
519 result.allocN32Pixels(width, height);
520 SkCanvas canvas(result);
521 canvas.clear(0);
522
523 SkPaint filterPaint;
524 filterPaint.setImageFilter(filter);
525 SkRect bounds = SkRect::MakeWH(1, 10);
526 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
527 SkPaint rectPaint;
528 canvas.saveLayer(&bounds, &filterPaint);
529 canvas.drawRect(rect, rectPaint);
530 canvas.restore();
531}
532
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000533DEF_TEST(ImageFilterCropRect, reporter) {
534 SkBitmap temp;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000535 temp.allocN32Pixels(100, 100);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000536 SkBitmapDevice device(temp);
537 test_crop_rects(&device, reporter);
538}
539
tfarina9ea53f92014-06-24 06:50:39 -0700540DEF_TEST(ImageFilterMatrix, reporter) {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000541 SkBitmap temp;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000542 temp.allocN32Pixels(100, 100);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000543 SkBitmapDevice device(temp);
544 SkCanvas canvas(&device);
545 canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
546
547 SkMatrix expectedMatrix = canvas.getTotalMatrix();
548
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000549 SkRTreeFactory factory;
550 SkPictureRecorder recorder;
551 SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000552
553 SkPaint paint;
554 SkAutoTUnref<MatrixTestImageFilter> imageFilter(
555 new MatrixTestImageFilter(reporter, expectedMatrix));
556 paint.setImageFilter(imageFilter.get());
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000557 recordingCanvas->saveLayer(NULL, &paint);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000558 SkPaint solidPaint;
559 solidPaint.setColor(0xFFFFFFFF);
560 recordingCanvas->save();
561 recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
562 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
563 recordingCanvas->restore(); // scale
564 recordingCanvas->restore(); // saveLayer
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000565 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000566
robertphillips9b14f262014-06-04 05:40:44 -0700567 canvas.drawPicture(picture);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000568}
569
senorblanco3d822c22014-07-30 14:49:31 -0700570DEF_TEST(ImageFilterCrossProcessPictureImageFilter, reporter) {
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000571 SkRTreeFactory factory;
572 SkPictureRecorder recorder;
573 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
574
575 // Create an SkPicture which simply draws a green 1x1 rectangle.
576 SkPaint greenPaint;
577 greenPaint.setColor(SK_ColorGREEN);
578 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
579 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
580
581 // Wrap that SkPicture in an SkPictureImageFilter.
582 SkAutoTUnref<SkImageFilter> imageFilter(
583 SkPictureImageFilter::Create(picture.get()));
584
585 // Check that SkPictureImageFilter successfully serializes its contained
586 // SkPicture when not in cross-process mode.
587 SkPaint paint;
588 paint.setImageFilter(imageFilter.get());
589 SkPictureRecorder outerRecorder;
590 SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
591 SkPaint redPaintWithFilter;
592 redPaintWithFilter.setColor(SK_ColorRED);
593 redPaintWithFilter.setImageFilter(imageFilter.get());
594 outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
595 SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording());
596
597 SkBitmap bitmap;
598 bitmap.allocN32Pixels(1, 1);
599 SkBitmapDevice device(bitmap);
600 SkCanvas canvas(&device);
601
602 // The result here should be green, since the filter replaces the primitive's red interior.
603 canvas.clear(0x0);
robertphillips9b14f262014-06-04 05:40:44 -0700604 canvas.drawPicture(outerPicture);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000605 uint32_t pixel = *bitmap.getAddr32(0, 0);
606 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
607
608 // Check that, for now, SkPictureImageFilter does not serialize or
609 // deserialize its contained picture when the filter is serialized
610 // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
611 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
612 SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
613 data->data(), data->size(), SkImageFilter::GetFlattenableType()));
614 SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
615
616 redPaintWithFilter.setImageFilter(unflattenedFilter);
617 SkPictureRecorder crossProcessRecorder;
618 SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
619 crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
620 SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording());
621
622 canvas.clear(0x0);
robertphillips9b14f262014-06-04 05:40:44 -0700623 canvas.drawPicture(crossProcessPicture);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000624 pixel = *bitmap.getAddr32(0, 0);
625 // The result here should not be green, since the filter draws nothing.
626 REPORTER_ASSERT(reporter, pixel != SK_ColorGREEN);
627}
628
senorblanco3d822c22014-07-30 14:49:31 -0700629DEF_TEST(ImageFilterClippedPictureImageFilter, reporter) {
630 SkRTreeFactory factory;
631 SkPictureRecorder recorder;
632 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
633
634 // Create an SkPicture which simply draws a green 1x1 rectangle.
635 SkPaint greenPaint;
636 greenPaint.setColor(SK_ColorGREEN);
637 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
638 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
639
640 SkAutoTUnref<SkImageFilter> imageFilter(
641 SkPictureImageFilter::Create(picture.get()));
642
643 SkBitmap result;
644 SkIPoint offset;
645 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(1, 1, 1, 1), NULL);
646 SkBitmap bitmap;
647 bitmap.allocN32Pixels(2, 2);
648 SkBitmapDevice device(bitmap);
649 SkDeviceImageFilterProxy proxy(&device);
650 REPORTER_ASSERT(reporter, !imageFilter->filterImage(&proxy, bitmap, ctx, &result, &offset));
651}
652
tfarina9ea53f92014-06-24 06:50:39 -0700653DEF_TEST(ImageFilterEmptySaveLayer, reporter) {
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000654 // Even when there's an empty saveLayer()/restore(), ensure that an image
655 // filter or color filter which affects transparent black still draws.
656
657 SkBitmap bitmap;
658 bitmap.allocN32Pixels(10, 10);
659 SkBitmapDevice device(bitmap);
660 SkCanvas canvas(&device);
661
662 SkRTreeFactory factory;
663 SkPictureRecorder recorder;
664
665 SkAutoTUnref<SkColorFilter> green(
666 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode));
667 SkAutoTUnref<SkColorFilterImageFilter> imageFilter(
668 SkColorFilterImageFilter::Create(green.get()));
669 SkPaint imageFilterPaint;
670 imageFilterPaint.setImageFilter(imageFilter.get());
671 SkPaint colorFilterPaint;
672 colorFilterPaint.setColorFilter(green.get());
673
674 SkRect bounds = SkRect::MakeWH(10, 10);
675
676 SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
677 recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
678 recordingCanvas->restore();
679 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
680
681 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -0700682 canvas.drawPicture(picture);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000683 uint32_t pixel = *bitmap.getAddr32(0, 0);
684 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
685
686 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
687 recordingCanvas->saveLayer(NULL, &imageFilterPaint);
688 recordingCanvas->restore();
689 SkAutoTUnref<SkPicture> picture2(recorder.endRecording());
690
691 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -0700692 canvas.drawPicture(picture2);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000693 pixel = *bitmap.getAddr32(0, 0);
694 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
695
696 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
697 recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
698 recordingCanvas->restore();
699 SkAutoTUnref<SkPicture> picture3(recorder.endRecording());
700
701 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -0700702 canvas.drawPicture(picture3);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000703 pixel = *bitmap.getAddr32(0, 0);
704 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
705}
706
senorblanco@chromium.org28ae55d2014-03-24 21:32:28 +0000707static void test_huge_blur(SkBaseDevice* device, skiatest::Reporter* reporter) {
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000708 SkCanvas canvas(device);
709
710 SkBitmap bitmap;
711 bitmap.allocN32Pixels(100, 100);
712 bitmap.eraseARGB(0, 0, 0, 0);
713
714 // Check that a blur with an insane radius does not crash or assert.
715 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(SkIntToScalar(1<<30), SkIntToScalar(1<<30)));
716
717 SkPaint paint;
718 paint.setImageFilter(blur);
719 canvas.drawSprite(bitmap, 0, 0, &paint);
720}
721
722DEF_TEST(HugeBlurImageFilter, reporter) {
723 SkBitmap temp;
724 temp.allocN32Pixels(100, 100);
725 SkBitmapDevice device(temp);
726 test_huge_blur(&device, reporter);
727}
728
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +0000729static void test_xfermode_cropped_input(SkBaseDevice* device, skiatest::Reporter* reporter) {
730 SkCanvas canvas(device);
731 canvas.clear(0);
732
733 SkBitmap bitmap;
734 bitmap.allocN32Pixels(1, 1);
735 bitmap.eraseARGB(255, 255, 255, 255);
736
737 SkAutoTUnref<SkColorFilter> green(
738 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode));
739 SkAutoTUnref<SkColorFilterImageFilter> greenFilter(
740 SkColorFilterImageFilter::Create(green.get()));
741 SkImageFilter::CropRect cropRect(SkRect::MakeEmpty());
742 SkAutoTUnref<SkColorFilterImageFilter> croppedOut(
743 SkColorFilterImageFilter::Create(green.get(), NULL, &cropRect));
744
745 // Check that an xfermode image filter whose input has been cropped out still draws the other
746 // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
747 SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode);
748 SkAutoTUnref<SkImageFilter> xfermodeNoFg(
749 SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut));
750 SkAutoTUnref<SkImageFilter> xfermodeNoBg(
751 SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter));
752 SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg(
753 SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut));
754
755 SkPaint paint;
756 paint.setImageFilter(xfermodeNoFg);
757 canvas.drawSprite(bitmap, 0, 0, &paint);
758
759 uint32_t pixel;
760 SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
761 canvas.readPixels(info, &pixel, 4, 0, 0);
762 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
763
764 paint.setImageFilter(xfermodeNoBg);
765 canvas.drawSprite(bitmap, 0, 0, &paint);
766 canvas.readPixels(info, &pixel, 4, 0, 0);
767 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
768
769 paint.setImageFilter(xfermodeNoFgNoBg);
770 canvas.drawSprite(bitmap, 0, 0, &paint);
771 canvas.readPixels(info, &pixel, 4, 0, 0);
772 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
773}
774
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +0000775DEF_TEST(ImageFilterNestedSaveLayer, reporter) {
776 SkBitmap temp;
777 temp.allocN32Pixels(50, 50);
778 SkBitmapDevice device(temp);
779 SkCanvas canvas(&device);
780 canvas.clear(0x0);
781
782 SkBitmap bitmap;
783 bitmap.allocN32Pixels(10, 10);
784 bitmap.eraseColor(SK_ColorGREEN);
785
786 SkMatrix matrix;
787 matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
788 matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
789 SkAutoTUnref<SkImageFilter> matrixFilter(
790 SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel));
791
792 // Test that saveLayer() with a filter nested inside another saveLayer() applies the
793 // correct offset to the filter matrix.
794 SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
795 canvas.saveLayer(&bounds1, NULL);
796 SkPaint filterPaint;
797 filterPaint.setImageFilter(matrixFilter);
798 SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
799 canvas.saveLayer(&bounds2, &filterPaint);
800 SkPaint greenPaint;
801 greenPaint.setColor(SK_ColorGREEN);
802 canvas.drawRect(bounds2, greenPaint);
803 canvas.restore();
804 canvas.restore();
805 SkPaint strokePaint;
806 strokePaint.setStyle(SkPaint::kStroke_Style);
807 strokePaint.setColor(SK_ColorRED);
808
809 SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
810 uint32_t pixel;
811 canvas.readPixels(info, &pixel, 4, 25, 25);
812 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
813
814 // Test that drawSprite() with a filter nested inside a saveLayer() applies the
815 // correct offset to the filter matrix.
816 canvas.clear(0x0);
817 canvas.readPixels(info, &pixel, 4, 25, 25);
818 canvas.saveLayer(&bounds1, NULL);
819 canvas.drawSprite(bitmap, 20, 20, &filterPaint);
820 canvas.restore();
821
822 canvas.readPixels(info, &pixel, 4, 25, 25);
823 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
824}
825
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +0000826DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
827 SkBitmap temp;
828 temp.allocN32Pixels(100, 100);
829 SkBitmapDevice device(temp);
830 test_xfermode_cropped_input(&device, reporter);
831}
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000832
senorblanco@chromium.org58d14662014-02-03 22:36:39 +0000833#if SK_SUPPORT_GPU
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000834DEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) {
835 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000836 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
837 SkImageInfo::MakeN32Premul(100, 100),
838 0));
839 test_crop_rects(device, reporter);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000840}
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000841
842DEF_GPUTEST(HugeBlurImageFilterGPU, reporter, factory) {
843 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
844 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
845 SkImageInfo::MakeN32Premul(100, 100),
846 0));
847 test_huge_blur(device, reporter);
848}
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +0000849
850DEF_GPUTEST(XfermodeImageFilterCroppedInputGPU, reporter, factory) {
851 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
852 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
853 SkImageInfo::MakeN32Premul(1, 1),
854 0));
855 test_xfermode_cropped_input(device, reporter);
856}
senorblanco@chromium.org58d14662014-02-03 22:36:39 +0000857#endif