Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2011 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 
      8 #include "gm.h"
      9 #include "SkCanvas.h"
     10 #include "SkColorFilterImageFilter.h"
     11 #include "SkGradientShader.h"
     12 #include "SkTableColorFilter.h"
     13 
     14 static SkShader* make_shader0(int w, int h) {
     15     SkPoint pts[] = { {0, 0}, {SkIntToScalar(w), SkIntToScalar(h)} };
     16     SkColor colors[] = {
     17         SK_ColorBLACK, SK_ColorGREEN, SK_ColorCYAN,
     18         SK_ColorRED, 0, SK_ColorBLUE, SK_ColorWHITE
     19     };
     20     return SkGradientShader::CreateLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
     21                                           SkShader::kClamp_TileMode);
     22 }
     23 static void make_bm0(SkBitmap* bm) {
     24     int W = 120;
     25     int H = 120;
     26     bm->allocN32Pixels(W, H);
     27     bm->eraseColor(SK_ColorTRANSPARENT);
     28 
     29     SkCanvas canvas(*bm);
     30     SkPaint paint;
     31     paint.setShader(make_shader0(W, H))->unref();
     32     canvas.drawPaint(paint);
     33 }
     34 static SkShader* make_shader1(int w, int h) {
     35     SkScalar cx = SkIntToScalar(w)/2;
     36     SkScalar cy = SkIntToScalar(h)/2;
     37     SkColor colors[] = {
     38         SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
     39     };
     40     return SkGradientShader::CreateRadial(SkPoint::Make(cx, cy), cx, colors, nullptr,
     41                                           SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode);
     42 }
     43 static void make_bm1(SkBitmap* bm) {
     44     int W = 120;
     45     int H = 120;
     46     SkScalar cx = SkIntToScalar(W)/2;
     47     SkScalar cy = SkIntToScalar(H)/2;
     48     bm->allocN32Pixels(W, H);
     49     bm->eraseColor(SK_ColorTRANSPARENT);
     50 
     51     SkCanvas canvas(*bm);
     52     SkPaint paint;
     53     paint.setShader(make_shader1(W, H))->unref();
     54     paint.setAntiAlias(true);
     55     canvas.drawCircle(cx, cy, cx, paint);
     56 }
     57 
     58 static void make_table0(uint8_t table[]) {
     59     for (int i = 0; i < 256; ++i) {
     60         int n = i >> 5;
     61         table[i] = (n << 5) | (n << 2) | (n >> 1);
     62     }
     63 }
     64 static void make_table1(uint8_t table[]) {
     65     for (int i = 0; i < 256; ++i) {
     66         table[i] = i * i / 255;
     67     }
     68 }
     69 static void make_table2(uint8_t table[]) {
     70     for (int i = 0; i < 256; ++i) {
     71         float fi = i / 255.0f;
     72         table[i] = static_cast<uint8_t>(sqrtf(fi) * 255);
     73     }
     74 }
     75 
     76 static SkColorFilter* make_null_cf() {
     77     return nullptr;
     78 }
     79 
     80 static SkColorFilter* make_cf0() {
     81     uint8_t table[256]; make_table0(table);
     82     return SkTableColorFilter::Create(table);
     83 }
     84 static SkColorFilter* make_cf1() {
     85     uint8_t table[256]; make_table1(table);
     86     return SkTableColorFilter::Create(table);
     87 }
     88 static SkColorFilter* make_cf2() {
     89     uint8_t table[256]; make_table2(table);
     90     return SkTableColorFilter::Create(table);
     91 }
     92 static SkColorFilter* make_cf3() {
     93     uint8_t table0[256]; make_table0(table0);
     94     uint8_t table1[256]; make_table1(table1);
     95     uint8_t table2[256]; make_table2(table2);
     96     return SkTableColorFilter::CreateARGB(nullptr, table0, table1, table2);
     97 }
     98 
     99 class TableColorFilterGM : public skiagm::GM {
    100 public:
    101     TableColorFilterGM() {}
    102 
    103 protected:
    104     virtual SkString onShortName() {
    105         return SkString("tablecolorfilter");
    106     }
    107 
    108     virtual SkISize onISize() {
    109         return SkISize::Make(700, 1650);
    110     }
    111 
    112     virtual void onDraw(SkCanvas* canvas) {
    113         canvas->drawColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
    114         canvas->translate(20, 20);
    115 
    116 
    117         static SkColorFilter* (*gColorFilterMakers[])() = { make_null_cf, make_cf0, make_cf1,
    118                                                  make_cf2, make_cf3 };
    119         static void (*gBitmapMakers[])(SkBitmap*) = { make_bm0, make_bm1 };
    120 
    121         // This test will be done once for each bitmap with the results stacked vertically.
    122         // For a single bitmap the resulting image will be the following:
    123         //  - A first line with the original bitmap, followed by the image drawn once
    124         //  with each of the N color filters
    125         //  - N lines of the bitmap drawn N times, this will cover all N*N combinations of
    126         //  pair of color filters in order to test the collpsing of consecutive table
    127         //  color filters.
    128         //
    129         //  Here is a graphical representation of the result for 2 bitmaps and 2 filters
    130         //  with the number corresponding to the number of filters the bitmap goes through:
    131         //
    132         //  --bitmap1
    133         //  011
    134         //  22
    135         //  22
    136         //  --bitmap2
    137         //  011
    138         //  22
    139         //  22
    140 
    141         SkScalar x = 0, y = 0;
    142         for (size_t bitmapMaker = 0; bitmapMaker < SK_ARRAY_COUNT(gBitmapMakers); ++bitmapMaker) {
    143             SkBitmap bm;
    144             gBitmapMakers[bitmapMaker](&bm);
    145 
    146             SkScalar xOffset = SkScalar(bm.width() * 9 / 8);
    147             SkScalar yOffset = SkScalar(bm.height() * 9 / 8);
    148 
    149             // Draw the first element of the first line
    150             x = 0;
    151             SkPaint paint;
    152             canvas->drawBitmap(bm, x, y, &paint);
    153 
    154             // Draws the rest of the first line for this bitmap
    155             // each draw being at xOffset of the previous one
    156             for (unsigned i = 1; i < SK_ARRAY_COUNT(gColorFilterMakers); ++i) {
    157                 x += xOffset;
    158                 paint.setColorFilter(gColorFilterMakers[i]())->unref();
    159                 canvas->drawBitmap(bm, x, y, &paint);
    160             }
    161 
    162             paint.setColorFilter(nullptr);
    163 
    164             for (unsigned i = 0; i < SK_ARRAY_COUNT(gColorFilterMakers); ++i) {
    165                 SkAutoTUnref<SkColorFilter> colorFilter1(gColorFilterMakers[i]());
    166                 SkAutoTUnref<SkImageFilter> imageFilter1(SkColorFilterImageFilter::Create(
    167                             colorFilter1, nullptr, nullptr));
    168 
    169                 // Move down to the next line and draw it
    170                 // each draw being at xOffset of the previous one
    171                 y += yOffset;
    172                 x = 0;
    173                 for (unsigned j = 1; j < SK_ARRAY_COUNT(gColorFilterMakers); ++j) {
    174                     SkAutoTUnref<SkColorFilter> colorFilter2(gColorFilterMakers[j]());
    175                     SkAutoTUnref<SkImageFilter> imageFilter2(SkColorFilterImageFilter::Create(
    176                                 colorFilter2, imageFilter1, nullptr));
    177                     paint.setImageFilter(imageFilter2);
    178                     canvas->drawBitmap(bm, x, y, &paint);
    179                     x += xOffset;
    180                 }
    181             }
    182 
    183             // Move down one line to the beginning of the block for next bitmap
    184             y += yOffset;
    185         }
    186     }
    187 
    188 private:
    189     typedef GM INHERITED;
    190 };
    191 DEF_GM( return new TableColorFilterGM; )
    192 
    193 //////////////////////////////////////////////////////////////////////////////
    194 
    195 class ComposeColorFilterGM : public skiagm::GM {
    196     enum {
    197         COLOR_COUNT = 3,
    198         MODE_COUNT = 4,
    199     };
    200     const SkColor*          fColors;
    201     const SkXfermode::Mode* fModes;
    202     SkString                fName;
    203 
    204 public:
    205     ComposeColorFilterGM(const SkColor colors[], const SkXfermode::Mode modes[],
    206                          const char suffix[])
    207         : fColors(colors), fModes(modes)
    208     {
    209         fName.printf("colorcomposefilter_%s", suffix);
    210     }
    211 
    212 protected:
    213     virtual SkString onShortName() {
    214         return fName;
    215     }
    216 
    217     virtual SkISize onISize() {
    218         return SkISize::Make(790, 790);
    219     }
    220 
    221     virtual void onDraw(SkCanvas* canvas) {
    222         SkBitmap bm;
    223         make_bm1(&bm);
    224 
    225         canvas->drawColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
    226 
    227         const int MODES = MODE_COUNT * COLOR_COUNT;
    228         SkAutoTUnref<SkColorFilter> filters[MODES];
    229         int index = 0;
    230         for (int i = 0; i < MODE_COUNT; ++i) {
    231             for (int j = 0; j < COLOR_COUNT; ++j) {
    232                 filters[index++].reset(SkColorFilter::CreateModeFilter(fColors[j], fModes[i]));
    233             }
    234         }
    235 
    236         SkPaint paint;
    237         paint.setShader(make_shader1(50, 50))->unref();
    238         SkRect r = SkRect::MakeWH(50, 50);
    239         const SkScalar spacer = 10;
    240 
    241         canvas->translate(spacer, spacer);
    242 
    243         canvas->drawRect(r, paint); // orig
    244 
    245         for (int i = 0; i < MODES; ++i) {
    246             paint.setColorFilter(filters[i]);
    247 
    248             canvas->save();
    249             canvas->translate((i + 1) * (r.width() + spacer), 0);
    250             canvas->drawRect(r, paint);
    251             canvas->restore();
    252 
    253             canvas->save();
    254             canvas->translate(0, (i + 1) * (r.width() + spacer));
    255             canvas->drawRect(r, paint);
    256             canvas->restore();
    257         }
    258 
    259         canvas->translate(r.width() + spacer, r.width() + spacer);
    260 
    261         for (int y = 0; y < MODES; ++y) {
    262             canvas->save();
    263             for (int x = 0; x < MODES; ++x) {
    264                 SkAutoTUnref<SkColorFilter> compose(SkColorFilter::CreateComposeFilter(filters[y],
    265                                                                                        filters[x]));
    266                 paint.setColorFilter(compose);
    267                 canvas->drawRect(r, paint);
    268                 canvas->translate(r.width() + spacer, 0);
    269             }
    270             canvas->restore();
    271             canvas->translate(0, r.height() + spacer);
    272         }
    273     }
    274 
    275 private:
    276     typedef GM INHERITED;
    277 };
    278 
    279 const SkColor gColors0[] = { SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW };
    280 const SkXfermode::Mode gModes0[] = {
    281     SkXfermode::kOverlay_Mode,
    282     SkXfermode::kDarken_Mode,
    283     SkXfermode::kColorBurn_Mode,
    284     SkXfermode::kExclusion_Mode,
    285 };
    286 DEF_GM( return new ComposeColorFilterGM(gColors0, gModes0, "wacky"); )
    287 
    288 const SkColor gColors1[] = { 0x80FF0000, 0x8000FF00, 0x800000FF };
    289 const SkXfermode::Mode gModes1[] = {
    290     SkXfermode::kSrcOver_Mode,
    291     SkXfermode::kXor_Mode,
    292     SkXfermode::kDstOut_Mode,
    293     SkXfermode::kSrcATop_Mode,
    294 };
    295 DEF_GM( return new ComposeColorFilterGM(gColors1, gModes1, "alpha"); )
    296