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