blurroundrect.cpp revision 770269d962ffeb2913ba7b495b5aa08e2e962272
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.h" 9#include "SkBlurMask.h" 10#include "SkBlurMaskFilter.h" 11#include "SkCanvas.h" 12#include "SkColorFilter.h" 13#include "SkLayerDrawLooper.h" 14#include "SkPaint.h" 15#include "SkPath.h" 16#include "SkPoint.h" 17#include "SkRect.h" 18#include "SkRRect.h" 19#include "SkString.h" 20#include "SkXfermode.h" 21 22class BlurRoundRectGM : public skiagm::GM { 23public: 24 BlurRoundRectGM(int width, int height, 25 // X and Y radii for the upper left corner 26 int ulX, int ulY, 27 // X and Y radii for the upper right corner 28 int urX, int urY, 29 // X and Y radii for the lower right corner 30 int lrX, int lrY, 31 // X and Y radii for the lower left corner 32 int llX, int llY, 33 int scaleX, int scaleY) 34 : fName("blurroundrect") 35 , fWidth(width) 36 , fHeight(height) 37 , fScaleX(SkIntToScalar(scaleX)) 38 , fScaleY(SkIntToScalar(scaleY)) { 39 fName.appendf("-WH[%ix%i]-UL[%ix%i]-UR[%ix%i]-LR[%ix%i]-LL[%ix%i]-scale[%ix%i]", 40 width, height, 41 ulX, ulY, 42 urX, urY, 43 lrX, lrY, 44 llX, llY, 45 scaleX, scaleY); 46 SkVector radii[4]; 47 radii[0].set(SkIntToScalar(ulX), SkIntToScalar(ulY)); 48 radii[1].set(SkIntToScalar(urX), SkIntToScalar(urY)); 49 radii[2].set(SkIntToScalar(lrX), SkIntToScalar(lrY)); 50 radii[3].set(SkIntToScalar(llX), SkIntToScalar(llY)); 51 SkRect r = SkRect::MakeWH(SkIntToScalar(fWidth), SkIntToScalar(fHeight)); 52 fRRect.setRectRadii(r, radii); 53 } 54 55 virtual SkString onShortName() SK_OVERRIDE { 56 return fName; 57 } 58 59 virtual SkISize onISize() SK_OVERRIDE { 60 SkISize size = this->getUnscaledSize(); 61 return SkISize::Make(SkScalarCeilToInt(SkScalarMul(size.fWidth, fScaleX)), 62 SkScalarCeilToInt(SkScalarMul(size.fHeight, fScaleY))); 63 } 64 65 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 66 canvas->scale(fScaleX, fScaleY); 67 } 68 69 const SkRRect& getRRect() const { 70 return fRRect; 71 } 72 73 // The subclass will implement this to inform us how big they 74 // draw before scaling. 75 virtual SkISize getUnscaledSize() const = 0; 76 77 // So subclasses can modify the name. 78 SkString* getName() { 79 return &fName; 80 } 81 82private: 83 SkString fName; 84 const int fWidth; 85 const int fHeight; 86 const SkScalar fScaleX; 87 const SkScalar fScaleY; 88 SkRRect fRRect; 89 typedef skiagm::GM INHERITED; 90}; 91 92class SKPBlurRoundRectGM : public BlurRoundRectGM { 93public: 94 SKPBlurRoundRectGM(int width, int height, 95 int ulX, int ulY, 96 int urX, int urY, 97 int lrX, int lrY, 98 int llX, int llY, 99 int scaleX, int scaleY) 100 : INHERITED(width, height, ulX, ulY, urX, urY, lrX, lrY, llX, llY, scaleX, scaleY) { 101 this->getName()->prepend("skp-"); 102 } 103 104protected: 105 virtual SkISize getUnscaledSize() const SK_OVERRIDE { 106 return SkISize::Make(SkScalarCeilToInt(this->getRRect().rect().width()), 107 SkScalarCeilToInt(this->getRRect().rect().height())); 108 } 109 110 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 111 this->INHERITED::onDraw(canvas); 112 SkLayerDrawLooper* looper = new SkLayerDrawLooper; 113 { 114 SkLayerDrawLooper::LayerInfo info; 115 info.fFlagsMask = 0; 116 info.fPaintBits = 40; 117 info.fColorMode = SkXfermode::kSrc_Mode; 118 info.fOffset = SkPoint::Make(SkIntToScalar(-1), SkIntToScalar(0)); 119 info.fPostTranslate = false; 120 SkPaint* paint = looper->addLayerOnTop(info); 121 SkMaskFilter* maskFilter = SkBlurMaskFilter::Create(SK_ScalarHalf, 122 SkBlurMaskFilter::kNormal_BlurStyle, 123 SkBlurMaskFilter::kHighQuality_BlurFlag); 124 paint->setMaskFilter(maskFilter)->unref(); 125 SkColorFilter* colorFilter = SkColorFilter::CreateModeFilter(SK_ColorLTGRAY, 126 SkXfermode::kSrcIn_Mode); 127 paint->setColorFilter(colorFilter)->unref(); 128 paint->setColor(SK_ColorGRAY); 129 } 130 { 131 SkLayerDrawLooper::LayerInfo info; 132 looper->addLayerOnTop(info); 133 } 134 SkPaint paint; 135 canvas->drawRect(this->getRRect().rect(), paint); 136 137 paint.setLooper(looper)->unref(); 138 paint.setColor(SK_ColorCYAN); 139 paint.setAntiAlias(true); 140 141 canvas->drawRRect(this->getRRect(), paint); 142 } 143 144private: 145 typedef BlurRoundRectGM INHERITED; 146}; 147 148class SimpleBlurRoundRectGM : public BlurRoundRectGM { 149public: 150 SimpleBlurRoundRectGM(int width, int height, 151 int blurRadius, int cornerRadius, 152 int scaleX = 1, int scaleY = 1) 153 : INHERITED(width, height, cornerRadius, cornerRadius, 154 cornerRadius, cornerRadius, cornerRadius, 155 cornerRadius, cornerRadius, cornerRadius, scaleX, scaleY) 156 , fBlurRadius(blurRadius) { 157 // For now at least, change the name to reflect only the 158 // variables that are changing. 159 this->getName()->printf("blurround-blur[%i]-corner[%i]-scale[%ix%i]", fBlurRadius, cornerRadius, scaleX, scaleY); 160 } 161 162protected: 163 virtual SkISize getUnscaledSize() const SK_OVERRIDE { 164 return SkISize::Make(SkScalarCeilToInt(this->getRRect().rect().width() + 20), 165 SkScalarCeilToInt(this->getRRect().rect().height() + 20)); 166 } 167 168 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 169 // Handle the scaling. 170 this->INHERITED::onDraw(canvas); 171 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 172 SkMaskFilter* filter = SkBlurMaskFilter::Create(fBlurRadius, 173 SkBlurMaskFilter::kNormal_BlurStyle); 174 SkPaint paint; 175 paint.setColor(SK_ColorBLUE); 176 paint.setMaskFilter(filter)->unref(); 177 canvas->drawRRect(this->getRRect(), paint); 178 } 179private: 180 const int fBlurRadius; 181 182 typedef BlurRoundRectGM INHERITED; 183}; 184 185// Create one with dimensions/rounded corners based on the skp 186DEF_GM(return new SKPBlurRoundRectGM(600, 5514, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1);) 187// Same radii, much smaller rectangle 188DEF_GM(return new SKPBlurRoundRectGM(100, 100, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2);) 189// Rounded rect with two opposite corners with large radii, the other two 190// small. 191DEF_GM(return new SKPBlurRoundRectGM(100, 100, 30, 30, 10, 10, 30, 30, 10, 10, 3, 4);) 192DEF_GM(return new SKPBlurRoundRectGM(100, 100, 90, 90, 90, 90, 90, 90, 90, 90, 2, 3);) 193 194// Try a few blur values with a small corner radius 195DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 1, 1)); 196DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 3, 1, 2, 2)); 197DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 6, 1)); 198DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 10, 1, 3, 3)); 199 200// Now a few blur values with a larger corner radius 201DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 1, 3, 2, 2)); 202DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 3, 3)); 203DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 6, 3, 3, 3)); 204DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 10, 3)); 205 206// Even larger corner radius 207DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 1, 6, 2, 4)); 208DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 3, 6)); 209DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 6, 6)); 210DEF_GM(return new SimpleBlurRoundRectGM(100, 100, 10, 6, 1, 3)); 211 212