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 "SkBlurMaskFilter.h" 10 #include "SkBlurMask.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 18 static void fill_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) { 19 canvas->drawRect(r, p); 20 } 21 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 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 static const char* gBlurStyle2Name[] = { 61 "normal", 62 "solid", 63 "outer", 64 "inner" 65 }; 66 67 class BlurRectGM : public skiagm::GM { 68 SkAutoTUnref<SkMaskFilter> fMaskFilter; 69 SkString fName; 70 PaintProc fPProc; 71 SkAlpha fAlpha; 72 public: 73 BlurRectGM(const char name[], PaintProc pproc, U8CPU alpha, 74 SkBlurMaskFilter::BlurStyle bs) : 75 fMaskFilter(SkBlurMaskFilter::Create(STROKE_WIDTH/2, bs, 76 SkBlurMaskFilter::kHighQuality_BlurFlag)) 77 , fName(name) 78 , fPProc(pproc) 79 , fAlpha(SkToU8(alpha)) 80 { 81 fName.appendf("_%s", gBlurStyle2Name[bs]); 82 } 83 84 protected: 85 virtual SkString onShortName() { 86 return fName; 87 } 88 89 virtual SkISize onISize() { 90 return SkISize::Make(640, 480); 91 } 92 93 virtual void onDraw(SkCanvas* canvas) { 94 canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2); 95 96 SkRect r = { 0, 0, 250, 120 }; 97 98 SkPaint paint; 99 paint.setMaskFilter(fMaskFilter); 100 if (fPProc) { 101 fPProc(&paint, r.width()); 102 } 103 paint.setAlpha(fAlpha); 104 105 static const Proc procs[] = { 106 fill_rect, draw_donut, draw_donut_skewed 107 }; 108 109 this->drawProcs(canvas, r, paint, false, procs, SK_ARRAY_COUNT(procs)); 110 canvas->translate(r.width() * 4/3, 0); 111 this->drawProcs(canvas, r, paint, true, procs, SK_ARRAY_COUNT(procs)); 112 } 113 114 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; } 115 116 private: 117 void drawProcs(SkCanvas* canvas, const SkRect& r, const SkPaint& paint, 118 bool doClip, const Proc procs[], size_t procsCount) { 119 SkAutoCanvasRestore acr(canvas, true); 120 for (size_t i = 0; i < procsCount; ++i) { 121 if (doClip) { 122 SkRect clipRect(r); 123 clipRect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2); 124 canvas->save(); 125 canvas->clipRect(r); 126 } 127 procs[i](canvas, r, paint); 128 if (doClip) { 129 canvas->restore(); 130 } 131 canvas->translate(0, r.height() * 4/3); 132 } 133 } 134 135 typedef GM INHERITED; 136 }; 137 138 class BlurRectCompareGM : public skiagm::GM { 139 SkString fName; 140 unsigned int fRectWidth, fRectHeight; 141 SkScalar fRadius; 142 public: 143 BlurRectCompareGM(const char name[], unsigned int rectWidth, unsigned int rectHeight, float radius) 144 : fName(name) 145 , fRectWidth(rectWidth) 146 , fRectHeight(rectHeight) 147 , fRadius(radius) 148 {} 149 150 int width() const { return fRectWidth; } 151 int height() const { return fRectHeight; } 152 SkScalar radius() const { return fRadius; } 153 154 protected: 155 virtual SkString onShortName() { 156 return fName; 157 } 158 159 virtual SkISize onISize() { 160 return SkISize::Make(640, 480); 161 } 162 163 virtual void makeMask(SkMask *m, const SkRect&) = 0; 164 165 virtual void onDraw(SkCanvas* canvas) { 166 SkRect r; 167 r.setWH(SkIntToScalar(fRectWidth), SkIntToScalar(fRectHeight)); 168 169 SkMask mask; 170 171 this->makeMask(&mask, r); 172 SkAutoMaskFreeImage amfi(mask.fImage); 173 174 SkBitmap bm; 175 bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height()); 176 bm.setPixels(mask.fImage); 177 canvas->drawBitmap(bm, 50, 50, NULL); 178 } 179 180 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; } 181 182 private: 183 typedef GM INHERITED; 184 }; 185 186 class BlurRectFastGM: public BlurRectCompareGM { 187 public: 188 BlurRectFastGM(const char name[], unsigned int rect_width, 189 unsigned int rect_height, float blur_radius) : 190 BlurRectCompareGM(name, rect_width, rect_height, blur_radius) {} 191 protected: 192 virtual void makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE { 193 SkBlurMask::BlurRect(m, r, radius(), SkBlurMask::kNormal_Style, 194 SkBlurMask::kHigh_Quality ); 195 } 196 }; 197 198 class BlurRectSlowGM: public BlurRectCompareGM { 199 public: 200 BlurRectSlowGM(const char name[], unsigned int rect_width, unsigned int rect_height, float blur_radius) : 201 BlurRectCompareGM( name, rect_width, rect_height, blur_radius ) {} 202 protected: 203 virtual void makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE { 204 SkMask src; 205 r.roundOut(&src.fBounds); 206 src.fBounds.offset(-src.fBounds.fLeft, -src.fBounds.fTop); // move to origin 207 src.fFormat = SkMask::kA8_Format; 208 src.fRowBytes = src.fBounds.width(); 209 src.fImage = SkMask::AllocImage( src.computeTotalImageSize() ); 210 SkAutoMaskFreeImage amfi(src.fImage); 211 212 memset(src.fImage, 0xff, src.computeTotalImageSize()); 213 214 SkBlurMask::BlurSeparable(m, src, radius()/2, SkBlurMask::kNormal_Style, SkBlurMask::kHigh_Quality); 215 } 216 }; 217 218 219 ////////////////////////////////////////////////////////////////////////////// 220 221 DEF_GM(return new BlurRectGM("blurrect", NULL, 0xFF, SkBlurMaskFilter::kNormal_BlurStyle);) 222 DEF_GM(return new BlurRectGM("blurrect", NULL, 0xFF, SkBlurMaskFilter::kSolid_BlurStyle);) 223 DEF_GM(return new BlurRectGM("blurrect", NULL, 0xFF, SkBlurMaskFilter::kOuter_BlurStyle);) 224 DEF_GM(return new BlurRectGM("blurrect", NULL, 0xFF, SkBlurMaskFilter::kInner_BlurStyle);) 225 226 DEF_GM(return new BlurRectFastGM("blurrect_fast_100_100_10", 100, 100, 10);) 227 DEF_GM(return new BlurRectFastGM("blurrect_fast_100_100_2", 100, 100, 2);) 228 DEF_GM(return new BlurRectFastGM("blurrect_fast_10_10_100", 10, 10, 100);) 229 DEF_GM(return new BlurRectFastGM("blurrect_fast_10_100_10", 10, 100, 10);) 230 231 DEF_GM(return new BlurRectSlowGM("blurrect_slow_100_100_10", 100, 100, 10);) 232 DEF_GM(return new BlurRectSlowGM("blurrect_slow_100_100_2", 100, 100, 2);) 233 DEF_GM(return new BlurRectSlowGM("blurrect_slow_10_10_100", 10, 10, 100);) 234 DEF_GM(return new BlurRectSlowGM("blurrect_slow_10_100_10", 10, 100, 10);) 235