blob: 768e7982104bfa250bfd4fe82976830da49ea295 [file] [log] [blame]
reed@google.comdb87c962012-11-02 21:11:12 +00001/*
humper@google.coma99a92c2013-02-20 16:42:06 +00002* 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*/
reed@google.comdb87c962012-11-02 21:11:12 +00007
8#include "gm.h"
humper@google.com7c7292c2013-01-04 20:29:03 +00009#include "SkBlurMask.h"
robertphillips@google.comb7061172013-09-06 14:16:12 +000010#include "SkBlurMaskFilter.h"
reed@google.comdb87c962012-11-02 21:11:12 +000011#include "SkCanvas.h"
12#include "SkPath.h"
13
14#define STROKE_WIDTH SkIntToScalar(10)
15
16typedef void (*Proc)(SkCanvas*, const SkRect&, const SkPaint&);
17
18static void fill_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
19 canvas->drawRect(r, p);
20}
21
reed@google.comdb87c962012-11-02 21:11:12 +000022static void draw_donut(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
23 SkRect rect;
24 SkPath path;
skia.committer@gmail.com34587162012-11-20 02:01:23 +000025
reed@google.comdb87c962012-11-02 21:11:12 +000026 rect = r;
27 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
28 path.addRect(rect);
29 rect = r;
30 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000031
reed@google.comdb87c962012-11-02 21:11:12 +000032 path.addRect(rect);
33 path.setFillType(SkPath::kEvenOdd_FillType);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000034
reed@google.com808b70f2012-11-19 16:14:02 +000035 canvas->drawPath(path, p);
36}
reed@google.comdb87c962012-11-02 21:11:12 +000037
reed@google.com808b70f2012-11-19 16:14:02 +000038static void draw_donut_skewed(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
39 SkRect rect;
40 SkPath path;
skia.committer@gmail.com34587162012-11-20 02:01:23 +000041
reed@google.com808b70f2012-11-19 16:14:02 +000042 rect = r;
43 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
44 path.addRect(rect);
45 rect = r;
46 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000047
reed@google.com808b70f2012-11-19 16:14:02 +000048 rect.offset(7, -7);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000049
reed@google.com808b70f2012-11-19 16:14:02 +000050 path.addRect(rect);
51 path.setFillType(SkPath::kEvenOdd_FillType);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000052
reed@google.comdb87c962012-11-02 21:11:12 +000053 canvas->drawPath(path, p);
54}
55
reed@google.com53007a22012-11-26 14:39:50 +000056#include "SkGradientShader.h"
57
58typedef void (*PaintProc)(SkPaint*, SkScalar width);
59
reed@google.comdb87c962012-11-02 21:11:12 +000060class BlurRectGM : public skiagm::GM {
commit-bot@chromium.orge3964552014-04-28 16:25:35 +000061 SkAutoTUnref<SkMaskFilter> fMaskFilters[kLastEnum_SkBlurStyle + 1];
humper@google.coma99a92c2013-02-20 16:42:06 +000062 SkString fName;
humper@google.coma99a92c2013-02-20 16:42:06 +000063 SkAlpha fAlpha;
reed@google.comdb87c962012-11-02 21:11:12 +000064public:
commit-bot@chromium.org7cced562014-01-10 23:10:13 +000065 BlurRectGM(const char name[], U8CPU alpha)
66 : fName(name)
67 , fAlpha(SkToU8(alpha)) {
reed@google.com57850b92012-12-17 21:20:53 +000068 }
reed@google.comdb87c962012-11-02 21:11:12 +000069
70protected:
commit-bot@chromium.org7cced562014-01-10 23:10:13 +000071 virtual void onOnceBeforeDraw() SK_OVERRIDE {
commit-bot@chromium.orge3964552014-04-28 16:25:35 +000072 for (int i = 0; i <= kLastEnum_SkBlurStyle; ++i) {
73 fMaskFilters[i].reset(SkBlurMaskFilter::Create((SkBlurStyle)i,
commit-bot@chromium.org7cced562014-01-10 23:10:13 +000074 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(STROKE_WIDTH/2)),
75 SkBlurMaskFilter::kHighQuality_BlurFlag));
76 }
77 }
78
reed@google.comdb87c962012-11-02 21:11:12 +000079 virtual SkString onShortName() {
reed@google.com53007a22012-11-26 14:39:50 +000080 return fName;
reed@google.comdb87c962012-11-02 21:11:12 +000081 }
82
83 virtual SkISize onISize() {
commit-bot@chromium.org7cced562014-01-10 23:10:13 +000084 return SkISize::Make(440, 820);
reed@google.comdb87c962012-11-02 21:11:12 +000085 }
86
87 virtual void onDraw(SkCanvas* canvas) {
88 canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
89
commit-bot@chromium.org7cced562014-01-10 23:10:13 +000090 SkRect r = { 0, 0, 100, 50 };
91 SkScalar scales[] = { SK_Scalar1, 0.6f };
skia.committer@gmail.com8ccf5902012-11-27 02:01:19 +000092
commit-bot@chromium.org7cced562014-01-10 23:10:13 +000093 for (size_t s = 0; s < SK_ARRAY_COUNT(scales); ++s) {
94 canvas->save();
95 for (size_t f = 0; f < SK_ARRAY_COUNT(fMaskFilters); ++f) {
96 SkPaint paint;
97 paint.setMaskFilter(fMaskFilters[f]);
98 paint.setAlpha(fAlpha);
99
100 static const Proc procs[] = {
101 fill_rect, draw_donut, draw_donut_skewed
102 };
103
104 canvas->save();
105 canvas->scale(scales[s], scales[s]);
106 this->drawProcs(canvas, r, paint, false, procs, SK_ARRAY_COUNT(procs));
107 canvas->translate(r.width() * 4/3, 0);
108 this->drawProcs(canvas, r, paint, true, procs, SK_ARRAY_COUNT(procs));
109 canvas->restore();
110
111 canvas->translate(0, SK_ARRAY_COUNT(procs) * r.height() * 4/3 * scales[s]);
112 }
113 canvas->restore();
114 canvas->translate(2 * r.width() * 4/3 * scales[s], 0);
reed@google.com53007a22012-11-26 14:39:50 +0000115 }
reed@google.comdb87c962012-11-02 21:11:12 +0000116 }
117
mtklein7cdc1ee2014-07-07 10:41:04 -0700118 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
reed@google.comdb87c962012-11-02 21:11:12 +0000119
120private:
121 void drawProcs(SkCanvas* canvas, const SkRect& r, const SkPaint& paint,
122 bool doClip, const Proc procs[], size_t procsCount) {
123 SkAutoCanvasRestore acr(canvas, true);
124 for (size_t i = 0; i < procsCount; ++i) {
125 if (doClip) {
126 SkRect clipRect(r);
127 clipRect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
128 canvas->save();
129 canvas->clipRect(r);
130 }
131 procs[i](canvas, r, paint);
132 if (doClip) {
133 canvas->restore();
134 }
135 canvas->translate(0, r.height() * 4/3);
136 }
137 }
humper@google.coma99a92c2013-02-20 16:42:06 +0000138private:
reed@google.comdb87c962012-11-02 21:11:12 +0000139 typedef GM INHERITED;
140};
141
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000142
143class BlurRectDirectGM : public skiagm::GM {
144 SkString fName;
145 int fGMWidth, fGMHeight;
146 int fPadding, fMargin;
147public:
148 BlurRectDirectGM(const char name[])
149 : fName(name),
150 fGMWidth(1200),
151 fGMHeight(1024),
152 fPadding(10),
153 fMargin(100)
154 {
155 }
156
157protected:
158 virtual SkString onShortName() {
159 return fName;
160 }
161
162 virtual SkISize onISize() {
163 return SkISize::Make(fGMWidth, fGMHeight);
164 }
165
166 virtual void onDraw(SkCanvas* canvas) {
167 const int widths[] = {25, 5, 5, 100, 150, 25};
168 const int heights[] = {100, 100, 5, 25, 150, 25};
169 const SkBlurStyle styles[] = {kNormal_SkBlurStyle, kInner_SkBlurStyle, kOuter_SkBlurStyle};
170 const float radii[] = {20, 5, 10};
171
172 canvas->translate(50,20);
173
174 int cur_x = 0;
175 int cur_y = 0;
176
177 int max_height = 0;
178
179 for (size_t i = 0 ; i < SK_ARRAY_COUNT(widths) ; i++) {
180 int width = widths[i];
181 int height = heights[i];
182 SkRect r;
183 r.setWH(SkIntToScalar(width), SkIntToScalar(height));
184 SkAutoCanvasRestore autoRestore(canvas, true);
185
186 for (size_t j = 0 ; j < SK_ARRAY_COUNT(radii) ; j++) {
187 float radius = radii[j];
188 for (size_t k = 0 ; k < SK_ARRAY_COUNT(styles) ; k++) {
189 SkBlurStyle style = styles[k];
190
191 SkMask mask;
192 SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius), &mask, r, style);
193
194 SkAutoMaskFreeImage amfi(mask.fImage);
195
196 SkBitmap bm;
197 bm.installMaskPixels(mask);
198
199 if (cur_x + bm.width() >= fGMWidth - fMargin) {
200 cur_x = 0;
201 cur_y += max_height + fPadding;
202 max_height = 0;
203 }
204
205 canvas->save();
commit-bot@chromium.org793ddd92014-05-28 22:42:31 +0000206 canvas->translate((SkScalar)cur_x, (SkScalar)cur_y);
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000207 canvas->translate(-(bm.width() - r.width())/2, -(bm.height()-r.height())/2);
208 canvas->drawBitmap(bm, 0.f, 0.f, NULL);
209 canvas->restore();
210
211 cur_x += bm.width() + fPadding;
212 if (bm.height() > max_height)
213 max_height = bm.height();
214 }
215 }
216 }
217 }
218
219 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
220
221private:
222 typedef GM INHERITED;
223};
224
humper@google.com7c7292c2013-01-04 20:29:03 +0000225class BlurRectCompareGM : public skiagm::GM {
226 SkString fName;
227 unsigned int fRectWidth, fRectHeight;
reed@google.com140d7282013-01-07 20:25:04 +0000228 SkScalar fRadius;
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000229 SkBlurStyle fStyle;
humper@google.com7c7292c2013-01-04 20:29:03 +0000230public:
skia.committer@gmail.comb3ec29d2013-09-07 07:01:16 +0000231 BlurRectCompareGM(const char name[], unsigned int rectWidth,
232 unsigned int rectHeight, float radius,
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000233 SkBlurStyle style)
bsalomon@google.com33cdbde2013-01-11 20:54:44 +0000234 : fName(name)
235 , fRectWidth(rectWidth)
236 , fRectHeight(rectHeight)
237 , fRadius(radius)
robertphillips@google.comb7061172013-09-06 14:16:12 +0000238 , fStyle(style) {
239 }
skia.committer@gmail.comd454ec12013-02-21 07:15:03 +0000240 int width() const {
241 return fRectWidth;
humper@google.coma99a92c2013-02-20 16:42:06 +0000242 }
skia.committer@gmail.comd454ec12013-02-21 07:15:03 +0000243 int height() const {
244 return fRectHeight;
humper@google.coma99a92c2013-02-20 16:42:06 +0000245 }
skia.committer@gmail.comd454ec12013-02-21 07:15:03 +0000246 SkScalar radius() const {
247 return fRadius;
humper@google.coma99a92c2013-02-20 16:42:06 +0000248 }
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000249 SkBlurStyle style() const {
skia.committer@gmail.comd454ec12013-02-21 07:15:03 +0000250 return fStyle;
humper@google.coma99a92c2013-02-20 16:42:06 +0000251 }
humper@google.com7c7292c2013-01-04 20:29:03 +0000252
253protected:
254 virtual SkString onShortName() {
255 return fName;
256 }
257
258 virtual SkISize onISize() {
259 return SkISize::Make(640, 480);
260 }
skia.committer@gmail.com8ae714b2013-01-05 02:02:05 +0000261
humper@google.coma99a92c2013-02-20 16:42:06 +0000262 virtual bool makeMask(SkMask *m, const SkRect&) = 0;
humper@google.com7c7292c2013-01-04 20:29:03 +0000263
264 virtual void onDraw(SkCanvas* canvas) {
humper@google.coma99a92c2013-02-20 16:42:06 +0000265 SkRect r;
266 r.setWH(SkIntToScalar(fRectWidth), SkIntToScalar(fRectHeight));
humper@google.com7c7292c2013-01-04 20:29:03 +0000267
humper@google.coma99a92c2013-02-20 16:42:06 +0000268 SkISize canvas_size = canvas->getDeviceSize();
jvanverth@google.comd98df1a2013-02-20 19:02:34 +0000269 int center_x = (canvas_size.fWidth - (int)(r.width()))/2;
270 int center_y = (canvas_size.fHeight - (int)(r.height()))/2;
humper@google.com7c7292c2013-01-04 20:29:03 +0000271
humper@google.coma99a92c2013-02-20 16:42:06 +0000272 SkMask mask;
humper@google.com7c7292c2013-01-04 20:29:03 +0000273
humper@google.coma99a92c2013-02-20 16:42:06 +0000274 if (!this->makeMask(&mask, r)) {
275 SkPaint paint;
jvanverth@google.comd98df1a2013-02-20 19:02:34 +0000276 r.offset( SkIntToScalar(center_x), SkIntToScalar(center_y) );
humper@google.coma99a92c2013-02-20 16:42:06 +0000277 canvas->drawRect(r,paint);
278 return;
279 }
280 SkAutoMaskFreeImage amfi(mask.fImage);
281
282 SkBitmap bm;
commit-bot@chromium.orgdac52252014-02-17 21:21:46 +0000283 bm.installMaskPixels(mask);
humper@google.coma99a92c2013-02-20 16:42:06 +0000284
285 center_x = (canvas_size.fWidth - mask.fBounds.width())/2;
286 center_y = (canvas_size.fHeight - mask.fBounds.height())/2;
287
jvanverth@google.comd98df1a2013-02-20 19:02:34 +0000288 canvas->drawBitmap(bm, SkIntToScalar(center_x), SkIntToScalar(center_y), NULL);
humper@google.com7c7292c2013-01-04 20:29:03 +0000289 }
290
291 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
292
293private:
294 typedef GM INHERITED;
295};
296
297class BlurRectFastGM: public BlurRectCompareGM {
298public:
robertphillips@google.com7ce661d2013-08-27 16:14:03 +0000299 BlurRectFastGM(const char name[], unsigned int rectWidth,
300 unsigned int rectHeight, float blurRadius,
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000301 SkBlurStyle style) :
robertphillips@google.com7ce661d2013-08-27 16:14:03 +0000302 INHERITED(name, rectWidth, rectHeight, blurRadius, style) {
humper@google.coma99a92c2013-02-20 16:42:06 +0000303 }
robertphillips@google.com7ce661d2013-08-27 16:14:03 +0000304
humper@google.com7c7292c2013-01-04 20:29:03 +0000305protected:
humper@google.coma99a92c2013-02-20 16:42:06 +0000306 virtual bool makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE {
robertphillips@google.comb7061172013-09-06 14:16:12 +0000307 return SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(this->radius()),
308 m, r, this->style());
reed@google.com140d7282013-01-07 20:25:04 +0000309 }
humper@google.coma99a92c2013-02-20 16:42:06 +0000310private:
311 typedef BlurRectCompareGM INHERITED;
humper@google.com7c7292c2013-01-04 20:29:03 +0000312};
313
314class BlurRectSlowGM: public BlurRectCompareGM {
315public:
robertphillips@google.comb7061172013-09-06 14:16:12 +0000316 BlurRectSlowGM(const char name[], unsigned int rectWidth, unsigned int rectHeight,
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000317 float blurRadius, SkBlurStyle style)
robertphillips@google.comb7061172013-09-06 14:16:12 +0000318 : INHERITED(name, rectWidth, rectHeight, blurRadius, style) {
humper@google.coma99a92c2013-02-20 16:42:06 +0000319 }
robertphillips@google.comb7061172013-09-06 14:16:12 +0000320
humper@google.com7c7292c2013-01-04 20:29:03 +0000321protected:
humper@google.coma99a92c2013-02-20 16:42:06 +0000322 virtual bool makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE {
reed@google.com140d7282013-01-07 20:25:04 +0000323 SkMask src;
324 r.roundOut(&src.fBounds);
325 src.fBounds.offset(-src.fBounds.fLeft, -src.fBounds.fTop); // move to origin
326 src.fFormat = SkMask::kA8_Format;
327 src.fRowBytes = src.fBounds.width();
humper@google.coma99a92c2013-02-20 16:42:06 +0000328 src.fImage = SkMask::AllocImage(src.computeTotalImageSize());
bsalomon@google.com33cdbde2013-01-11 20:54:44 +0000329 SkAutoMaskFreeImage amfi(src.fImage);
humper@google.com7c7292c2013-01-04 20:29:03 +0000330
bsalomon@google.com33cdbde2013-01-11 20:54:44 +0000331 memset(src.fImage, 0xff, src.computeTotalImageSize());
humper@google.com7c7292c2013-01-04 20:29:03 +0000332
skia.committer@gmail.comb3ec29d2013-09-07 07:01:16 +0000333 return SkBlurMask::BoxBlur(m, src,
334 SkBlurMask::ConvertRadiusToSigma(this->radius()),
robertphillips@google.comb7061172013-09-06 14:16:12 +0000335 this->style(), this->getQuality());
reed@google.com140d7282013-01-07 20:25:04 +0000336 }
humper@google.coma99a92c2013-02-20 16:42:06 +0000337
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000338 virtual SkBlurQuality getQuality() {
339 return kHigh_SkBlurQuality;
humper@google.coma99a92c2013-02-20 16:42:06 +0000340 }
341private:
342 typedef BlurRectCompareGM INHERITED;
343};
344
345class BlurRectSlowLowGM: public BlurRectSlowGM {
346public:
skia.committer@gmail.comd454ec12013-02-21 07:15:03 +0000347 BlurRectSlowLowGM(const char name[], unsigned int rectWidth, unsigned int rectHeight,
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000348 float blurRadius, SkBlurStyle style)
robertphillips@google.comb7061172013-09-06 14:16:12 +0000349 : INHERITED(name, rectWidth, rectHeight, blurRadius, style) {
humper@google.coma99a92c2013-02-20 16:42:06 +0000350 }
robertphillips@google.comb7061172013-09-06 14:16:12 +0000351
humper@google.coma99a92c2013-02-20 16:42:06 +0000352protected:
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000353 virtual SkBlurQuality getQuality() SK_OVERRIDE {
354 return kLow_SkBlurQuality;
humper@google.coma99a92c2013-02-20 16:42:06 +0000355 }
356private:
357 typedef BlurRectSlowGM INHERITED;
358};
359
360class BlurRectGroundTruthGM: public BlurRectCompareGM {
361public:
skia.committer@gmail.comd454ec12013-02-21 07:15:03 +0000362 BlurRectGroundTruthGM(const char name[], unsigned int rectWidth, unsigned int rectHeight,
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000363 float blurRadius, SkBlurStyle style)
robertphillips@google.comb7061172013-09-06 14:16:12 +0000364 : INHERITED(name, rectWidth, rectHeight, blurRadius, style) {
humper@google.coma99a92c2013-02-20 16:42:06 +0000365 }
robertphillips@google.comb7061172013-09-06 14:16:12 +0000366
humper@google.coma99a92c2013-02-20 16:42:06 +0000367protected:
368 virtual bool makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE {
369 SkMask src;
370 r.roundOut(&src.fBounds);
371 src.fBounds.offset(-src.fBounds.fLeft, -src.fBounds.fTop); // move to origin
372 src.fFormat = SkMask::kA8_Format;
373 src.fRowBytes = src.fBounds.width();
374 src.fImage = SkMask::AllocImage(src.computeTotalImageSize());
375 SkAutoMaskFreeImage amfi(src.fImage);
376
377 memset(src.fImage, 0xff, src.computeTotalImageSize());
378
robertphillips@google.comb7061172013-09-06 14:16:12 +0000379 return SkBlurMask::BlurGroundTruth(SkBlurMask::ConvertRadiusToSigma(this->radius()),
380 m, src, this->style());
humper@google.coma99a92c2013-02-20 16:42:06 +0000381 }
382
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000383 virtual SkBlurQuality getQuality() {
384 return kHigh_SkBlurQuality;
humper@google.coma99a92c2013-02-20 16:42:06 +0000385 }
386private:
387 typedef BlurRectCompareGM INHERITED;
humper@google.com7c7292c2013-01-04 20:29:03 +0000388};
389
390
reed@google.comdb87c962012-11-02 21:11:12 +0000391//////////////////////////////////////////////////////////////////////////////
392
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000393DEF_GM(return new BlurRectGM("blurrects", 0xFF);)
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000394DEF_GM(return new BlurRectDirectGM("blurrect_gallery");)