Revert "replace SkXfermode obj with SkBlendMode enum in paints"
[platform/upstream/libSkiaSharp.git] / gm / xfermodeimagefilter.cpp
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 "SkImage.h"
11 #include "SkImageSource.h"
12 #include "SkOffsetImageFilter.h"
13 #include "SkXfermodeImageFilter.h"
14
15 #define WIDTH 600
16 #define HEIGHT 700
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     SkISize onISize() override {
33         return SkISize::Make(WIDTH, HEIGHT);
34     }
35
36     void onOnceBeforeDraw() override {
37         fBitmap = sk_tool_utils::create_string_bitmap(80, 80, 0xD000D000, 15, 65, 96, "e");
38
39         fCheckerboard = SkImage::MakeFromBitmap(
40             sk_tool_utils::create_checkerboard_bitmap(80, 80,
41                                                       sk_tool_utils::color_to_565(0xFFA0A0A0),
42                                                       sk_tool_utils::color_to_565(0xFF404040),
43                                                       8));
44     }
45
46     void onDraw(SkCanvas* canvas) override {
47         canvas->clear(SK_ColorBLACK);
48         SkPaint paint;
49
50         const struct {
51             SkXfermode::Mode  fMode;
52             const char*         fLabel;
53         } gModes[] = {
54             { SkXfermode::kClear_Mode,    "Clear"     },
55             { SkXfermode::kSrc_Mode,      "Src"       },
56             { SkXfermode::kDst_Mode,      "Dst"       },
57             { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
58             { SkXfermode::kDstOver_Mode,  "DstOver"   },
59             { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
60             { SkXfermode::kDstIn_Mode,    "DstIn"     },
61             { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
62             { SkXfermode::kDstOut_Mode,   "DstOut"    },
63             { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
64             { SkXfermode::kDstATop_Mode,  "DstATop"   },
65             { SkXfermode::kXor_Mode,      "Xor"       },
66
67             { SkXfermode::kPlus_Mode,         "Plus"          },
68             { SkXfermode::kModulate_Mode,     "Modulate"      },
69             { SkXfermode::kScreen_Mode,       "Screen"        },
70             { SkXfermode::kOverlay_Mode,      "Overlay"       },
71             { SkXfermode::kDarken_Mode,       "Darken"        },
72             { SkXfermode::kLighten_Mode,      "Lighten"       },
73             { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
74             { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
75             { SkXfermode::kHardLight_Mode,    "HardLight"     },
76             { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
77             { SkXfermode::kDifference_Mode,   "Difference"    },
78             { SkXfermode::kExclusion_Mode,    "Exclusion"     },
79             { SkXfermode::kMultiply_Mode,     "Multiply"      },
80             { SkXfermode::kHue_Mode,          "Hue"           },
81             { SkXfermode::kSaturation_Mode,   "Saturation"    },
82             { SkXfermode::kColor_Mode,        "Color"         },
83             { SkXfermode::kLuminosity_Mode,   "Luminosity"    },
84         };
85
86         int x = 0, y = 0;
87         sk_sp<SkImageFilter> background(SkImageSource::Make(fCheckerboard));
88         for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
89             paint.setImageFilter(SkXfermodeImageFilter::Make(SkXfermode::Make(gModes[i].fMode),
90                                                              background));
91             DrawClippedBitmap(canvas, fBitmap, paint, x, y);
92             x += fBitmap.width() + MARGIN;
93             if (x + fBitmap.width() > WIDTH) {
94                 x = 0;
95                 y += fBitmap.height() + MARGIN;
96             }
97         }
98         // Test arithmetic mode as image filter
99         paint.setImageFilter(SkXfermodeImageFilter::MakeArithmetic(0, 1, 1, 0, true, background));
100         DrawClippedBitmap(canvas, fBitmap, paint, x, y);
101         x += fBitmap.width() + MARGIN;
102         if (x + fBitmap.width() > WIDTH) {
103             x = 0;
104             y += fBitmap.height() + MARGIN;
105         }
106         // Test nullptr mode
107         paint.setImageFilter(SkXfermodeImageFilter::Make(nullptr, background));
108         DrawClippedBitmap(canvas, fBitmap, paint, x, y);
109         x += fBitmap.width() + MARGIN;
110         if (x + fBitmap.width() > WIDTH) {
111             x = 0;
112             y += fBitmap.height() + MARGIN;
113         }
114         SkRect clipRect = SkRect::MakeWH(SkIntToScalar(fBitmap.width() + 4),
115                                          SkIntToScalar(fBitmap.height() + 4));
116         // Test offsets on SrcMode (uses fixed-function blend)
117         sk_sp<SkImage> bitmapImage(SkImage::MakeFromBitmap(fBitmap));
118         sk_sp<SkImageFilter> foreground(SkImageSource::Make(std::move(bitmapImage)));
119         sk_sp<SkImageFilter> offsetForeground(SkOffsetImageFilter::Make(SkIntToScalar(4),
120                                                                         SkIntToScalar(-4),
121                                                                         foreground));
122         sk_sp<SkImageFilter> offsetBackground(SkOffsetImageFilter::Make(SkIntToScalar(4),
123                                                                         SkIntToScalar(4),
124                                                                         background));
125         paint.setImageFilter(SkXfermodeImageFilter::Make(
126                                                      SkXfermode::Make(SkXfermode::kSrcOver_Mode),
127                                                      offsetBackground,
128                                                      offsetForeground,
129                                                      nullptr));
130         DrawClippedPaint(canvas, clipRect, paint, x, y);
131         x += fBitmap.width() + MARGIN;
132         if (x + fBitmap.width() > WIDTH) {
133             x = 0;
134             y += fBitmap.height() + MARGIN;
135         }
136         // Test offsets on Darken (uses shader blend)
137         paint.setImageFilter(SkXfermodeImageFilter::Make(SkXfermode::Make(SkXfermode::kDarken_Mode),
138                                                          offsetBackground,
139                                                          offsetForeground,
140                                                          nullptr));
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         constexpr 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             paint.setImageFilter(SkXfermodeImageFilter::Make(SkXfermode::Make(sampledModes[i]),
162                                                              offsetBackground,
163                                                              offsetForeground,
164                                                              &rect));
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         auto mode = SkXfermode::Make(SkXfermode::kScreen_Mode);
174         SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(10, 10, 60, 60));
175         sk_sp<SkImageFilter> cropped(SkOffsetImageFilter::Make(0, 0, foreground, &cropRect));
176         paint.setImageFilter(SkXfermodeImageFilter::Make(mode, cropped, background, nullptr));
177         DrawClippedPaint(canvas, clipRect, paint, x, y);
178         x += fBitmap.width() + MARGIN;
179         if (x + fBitmap.width() > WIDTH) {
180             x = 0;
181             y += fBitmap.height() + MARGIN;
182         }
183         // Test small fg, large bg with Screen (uses shader blend)
184         paint.setImageFilter(SkXfermodeImageFilter::Make(mode, background, cropped, nullptr));
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 small fg, large bg with SrcIn with a crop that forces it to full size.
192         // This tests that SkXfermodeImageFilter correctly applies the compositing mode to
193         // the region outside the foreground.
194         mode = SkXfermode::Make(SkXfermode::kSrcIn_Mode);
195         SkImageFilter::CropRect cropRectFull(SkRect::MakeXYWH(0, 0, 80, 80));
196         paint.setImageFilter(SkXfermodeImageFilter::Make(mode, background,
197                                                          cropped, &cropRectFull));
198         DrawClippedPaint(canvas, clipRect, paint, x, y);
199         x += fBitmap.width() + MARGIN;
200         if (x + fBitmap.width() > WIDTH) {
201             x = 0;
202             y += fBitmap.height() + MARGIN;
203         }
204     }
205
206 private:
207     static void DrawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint,
208                            int x, int y) {
209         canvas->save();
210         canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
211         canvas->clipRect(SkRect::MakeWH(
212             SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
213         canvas->drawBitmap(bitmap, 0, 0, &paint);
214         canvas->restore();
215     }
216
217     static void DrawClippedPaint(SkCanvas* canvas, const SkRect& rect, const SkPaint& paint,
218                           int x, int y) {
219         canvas->save();
220         canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
221         canvas->clipRect(rect);
222         canvas->drawPaint(paint);
223         canvas->restore();
224     }
225
226     SkBitmap        fBitmap;
227     sk_sp<SkImage>  fCheckerboard;
228
229     typedef GM INHERITED;
230 };
231
232 //////////////////////////////////////////////////////////////////////////////
233
234 DEF_GM( return new XfermodeImageFilterGM; );
235
236 }