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