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 "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 
     41 static const uint32_t kSeed = (uint32_t)(time(NULL));
     42 static SkRandom gRand(kSeed);
     43 static bool return_large = false;
     44 static bool return_undef = false;
     45 
     46 static const int kBitmapSize = 24;
     47 
     48 static 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 
     59 static 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 
     69 static 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 
     92 static SkScalar make_scalar(bool positiveOnly = false) {
     93     return make_number(positiveOnly);
     94 }
     95 
     96 static SkRect make_rect() {
     97     return SkRect::MakeWH(SkIntToScalar(R(static_cast<float>(kBitmapSize))),
     98                           SkIntToScalar(R(static_cast<float>(kBitmapSize))));
     99 }
    100 
    101 static 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 
    109 static 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 
    117 static SkXfermode::Mode make_xfermode() {
    118     return static_cast<SkXfermode::Mode>(R(SkXfermode::kLastMode+1));
    119 }
    120 
    121 static SkColor make_color() {
    122     return (R(2) == 1) ? 0xFFC0F0A0 : 0xFF000090;
    123 }
    124 
    125 static SkPoint3 make_point() {
    126     return SkPoint3(make_scalar(), make_scalar(), make_scalar(true));
    127 }
    128 
    129 static SkDisplacementMapEffect::ChannelSelectorType make_channel_selector_type() {
    130     return static_cast<SkDisplacementMapEffect::ChannelSelectorType>(R(4)+1);
    131 }
    132 
    133 static 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 
    147 static SkColorType rand_colortype() {
    148     return (SkColorType)R(kLastEnum_SkColorType + 1);
    149 }
    150 
    151 static 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 
    159 static 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 
    173 static 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 
    197 static 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 
    208 static 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 
    230 static 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 
    388 static 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 
    420 static 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 
    428 static 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 
    452 class ImageFilterFuzzView : public SampleView {
    453 public:
    454     ImageFilterFuzzView() {
    455         this->setBGColor(0xFFDDDDDD);
    456     }
    457 
    458 protected:
    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 
    477 private:
    478     typedef SkView INHERITED;
    479 };
    480 
    481 //////////////////////////////////////////////////////////////////////////////
    482 
    483 static SkView* MyFactory() { return new ImageFilterFuzzView; }
    484 static SkViewRegister reg(MyFactory);
    485