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