1 /*
2 * Copyright 2012 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/gm.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkBlendMode.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkColor.h"
13 #include "include/core/SkColorFilter.h"
14 #include "include/core/SkPaint.h"
15 #include "include/core/SkPoint.h"
16 #include "include/core/SkRect.h"
17 #include "include/core/SkRefCnt.h"
18 #include "include/core/SkScalar.h"
19 #include "include/core/SkShader.h"
20 #include "include/core/SkSize.h"
21 #include "include/core/SkString.h"
22 #include "include/core/SkTileMode.h"
23 #include "include/core/SkTypes.h"
24 #include "include/effects/SkGradientShader.h"
25 #include "tools/ToolUtils.h"
26
27 #define WIDTH 512
28 #define HEIGHT 1024
29
30 namespace skiagm {
31
32 // Using gradients because GPU doesn't currently have an implementation of SkColorShader (duh!)
make_color_shader(SkColor color)33 static sk_sp<SkShader> make_color_shader(SkColor color) {
34 constexpr SkPoint kPts[] = {{0, 0}, {1, 1}};
35 SkColor colors[] = {color, color};
36
37 return SkGradientShader::MakeLinear(kPts, colors, nullptr, 2, SkTileMode::kClamp);
38 }
39
make_solid_shader()40 static sk_sp<SkShader> make_solid_shader() {
41 return make_color_shader(SkColorSetARGB(0xFF, 0x42, 0x82, 0x21));
42 }
43
make_transparent_shader()44 static sk_sp<SkShader> make_transparent_shader() {
45 return make_color_shader(SkColorSetARGB(0x80, 0x10, 0x70, 0x20));
46 }
47
make_trans_black_shader()48 static sk_sp<SkShader> make_trans_black_shader() {
49 return make_color_shader(0x0);
50 }
51
52 // draws a background behind each test rect to see transparency
make_bg_shader(int checkSize)53 static sk_sp<SkShader> make_bg_shader(int checkSize) {
54 SkBitmap bmp;
55 bmp.allocN32Pixels(2 * checkSize, 2 * checkSize);
56 SkCanvas canvas(bmp);
57 canvas.clear(ToolUtils::color_to_565(0xFF800000));
58 SkPaint paint;
59 paint.setColor(ToolUtils::color_to_565(0xFF000080));
60 SkRect rect0 = SkRect::MakeXYWH(0, 0,
61 SkIntToScalar(checkSize), SkIntToScalar(checkSize));
62 SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(checkSize), SkIntToScalar(checkSize),
63 SkIntToScalar(checkSize), SkIntToScalar(checkSize));
64 canvas.drawRect(rect1, paint);
65 canvas.drawRect(rect0, paint);
66 return bmp.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions());
67 }
68
69 class ModeColorFilterGM : public GM {
70 public:
ModeColorFilterGM()71 ModeColorFilterGM() {
72 this->setBGColor(0xFF303030);
73 }
74
75 protected:
getName() const76 SkString getName() const override { return SkString("modecolorfilters"); }
77
getISize()78 SkISize getISize() override { return SkISize::Make(WIDTH, HEIGHT); }
79
onDraw(SkCanvas * canvas)80 void onDraw(SkCanvas* canvas) override {
81 // size of rect for each test case
82 constexpr int kRectWidth = 20;
83 constexpr int kRectHeight = 20;
84
85 constexpr int kCheckSize = 10;
86
87 if (!fBmpShader) {
88 fBmpShader = make_bg_shader(kCheckSize);
89 }
90 SkPaint bgPaint;
91 bgPaint.setShader(fBmpShader);
92 bgPaint.setBlendMode(SkBlendMode::kSrc);
93
94 sk_sp<SkShader> shaders[] = {
95 nullptr, // use a paint color instead of a shader
96 make_solid_shader(),
97 make_transparent_shader(),
98 make_trans_black_shader(),
99 };
100
101 // used without shader
102 SkColor colors[] = {
103 SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF),
104 SkColorSetARGB(0xFF, 0x00, 0x00, 0x00),
105 SkColorSetARGB(0x00, 0x00, 0x00, 0x00),
106 SkColorSetARGB(0xFF, 0x10, 0x20, 0x42),
107 SkColorSetARGB(0xA0, 0x20, 0x30, 0x90),
108 };
109
110 // used with shaders
111 SkColor alphas[] = {0xFFFFFFFF, 0x80808080};
112
113 const SkBlendMode modes[] = { // currently just doing the Modes expressible as Coeffs
114 SkBlendMode::kClear,
115 SkBlendMode::kSrc,
116 SkBlendMode::kDst,
117 SkBlendMode::kSrcOver,
118 SkBlendMode::kDstOver,
119 SkBlendMode::kSrcIn,
120 SkBlendMode::kDstIn,
121 SkBlendMode::kSrcOut,
122 SkBlendMode::kDstOut,
123 SkBlendMode::kSrcATop,
124 SkBlendMode::kDstATop,
125 SkBlendMode::kXor,
126 SkBlendMode::kPlus,
127 SkBlendMode::kModulate,
128 };
129
130 SkPaint paint;
131 int idx = 0;
132 const int kRectsPerRow = std::max(this->getISize().fWidth / kRectWidth, 1);
133 for (size_t cfm = 0; cfm < std::size(modes); ++cfm) {
134 for (size_t cfc = 0; cfc < std::size(colors); ++cfc) {
135 paint.setColorFilter(SkColorFilters::Blend(colors[cfc], modes[cfm]));
136 for (size_t s = 0; s < std::size(shaders); ++s) {
137 paint.setShader(shaders[s]);
138 bool hasShader = nullptr == paint.getShader();
139 int paintColorCnt = hasShader ? std::size(alphas) : std::size(colors);
140 SkColor* paintColors = hasShader ? alphas : colors;
141 for (int pc = 0; pc < paintColorCnt; ++pc) {
142 paint.setColor(paintColors[pc]);
143 SkScalar x = SkIntToScalar(idx % kRectsPerRow);
144 SkScalar y = SkIntToScalar(idx / kRectsPerRow);
145 SkRect rect = SkRect::MakeXYWH(x * kRectWidth, y * kRectHeight,
146 SkIntToScalar(kRectWidth),
147 SkIntToScalar(kRectHeight));
148 canvas->saveLayer(&rect, nullptr);
149 canvas->drawRect(rect, bgPaint);
150 canvas->drawRect(rect, paint);
151 canvas->restore();
152 ++idx;
153 }
154 }
155 }
156 }
157 }
158
159 private:
160 sk_sp<SkShader> fBmpShader;
161 using INHERITED = GM;
162 };
163
164 //////////////////////////////////////////////////////////////////////////////
165
166 DEF_GM( return new ModeColorFilterGM; )
167
168 } // namespace skiagm
169