• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
9 #include "SkBlurMask.h"
10 #include "SkBlurMaskFilter.h"
11 #include "SkCanvas.h"
12 #include "SkPath.h"
13 
14 #define STROKE_WIDTH    SkIntToScalar(10)
15 
16 typedef void (*Proc)(SkCanvas*, const SkRect&, const SkPaint&);
17 
fill_rect(SkCanvas * canvas,const SkRect & r,const SkPaint & p)18 static void fill_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
19     canvas->drawRect(r, p);
20 }
21 
draw_donut(SkCanvas * canvas,const SkRect & r,const SkPaint & p)22 static void draw_donut(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
23     SkRect  rect;
24     SkPath  path;
25 
26     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);
31 
32     path.addRect(rect);
33     path.setFillType(SkPath::kEvenOdd_FillType);
34 
35     canvas->drawPath(path, p);
36 }
37 
draw_donut_skewed(SkCanvas * canvas,const SkRect & r,const SkPaint & p)38 static void draw_donut_skewed(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
39     SkRect  rect;
40     SkPath  path;
41 
42     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);
47 
48     rect.offset(7, -7);
49 
50     path.addRect(rect);
51     path.setFillType(SkPath::kEvenOdd_FillType);
52 
53     canvas->drawPath(path, p);
54 }
55 
56 #include "SkGradientShader.h"
57 
58 typedef void (*PaintProc)(SkPaint*, SkScalar width);
59 
60 class BlurRectGM : public skiagm::GM {
61       SkAutoTUnref<SkMaskFilter> fMaskFilters[kLastEnum_SkBlurStyle + 1];
62       SkString  fName;
63       SkAlpha   fAlpha;
64 public:
BlurRectGM(const char name[],U8CPU alpha)65     BlurRectGM(const char name[], U8CPU alpha)
66         : fName(name)
67         , fAlpha(SkToU8(alpha)) {
68     }
69 
70 protected:
onOnceBeforeDraw()71     virtual void onOnceBeforeDraw() SK_OVERRIDE {
72         for (int i = 0; i <= kLastEnum_SkBlurStyle; ++i) {
73             fMaskFilters[i].reset(SkBlurMaskFilter::Create((SkBlurStyle)i,
74                                   SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(STROKE_WIDTH/2)),
75                                   SkBlurMaskFilter::kHighQuality_BlurFlag));
76         }
77     }
78 
onShortName()79     virtual SkString onShortName() {
80         return fName;
81     }
82 
onISize()83     virtual SkISize onISize() {
84         return SkISize::Make(440, 820);
85     }
86 
onDraw(SkCanvas * canvas)87     virtual void onDraw(SkCanvas* canvas) {
88         canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
89 
90         SkRect  r = { 0, 0, 100, 50 };
91         SkScalar scales[] = { SK_Scalar1, 0.6f };
92 
93         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);
115         }
116     }
117 
onGetFlags() const118     virtual uint32_t onGetFlags() const { return kSkipPipe_Flag | kSkipTiled_Flag; }
119 
120 private:
drawProcs(SkCanvas * canvas,const SkRect & r,const SkPaint & paint,bool doClip,const Proc procs[],size_t procsCount)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     }
138 private:
139     typedef GM INHERITED;
140 };
141 
142 
143 class BlurRectDirectGM : public skiagm::GM {
144     SkString  fName;
145     int fGMWidth, fGMHeight;
146     int fPadding, fMargin;
147 public:
BlurRectDirectGM(const char name[])148     BlurRectDirectGM(const char name[])
149         : fName(name),
150           fGMWidth(1200),
151           fGMHeight(1024),
152           fPadding(10),
153           fMargin(100)
154     {
155     }
156 
157 protected:
onShortName()158     virtual SkString onShortName() {
159         return fName;
160     }
161 
onISize()162     virtual SkISize onISize() {
163         return SkISize::Make(fGMWidth, fGMHeight);
164     }
165 
onDraw(SkCanvas * canvas)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();
206                     canvas->translate((SkScalar)cur_x, (SkScalar)cur_y);
207                     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 
onGetFlags() const219     virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
220 
221 private:
222     typedef GM INHERITED;
223 };
224 
225 class BlurRectCompareGM : public skiagm::GM {
226     SkString  fName;
227     unsigned int fRectWidth, fRectHeight;
228     SkScalar fRadius;
229     SkBlurStyle fStyle;
230 public:
BlurRectCompareGM(const char name[],unsigned int rectWidth,unsigned int rectHeight,float radius,SkBlurStyle style)231     BlurRectCompareGM(const char name[], unsigned int rectWidth,
232                       unsigned int rectHeight, float radius,
233                       SkBlurStyle style)
234         : fName(name)
235         , fRectWidth(rectWidth)
236         , fRectHeight(rectHeight)
237         , fRadius(radius)
238         , fStyle(style) {
239     }
width() const240     int width() const {
241         return fRectWidth;
242     }
height() const243     int height() const {
244         return fRectHeight;
245     }
radius() const246     SkScalar radius() const {
247         return fRadius;
248     }
style() const249     SkBlurStyle style() const {
250         return fStyle;
251     }
252 
253 protected:
onShortName()254     virtual SkString onShortName() {
255         return fName;
256     }
257 
onISize()258     virtual SkISize onISize() {
259         return SkISize::Make(640, 480);
260     }
261 
262     virtual bool makeMask(SkMask *m, const SkRect&) = 0;
263 
onDraw(SkCanvas * canvas)264     virtual void onDraw(SkCanvas* canvas) {
265         SkRect r;
266         r.setWH(SkIntToScalar(fRectWidth), SkIntToScalar(fRectHeight));
267 
268         SkISize canvas_size = canvas->getDeviceSize();
269         int center_x = (canvas_size.fWidth - (int)(r.width()))/2;
270         int center_y = (canvas_size.fHeight - (int)(r.height()))/2;
271 
272         SkMask mask;
273 
274         if (!this->makeMask(&mask, r)) {
275             SkPaint paint;
276             r.offset( SkIntToScalar(center_x), SkIntToScalar(center_y) );
277             canvas->drawRect(r,paint);
278             return;
279         }
280         SkAutoMaskFreeImage amfi(mask.fImage);
281 
282         SkBitmap bm;
283         bm.installMaskPixels(mask);
284 
285         center_x = (canvas_size.fWidth - mask.fBounds.width())/2;
286         center_y = (canvas_size.fHeight - mask.fBounds.height())/2;
287 
288         canvas->drawBitmap(bm, SkIntToScalar(center_x), SkIntToScalar(center_y), NULL);
289     }
290 
onGetFlags() const291     virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
292 
293 private:
294     typedef GM INHERITED;
295 };
296 
297 class BlurRectFastGM: public BlurRectCompareGM {
298 public:
BlurRectFastGM(const char name[],unsigned int rectWidth,unsigned int rectHeight,float blurRadius,SkBlurStyle style)299     BlurRectFastGM(const char name[], unsigned int rectWidth,
300                    unsigned int rectHeight, float blurRadius,
301                    SkBlurStyle style) :
302         INHERITED(name, rectWidth, rectHeight, blurRadius, style) {
303         }
304 
305 protected:
makeMask(SkMask * m,const SkRect & r)306     virtual bool makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE {
307         return SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(this->radius()),
308                                     m, r, this->style());
309     }
310 private:
311     typedef BlurRectCompareGM INHERITED;
312 };
313 
314 class BlurRectSlowGM: public BlurRectCompareGM {
315 public:
BlurRectSlowGM(const char name[],unsigned int rectWidth,unsigned int rectHeight,float blurRadius,SkBlurStyle style)316     BlurRectSlowGM(const char name[], unsigned int rectWidth, unsigned int rectHeight,
317                    float blurRadius, SkBlurStyle style)
318         : INHERITED(name, rectWidth, rectHeight, blurRadius, style) {
319         }
320 
321 protected:
makeMask(SkMask * m,const SkRect & r)322     virtual bool makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE {
323         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();
328         src.fImage = SkMask::AllocImage(src.computeTotalImageSize());
329         SkAutoMaskFreeImage amfi(src.fImage);
330 
331         memset(src.fImage, 0xff, src.computeTotalImageSize());
332 
333         return SkBlurMask::BoxBlur(m, src,
334                                    SkBlurMask::ConvertRadiusToSigma(this->radius()),
335                                    this->style(), this->getQuality());
336     }
337 
getQuality()338     virtual SkBlurQuality getQuality() {
339         return kHigh_SkBlurQuality;
340     }
341 private:
342     typedef BlurRectCompareGM INHERITED;
343 };
344 
345 class BlurRectSlowLowGM: public BlurRectSlowGM {
346 public:
BlurRectSlowLowGM(const char name[],unsigned int rectWidth,unsigned int rectHeight,float blurRadius,SkBlurStyle style)347     BlurRectSlowLowGM(const char name[], unsigned int rectWidth, unsigned int rectHeight,
348                       float blurRadius, SkBlurStyle style)
349         : INHERITED(name, rectWidth, rectHeight, blurRadius, style) {
350         }
351 
352 protected:
getQuality()353     virtual SkBlurQuality getQuality() SK_OVERRIDE {
354         return kLow_SkBlurQuality;
355     }
356 private:
357     typedef BlurRectSlowGM INHERITED;
358 };
359 
360 class BlurRectGroundTruthGM: public BlurRectCompareGM {
361 public:
BlurRectGroundTruthGM(const char name[],unsigned int rectWidth,unsigned int rectHeight,float blurRadius,SkBlurStyle style)362     BlurRectGroundTruthGM(const char name[], unsigned int rectWidth, unsigned int rectHeight,
363                           float blurRadius, SkBlurStyle style)
364         : INHERITED(name, rectWidth, rectHeight, blurRadius, style) {
365         }
366 
367 protected:
makeMask(SkMask * m,const SkRect & r)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 
379         return SkBlurMask::BlurGroundTruth(SkBlurMask::ConvertRadiusToSigma(this->radius()),
380                                            m, src, this->style());
381     }
382 
getQuality()383     virtual SkBlurQuality getQuality() {
384         return kHigh_SkBlurQuality;
385     }
386 private:
387     typedef BlurRectCompareGM INHERITED;
388 };
389 
390 
391 //////////////////////////////////////////////////////////////////////////////
392 
393 DEF_GM(return new BlurRectGM("blurrects", 0xFF);)
394 DEF_GM(return new BlurRectDirectGM("blurrect_gallery");)
395