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
43static const uint32_t kSeed = (uint32_t)(time(NULL));
44static SkRandom gRand(kSeed);
45static bool return_large = false;
46static bool return_undef = false;
47
48static const int kBitmapSize = 24;
49
50static 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
61static 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
71static 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
94static SkScalar make_scalar(bool positiveOnly = false) {
95    return make_number(positiveOnly);
96}
97
98static SkRect make_rect() {
99    return SkRect::MakeWH(SkIntToScalar(R(static_cast<float>(kBitmapSize))),
100                          SkIntToScalar(R(static_cast<float>(kBitmapSize))));
101}
102
103static 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
111static 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
119static SkXfermode::Mode make_xfermode() {
120    return static_cast<SkXfermode::Mode>(R(SkXfermode::kLastMode+1));
121}
122
123static SkColor make_color() {
124    return (R(2) == 1) ? 0xFFC0F0A0 : 0xFF000090;
125}
126
127static SkPoint3 make_point() {
128    return SkPoint3(make_scalar(), make_scalar(), make_scalar(true));
129}
130
131static SkDisplacementMapEffect::ChannelSelectorType make_channel_selector_type() {
132    return static_cast<SkDisplacementMapEffect::ChannelSelectorType>(R(4)+1);
133}
134
135static 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
149static SkColorType rand_colortype() {
150    return (SkColorType)R(kLastEnum_SkColorType + 1);
151}
152
153static 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
161static 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
175static 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
199static 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
210static 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
232static 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
392static 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
424static 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
432static 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
456class ImageFilterFuzzView : public SampleView {
457public:
458    ImageFilterFuzzView() {
459        this->setBGColor(0xFFDDDDDD);
460    }
461
462protected:
463    // overrides from SkEventSink
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
472    void drawBG(SkCanvas* canvas) {
473        canvas->drawColor(0xFFDDDDDD);
474    }
475
476    virtual void onDrawContent(SkCanvas* canvas) {
477        do_fuzz(canvas);
478        this->inval(0);
479    }
480
481private:
482    typedef SkView INHERITED;
483};
484
485//////////////////////////////////////////////////////////////////////////////
486
487static SkView* MyFactory() { return new ImageFilterFuzzView; }
488static SkViewRegister reg(MyFactory);
489