blob: 7da4a911ef37c821d6da9c61808fe1ee61b51b3e [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.org5251e2b2014-02-05 22:36:31 +000018#include "SkFlattenableBuffers.h"
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +000019#include "SkFlattenableSerialization.h"
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +000020#include "SkGradientShader.h"
commit-bot@chromium.org4b681bc2013-09-13 12:40:02 +000021#include "SkLightingImageFilter.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000022#include "SkMatrixConvolutionImageFilter.h"
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +000023#include "SkMatrixImageFilter.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"
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +000027#include "SkPicture.h"
senorblanco@chromium.org910702b2014-05-30 20:36:15 +000028#include "SkPictureImageFilter.h"
robertphillips@google.com770963f2014-04-18 18:04:41 +000029#include "SkPictureRecorder.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));
Mike Klein874a62a2014-07-09 09:04:07 -0400265 SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(2));
commit-bot@chromium.orgf7efa502014-04-11 18:57:00 +0000266 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), cache.get());
267 REPORTER_ASSERT_MESSAGE(reporter, filter->filterImage(&proxy, bitmap, ctx,
268 &result, &offset), str.c_str());
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000269 REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str());
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000270 }
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000271
272 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
273 SkSafeUnref(filters[i]);
274 }
275}
276
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000277static SkBitmap make_gradient_circle(int width, int height) {
278 SkBitmap bitmap;
279 SkScalar x = SkIntToScalar(width / 2);
280 SkScalar y = SkIntToScalar(height / 2);
281 SkScalar radius = SkMinScalar(x, y) * 0.8f;
282 bitmap.allocN32Pixels(width, height);
283 SkCanvas canvas(bitmap);
284 canvas.clear(0x00000000);
285 SkColor colors[2];
286 colors[0] = SK_ColorWHITE;
287 colors[1] = SK_ColorBLACK;
288 SkAutoTUnref<SkShader> shader(
289 SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, NULL, 2,
290 SkShader::kClamp_TileMode)
291 );
292 SkPaint paint;
293 paint.setShader(shader);
294 canvas.drawCircle(x, y, radius, paint);
295 return bitmap;
296}
297
298DEF_TEST(ImageFilterDrawTiled, reporter) {
299 // Check that all filters when drawn tiled (with subsequent clip rects) exactly
300 // match the same filters drawn with a single full-canvas bitmap draw.
301 // Tests pass by not asserting.
302
303 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
304 SkPoint3 location(0, 0, SK_Scalar1);
305 SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
306 SkScalar kernel[9] = {
307 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
308 SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
309 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
310 };
311 SkISize kernelSize = SkISize::Make(3, 3);
312 SkScalar gain = SK_Scalar1, bias = 0;
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000313 SkScalar five = SkIntToScalar(5);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000314
315 SkAutoTUnref<SkImageFilter> gradient_source(SkBitmapSource::Create(make_gradient_circle(64, 64)));
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000316 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(five, five));
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000317 SkMatrix matrix;
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000318
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000319 matrix.setTranslate(SK_Scalar1, SK_Scalar1);
320 matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1);
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000321
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000322 SkRTreeFactory factory;
323 SkPictureRecorder recorder;
324 SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0);
325
326 SkPaint greenPaint;
327 greenPaint.setColor(SK_ColorGREEN);
328 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
329 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
330 SkAutoTUnref<SkImageFilter> pictureFilter(SkPictureImageFilter::Create(picture.get()));
331
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000332 struct {
333 const char* fName;
334 SkImageFilter* fFilter;
335 } filters[] = {
336 { "color filter", SkColorFilterImageFilter::Create(cf.get()) },
337 { "displacement map", SkDisplacementMapEffect::Create(
338 SkDisplacementMapEffect::kR_ChannelSelectorType,
339 SkDisplacementMapEffect::kB_ChannelSelectorType,
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000340 20.0f, gradient_source.get()) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000341 { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
342 { "drop shadow", SkDropShadowImageFilter::Create(
343 SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN) },
344 { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse(
345 location, SK_ColorGREEN, 0, 0) },
346 { "specular lighting",
347 SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) },
348 { "matrix convolution",
349 SkMatrixConvolutionImageFilter::Create(
350 kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1),
351 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) },
352 { "merge", SkMergeImageFilter::Create(NULL, NULL, SkXfermode::kSrcOver_Mode) },
353 { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) },
354 { "dilate", SkDilateImageFilter::Create(3, 2) },
355 { "erode", SkErodeImageFilter::Create(2, 3) },
356 { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50),
357 SkRect::MakeXYWH(0, 0, 100, 100), NULL) },
senorblanco@chromium.orgba31f1d2014-05-07 20:56:08 +0000358 { "matrix", SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel) },
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +0000359 { "blur and offset", SkOffsetImageFilter::Create(five, five, blur.get()) },
senorblanco@chromium.org910702b2014-05-30 20:36:15 +0000360 { "picture and blur", SkBlurImageFilter::Create(five, five, pictureFilter.get()) },
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000361 };
362
363 SkBitmap untiledResult, tiledResult;
364 int width = 64, height = 64;
365 untiledResult.allocN32Pixels(width, height);
366 tiledResult.allocN32Pixels(width, height);
367 SkCanvas tiledCanvas(tiledResult);
368 SkCanvas untiledCanvas(untiledResult);
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000369 int tileSize = 8;
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000370
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000371 for (int scale = 1; scale <= 2; ++scale) {
372 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
373 tiledCanvas.clear(0);
374 untiledCanvas.clear(0);
375 SkPaint paint;
376 paint.setImageFilter(filters[i].fFilter);
377 paint.setTextSize(SkIntToScalar(height));
378 paint.setColor(SK_ColorWHITE);
379 SkString str;
380 const char* text = "ABC";
381 SkScalar ypos = SkIntToScalar(height);
382 untiledCanvas.save();
383 untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
384 untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
385 untiledCanvas.restore();
386 for (int y = 0; y < height; y += tileSize) {
387 for (int x = 0; x < width; x += tileSize) {
388 tiledCanvas.save();
389 tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
390 tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
391 tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
392 tiledCanvas.restore();
393 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000394 }
senorblanco@chromium.orgd4db6572014-05-07 20:00:04 +0000395 untiledCanvas.flush();
396 tiledCanvas.flush();
397 for (int y = 0; y < height; y++) {
398 int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
399 REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
400 if (diffs) {
401 break;
402 }
senorblanco@chromium.org0a5c2332014-04-29 15:20:39 +0000403 }
404 }
405 }
406
407 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
408 SkSafeUnref(filters[i].fFilter);
409 }
410}
411
senorblanco837f5322014-07-14 10:19:54 -0700412static void drawBlurredRect(SkCanvas* canvas) {
413 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0));
414 SkPaint filterPaint;
415 filterPaint.setColor(SK_ColorWHITE);
416 filterPaint.setImageFilter(filter);
417 canvas->saveLayer(NULL, &filterPaint);
418 SkPaint whitePaint;
419 whitePaint.setColor(SK_ColorWHITE);
420 canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
421 canvas->restore();
422}
423
424static void drawPictureClipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) {
425 canvas->save();
426 canvas->clipRect(clipRect);
427 canvas->drawPicture(picture);
428 canvas->restore();
429}
430
431DEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) {
432 // Check that the blur filter when recorded with RTree acceleration,
433 // and drawn tiled (with subsequent clip rects) exactly
434 // matches the same filter drawn with without RTree acceleration.
435 // This tests that the "bleed" from the blur into the otherwise-blank
436 // tiles is correctly rendered.
437 // Tests pass by not asserting.
438
439 int width = 16, height = 8;
440 SkBitmap result1, result2;
441 result1.allocN32Pixels(width, height);
442 result2.allocN32Pixels(width, height);
443 SkCanvas canvas1(result1);
444 SkCanvas canvas2(result2);
445 int tileSize = 8;
446
447 canvas1.clear(0);
448 canvas2.clear(0);
449
450 SkRTreeFactory factory;
451
452 SkPictureRecorder recorder1, recorder2;
453 // The only difference between these two pictures is that one has RTree aceleration.
454 SkCanvas* recordingCanvas1 = recorder1.beginRecording(width, height, NULL, 0);
455 SkCanvas* recordingCanvas2 = recorder2.beginRecording(width, height, &factory, 0);
456 drawBlurredRect(recordingCanvas1);
457 drawBlurredRect(recordingCanvas2);
458 SkAutoTUnref<SkPicture> picture1(recorder1.endRecording());
459 SkAutoTUnref<SkPicture> picture2(recorder2.endRecording());
460 for (int y = 0; y < height; y += tileSize) {
461 for (int x = 0; x < width; x += tileSize) {
462 SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
463 drawPictureClipped(&canvas1, tileRect, picture1);
464 drawPictureClipped(&canvas2, tileRect, picture2);
465 }
466 }
467 for (int y = 0; y < height; y++) {
468 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
469 REPORTER_ASSERT(reporter, !diffs);
470 if (diffs) {
471 break;
472 }
473 }
474}
475
senorblanco@chromium.org91957432014-05-01 14:03:41 +0000476DEF_TEST(ImageFilterMatrixConvolution, reporter) {
477 // Check that a 1x3 filter does not cause a spurious assert.
478 SkScalar kernel[3] = {
479 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
480 };
481 SkISize kernelSize = SkISize::Make(1, 3);
482 SkScalar gain = SK_Scalar1, bias = 0;
483 SkIPoint kernelOffset = SkIPoint::Make(0, 0);
484
485 SkAutoTUnref<SkImageFilter> filter(
486 SkMatrixConvolutionImageFilter::Create(
487 kernelSize, kernel, gain, bias, kernelOffset,
488 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false));
489
490 SkBitmap result;
491 int width = 16, height = 16;
492 result.allocN32Pixels(width, height);
493 SkCanvas canvas(result);
494 canvas.clear(0);
495
496 SkPaint paint;
497 paint.setImageFilter(filter);
498 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
499 canvas.drawRect(rect, paint);
500}
501
senorblanco@chromium.org8c7372b2014-05-02 19:13:11 +0000502DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) {
503 // Check that a filter with borders outside the target bounds
504 // does not crash.
505 SkScalar kernel[3] = {
506 0, 0, 0,
507 };
508 SkISize kernelSize = SkISize::Make(3, 1);
509 SkScalar gain = SK_Scalar1, bias = 0;
510 SkIPoint kernelOffset = SkIPoint::Make(2, 0);
511
512 SkAutoTUnref<SkImageFilter> filter(
513 SkMatrixConvolutionImageFilter::Create(
514 kernelSize, kernel, gain, bias, kernelOffset,
515 SkMatrixConvolutionImageFilter::kClamp_TileMode, true));
516
517 SkBitmap result;
518
519 int width = 10, height = 10;
520 result.allocN32Pixels(width, height);
521 SkCanvas canvas(result);
522 canvas.clear(0);
523
524 SkPaint filterPaint;
525 filterPaint.setImageFilter(filter);
526 SkRect bounds = SkRect::MakeWH(1, 10);
527 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height));
528 SkPaint rectPaint;
529 canvas.saveLayer(&bounds, &filterPaint);
530 canvas.drawRect(rect, rectPaint);
531 canvas.restore();
532}
533
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000534DEF_TEST(ImageFilterCropRect, reporter) {
535 SkBitmap temp;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000536 temp.allocN32Pixels(100, 100);
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000537 SkBitmapDevice device(temp);
538 test_crop_rects(&device, reporter);
539}
540
tfarina9ea53f92014-06-24 06:50:39 -0700541DEF_TEST(ImageFilterMatrix, reporter) {
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000542 SkBitmap temp;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000543 temp.allocN32Pixels(100, 100);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000544 SkBitmapDevice device(temp);
545 SkCanvas canvas(&device);
546 canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
547
548 SkMatrix expectedMatrix = canvas.getTotalMatrix();
549
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000550 SkRTreeFactory factory;
551 SkPictureRecorder recorder;
552 SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000553
554 SkPaint paint;
555 SkAutoTUnref<MatrixTestImageFilter> imageFilter(
556 new MatrixTestImageFilter(reporter, expectedMatrix));
557 paint.setImageFilter(imageFilter.get());
commit-bot@chromium.org091a5942014-04-18 14:19:31 +0000558 recordingCanvas->saveLayer(NULL, &paint);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000559 SkPaint solidPaint;
560 solidPaint.setColor(0xFFFFFFFF);
561 recordingCanvas->save();
562 recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
563 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
564 recordingCanvas->restore(); // scale
565 recordingCanvas->restore(); // saveLayer
robertphillips@google.com84b18c72014-04-13 19:09:42 +0000566 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000567
robertphillips9b14f262014-06-04 05:40:44 -0700568 canvas.drawPicture(picture);
senorblanco@chromium.org5251e2b2014-02-05 22:36:31 +0000569}
570
tfarina9ea53f92014-06-24 06:50:39 -0700571DEF_TEST(ImageFilterPictureImageFilter, reporter) {
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000572 SkRTreeFactory factory;
573 SkPictureRecorder recorder;
574 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0);
575
576 // Create an SkPicture which simply draws a green 1x1 rectangle.
577 SkPaint greenPaint;
578 greenPaint.setColor(SK_ColorGREEN);
579 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
580 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
581
582 // Wrap that SkPicture in an SkPictureImageFilter.
583 SkAutoTUnref<SkImageFilter> imageFilter(
584 SkPictureImageFilter::Create(picture.get()));
585
586 // Check that SkPictureImageFilter successfully serializes its contained
587 // SkPicture when not in cross-process mode.
588 SkPaint paint;
589 paint.setImageFilter(imageFilter.get());
590 SkPictureRecorder outerRecorder;
591 SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0);
592 SkPaint redPaintWithFilter;
593 redPaintWithFilter.setColor(SK_ColorRED);
594 redPaintWithFilter.setImageFilter(imageFilter.get());
595 outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
596 SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording());
597
598 SkBitmap bitmap;
599 bitmap.allocN32Pixels(1, 1);
600 SkBitmapDevice device(bitmap);
601 SkCanvas canvas(&device);
602
603 // The result here should be green, since the filter replaces the primitive's red interior.
604 canvas.clear(0x0);
robertphillips9b14f262014-06-04 05:40:44 -0700605 canvas.drawPicture(outerPicture);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000606 uint32_t pixel = *bitmap.getAddr32(0, 0);
607 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
608
609 // Check that, for now, SkPictureImageFilter does not serialize or
610 // deserialize its contained picture when the filter is serialized
611 // cross-process. Do this by "laundering" it through SkValidatingReadBuffer.
612 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get()));
613 SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable(
614 data->data(), data->size(), SkImageFilter::GetFlattenableType()));
615 SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get());
616
617 redPaintWithFilter.setImageFilter(unflattenedFilter);
618 SkPictureRecorder crossProcessRecorder;
619 SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0);
620 crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter);
621 SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording());
622
623 canvas.clear(0x0);
robertphillips9b14f262014-06-04 05:40:44 -0700624 canvas.drawPicture(crossProcessPicture);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +0000625 pixel = *bitmap.getAddr32(0, 0);
626 // The result here should not be green, since the filter draws nothing.
627 REPORTER_ASSERT(reporter, pixel != SK_ColorGREEN);
628}
629
tfarina9ea53f92014-06-24 06:50:39 -0700630DEF_TEST(ImageFilterEmptySaveLayer, reporter) {
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000631 // Even when there's an empty saveLayer()/restore(), ensure that an image
632 // filter or color filter which affects transparent black still draws.
633
634 SkBitmap bitmap;
635 bitmap.allocN32Pixels(10, 10);
636 SkBitmapDevice device(bitmap);
637 SkCanvas canvas(&device);
638
639 SkRTreeFactory factory;
640 SkPictureRecorder recorder;
641
642 SkAutoTUnref<SkColorFilter> green(
643 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode));
644 SkAutoTUnref<SkColorFilterImageFilter> imageFilter(
645 SkColorFilterImageFilter::Create(green.get()));
646 SkPaint imageFilterPaint;
647 imageFilterPaint.setImageFilter(imageFilter.get());
648 SkPaint colorFilterPaint;
649 colorFilterPaint.setColorFilter(green.get());
650
651 SkRect bounds = SkRect::MakeWH(10, 10);
652
653 SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
654 recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
655 recordingCanvas->restore();
656 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
657
658 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -0700659 canvas.drawPicture(picture);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000660 uint32_t pixel = *bitmap.getAddr32(0, 0);
661 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
662
663 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
664 recordingCanvas->saveLayer(NULL, &imageFilterPaint);
665 recordingCanvas->restore();
666 SkAutoTUnref<SkPicture> picture2(recorder.endRecording());
667
668 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -0700669 canvas.drawPicture(picture2);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000670 pixel = *bitmap.getAddr32(0, 0);
671 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
672
673 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0);
674 recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
675 recordingCanvas->restore();
676 SkAutoTUnref<SkPicture> picture3(recorder.endRecording());
677
678 canvas.clear(0);
robertphillips9b14f262014-06-04 05:40:44 -0700679 canvas.drawPicture(picture3);
senorblanco@chromium.org68250c82014-05-06 22:52:55 +0000680 pixel = *bitmap.getAddr32(0, 0);
681 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
682}
683
senorblanco@chromium.org28ae55d2014-03-24 21:32:28 +0000684static void test_huge_blur(SkBaseDevice* device, skiatest::Reporter* reporter) {
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000685 SkCanvas canvas(device);
686
687 SkBitmap bitmap;
688 bitmap.allocN32Pixels(100, 100);
689 bitmap.eraseARGB(0, 0, 0, 0);
690
691 // Check that a blur with an insane radius does not crash or assert.
692 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(SkIntToScalar(1<<30), SkIntToScalar(1<<30)));
693
694 SkPaint paint;
695 paint.setImageFilter(blur);
696 canvas.drawSprite(bitmap, 0, 0, &paint);
697}
698
699DEF_TEST(HugeBlurImageFilter, reporter) {
700 SkBitmap temp;
701 temp.allocN32Pixels(100, 100);
702 SkBitmapDevice device(temp);
703 test_huge_blur(&device, reporter);
704}
705
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +0000706static void test_xfermode_cropped_input(SkBaseDevice* device, skiatest::Reporter* reporter) {
707 SkCanvas canvas(device);
708 canvas.clear(0);
709
710 SkBitmap bitmap;
711 bitmap.allocN32Pixels(1, 1);
712 bitmap.eraseARGB(255, 255, 255, 255);
713
714 SkAutoTUnref<SkColorFilter> green(
715 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode));
716 SkAutoTUnref<SkColorFilterImageFilter> greenFilter(
717 SkColorFilterImageFilter::Create(green.get()));
718 SkImageFilter::CropRect cropRect(SkRect::MakeEmpty());
719 SkAutoTUnref<SkColorFilterImageFilter> croppedOut(
720 SkColorFilterImageFilter::Create(green.get(), NULL, &cropRect));
721
722 // Check that an xfermode image filter whose input has been cropped out still draws the other
723 // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
724 SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode);
725 SkAutoTUnref<SkImageFilter> xfermodeNoFg(
726 SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut));
727 SkAutoTUnref<SkImageFilter> xfermodeNoBg(
728 SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter));
729 SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg(
730 SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut));
731
732 SkPaint paint;
733 paint.setImageFilter(xfermodeNoFg);
734 canvas.drawSprite(bitmap, 0, 0, &paint);
735
736 uint32_t pixel;
737 SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
738 canvas.readPixels(info, &pixel, 4, 0, 0);
739 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
740
741 paint.setImageFilter(xfermodeNoBg);
742 canvas.drawSprite(bitmap, 0, 0, &paint);
743 canvas.readPixels(info, &pixel, 4, 0, 0);
744 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
745
746 paint.setImageFilter(xfermodeNoFgNoBg);
747 canvas.drawSprite(bitmap, 0, 0, &paint);
748 canvas.readPixels(info, &pixel, 4, 0, 0);
749 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
750}
751
senorblanco@chromium.orgd5424a42014-04-02 19:20:05 +0000752DEF_TEST(ImageFilterNestedSaveLayer, reporter) {
753 SkBitmap temp;
754 temp.allocN32Pixels(50, 50);
755 SkBitmapDevice device(temp);
756 SkCanvas canvas(&device);
757 canvas.clear(0x0);
758
759 SkBitmap bitmap;
760 bitmap.allocN32Pixels(10, 10);
761 bitmap.eraseColor(SK_ColorGREEN);
762
763 SkMatrix matrix;
764 matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
765 matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
766 SkAutoTUnref<SkImageFilter> matrixFilter(
767 SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel));
768
769 // Test that saveLayer() with a filter nested inside another saveLayer() applies the
770 // correct offset to the filter matrix.
771 SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
772 canvas.saveLayer(&bounds1, NULL);
773 SkPaint filterPaint;
774 filterPaint.setImageFilter(matrixFilter);
775 SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
776 canvas.saveLayer(&bounds2, &filterPaint);
777 SkPaint greenPaint;
778 greenPaint.setColor(SK_ColorGREEN);
779 canvas.drawRect(bounds2, greenPaint);
780 canvas.restore();
781 canvas.restore();
782 SkPaint strokePaint;
783 strokePaint.setStyle(SkPaint::kStroke_Style);
784 strokePaint.setColor(SK_ColorRED);
785
786 SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
787 uint32_t pixel;
788 canvas.readPixels(info, &pixel, 4, 25, 25);
789 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
790
791 // Test that drawSprite() with a filter nested inside a saveLayer() applies the
792 // correct offset to the filter matrix.
793 canvas.clear(0x0);
794 canvas.readPixels(info, &pixel, 4, 25, 25);
795 canvas.saveLayer(&bounds1, NULL);
796 canvas.drawSprite(bitmap, 20, 20, &filterPaint);
797 canvas.restore();
798
799 canvas.readPixels(info, &pixel, 4, 25, 25);
800 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN);
801}
802
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +0000803DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
804 SkBitmap temp;
805 temp.allocN32Pixels(100, 100);
806 SkBitmapDevice device(temp);
807 test_xfermode_cropped_input(&device, reporter);
808}
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000809
senorblanco@chromium.org58d14662014-02-03 22:36:39 +0000810#if SK_SUPPORT_GPU
senorblanco@chromium.orgaba651c2014-02-03 22:22:16 +0000811DEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) {
812 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000813 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
814 SkImageInfo::MakeN32Premul(100, 100),
815 0));
816 test_crop_rects(device, reporter);
tfarina@chromium.org9f9d5822013-12-18 22:15:12 +0000817}
senorblanco@chromium.org09843fd2014-03-24 20:50:59 +0000818
819DEF_GPUTEST(HugeBlurImageFilterGPU, reporter, factory) {
820 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
821 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
822 SkImageInfo::MakeN32Premul(100, 100),
823 0));
824 test_huge_blur(device, reporter);
825}
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +0000826
827DEF_GPUTEST(XfermodeImageFilterCroppedInputGPU, reporter, factory) {
828 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
829 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context,
830 SkImageInfo::MakeN32Premul(1, 1),
831 0));
832 test_xfermode_cropped_input(device, reporter);
833}
senorblanco@chromium.org58d14662014-02-03 22:36:39 +0000834#endif