1 /*
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 #include "SampleCode.h"
8 #include "SkAlphaThresholdFilter.h"
9 #include "SkBicubicImageFilter.h"
10 #include "SkBitmapDevice.h"
11 #include "SkBitmapSource.h"
12 #include "SkBlurImageFilter.h"
13 #include "SkCanvas.h"
14 #include "SkColorFilter.h"
15 #include "SkColorFilterImageFilter.h"
16 #include "SkComposeImageFilter.h"
17 #include "SkData.h"
18 #include "SkDisplacementMapEffect.h"
19 #include "SkDropShadowImageFilter.h"
20 #include "SkFlattenableSerialization.h"
21 #include "SkLightingImageFilter.h"
22 #include "SkMagnifierImageFilter.h"
23 #include "SkMatrixImageFilter.h"
24 #include "SkMatrixConvolutionImageFilter.h"
25 #include "SkMergeImageFilter.h"
26 #include "SkMorphologyImageFilter.h"
27 #include "SkOffsetImageFilter.h"
28 #include "SkPerlinNoiseShader.h"
29 #include "SkPictureImageFilter.h"
30 #include "SkPictureRecorder.h"
31 #include "SkRandom.h"
32 #include "SkRectShaderImageFilter.h"
33 #include "SkTestImageFilters.h"
34 #include "SkTileImageFilter.h"
35 #include "SkView.h"
36 #include "SkXfermodeImageFilter.h"
37 #include <stdio.h>
38 #include <time.h>
39
40 //#define SK_ADD_RANDOM_BIT_FLIPS
41 //#define SK_FUZZER_IS_VERBOSE
42
43 static const uint32_t kSeed = (uint32_t)(time(NULL));
44 static SkRandom gRand(kSeed);
45 static bool return_large = false;
46 static bool return_undef = false;
47
48 static const int kBitmapSize = 24;
49
R(float x)50 static int R(float x) {
51 return (int)floor(SkScalarToFloat(gRand.nextUScalar1()) * x);
52 }
53
54 #if defined _WIN32
55 #pragma warning ( push )
56 // we are intentionally causing an overflow here
57 // (warning C4756: overflow in constant arithmetic)
58 #pragma warning ( disable : 4756 )
59 #endif
60
huge()61 static float huge() {
62 double d = 1e100;
63 float f = (float)d;
64 return f;
65 }
66
67 #if defined _WIN32
68 #pragma warning ( pop )
69 #endif
70
make_number(bool positiveOnly)71 static float make_number(bool positiveOnly) {
72 float f = positiveOnly ? 1.0f : 0.0f;
73 float v = f;
74 int sel;
75
76 if (return_large) sel = R(6); else sel = R(4);
77 if (!return_undef && sel == 0) sel = 1;
78
79 if (R(2) == 1) v = (float)(R(100)+f); else
80
81 switch (sel) {
82 case 0: break;
83 case 1: v = f; break;
84 case 2: v = 0.000001f; break;
85 case 3: v = 10000.0f; break;
86 case 4: v = 2000000000.0f; break;
87 case 5: v = huge(); break;
88 }
89
90 if (!positiveOnly && (R(4) == 1)) v = -v;
91 return v;
92 }
93
make_scalar(bool positiveOnly=false)94 static SkScalar make_scalar(bool positiveOnly = false) {
95 return make_number(positiveOnly);
96 }
97
make_rect()98 static SkRect make_rect() {
99 return SkRect::MakeWH(SkIntToScalar(R(static_cast<float>(kBitmapSize))),
100 SkIntToScalar(R(static_cast<float>(kBitmapSize))));
101 }
102
make_region()103 static SkRegion make_region() {
104 SkIRect iRegion = SkIRect::MakeXYWH(R(static_cast<float>(kBitmapSize)),
105 R(static_cast<float>(kBitmapSize)),
106 R(static_cast<float>(kBitmapSize)),
107 R(static_cast<float>(kBitmapSize)));
108 return SkRegion(iRegion);
109 }
110
make_matrix()111 static SkMatrix make_matrix() {
112 SkMatrix m;
113 for (int i = 0; i < 9; ++i) {
114 m[i] = make_scalar();
115 }
116 return m;
117 }
118
make_xfermode()119 static SkXfermode::Mode make_xfermode() {
120 return static_cast<SkXfermode::Mode>(R(SkXfermode::kLastMode+1));
121 }
122
make_color()123 static SkColor make_color() {
124 return (R(2) == 1) ? 0xFFC0F0A0 : 0xFF000090;
125 }
126
make_point()127 static SkPoint3 make_point() {
128 return SkPoint3(make_scalar(), make_scalar(), make_scalar(true));
129 }
130
make_channel_selector_type()131 static SkDisplacementMapEffect::ChannelSelectorType make_channel_selector_type() {
132 return static_cast<SkDisplacementMapEffect::ChannelSelectorType>(R(4)+1);
133 }
134
valid_for_raster_canvas(const SkImageInfo & info)135 static bool valid_for_raster_canvas(const SkImageInfo& info) {
136 switch (info.colorType()) {
137 case kAlpha_8_SkColorType:
138 case kRGB_565_SkColorType:
139 return true;
140 case kN32_SkColorType:
141 return kPremul_SkAlphaType == info.alphaType() ||
142 kOpaque_SkAlphaType == info.alphaType();
143 default:
144 break;
145 }
146 return false;
147 }
148
rand_colortype()149 static SkColorType rand_colortype() {
150 return (SkColorType)R(kLastEnum_SkColorType + 1);
151 }
152
rand_bitmap_for_canvas(SkBitmap * bitmap)153 static void rand_bitmap_for_canvas(SkBitmap* bitmap) {
154 SkImageInfo info;
155 do {
156 info = SkImageInfo::Make(kBitmapSize, kBitmapSize, rand_colortype(),
157 kPremul_SkAlphaType);
158 } while (!valid_for_raster_canvas(info) || !bitmap->allocPixels(info));
159 }
160
make_g_bitmap(SkBitmap & bitmap)161 static void make_g_bitmap(SkBitmap& bitmap) {
162 rand_bitmap_for_canvas(&bitmap);
163
164 SkCanvas canvas(bitmap);
165 canvas.clear(0x00000000);
166 SkPaint paint;
167 paint.setAntiAlias(true);
168 paint.setColor(0xFF884422);
169 paint.setTextSize(SkIntToScalar(kBitmapSize/2));
170 const char* str = "g";
171 canvas.drawText(str, strlen(str), SkIntToScalar(kBitmapSize/8),
172 SkIntToScalar(kBitmapSize/4), paint);
173 }
174
make_checkerboard_bitmap(SkBitmap & bitmap)175 static void make_checkerboard_bitmap(SkBitmap& bitmap) {
176 rand_bitmap_for_canvas(&bitmap);
177
178 SkCanvas canvas(bitmap);
179 canvas.clear(0x00000000);
180 SkPaint darkPaint;
181 darkPaint.setColor(0xFF804020);
182 SkPaint lightPaint;
183 lightPaint.setColor(0xFF244484);
184 const int i = kBitmapSize / 8;
185 const SkScalar f = SkIntToScalar(i);
186 for (int y = 0; y < kBitmapSize; y += i) {
187 for (int x = 0; x < kBitmapSize; x += i) {
188 canvas.save();
189 canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
190 canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint);
191 canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint);
192 canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint);
193 canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint);
194 canvas.restore();
195 }
196 }
197 }
198
make_bitmap()199 static const SkBitmap& make_bitmap() {
200 static SkBitmap bitmap[2];
201 static bool initialized = false;
202 if (!initialized) {
203 make_g_bitmap(bitmap[0]);
204 make_checkerboard_bitmap(bitmap[1]);
205 initialized = true;
206 }
207 return bitmap[R(2)];
208 }
209
drawSomething(SkCanvas * canvas)210 static void drawSomething(SkCanvas* canvas) {
211 SkPaint paint;
212
213 canvas->save();
214 canvas->scale(0.5f, 0.5f);
215 canvas->drawBitmap(make_bitmap(), 0, 0, NULL);
216 canvas->restore();
217
218 const char beforeStr[] = "before circle";
219 const char afterStr[] = "after circle";
220
221 paint.setAntiAlias(true);
222
223 paint.setColor(SK_ColorRED);
224 canvas->drawData(beforeStr, sizeof(beforeStr));
225 canvas->drawCircle(SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/3), paint);
226 canvas->drawData(afterStr, sizeof(afterStr));
227 paint.setColor(SK_ColorBLACK);
228 paint.setTextSize(SkIntToScalar(kBitmapSize/3));
229 canvas->drawText("Picture", 7, SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), paint);
230 }
231
make_image_filter(bool canBeNull=true)232 static SkImageFilter* make_image_filter(bool canBeNull = true) {
233 SkImageFilter* filter = 0;
234
235 // Add a 1 in 3 chance to get a NULL input
236 if (canBeNull && (R(3) == 1)) { return filter; }
237
238 enum { ALPHA_THRESHOLD, BICUBIC, MERGE, COLOR, BLUR, MAGNIFIER,
239 DOWN_SAMPLE, XFERMODE, OFFSET, MATRIX, MATRIX_CONVOLUTION, COMPOSE,
240 DISTANT_LIGHT, POINT_LIGHT, SPOT_LIGHT, NOISE, DROP_SHADOW,
241 MORPHOLOGY, BITMAP, DISPLACE, TILE, PICTURE, NUM_FILTERS };
242
243 switch (R(NUM_FILTERS)) {
244 case ALPHA_THRESHOLD:
245 filter = SkAlphaThresholdFilter::Create(make_region(), make_scalar(), make_scalar());
246 break;
247 case BICUBIC:
248 // Scale is set to 1 here so that it can fit in the DAG without resizing the output
249 filter = SkBicubicImageFilter::CreateMitchell(SkSize::Make(1, 1), make_image_filter());
250 break;
251 case MERGE:
252 filter = SkMergeImageFilter::Create(make_image_filter(), make_image_filter(), make_xfermode());
253 break;
254 case COLOR:
255 {
256 SkAutoTUnref<SkColorFilter> cf((R(2) == 1) ?
257 SkColorFilter::CreateModeFilter(make_color(), make_xfermode()) :
258 SkColorFilter::CreateLightingFilter(make_color(), make_color()));
259 filter = cf.get() ? SkColorFilterImageFilter::Create(cf, make_image_filter()) : 0;
260 }
261 break;
262 case BLUR:
263 filter = SkBlurImageFilter::Create(make_scalar(true), make_scalar(true), make_image_filter());
264 break;
265 case MAGNIFIER:
266 filter = SkMagnifierImageFilter::Create(make_rect(), make_scalar(true));
267 break;
268 case DOWN_SAMPLE:
269 filter = SkDownSampleImageFilter::Create(make_scalar());
270 break;
271 case XFERMODE:
272 {
273 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(make_xfermode()));
274 filter = SkXfermodeImageFilter::Create(mode, make_image_filter(), make_image_filter());
275 }
276 break;
277 case OFFSET:
278 filter = SkOffsetImageFilter::Create(make_scalar(), make_scalar(), make_image_filter());
279 break;
280 case MATRIX:
281 filter = SkMatrixImageFilter::Create(make_matrix(),
282 (SkPaint::FilterLevel)R(4),
283 make_image_filter());
284 break;
285 case MATRIX_CONVOLUTION:
286 {
287 SkImageFilter::CropRect cropR(SkRect::MakeWH(SkIntToScalar(kBitmapSize),
288 SkIntToScalar(kBitmapSize)));
289 SkISize size = SkISize::Make(R(10)+1, R(10)+1);
290 int arraySize = size.width() * size.height();
291 SkTArray<SkScalar> kernel(arraySize);
292 for (int i = 0; i < arraySize; ++i) {
293 kernel.push_back() = make_scalar();
294 }
295 SkIPoint kernelOffset = SkIPoint::Make(R(SkIntToScalar(size.width())),
296 R(SkIntToScalar(size.height())));
297 filter = SkMatrixConvolutionImageFilter::Create(size,
298 kernel.begin(),
299 make_scalar(),
300 make_scalar(),
301 kernelOffset,
302 (SkMatrixConvolutionImageFilter::TileMode)R(3),
303 R(2) == 1,
304 make_image_filter(),
305 &cropR);
306 }
307 break;
308 case COMPOSE:
309 filter = SkComposeImageFilter::Create(make_image_filter(), make_image_filter());
310 break;
311 case DISTANT_LIGHT:
312 filter = (R(2) == 1) ?
313 SkLightingImageFilter::CreateDistantLitDiffuse(make_point(),
314 make_color(), make_scalar(), make_scalar(), make_image_filter()) :
315 SkLightingImageFilter::CreateDistantLitSpecular(make_point(),
316 make_color(), make_scalar(), make_scalar(), SkIntToScalar(R(10)),
317 make_image_filter());
318 break;
319 case POINT_LIGHT:
320 filter = (R(2) == 1) ?
321 SkLightingImageFilter::CreatePointLitDiffuse(make_point(),
322 make_color(), make_scalar(), make_scalar(), make_image_filter()) :
323 SkLightingImageFilter::CreatePointLitSpecular(make_point(),
324 make_color(), make_scalar(), make_scalar(), SkIntToScalar(R(10)),
325 make_image_filter());
326 break;
327 case SPOT_LIGHT:
328 filter = (R(2) == 1) ?
329 SkLightingImageFilter::CreateSpotLitDiffuse(SkPoint3(0, 0, 0),
330 make_point(), make_scalar(), make_scalar(), make_color(),
331 make_scalar(), make_scalar(), make_image_filter()) :
332 SkLightingImageFilter::CreateSpotLitSpecular(SkPoint3(0, 0, 0),
333 make_point(), make_scalar(), make_scalar(), make_color(),
334 make_scalar(), make_scalar(), SkIntToScalar(R(10)), make_image_filter());
335 break;
336 case NOISE:
337 {
338 SkAutoTUnref<SkShader> shader((R(2) == 1) ?
339 SkPerlinNoiseShader::CreateFractalNoise(
340 make_scalar(true), make_scalar(true), R(10.0f), make_scalar()) :
341 SkPerlinNoiseShader::CreateTurbulence(
342 make_scalar(true), make_scalar(true), R(10.0f), make_scalar()));
343 SkImageFilter::CropRect cropR(SkRect::MakeWH(SkIntToScalar(kBitmapSize),
344 SkIntToScalar(kBitmapSize)));
345 filter = SkRectShaderImageFilter::Create(shader, &cropR);
346 }
347 break;
348 case DROP_SHADOW:
349 filter = SkDropShadowImageFilter::Create(make_scalar(), make_scalar(),
350 make_scalar(true), make_color(), make_image_filter());
351 break;
352 case MORPHOLOGY:
353 if (R(2) == 1) {
354 filter = SkDilateImageFilter::Create(R(static_cast<float>(kBitmapSize)),
355 R(static_cast<float>(kBitmapSize)), make_image_filter());
356 } else {
357 filter = SkErodeImageFilter::Create(R(static_cast<float>(kBitmapSize)),
358 R(static_cast<float>(kBitmapSize)), make_image_filter());
359 }
360 break;
361 case BITMAP:
362 if (R(2) == 1) {
363 filter = SkBitmapSource::Create(make_bitmap(), make_rect(), make_rect());
364 } else {
365 filter = SkBitmapSource::Create(make_bitmap());
366 }
367 break;
368 case DISPLACE:
369 filter = SkDisplacementMapEffect::Create(make_channel_selector_type(),
370 make_channel_selector_type(), make_scalar(),
371 make_image_filter(false), make_image_filter());
372 break;
373 case TILE:
374 filter = SkTileImageFilter::Create(make_rect(), make_rect(), make_image_filter(false));
375 break;
376 case PICTURE:
377 {
378 SkRTreeFactory factory;
379 SkPictureRecorder recorder;
380 SkCanvas* recordingCanvas = recorder.beginRecording(kBitmapSize, kBitmapSize, &factory, 0);
381 drawSomething(recordingCanvas);
382 SkAutoTUnref<SkPicture> pict(recorder.endRecording());
383 filter = SkPictureImageFilter::Create(pict.get(), make_rect());
384 }
385 break;
386 default:
387 break;
388 }
389 return (filter || canBeNull) ? filter : make_image_filter(canBeNull);
390 }
391
make_serialized_image_filter()392 static SkImageFilter* make_serialized_image_filter() {
393 SkAutoTUnref<SkImageFilter> filter(make_image_filter(false));
394 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(filter));
395 const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
396 size_t len = data->size();
397 #ifdef SK_ADD_RANDOM_BIT_FLIPS
398 unsigned char* p = const_cast<unsigned char*>(ptr);
399 for (size_t i = 0; i < len; ++i, ++p) {
400 if (R(250) == 1) { // 0.4% of the time, flip a bit or byte
401 if (R(10) == 1) { // Then 10% of the time, change a whole byte
402 switch(R(3)) {
403 case 0:
404 *p ^= 0xFF; // Flip entire byte
405 break;
406 case 1:
407 *p = 0xFF; // Set all bits to 1
408 break;
409 case 2:
410 *p = 0x00; // Set all bits to 0
411 break;
412 }
413 } else {
414 *p ^= (1 << R(8));
415 }
416 }
417 }
418 #endif // SK_ADD_RANDOM_BIT_FLIPS
419 SkFlattenable* flattenable = SkValidatingDeserializeFlattenable(ptr, len,
420 SkImageFilter::GetFlattenableType());
421 return static_cast<SkImageFilter*>(flattenable);
422 }
423
drawClippedBitmap(SkCanvas * canvas,int x,int y,const SkPaint & paint)424 static void drawClippedBitmap(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
425 canvas->save();
426 canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
427 SkIntToScalar(kBitmapSize), SkIntToScalar(kBitmapSize)));
428 canvas->drawBitmap(make_bitmap(), SkIntToScalar(x), SkIntToScalar(y), &paint);
429 canvas->restore();
430 }
431
do_fuzz(SkCanvas * canvas)432 static void do_fuzz(SkCanvas* canvas) {
433 SkImageFilter* filter = make_serialized_image_filter();
434
435 #ifdef SK_FUZZER_IS_VERBOSE
436 static uint32_t numFilters = 0;
437 static uint32_t numValidFilters = 0;
438 if (0 == numFilters) {
439 printf("Fuzzing with %u\n", kSeed);
440 }
441 numFilters++;
442 if (NULL != filter) {
443 numValidFilters++;
444 }
445 printf("Filter no : %u. Valid filters so far : %u\r", numFilters, numValidFilters);
446 fflush(stdout);
447 #endif
448
449 SkPaint paint;
450 SkSafeUnref(paint.setImageFilter(filter));
451 drawClippedBitmap(canvas, 0, 0, paint);
452 }
453
454 //////////////////////////////////////////////////////////////////////////////
455
456 class ImageFilterFuzzView : public SampleView {
457 public:
ImageFilterFuzzView()458 ImageFilterFuzzView() {
459 this->setBGColor(0xFFDDDDDD);
460 }
461
462 protected:
463 // overrides from SkEventSink
onQuery(SkEvent * evt)464 virtual bool onQuery(SkEvent* evt) {
465 if (SampleCode::TitleQ(*evt)) {
466 SampleCode::TitleR(evt, "ImageFilterFuzzer");
467 return true;
468 }
469 return this->INHERITED::onQuery(evt);
470 }
471
drawBG(SkCanvas * canvas)472 void drawBG(SkCanvas* canvas) {
473 canvas->drawColor(0xFFDDDDDD);
474 }
475
onDrawContent(SkCanvas * canvas)476 virtual void onDrawContent(SkCanvas* canvas) {
477 do_fuzz(canvas);
478 this->inval(0);
479 }
480
481 private:
482 typedef SkView INHERITED;
483 };
484
485 //////////////////////////////////////////////////////////////////////////////
486
MyFactory()487 static SkView* MyFactory() { return new ImageFilterFuzzView; }
488 static SkViewRegister reg(MyFactory);
489