SampleFilterFuzz.cpp revision ef74fa189b738e13295d6a96f86a6e10223505a8
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 "SkBicubicImageFilter.h"
9#include "SkBitmapDevice.h"
10#include "SkBitmapSource.h"
11#include "SkBlurImageFilter.h"
12#include "SkCanvas.h"
13#include "SkColorFilter.h"
14#include "SkColorFilterImageFilter.h"
15#include "SkComposeImageFilter.h"
16#include "SkData.h"
17#include "SkDisplacementMapEffect.h"
18#include "SkDropShadowImageFilter.h"
19#include "SkFlattenableSerialization.h"
20#include "SkLightingImageFilter.h"
21#include "SkMagnifierImageFilter.h"
22#include "SkMergeImageFilter.h"
23#include "SkMorphologyImageFilter.h"
24#include "SkOffsetImageFilter.h"
25#include "SkPerlinNoiseShader.h"
26#include "SkRandom.h"
27#include "SkRectShaderImageFilter.h"
28#include "SkTileImageFilter.h"
29#include "SkView.h"
30#include "SkXfermodeImageFilter.h"
31#include <stdio.h>
32#include <time.h>
33
34//#define SK_ADD_RANDOM_BIT_FLIPS
35//#define SK_FUZZER_IS_VERBOSE
36
37static const uint32_t kSeed = (uint32_t)(time(NULL));
38static SkRandom gRand(kSeed);
39static bool return_large = false;
40static bool return_undef = false;
41
42static const int kBitmapSize = 24;
43
44static int R(float x) {
45    return (int)floor(SkScalarToFloat(gRand.nextUScalar1()) * x);
46}
47
48#if defined _WIN32
49#pragma warning ( push )
50// we are intentionally causing an overflow here
51//      (warning C4756: overflow in constant arithmetic)
52#pragma warning ( disable : 4756 )
53#endif
54
55static float huge() {
56    double d = 1e100;
57    float f = (float)d;
58    return f;
59}
60
61#if defined _WIN32
62#pragma warning ( pop )
63#endif
64
65static float make_number(bool positiveOnly) {
66    float f = positiveOnly ? 1.0f : 0.0f;
67    float v = f;
68    int sel;
69
70    if (return_large) sel = R(6); else sel = R(4);
71    if (!return_undef && sel == 0) sel = 1;
72
73    if (R(2) == 1) v = (float)(R(100)+f); else
74
75    switch (sel) {
76        case 0: break;
77        case 1: v = f; break;
78        case 2: v = 0.000001f; break;
79        case 3: v = 10000.0f; break;
80        case 4: v = 2000000000.0f; break;
81        case 5: v = huge(); break;
82    }
83
84    if (!positiveOnly && (R(4) == 1)) v = -v;
85    return v;
86}
87
88static SkScalar make_scalar(bool positiveOnly = false) {
89    return make_number(positiveOnly);
90}
91
92static SkRect make_rect() {
93    return SkRect::MakeWH(SkIntToScalar(R(static_cast<float>(kBitmapSize))),
94                          SkIntToScalar(R(static_cast<float>(kBitmapSize))));
95}
96
97static SkXfermode::Mode make_xfermode() {
98    return static_cast<SkXfermode::Mode>(R(SkXfermode::kLastMode+1));
99}
100
101static SkColor make_color() {
102    return (R(2) == 1) ? 0xFFC0F0A0 : 0xFF000090;
103}
104
105static SkPoint3 make_point() {
106    return SkPoint3(make_scalar(), make_scalar(), make_scalar(true));
107}
108
109static SkDisplacementMapEffect::ChannelSelectorType make_channel_selector_type() {
110    return static_cast<SkDisplacementMapEffect::ChannelSelectorType>(R(4)+1);
111}
112
113static void make_g_bitmap(SkBitmap& bitmap) {
114    bitmap.setConfig((SkBitmap::Config)R(SkBitmap::kConfigCount), kBitmapSize, kBitmapSize);
115    while (!bitmap.allocPixels()) {
116        bitmap.setConfig((SkBitmap::Config)R(SkBitmap::kConfigCount), kBitmapSize, kBitmapSize);
117    }
118    SkBitmapDevice device(bitmap);
119    SkCanvas canvas(&device);
120    canvas.clear(0x00000000);
121    SkPaint paint;
122    paint.setAntiAlias(true);
123    paint.setColor(0xFF884422);
124    paint.setTextSize(SkIntToScalar(kBitmapSize/2));
125    const char* str = "g";
126    canvas.drawText(str, strlen(str), SkIntToScalar(kBitmapSize/8),
127                    SkIntToScalar(kBitmapSize/4), paint);
128}
129
130static void make_checkerboard_bitmap(SkBitmap& bitmap) {
131    bitmap.setConfig((SkBitmap::Config)R(SkBitmap::kConfigCount), kBitmapSize, kBitmapSize);
132    while (!bitmap.allocPixels()) {
133        bitmap.setConfig((SkBitmap::Config)R(SkBitmap::kConfigCount), kBitmapSize, kBitmapSize);
134    }
135    SkBitmapDevice device(bitmap);
136    SkCanvas canvas(&device);
137    canvas.clear(0x00000000);
138    SkPaint darkPaint;
139    darkPaint.setColor(0xFF804020);
140    SkPaint lightPaint;
141    lightPaint.setColor(0xFF244484);
142    const int i = kBitmapSize / 8;
143    const SkScalar f = SkIntToScalar(i);
144    for (int y = 0; y < kBitmapSize; y += i) {
145        for (int x = 0; x < kBitmapSize; x += i) {
146            canvas.save();
147            canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
148            canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint);
149            canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint);
150            canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint);
151            canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint);
152            canvas.restore();
153        }
154    }
155}
156
157static const SkBitmap& make_bitmap() {
158    static SkBitmap bitmap[2];
159    static bool initialized = false;
160    if (!initialized) {
161        make_g_bitmap(bitmap[0]);
162        make_checkerboard_bitmap(bitmap[1]);
163        initialized = true;
164    }
165    return bitmap[R(2)];
166}
167
168static SkImageFilter* make_image_filter(bool canBeNull = true) {
169    SkImageFilter* filter = 0;
170
171    // Add a 1 in 3 chance to get a NULL input
172    if (canBeNull && (R(3) == 1)) { return filter; }
173
174    enum { BICUBIC, MERGE, COLOR, BLUR, MAGNIFIER, XFERMODE, OFFSET, COMPOSE,
175           DISTANT_LIGHT, POINT_LIGHT, SPOT_LIGHT, NOISE, DROP_SHADOW,
176           MORPHOLOGY, BITMAP, DISPLACE, TILE, NUM_FILTERS };
177
178    switch (R(NUM_FILTERS)) {
179    case BICUBIC:
180        // Scale is set to 1 here so that it can fit in the DAG without resizing the output
181        filter = SkBicubicImageFilter::CreateMitchell(SkSize::Make(1, 1), make_image_filter());
182        break;
183    case MERGE:
184        filter = new SkMergeImageFilter(make_image_filter(), make_image_filter(), make_xfermode());
185        break;
186    case COLOR:
187    {
188        SkAutoTUnref<SkColorFilter> cf((R(2) == 1) ?
189                 SkColorFilter::CreateModeFilter(make_color(), make_xfermode()) :
190                 SkColorFilter::CreateLightingFilter(make_color(), make_color()));
191        filter = cf.get() ? SkColorFilterImageFilter::Create(cf, make_image_filter()) : 0;
192    }
193        break;
194    case BLUR:
195        filter = new SkBlurImageFilter(make_scalar(true), make_scalar(true), make_image_filter());
196        break;
197    case MAGNIFIER:
198        filter = new SkMagnifierImageFilter(make_rect(), make_scalar(true));
199        break;
200    case XFERMODE:
201    {
202        SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(make_xfermode()));
203        filter = new SkXfermodeImageFilter(mode, make_image_filter(), make_image_filter());
204    }
205        break;
206    case OFFSET:
207        filter = new SkOffsetImageFilter(make_scalar(), make_scalar(), make_image_filter());
208        break;
209    case COMPOSE:
210        filter = new SkComposeImageFilter(make_image_filter(), make_image_filter());
211        break;
212    case DISTANT_LIGHT:
213        filter = (R(2) == 1) ?
214                 SkLightingImageFilter::CreateDistantLitDiffuse(make_point(),
215                 make_color(), make_scalar(), make_scalar(), make_image_filter()) :
216                 SkLightingImageFilter::CreateDistantLitSpecular(make_point(),
217                 make_color(), make_scalar(), make_scalar(), SkIntToScalar(R(10)),
218                 make_image_filter());
219        break;
220    case POINT_LIGHT:
221        filter = (R(2) == 1) ?
222                 SkLightingImageFilter::CreatePointLitDiffuse(make_point(),
223                 make_color(), make_scalar(), make_scalar(), make_image_filter()) :
224                 SkLightingImageFilter::CreatePointLitSpecular(make_point(),
225                 make_color(), make_scalar(), make_scalar(), SkIntToScalar(R(10)),
226                 make_image_filter());
227        break;
228    case SPOT_LIGHT:
229        filter = (R(2) == 1) ?
230                 SkLightingImageFilter::CreateSpotLitDiffuse(SkPoint3(0, 0, 0),
231                 make_point(), make_scalar(), make_scalar(), make_color(),
232                 make_scalar(), make_scalar(), make_image_filter()) :
233                 SkLightingImageFilter::CreateSpotLitSpecular(SkPoint3(0, 0, 0),
234                 make_point(), make_scalar(), make_scalar(), make_color(),
235                 make_scalar(), make_scalar(), SkIntToScalar(R(10)), make_image_filter());
236        break;
237    case NOISE:
238    {
239        SkAutoTUnref<SkShader> shader((R(2) == 1) ?
240            SkPerlinNoiseShader::CreateFractalNoise(
241                make_scalar(true), make_scalar(true), R(10.0f), make_scalar()) :
242            SkPerlinNoiseShader::CreateTubulence(
243                make_scalar(true), make_scalar(true), R(10.0f), make_scalar()));
244        SkImageFilter::CropRect cropR(SkRect::MakeWH(SkIntToScalar(kBitmapSize),
245                                                     SkIntToScalar(kBitmapSize)));
246        filter = SkRectShaderImageFilter::Create(shader, &cropR);
247    }
248        break;
249    case DROP_SHADOW:
250        filter = new SkDropShadowImageFilter(make_scalar(), make_scalar(),
251                     make_scalar(true), make_color(), make_image_filter());
252        break;
253    case MORPHOLOGY:
254        if (R(2) == 1)
255            filter = new SkDilateImageFilter(R(static_cast<float>(kBitmapSize)),
256                R(static_cast<float>(kBitmapSize)), make_image_filter());
257        else
258            filter = new SkErodeImageFilter(R(static_cast<float>(kBitmapSize)),
259                R(static_cast<float>(kBitmapSize)), make_image_filter());
260        break;
261    case BITMAP:
262        filter = new SkBitmapSource(make_bitmap());
263        break;
264    case DISPLACE:
265        filter = new SkDisplacementMapEffect(make_channel_selector_type(),
266                     make_channel_selector_type(), make_scalar(),
267                     make_image_filter(false), make_image_filter());
268        break;
269    case TILE:
270        filter = new SkTileImageFilter(make_rect(), make_rect(), make_image_filter(false));
271        break;
272    default:
273        break;
274    }
275    return (filter || canBeNull) ? filter : make_image_filter(canBeNull);
276}
277
278static SkImageFilter* make_serialized_image_filter() {
279    SkAutoTUnref<SkImageFilter> filter(make_image_filter(false));
280    SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(filter));
281    const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
282    size_t len = data->size();
283#ifdef SK_ADD_RANDOM_BIT_FLIPS
284    unsigned char* p = const_cast<unsigned char*>(ptr);
285    for (size_t i = 0; i < len; ++i, ++p) {
286        if (R(250) == 1) { // 0.4% of the time, flip a bit or byte
287            if (R(10) == 1) { // Then 10% of the time, change a whole byte
288                switch(R(3)) {
289                case 0:
290                    *p ^= 0xFF; // Flip entire byte
291                    break;
292                case 1:
293                    *p = 0xFF; // Set all bits to 1
294                    break;
295                case 2:
296                    *p = 0x00; // Set all bits to 0
297                    break;
298                }
299            } else {
300                *p ^= (1 << R(8));
301            }
302        }
303    }
304#endif // SK_ADD_RANDOM_BIT_FLIPS
305    SkFlattenable* flattenable = SkValidatingDeserializeFlattenable(ptr, len,
306                                    SkImageFilter::GetFlattenableType());
307    return static_cast<SkImageFilter*>(flattenable);
308}
309
310static void drawClippedBitmap(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
311    canvas->save();
312    canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
313        SkIntToScalar(kBitmapSize), SkIntToScalar(kBitmapSize)));
314    canvas->drawBitmap(make_bitmap(), SkIntToScalar(x), SkIntToScalar(y), &paint);
315    canvas->restore();
316}
317
318static void do_fuzz(SkCanvas* canvas) {
319    SkImageFilter* filter = make_serialized_image_filter();
320
321#ifdef SK_FUZZER_IS_VERBOSE
322    static uint32_t numFilters = 0;
323    static uint32_t numValidFilters = 0;
324    if (0 == numFilters) {
325        printf("Fuzzing with %u\n", kSeed);
326    }
327    numFilters++;
328    if (NULL != filter) {
329        numValidFilters++;
330    }
331    printf("Filter no : %u. Valid filters so far : %u\r", numFilters, numValidFilters);
332    fflush(stdout);
333#endif
334
335    SkPaint paint;
336    SkSafeUnref(paint.setImageFilter(filter));
337    drawClippedBitmap(canvas, 0, 0, paint);
338}
339
340//////////////////////////////////////////////////////////////////////////////
341
342class ImageFilterFuzzView : public SampleView {
343public:
344    ImageFilterFuzzView() {
345        this->setBGColor(0xFFDDDDDD);
346    }
347
348protected:
349    // overrides from SkEventSink
350    virtual bool onQuery(SkEvent* evt) {
351        if (SampleCode::TitleQ(*evt)) {
352            SampleCode::TitleR(evt, "ImageFilterFuzzer");
353            return true;
354        }
355        return this->INHERITED::onQuery(evt);
356    }
357
358    void drawBG(SkCanvas* canvas) {
359        canvas->drawColor(0xFFDDDDDD);
360    }
361
362    virtual void onDrawContent(SkCanvas* canvas) {
363        do_fuzz(canvas);
364        this->inval(0);
365    }
366
367private:
368    typedef SkView INHERITED;
369};
370
371//////////////////////////////////////////////////////////////////////////////
372
373static SkView* MyFactory() { return new ImageFilterFuzzView; }
374static SkViewRegister reg(MyFactory);
375