• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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