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/gm.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkImage.h"
14 #include "include/core/SkImageFilter.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkMatrix.h"
17 #include "include/core/SkPaint.h"
18 #include "include/core/SkRect.h"
19 #include "include/core/SkRefCnt.h"
20 #include "include/core/SkRegion.h"
21 #include "include/core/SkSize.h"
22 #include "include/core/SkString.h"
23 #include "include/core/SkSurface.h"
24 #include "include/effects/SkImageFilters.h"
25 #include "include/utils/SkRandom.h"
26 #include "tools/ToolUtils.h"
27
28 #include <utility>
29
30 #define WIDTH 500
31 #define HEIGHT 500
32
draw_rects(SkCanvas * canvas)33 static void draw_rects(SkCanvas* canvas) {
34 SkPaint rectPaint;
35 rectPaint.setColor(SK_ColorBLUE);
36 canvas->drawRect(SkRect::MakeXYWH(0, 0, WIDTH / 2, HEIGHT / 2), rectPaint);
37 rectPaint.setColor(0xBFFF0000);
38 canvas->drawRect(SkRect::MakeXYWH(WIDTH / 2, 0, WIDTH / 2, HEIGHT / 2), rectPaint);
39 rectPaint.setColor(0x3F00FF00);
40 canvas->drawRect(SkRect::MakeXYWH(0, HEIGHT / 2, WIDTH / 2, HEIGHT / 2), rectPaint);
41 rectPaint.setColor(SK_ColorTRANSPARENT);
42 canvas->drawRect(SkRect::MakeXYWH(WIDTH / 2, HEIGHT / 2, WIDTH / 2, HEIGHT / 2), rectPaint);
43 }
44
create_filter_paint(SkIRect * cropRect=nullptr)45 static SkPaint create_filter_paint(SkIRect* cropRect = nullptr) {
46 SkIRect rects[2];
47 rects[0] = SkIRect::MakeXYWH(0, 150, WIDTH, HEIGHT - 300);
48 rects[1] = SkIRect::MakeXYWH(150, 0, WIDTH - 300, HEIGHT);
49 SkRegion region;
50 region.setRects(rects, 2);
51
52 SkPaint paint;
53 sk_sp<SkImageFilter> offset(SkImageFilters::Offset(25, 25, nullptr));
54 paint.setImageFilter(
55 SkImageFilters::AlphaThreshold(region, 0.2f, 0.7f, std::move(offset), cropRect));
56 return paint;
57 }
58
59 class ImageAlphaThresholdGM : public skiagm::GM {
60 public:
ImageAlphaThresholdGM(bool useCropRect)61 ImageAlphaThresholdGM(bool useCropRect) : fUseCropRect(useCropRect) {
62 this->setBGColor(SK_ColorWHITE);
63 }
64
65 protected:
66
onShortName()67 SkString onShortName() override {
68 if (fUseCropRect) {
69 return SkString("imagealphathreshold_crop");
70 }
71
72 return SkString("imagealphathreshold");
73 }
74
onISize()75 SkISize onISize() override {
76 return SkISize::Make(WIDTH, HEIGHT);
77 }
78
onDraw(SkCanvas * canvas)79 void onDraw(SkCanvas* canvas) override {
80 SkMatrix matrix;
81 matrix.reset();
82 matrix.setTranslate(WIDTH * .1f, HEIGHT * .1f);
83 matrix.postScale(.8f, .8f);
84
85 canvas->concat(matrix);
86
87 SkIRect cropRect = SkIRect::MakeLTRB(100, 100, WIDTH - 100, HEIGHT - 100);
88
89 SkPaint paint = create_filter_paint(fUseCropRect ? &cropRect : nullptr);
90 canvas->saveLayer(nullptr, &paint);
91 draw_rects(canvas);
92
93 canvas->restore();
94 }
95
96 private:
97 bool fUseCropRect;
98
99 typedef GM INHERITED;
100 };
101
102 // Create a 'width' x 'height' SkSurface that matches the colorType of 'canvas' as
103 // best we can
make_color_matching_surface(SkCanvas * canvas,int width,int height,SkAlphaType at)104 static sk_sp<SkSurface> make_color_matching_surface(SkCanvas* canvas, int width, int height,
105 SkAlphaType at) {
106
107 SkColorType ct = canvas->imageInfo().colorType();
108 sk_sp<SkColorSpace> cs(canvas->imageInfo().refColorSpace());
109
110 if (kUnknown_SkColorType == ct) {
111 // For backends that aren't yet color-space aware we just fallback to N32.
112 ct = kN32_SkColorType;
113 cs = nullptr;
114 } else if (SkColorTypeIsAlwaysOpaque(ct)) {
115 at = kOpaque_SkAlphaType;
116 }
117
118 SkImageInfo info = SkImageInfo::Make(width, height, ct, at, std::move(cs));
119
120 return ToolUtils::makeSurface(canvas, info);
121 }
122
123 class ImageAlphaThresholdSurfaceGM : public skiagm::GM {
124 public:
ImageAlphaThresholdSurfaceGM()125 ImageAlphaThresholdSurfaceGM() {
126 this->setBGColor(0xFFFFFFFF);
127 }
128
129 protected:
onShortName()130 SkString onShortName() override {
131 return SkString("imagealphathreshold_surface");
132 }
133
onISize()134 SkISize onISize() override {
135 return SkISize::Make(WIDTH, HEIGHT);
136 }
137
onDraw(SkCanvas * canvas,SkString * errorMsg)138 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
139 SkMatrix matrix;
140 matrix.reset();
141 matrix.setTranslate(WIDTH * .1f, HEIGHT * .1f);
142 matrix.postScale(.8f, .8f);
143
144 canvas->concat(matrix);
145
146 sk_sp<SkSurface> surface(make_color_matching_surface(canvas, WIDTH, HEIGHT,
147 kPremul_SkAlphaType));
148 if (!surface) {
149 *errorMsg = "make_color_matching_surface failed";
150 return DrawResult::kFail;
151 }
152
153 surface->getCanvas()->clear(SK_ColorTRANSPARENT);
154 draw_rects(surface->getCanvas());
155
156 SkPaint paint = create_filter_paint();
157 canvas->clipRect(SkRect::MakeLTRB(100, 100, WIDTH - 100, HEIGHT - 100));
158 canvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, &paint);
159 return DrawResult::kOk;
160 }
161
162 private:
163 typedef skiagm::GM INHERITED;
164 };
165
166 //////////////////////////////////////////////////////////////////////////////
167
168 DEF_GM(return new ImageAlphaThresholdGM(true);)
DEF_GM(return new ImageAlphaThresholdGM (false);)169 DEF_GM(return new ImageAlphaThresholdGM(false);)
170 DEF_GM(return new ImageAlphaThresholdSurfaceGM();)
171
172 //////////////////////////////////////////////////////////////////////////////
173
174 static sk_sp<SkImage> make_img() {
175 SkBitmap bitmap;
176 bitmap.allocPixels(SkImageInfo::MakeS32(WIDTH, HEIGHT, kPremul_SkAlphaType));
177 SkCanvas canvas(bitmap);
178
179 SkPaint paint;
180 SkRect rect = SkRect::MakeWH(WIDTH, HEIGHT);
181 SkRandom rnd;
182
183 while (!rect.isEmpty()) {
184 paint.setColor(rnd.nextU() | (0xFF << 24));
185 canvas.drawRect(rect, paint);
186 rect.inset(25, 25);
187 }
188
189 return SkImage::MakeFromBitmap(bitmap);
190 }
191
192 DEF_SIMPLE_GM_BG(imagealphathreshold_image, canvas, WIDTH * 2, HEIGHT, SK_ColorBLACK) {
193 sk_sp<SkImage> image(make_img());
194
195 SkIRect rects[2];
196 rects[0] = SkIRect::MakeXYWH(0, 150, WIDTH, HEIGHT - 300);
197 rects[1] = SkIRect::MakeXYWH(150, 0, WIDTH - 300, HEIGHT);
198 SkRegion region;
199 region.setRects(rects, 2);
200
201 SkPaint filterPaint;
202 sk_sp<SkImageFilter> imageSource(SkImageFilters::Image(image));
203 filterPaint.setImageFilter(SkImageFilters::AlphaThreshold(region, 0.2f, 0.7f,
204 std::move(imageSource)));
205
206 canvas->saveLayer(nullptr, &filterPaint);
207 canvas->restore();
208 canvas->translate(WIDTH, 0);
209 canvas->drawImage(image, 0, 0);
210 }
211