Home | History | Annotate | Download | only in gm
      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 
      8 #include "gm.h"
      9 #include "SkArithmeticMode.h"
     10 #include "SkOffsetImageFilter.h"
     11 #include "SkXfermodeImageFilter.h"
     12 #include "SkBitmapSource.h"
     13 
     14 #define WIDTH 600
     15 #define HEIGHT 600
     16 #define MARGIN 12
     17 
     18 namespace skiagm {
     19 
     20 class XfermodeImageFilterGM : public GM {
     21 public:
     22     XfermodeImageFilterGM(){
     23         this->setBGColor(0xFF000000);
     24     }
     25 
     26 protected:
     27     virtual SkString onShortName() SK_OVERRIDE {
     28         return SkString("xfermodeimagefilter");
     29     }
     30 
     31     void make_bitmap() {
     32         fBitmap.allocN32Pixels(80, 80);
     33         SkCanvas canvas(fBitmap);
     34         canvas.clear(0x00000000);
     35         SkPaint paint;
     36         paint.setAntiAlias(true);
     37         paint.setColor(0xD000D000);
     38         paint.setTextSize(SkIntToScalar(96));
     39         const char* str = "e";
     40         canvas.drawText(str, strlen(str), SkIntToScalar(15), SkIntToScalar(65), paint);
     41     }
     42 
     43     void make_checkerboard() {
     44         fCheckerboard.allocN32Pixels(80, 80);
     45         SkCanvas canvas(fCheckerboard);
     46         canvas.clear(0x00000000);
     47         SkPaint darkPaint;
     48         darkPaint.setColor(0xFF404040);
     49         SkPaint lightPaint;
     50         lightPaint.setColor(0xFFA0A0A0);
     51         for (int y = 0; y < 80; y += 16) {
     52           for (int x = 0; x < 80; x += 16) {
     53             canvas.save();
     54             canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
     55             canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
     56             canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
     57             canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
     58             canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
     59             canvas.restore();
     60           }
     61         }
     62     }
     63 
     64     virtual SkISize onISize() SK_OVERRIDE {
     65         return SkISize::Make(WIDTH, HEIGHT);
     66     }
     67 
     68     static void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint,
     69                            int x, int y) {
     70         canvas->save();
     71         canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
     72         canvas->clipRect(SkRect::MakeWH(
     73             SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
     74         canvas->drawBitmap(bitmap, 0, 0, &paint);
     75         canvas->restore();
     76     }
     77 
     78     static void drawClippedPaint(SkCanvas* canvas, const SkRect& rect, const SkPaint& paint,
     79                           int x, int y) {
     80         canvas->save();
     81         canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
     82         canvas->clipRect(rect);
     83         canvas->drawPaint(paint);
     84         canvas->restore();
     85     }
     86 
     87     virtual void onOnceBeforeDraw() SK_OVERRIDE {
     88         make_bitmap();
     89         make_checkerboard();
     90     }
     91 
     92     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
     93         canvas->clear(0x00000000);
     94         SkPaint paint;
     95 
     96         const struct {
     97             SkXfermode::Mode  fMode;
     98             const char*         fLabel;
     99         } gModes[] = {
    100             { SkXfermode::kClear_Mode,    "Clear"     },
    101             { SkXfermode::kSrc_Mode,      "Src"       },
    102             { SkXfermode::kDst_Mode,      "Dst"       },
    103             { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
    104             { SkXfermode::kDstOver_Mode,  "DstOver"   },
    105             { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
    106             { SkXfermode::kDstIn_Mode,    "DstIn"     },
    107             { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
    108             { SkXfermode::kDstOut_Mode,   "DstOut"    },
    109             { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
    110             { SkXfermode::kDstATop_Mode,  "DstATop"   },
    111             { SkXfermode::kXor_Mode,      "Xor"       },
    112 
    113             { SkXfermode::kPlus_Mode,         "Plus"          },
    114             { SkXfermode::kModulate_Mode,     "Modulate"      },
    115             { SkXfermode::kScreen_Mode,       "Screen"        },
    116             { SkXfermode::kOverlay_Mode,      "Overlay"       },
    117             { SkXfermode::kDarken_Mode,       "Darken"        },
    118             { SkXfermode::kLighten_Mode,      "Lighten"       },
    119             { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
    120             { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
    121             { SkXfermode::kHardLight_Mode,    "HardLight"     },
    122             { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
    123             { SkXfermode::kDifference_Mode,   "Difference"    },
    124             { SkXfermode::kExclusion_Mode,    "Exclusion"     },
    125             { SkXfermode::kMultiply_Mode,     "Multiply"      },
    126             { SkXfermode::kHue_Mode,          "Hue"           },
    127             { SkXfermode::kSaturation_Mode,   "Saturation"    },
    128             { SkXfermode::kColor_Mode,        "Color"         },
    129             { SkXfermode::kLuminosity_Mode,   "Luminosity"    },
    130         };
    131 
    132         int x = 0, y = 0;
    133         SkAutoTUnref<SkImageFilter> background(SkBitmapSource::Create(fCheckerboard));
    134         for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
    135             SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(gModes[i].fMode));
    136             SkAutoTUnref<SkImageFilter> filter(SkXfermodeImageFilter::Create(mode, background));
    137             paint.setImageFilter(filter);
    138             drawClippedBitmap(canvas, fBitmap, paint, x, y);
    139             x += fBitmap.width() + MARGIN;
    140             if (x + fBitmap.width() > WIDTH) {
    141                 x = 0;
    142                 y += fBitmap.height() + MARGIN;
    143             }
    144         }
    145         // Test arithmetic mode as image filter
    146         SkAutoTUnref<SkXfermode> mode(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
    147         SkAutoTUnref<SkImageFilter> filter(SkXfermodeImageFilter::Create(mode, background));
    148         paint.setImageFilter(filter);
    149         drawClippedBitmap(canvas, fBitmap, paint, x, y);
    150         x += fBitmap.width() + MARGIN;
    151         if (x + fBitmap.width() > WIDTH) {
    152             x = 0;
    153             y += fBitmap.height() + MARGIN;
    154         }
    155         // Test NULL mode
    156         filter.reset(SkXfermodeImageFilter::Create(NULL, background));
    157         paint.setImageFilter(filter);
    158         drawClippedBitmap(canvas, fBitmap, paint, x, y);
    159         x += fBitmap.width() + MARGIN;
    160         if (x + fBitmap.width() > WIDTH) {
    161             x = 0;
    162             y += fBitmap.height() + MARGIN;
    163         }
    164         SkRect clipRect = SkRect::MakeWH(SkIntToScalar(fBitmap.width() + 4),
    165                                          SkIntToScalar(fBitmap.height() + 4));
    166         // Test offsets on SrcMode (uses fixed-function blend)
    167         SkAutoTUnref<SkImageFilter> foreground(SkBitmapSource::Create(fBitmap));
    168         SkAutoTUnref<SkImageFilter> offsetForeground(SkOffsetImageFilter::Create(
    169             SkIntToScalar(4), SkIntToScalar(-4), foreground));
    170         SkAutoTUnref<SkImageFilter> offsetBackground(SkOffsetImageFilter::Create(
    171             SkIntToScalar(4), SkIntToScalar(4), background));
    172         mode.reset(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
    173         filter.reset(SkXfermodeImageFilter::Create(mode, offsetBackground, offsetForeground));
    174         paint.setImageFilter(filter);
    175         drawClippedPaint(canvas, clipRect, paint, x, y);
    176         x += fBitmap.width() + MARGIN;
    177         if (x + fBitmap.width() > WIDTH) {
    178             x = 0;
    179             y += fBitmap.height() + MARGIN;
    180         }
    181         // Test offsets on Darken (uses shader blend)
    182         mode.reset(SkXfermode::Create(SkXfermode::kDarken_Mode));
    183         filter.reset(SkXfermodeImageFilter::Create(mode, offsetBackground, offsetForeground));
    184         paint.setImageFilter(filter);
    185         drawClippedPaint(canvas, clipRect, paint, x, y);
    186         x += fBitmap.width() + MARGIN;
    187         if (x + fBitmap.width() > WIDTH) {
    188             x = 0;
    189             y += fBitmap.height() + MARGIN;
    190         }
    191         // Test cropping
    192         static const size_t nbSamples = 3;
    193         SkXfermode::Mode sampledModes[nbSamples] = {SkXfermode::kOverlay_Mode,
    194                                                     SkXfermode::kSrcOver_Mode,
    195                                                     SkXfermode::kPlus_Mode};
    196         int offsets[nbSamples][4] = {{ 10,  10, -16, -16},
    197                                      { 10,  10,  10,  10},
    198                                      {-10, -10,  -6,  -6}};
    199         for (size_t i = 0; i < nbSamples; ++i) {
    200             SkIRect cropRect = SkIRect::MakeXYWH(offsets[i][0],
    201                                                  offsets[i][1],
    202                                                  fBitmap.width()  + offsets[i][2],
    203                                                  fBitmap.height() + offsets[i][3]);
    204             SkImageFilter::CropRect rect(SkRect::Make(cropRect));
    205             mode.reset(SkXfermode::Create(sampledModes[i]));
    206             filter.reset(SkXfermodeImageFilter::Create(
    207                                     mode, offsetBackground, offsetForeground, &rect));
    208             paint.setImageFilter(filter);
    209             drawClippedPaint(canvas, clipRect, paint, x, y);
    210             x += fBitmap.width() + MARGIN;
    211             if (x + fBitmap.width() > WIDTH) {
    212                 x = 0;
    213                 y += fBitmap.height() + MARGIN;
    214             }
    215         }
    216     }
    217 private:
    218     SkBitmap fBitmap, fCheckerboard;
    219     typedef GM INHERITED;
    220 };
    221 
    222 //////////////////////////////////////////////////////////////////////////////
    223 
    224 DEF_GM( return new XfermodeImageFilterGM; );
    225 
    226 }
    227