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