Home | History | Annotate | Download | only in samplecode
      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 "Sk1DPathEffect.h"
      9 #include "Sk2DPathEffect.h"
     10 #include "SkAlphaThresholdFilter.h"
     11 #include "SkBlurImageFilter.h"
     12 #include "SkBlurMaskFilter.h"
     13 #include "SkCanvas.h"
     14 #include "SkColorFilter.h"
     15 #include "SkColorFilterImageFilter.h"
     16 #include "SkColorMatrixFilter.h"
     17 #include "SkComposeImageFilter.h"
     18 #include "SkCornerPathEffect.h"
     19 #include "SkDashPathEffect.h"
     20 #include "SkData.h"
     21 #include "SkDiscretePathEffect.h"
     22 #include "SkDisplacementMapEffect.h"
     23 #include "SkDropShadowImageFilter.h"
     24 #include "SkEmbossMaskFilter.h"
     25 #include "SkImageSource.h"
     26 #include "SkLightingImageFilter.h"
     27 #include "SkLumaColorFilter.h"
     28 #include "SkMagnifierImageFilter.h"
     29 #include "SkMatrixConvolutionImageFilter.h"
     30 #include "SkMergeImageFilter.h"
     31 #include "SkMorphologyImageFilter.h"
     32 #include "SkOffsetImageFilter.h"
     33 #include "SkPaintImageFilter.h"
     34 #include "SkPerlinNoiseShader.h"
     35 #include "SkPictureImageFilter.h"
     36 #include "SkPictureRecorder.h"
     37 #include "SkPoint3.h"
     38 #include "SkRandom.h"
     39 #include "SkRegion.h"
     40 #include "SkTableColorFilter.h"
     41 #include "SkTileImageFilter.h"
     42 #include "SkTypeface.h"
     43 #include "SkView.h"
     44 #include "SkXfermodeImageFilter.h"
     45 #include <stdio.h>
     46 #include <time.h>
     47 
     48 //#define SK_ADD_RANDOM_BIT_FLIPS
     49 //#define SK_FUZZER_IS_VERBOSE
     50 
     51 static const uint32_t kSeed = (uint32_t)(time(nullptr));
     52 static SkRandom gRand(kSeed);
     53 static bool return_large = false;
     54 static bool return_undef = false;
     55 
     56 static const int kBitmapSize = 24;
     57 
     58 static int R(float x) {
     59     return (int)floor(SkScalarToFloat(gRand.nextUScalar1()) * x);
     60 }
     61 
     62 #if defined _WIN32
     63 #pragma warning ( push )
     64 // we are intentionally causing an overflow here
     65 //      (warning C4756: overflow in constant arithmetic)
     66 #pragma warning ( disable : 4756 )
     67 #endif
     68 
     69 static float huge() {
     70     double d = 1e100;
     71     float f = (float)d;
     72     return f;
     73 }
     74 
     75 #if defined _WIN32
     76 #pragma warning ( pop )
     77 #endif
     78 
     79 static float make_number(bool positiveOnly) {
     80     float f = positiveOnly ? 1.0f : 0.0f;
     81     float v = f;
     82     int sel;
     83 
     84     if (return_large) sel = R(6); else sel = R(4);
     85     if (!return_undef && sel == 0) sel = 1;
     86 
     87     if (R(2) == 1) v = (float)(R(100)+f); else
     88 
     89     switch (sel) {
     90         case 0: break;
     91         case 1: v = f; break;
     92         case 2: v = 0.000001f; break;
     93         case 3: v = 10000.0f; break;
     94         case 4: v = 2000000000.0f; break;
     95         case 5: v = huge(); break;
     96     }
     97 
     98     if (!positiveOnly && (R(4) == 1)) v = -v;
     99     return v;
    100 }
    101 
    102 static SkScalar make_scalar(bool positiveOnly = false) {
    103     return make_number(positiveOnly);
    104 }
    105 
    106 static SkString make_string() {
    107     int length = R(1000);
    108     SkString str(length);
    109     for (int i = 0; i < length; ++i) {
    110         str[i] = static_cast<char>(R(256));
    111     }
    112     return str;
    113 }
    114 
    115 static SkString make_font_name() {
    116     int sel = R(8);
    117 
    118     switch(sel) {
    119         case 0: return SkString("Courier New");
    120         case 1: return SkString("Helvetica");
    121         case 2: return SkString("monospace");
    122         case 3: return SkString("sans-serif");
    123         case 4: return SkString("serif");
    124         case 5: return SkString("Times");
    125         case 6: return SkString("Times New Roman");
    126         case 7:
    127         default:
    128             return make_string();
    129     }
    130 }
    131 
    132 static bool make_bool() {
    133     return R(2) == 1;
    134 }
    135 
    136 static SkRect make_rect() {
    137     return SkRect::MakeWH(SkIntToScalar(R(static_cast<float>(kBitmapSize))),
    138                           SkIntToScalar(R(static_cast<float>(kBitmapSize))));
    139 }
    140 
    141 static SkRegion make_region() {
    142     SkIRect iRegion = SkIRect::MakeXYWH(R(static_cast<float>(kBitmapSize)),
    143                                         R(static_cast<float>(kBitmapSize)),
    144                                         R(static_cast<float>(kBitmapSize)),
    145                                         R(static_cast<float>(kBitmapSize)));
    146     return SkRegion(iRegion);
    147 }
    148 
    149 static SkMatrix make_matrix() {
    150     SkMatrix m;
    151     for (int i = 0; i < 9; ++i) {
    152         m[i] = make_scalar();
    153     }
    154     return m;
    155 }
    156 
    157 static SkBlendMode make_xfermode() {
    158     return static_cast<SkBlendMode>(R((int)SkBlendMode::kLastMode+1));
    159 }
    160 
    161 static SkPaint::Align make_paint_align() {
    162     return static_cast<SkPaint::Align>(R(SkPaint::kRight_Align+1));
    163 }
    164 
    165 static SkPaint::Hinting make_paint_hinting() {
    166     return static_cast<SkPaint::Hinting>(R(SkPaint::kFull_Hinting+1));
    167 }
    168 
    169 static SkPaint::Style make_paint_style() {
    170     return static_cast<SkPaint::Style>(R(SkPaint::kStrokeAndFill_Style+1));
    171 }
    172 
    173 static SkPaint::Cap make_paint_cap() {
    174     return static_cast<SkPaint::Cap>(R(SkPaint::kDefault_Cap+1));
    175 }
    176 
    177 static SkPaint::Join make_paint_join() {
    178     return static_cast<SkPaint::Join>(R(SkPaint::kDefault_Join+1));
    179 }
    180 
    181 static SkPaint::TextEncoding make_paint_text_encoding() {
    182     return static_cast<SkPaint::TextEncoding>(R(SkPaint::kGlyphID_TextEncoding+1));
    183 }
    184 
    185 static SkBlurStyle make_blur_style() {
    186     return static_cast<SkBlurStyle>(R(kLastEnum_SkBlurStyle+1));
    187 }
    188 
    189 static SkBlurMaskFilter::BlurFlags make_blur_mask_filter_flag() {
    190     return static_cast<SkBlurMaskFilter::BlurFlags>(R(SkBlurMaskFilter::kAll_BlurFlag+1));
    191 }
    192 
    193 static SkFilterQuality make_filter_quality() {
    194     return static_cast<SkFilterQuality>(R(kHigh_SkFilterQuality+1));
    195 }
    196 
    197 static SkFontStyle make_typeface_style() {
    198     return SkFontStyle::Normal();
    199 }
    200 
    201 static SkPath1DPathEffect::Style make_path_1d_path_effect_style() {
    202     return static_cast<SkPath1DPathEffect::Style>(R((int)SkPath1DPathEffect::kLastEnum_Style + 1));
    203 }
    204 
    205 static SkColor make_color() {
    206     return (R(2) == 1) ? 0xFFC0F0A0 : 0xFF000090;
    207 }
    208 
    209 static SkDropShadowImageFilter::ShadowMode make_shadow_mode() {
    210     return (R(2) == 1) ? SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode :
    211                          SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode;
    212 }
    213 
    214 static SkPoint3 make_point() {
    215     return SkPoint3::Make(make_scalar(), make_scalar(), make_scalar(true));
    216 }
    217 
    218 static SkDisplacementMapEffect::ChannelSelectorType make_channel_selector_type() {
    219     return static_cast<SkDisplacementMapEffect::ChannelSelectorType>(R(4)+1);
    220 }
    221 
    222 static bool valid_for_raster_canvas(const SkImageInfo& info) {
    223     switch (info.colorType()) {
    224         case kAlpha_8_SkColorType:
    225         case kRGB_565_SkColorType:
    226             return true;
    227         case kN32_SkColorType:
    228             return kPremul_SkAlphaType == info.alphaType() ||
    229                    kOpaque_SkAlphaType == info.alphaType();
    230         default:
    231             break;
    232     }
    233     return false;
    234 }
    235 
    236 static SkColorType rand_colortype() {
    237     return (SkColorType)R(kLastEnum_SkColorType + 1);
    238 }
    239 
    240 static void rand_bitmap_for_canvas(SkBitmap* bitmap) {
    241     SkImageInfo info;
    242     do {
    243         info = SkImageInfo::Make(kBitmapSize, kBitmapSize, rand_colortype(),
    244                                  kPremul_SkAlphaType);
    245     } while (!valid_for_raster_canvas(info) || !bitmap->tryAllocPixels(info));
    246 }
    247 
    248 static void make_g_bitmap(SkBitmap& bitmap) {
    249     rand_bitmap_for_canvas(&bitmap);
    250 
    251     SkCanvas canvas(bitmap);
    252     canvas.clear(0x00000000);
    253     SkPaint paint;
    254     paint.setAntiAlias(true);
    255     paint.setColor(0xFF884422);
    256     paint.setTextSize(SkIntToScalar(kBitmapSize/2));
    257     const char* str = "g";
    258     canvas.drawString(str, SkIntToScalar(kBitmapSize/8),
    259                     SkIntToScalar(kBitmapSize/4), paint);
    260 }
    261 
    262 static void make_checkerboard_bitmap(SkBitmap& bitmap) {
    263     rand_bitmap_for_canvas(&bitmap);
    264 
    265     SkCanvas canvas(bitmap);
    266     canvas.clear(0x00000000);
    267     SkPaint darkPaint;
    268     darkPaint.setColor(0xFF804020);
    269     SkPaint lightPaint;
    270     lightPaint.setColor(0xFF244484);
    271     const int i = kBitmapSize / 8;
    272     const SkScalar f = SkIntToScalar(i);
    273     for (int y = 0; y < kBitmapSize; y += i) {
    274         for (int x = 0; x < kBitmapSize; x += i) {
    275             canvas.save();
    276             canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
    277             canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint);
    278             canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint);
    279             canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint);
    280             canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint);
    281             canvas.restore();
    282         }
    283     }
    284 }
    285 
    286 static const SkBitmap& make_bitmap() {
    287     static SkBitmap bitmap[2];
    288     static bool initialized = false;
    289     if (!initialized) {
    290         make_g_bitmap(bitmap[0]);
    291         make_checkerboard_bitmap(bitmap[1]);
    292         initialized = true;
    293     }
    294     return bitmap[R(2)];
    295 }
    296 
    297 static sk_sp<SkData> make_3Dlut(int* cubeDimension, bool invR, bool invG, bool invB) {
    298     int size = 4 << R(5);
    299     auto data = SkData::MakeUninitialized(sizeof(SkColor) * size * size * size);
    300     SkColor* pixels = (SkColor*)(data->writable_data());
    301     SkAutoTMalloc<uint8_t> lutMemory(size);
    302     SkAutoTMalloc<uint8_t> invLutMemory(size);
    303     uint8_t* lut = lutMemory.get();
    304     uint8_t* invLut = invLutMemory.get();
    305     const int maxIndex = size - 1;
    306     for (int i = 0; i < size; i++) {
    307         lut[i] = (i * 255) / maxIndex;
    308         invLut[i] = ((maxIndex - i) * 255) / maxIndex;
    309     }
    310     for (int r = 0; r < size; ++r) {
    311         for (int g = 0; g < size; ++g) {
    312             for (int b = 0; b < size; ++b) {
    313                 pixels[(size * ((size * b) + g)) + r] = SkColorSetARGB(0xFF,
    314                         invR ? invLut[r] : lut[r],
    315                         invG ? invLut[g] : lut[g],
    316                         invB ? invLut[b] : lut[b]);
    317             }
    318         }
    319     }
    320     if (cubeDimension) {
    321         *cubeDimension = size;
    322     }
    323     return data;
    324 }
    325 
    326 static void drawSomething(SkCanvas* canvas) {
    327     SkPaint paint;
    328 
    329     canvas->save();
    330     canvas->scale(0.5f, 0.5f);
    331     canvas->drawBitmap(make_bitmap(), 0, 0, nullptr);
    332     canvas->restore();
    333 
    334     paint.setAntiAlias(true);
    335 
    336     paint.setColor(SK_ColorRED);
    337     canvas->drawCircle(SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/3), paint);
    338     paint.setColor(SK_ColorBLACK);
    339     paint.setTextSize(SkIntToScalar(kBitmapSize/3));
    340     canvas->drawString("Picture", SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), paint);
    341 }
    342 
    343 static void rand_color_table(uint8_t* table) {
    344     for (int i = 0; i < 256; ++i) {
    345         table[i] = R(256);
    346     }
    347 }
    348 
    349 static sk_sp<SkColorFilter> make_color_filter() {
    350     switch (R(6)) {
    351         case 0: {
    352             SkScalar array[20];
    353             for (int i = 0; i < 20; ++i) {
    354                 array[i] = make_scalar();
    355             }
    356             return SkColorFilter::MakeMatrixFilterRowMajor255(array);
    357         }
    358         case 1:
    359             return SkLumaColorFilter::Make();
    360         case 2: {
    361             uint8_t tableA[256];
    362             uint8_t tableR[256];
    363             uint8_t tableG[256];
    364             uint8_t tableB[256];
    365             rand_color_table(tableA);
    366             rand_color_table(tableR);
    367             rand_color_table(tableG);
    368             rand_color_table(tableB);
    369             return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
    370         }
    371         case 3:
    372             return SkColorFilter::MakeModeFilter(make_color(), make_xfermode());
    373         case 4:
    374             return SkColorMatrixFilter::MakeLightingFilter(make_color(), make_color());
    375         case 5:
    376         default:
    377             break;
    378     }
    379     return nullptr;
    380 }
    381 
    382 static SkPath make_path() {
    383     SkPath path;
    384     int numOps = R(30);
    385     for (int i = 0; i < numOps; ++i) {
    386         switch (R(6)) {
    387             case 0:
    388                 path.moveTo(make_scalar(), make_scalar());
    389                 break;
    390             case 1:
    391                 path.lineTo(make_scalar(), make_scalar());
    392                 break;
    393             case 2:
    394                 path.quadTo(make_scalar(), make_scalar(), make_scalar(), make_scalar());
    395                 break;
    396             case 3:
    397                 path.conicTo(make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar());
    398                 break;
    399             case 4:
    400                 path.cubicTo(make_scalar(), make_scalar(), make_scalar(),
    401                              make_scalar(), make_scalar(), make_scalar());
    402                 break;
    403             case 5:
    404             default:
    405                 path.arcTo(make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar());
    406                 break;
    407 
    408         }
    409     }
    410     path.close();
    411     return path;
    412 }
    413 
    414 static sk_sp<SkPathEffect> make_path_effect(bool canBeNull = true) {
    415     sk_sp<SkPathEffect> pathEffect;
    416     if (canBeNull && (R(3) == 1)) { return pathEffect; }
    417 
    418     switch (R(8)) {
    419         case 0:
    420             pathEffect = SkPath2DPathEffect::Make(make_matrix(), make_path());
    421             break;
    422         case 1:
    423             pathEffect = SkPathEffect::MakeCompose(make_path_effect(false),
    424                                                    make_path_effect(false));
    425             break;
    426         case 2:
    427             pathEffect = SkCornerPathEffect::Make(make_scalar());
    428             break;
    429         case 3: {
    430             int count = R(10);
    431             SkScalar intervals[10];
    432             for (int i = 0; i < count; ++i) {
    433                 intervals[i] = make_scalar();
    434             }
    435             pathEffect = SkDashPathEffect::Make(intervals, count, make_scalar());
    436             break;
    437         }
    438         case 4:
    439             pathEffect = SkDiscretePathEffect::Make(make_scalar(), make_scalar());
    440             break;
    441         case 5:
    442             pathEffect = SkPath1DPathEffect::Make(make_path(), make_scalar(), make_scalar(),
    443                                                   make_path_1d_path_effect_style());
    444             break;
    445         case 6:
    446             pathEffect = SkLine2DPathEffect::Make(make_scalar(), make_matrix());
    447             break;
    448         case 7:
    449         default:
    450             pathEffect = SkPathEffect::MakeSum(make_path_effect(false),
    451                                                make_path_effect(false));
    452             break;
    453     }
    454     return pathEffect;
    455 }
    456 
    457 static sk_sp<SkMaskFilter> make_mask_filter() {
    458     sk_sp<SkMaskFilter> maskFilter;
    459     switch (R(3)) {
    460         case 0:
    461             maskFilter = SkBlurMaskFilter::Make(make_blur_style(), make_scalar(),
    462                                                 make_blur_mask_filter_flag());
    463         case 1: {
    464             SkEmbossMaskFilter::Light light;
    465             for (int i = 0; i < 3; ++i) {
    466                 light.fDirection[i] = make_scalar();
    467             }
    468             light.fPad = R(65536);
    469             light.fAmbient = R(256);
    470             light.fSpecular = R(256);
    471             maskFilter = SkEmbossMaskFilter::Make(make_scalar(), light);
    472         }
    473         case 2:
    474         default:
    475             break;
    476     }
    477     return maskFilter;
    478 }
    479 
    480 static sk_sp<SkImageFilter> make_image_filter(bool canBeNull = true);
    481 
    482 static SkPaint make_paint() {
    483     SkPaint paint;
    484     paint.setHinting(make_paint_hinting());
    485     paint.setAntiAlias(make_bool());
    486     paint.setDither(make_bool());
    487     paint.setLinearText(make_bool());
    488     paint.setSubpixelText(make_bool());
    489     paint.setLCDRenderText(make_bool());
    490     paint.setEmbeddedBitmapText(make_bool());
    491     paint.setAutohinted(make_bool());
    492     paint.setVerticalText(make_bool());
    493     paint.setFakeBoldText(make_bool());
    494     paint.setDevKernText(make_bool());
    495     paint.setFilterQuality(make_filter_quality());
    496     paint.setStyle(make_paint_style());
    497     paint.setColor(make_color());
    498     paint.setStrokeWidth(make_scalar());
    499     paint.setStrokeMiter(make_scalar());
    500     paint.setStrokeCap(make_paint_cap());
    501     paint.setStrokeJoin(make_paint_join());
    502     paint.setColorFilter(make_color_filter());
    503     paint.setBlendMode(make_xfermode());
    504     paint.setPathEffect(make_path_effect());
    505     paint.setMaskFilter(make_mask_filter());
    506 
    507     if (false) {
    508         // our validating buffer does not support typefaces yet, so skip this for now
    509         paint.setTypeface(SkTypeface::MakeFromName(make_font_name().c_str(),
    510                                                    make_typeface_style()));
    511     }
    512 
    513     paint.setImageFilter(make_image_filter());
    514     sk_sp<SkData> data(make_3Dlut(nullptr, make_bool(), make_bool(), make_bool()));
    515     paint.setTextAlign(make_paint_align());
    516     paint.setTextSize(make_scalar());
    517     paint.setTextScaleX(make_scalar());
    518     paint.setTextSkewX(make_scalar());
    519     paint.setTextEncoding(make_paint_text_encoding());
    520     return paint;
    521 }
    522 
    523 static sk_sp<SkImageFilter> make_image_filter(bool canBeNull) {
    524     sk_sp<SkImageFilter> filter;
    525 
    526     // Add a 1 in 3 chance to get a nullptr input
    527     if (canBeNull && (R(3) == 1)) {
    528         return filter;
    529     }
    530 
    531     enum { ALPHA_THRESHOLD, MERGE, COLOR, BLUR, MAGNIFIER,
    532            XFERMODE, OFFSET, MATRIX, MATRIX_CONVOLUTION, COMPOSE,
    533            DISTANT_LIGHT, POINT_LIGHT, SPOT_LIGHT, NOISE, DROP_SHADOW,
    534            MORPHOLOGY, BITMAP, DISPLACE, TILE, PICTURE, PAINT, NUM_FILTERS };
    535 
    536     switch (R(NUM_FILTERS)) {
    537     case ALPHA_THRESHOLD:
    538         filter = SkAlphaThresholdFilter::Make(make_region(),
    539                                               make_scalar(),
    540                                               make_scalar(),
    541                                               make_image_filter());
    542         break;
    543     case MERGE:
    544         filter = SkMergeImageFilter::Make(make_image_filter(),
    545                                           make_image_filter());
    546         break;
    547     case COLOR: {
    548         sk_sp<SkColorFilter> cf(make_color_filter());
    549         filter = cf ? SkColorFilterImageFilter::Make(std::move(cf), make_image_filter())
    550                     : nullptr;
    551         break;
    552     }
    553     case BLUR:
    554         filter = SkBlurImageFilter::Make(make_scalar(true),
    555                                          make_scalar(true),
    556                                          make_image_filter());
    557         break;
    558     case MAGNIFIER:
    559         filter = SkMagnifierImageFilter::Make(make_rect(),
    560                                               make_scalar(true),
    561                                               make_image_filter());
    562         break;
    563     case XFERMODE:
    564         filter = SkXfermodeImageFilter::Make(make_xfermode(),
    565                                              make_image_filter(),
    566                                              make_image_filter(),
    567                                              nullptr);
    568         break;
    569     case OFFSET:
    570         filter = SkOffsetImageFilter::Make(make_scalar(), make_scalar(), make_image_filter());
    571         break;
    572     case MATRIX:
    573         filter = SkImageFilter::MakeMatrixFilter(make_matrix(),
    574                                                  (SkFilterQuality)R(4),
    575                                                  make_image_filter());
    576         break;
    577     case MATRIX_CONVOLUTION: {
    578         SkImageFilter::CropRect cropR(SkRect::MakeWH(SkIntToScalar(kBitmapSize),
    579                                                      SkIntToScalar(kBitmapSize)));
    580         SkISize size = SkISize::Make(R(10)+1, R(10)+1);
    581         int arraySize = size.width() * size.height();
    582         SkTArray<SkScalar> kernel(arraySize);
    583         for (int i = 0; i < arraySize; ++i) {
    584             kernel.push_back() = make_scalar();
    585         }
    586         SkIPoint kernelOffset = SkIPoint::Make(R(SkIntToScalar(size.width())),
    587                                                R(SkIntToScalar(size.height())));
    588 
    589         filter = SkMatrixConvolutionImageFilter::Make(size,
    590                                                       kernel.begin(),
    591                                                       make_scalar(),
    592                                                       make_scalar(),
    593                                                       kernelOffset,
    594                                                       (SkMatrixConvolutionImageFilter::TileMode)R(3),
    595                                                       R(2) == 1,
    596                                                       make_image_filter(),
    597                                                       &cropR);
    598         break;
    599     }
    600     case COMPOSE:
    601         filter = SkComposeImageFilter::Make(make_image_filter(), make_image_filter());
    602         break;
    603     case DISTANT_LIGHT:
    604         filter = (R(2) == 1)
    605                  ? SkLightingImageFilter::MakeDistantLitDiffuse(make_point(), make_color(),
    606                                                                 make_scalar(), make_scalar(),
    607                                                                 make_image_filter())
    608                  : SkLightingImageFilter::MakeDistantLitSpecular(make_point(), make_color(),
    609                                                                  make_scalar(), make_scalar(),
    610                                                                  SkIntToScalar(R(10)),
    611                                                                  make_image_filter());
    612         break;
    613     case POINT_LIGHT:
    614         filter = (R(2) == 1)
    615                  ? SkLightingImageFilter::MakePointLitDiffuse(make_point(), make_color(),
    616                                                               make_scalar(), make_scalar(),
    617                                                               make_image_filter())
    618                  : SkLightingImageFilter::MakePointLitSpecular(make_point(), make_color(),
    619                                                                make_scalar(), make_scalar(),
    620                                                                SkIntToScalar(R(10)),
    621                                                                make_image_filter());
    622         break;
    623     case SPOT_LIGHT:
    624         filter = (R(2) == 1)
    625                  ? SkLightingImageFilter::MakeSpotLitDiffuse(SkPoint3::Make(0, 0, 0),
    626                                                              make_point(), make_scalar(),
    627                                                              make_scalar(), make_color(),
    628                                                              make_scalar(), make_scalar(),
    629                                                              make_image_filter())
    630                  : SkLightingImageFilter::MakeSpotLitSpecular(SkPoint3::Make(0, 0, 0),
    631                                                               make_point(), make_scalar(),
    632                                                               make_scalar(), make_color(),
    633                                                               make_scalar(), make_scalar(),
    634                                                               SkIntToScalar(R(10)),
    635                                                               make_image_filter());
    636         break;
    637     case NOISE: {
    638         sk_sp<SkShader> shader((R(2) == 1)
    639                 ? SkPerlinNoiseShader::MakeFractalNoise(make_scalar(true), make_scalar(true),
    640                                                         R(10.0f), make_scalar())
    641                 : SkPerlinNoiseShader::MakeTurbulence(make_scalar(true), make_scalar(true),
    642                                                       R(10.0f), make_scalar()));
    643         SkPaint paint;
    644         paint.setShader(shader);
    645         SkImageFilter::CropRect cropR(SkRect::MakeWH(SkIntToScalar(kBitmapSize),
    646                                                      SkIntToScalar(kBitmapSize)));
    647         filter = SkPaintImageFilter::Make(paint, &cropR);
    648         break;
    649     }
    650     case DROP_SHADOW:
    651         filter = SkDropShadowImageFilter::Make(make_scalar(),
    652                                                make_scalar(),
    653                                                make_scalar(true),
    654                                                make_scalar(true),
    655                                                make_color(),
    656                                                make_shadow_mode(),
    657                                                make_image_filter(),
    658                                                nullptr);
    659         break;
    660     case MORPHOLOGY:
    661         if (R(2) == 1) {
    662             filter = SkDilateImageFilter::Make(R(static_cast<float>(kBitmapSize)),
    663                                                R(static_cast<float>(kBitmapSize)),
    664                                                make_image_filter());
    665         } else {
    666             filter = SkErodeImageFilter::Make(R(static_cast<float>(kBitmapSize)),
    667                                               R(static_cast<float>(kBitmapSize)),
    668                                               make_image_filter());
    669         }
    670         break;
    671     case BITMAP: {
    672         sk_sp<SkImage> image(SkImage::MakeFromBitmap(make_bitmap()));
    673         if (R(2) == 1) {
    674             filter = SkImageSource::Make(std::move(image),
    675                                          make_rect(),
    676                                          make_rect(),
    677                                          kHigh_SkFilterQuality);
    678         } else {
    679             filter = SkImageSource::Make(std::move(image));
    680         }
    681         break;
    682     }
    683     case DISPLACE:
    684         filter = SkDisplacementMapEffect::Make(make_channel_selector_type(),
    685                                                make_channel_selector_type(),
    686                                                make_scalar(),
    687                                                make_image_filter(false),
    688                                                make_image_filter());
    689         break;
    690     case TILE:
    691         filter = SkTileImageFilter::Make(make_rect(), make_rect(), make_image_filter(false));
    692         break;
    693     case PICTURE: {
    694         SkRTreeFactory factory;
    695         SkPictureRecorder recorder;
    696         SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(kBitmapSize),
    697                                                             SkIntToScalar(kBitmapSize),
    698                                                             &factory, 0);
    699         drawSomething(recordingCanvas);
    700         sk_sp<SkPicture> pict(recorder.finishRecordingAsPicture());
    701         filter = SkPictureImageFilter::Make(pict, make_rect());
    702         break;
    703     }
    704     case PAINT: {
    705         SkImageFilter::CropRect cropR(make_rect());
    706         filter = SkPaintImageFilter::Make(make_paint(), &cropR);
    707         break;
    708     }
    709     default:
    710         break;
    711     }
    712     return (filter || canBeNull) ? filter : make_image_filter(canBeNull);
    713 }
    714 
    715 static sk_sp<SkImageFilter> make_serialized_image_filter() {
    716     sk_sp<SkImageFilter> filter(make_image_filter(false));
    717     sk_sp<SkData> data(filter->serialize());
    718     const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
    719     size_t len = data->size();
    720 #ifdef SK_ADD_RANDOM_BIT_FLIPS
    721     unsigned char* p = const_cast<unsigned char*>(ptr);
    722     for (size_t i = 0; i < len; ++i, ++p) {
    723         if (R(250) == 1) { // 0.4% of the time, flip a bit or byte
    724             if (R(10) == 1) { // Then 10% of the time, change a whole byte
    725                 switch(R(3)) {
    726                 case 0:
    727                     *p ^= 0xFF; // Flip entire byte
    728                     break;
    729                 case 1:
    730                     *p = 0xFF; // Set all bits to 1
    731                     break;
    732                 case 2:
    733                     *p = 0x00; // Set all bits to 0
    734                     break;
    735                 }
    736             } else {
    737                 *p ^= (1 << R(8));
    738             }
    739         }
    740     }
    741 #endif // SK_ADD_RANDOM_BIT_FLIPS
    742     return SkImageFilter::Deserialize(ptr, len);
    743 }
    744 
    745 static void drawClippedBitmap(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
    746     canvas->save();
    747     canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
    748         SkIntToScalar(kBitmapSize), SkIntToScalar(kBitmapSize)));
    749     canvas->drawBitmap(make_bitmap(), SkIntToScalar(x), SkIntToScalar(y), &paint);
    750     canvas->restore();
    751 }
    752 
    753 static void do_fuzz(SkCanvas* canvas) {
    754     sk_sp<SkImageFilter> filter = make_serialized_image_filter();
    755 
    756 #ifdef SK_FUZZER_IS_VERBOSE
    757     static uint32_t numFilters = 0;
    758     static uint32_t numValidFilters = 0;
    759     if (0 == numFilters) {
    760         printf("Fuzzing with %u\n", kSeed);
    761     }
    762     numFilters++;
    763     if (filter) {
    764         numValidFilters++;
    765     }
    766     printf("Filter no : %u. Valid filters so far : %u\r", numFilters, numValidFilters);
    767     fflush(stdout);
    768 #endif
    769 
    770     SkPaint paint;
    771     paint.setImageFilter(filter);
    772     drawClippedBitmap(canvas, 0, 0, paint);
    773 }
    774 
    775 //////////////////////////////////////////////////////////////////////////////
    776 
    777 class ImageFilterFuzzView : public SampleView {
    778 public:
    779     ImageFilterFuzzView() {
    780         this->setBGColor(0xFFDDDDDD);
    781     }
    782 
    783 protected:
    784     // overrides from SkEventSink
    785     virtual bool onQuery(SkEvent* evt) {
    786         if (SampleCode::TitleQ(*evt)) {
    787             SampleCode::TitleR(evt, "ImageFilterFuzzer");
    788             return true;
    789         }
    790         return this->INHERITED::onQuery(evt);
    791     }
    792 
    793     void drawBG(SkCanvas* canvas) {
    794         canvas->drawColor(0xFFDDDDDD);
    795     }
    796 
    797     virtual void onDrawContent(SkCanvas* canvas) {
    798         do_fuzz(canvas);
    799     }
    800 
    801 private:
    802     typedef SkView INHERITED;
    803 };
    804 
    805 //////////////////////////////////////////////////////////////////////////////
    806 
    807 static SkView* MyFactory() { return new ImageFilterFuzzView; }
    808 static SkViewRegister reg(MyFactory);
    809