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