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 22 // This GM mimics a blurred RR seen in the wild. 23 class BlurRoundRectGM : public skiagm::GM { 24 public: BlurRoundRectGM(int width,int height,int radius)25 BlurRoundRectGM(int width, int height, int radius) 26 : fName("blurroundrect") 27 { 28 SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 29 fRRect.setRectXY(r, SkIntToScalar(radius), SkIntToScalar(radius)); 30 fName.appendf("-WH-%ix%i-corner-%i", width, height, radius); 31 } 32 BlurRoundRectGM(int width,int height)33 BlurRoundRectGM(int width, int height) 34 : fName("blurroundrect") { 35 fName.appendf("-WH-%ix%i-unevenCorners", width, height); 36 SkVector radii[4]; 37 radii[0].set(SkIntToScalar(30), SkIntToScalar(30)); 38 radii[1].set(SkIntToScalar(10), SkIntToScalar(10)); 39 radii[2].set(SkIntToScalar(30), SkIntToScalar(30)); 40 radii[3].set(SkIntToScalar(10), SkIntToScalar(10)); 41 SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 42 fRRect.setRectRadii(r, radii); 43 } 44 onGetFlags() const45 virtual uint32_t onGetFlags() const SK_OVERRIDE { 46 return kSkipTiled_Flag; 47 } 48 onShortName()49 virtual SkString onShortName() SK_OVERRIDE { 50 return fName; 51 } 52 onISize()53 virtual SkISize onISize() SK_OVERRIDE { 54 return SkISize::Make(SkScalarCeilToInt(fRRect.rect().width()), 55 SkScalarCeilToInt(fRRect.rect().height())); 56 } 57 onDraw(SkCanvas * canvas)58 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 59 SkLayerDrawLooper::Builder looperBuilder; 60 { 61 SkLayerDrawLooper::LayerInfo info; 62 info.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit 63 | SkLayerDrawLooper::kColorFilter_Bit; 64 info.fColorMode = SkXfermode::kSrc_Mode; 65 info.fOffset = SkPoint::Make(SkIntToScalar(-1), SkIntToScalar(0)); 66 info.fPostTranslate = false; 67 SkPaint* paint = looperBuilder.addLayerOnTop(info); 68 SkMaskFilter* maskFilter = SkBlurMaskFilter::Create( 69 kNormal_SkBlurStyle, 70 SkBlurMask::ConvertRadiusToSigma(SK_ScalarHalf), 71 SkBlurMaskFilter::kHighQuality_BlurFlag); 72 paint->setMaskFilter(maskFilter)->unref(); 73 SkColorFilter* colorFilter = SkColorFilter::CreateModeFilter(SK_ColorLTGRAY, 74 SkXfermode::kSrcIn_Mode); 75 paint->setColorFilter(colorFilter)->unref(); 76 paint->setColor(SK_ColorGRAY); 77 } 78 { 79 SkLayerDrawLooper::LayerInfo info; 80 looperBuilder.addLayerOnTop(info); 81 } 82 SkPaint paint; 83 canvas->drawRect(fRRect.rect(), paint); 84 85 paint.setLooper(looperBuilder.detachLooper())->unref(); 86 paint.setColor(SK_ColorCYAN); 87 paint.setAntiAlias(true); 88 89 canvas->drawRRect(fRRect, paint); 90 } 91 92 private: 93 SkString fName; 94 SkRRect fRRect; 95 96 typedef skiagm::GM INHERITED; 97 }; 98 99 // Simpler blurred RR test cases where all the radii are the same. 100 class SimpleBlurRoundRectGM : public skiagm::GM { 101 public: SimpleBlurRoundRectGM()102 SimpleBlurRoundRectGM() 103 : fName("simpleblurroundrect") { 104 } 105 106 protected: onGetFlags() const107 virtual uint32_t onGetFlags() const SK_OVERRIDE { 108 return kSkipTiled_Flag; 109 } 110 onShortName()111 virtual SkString onShortName() SK_OVERRIDE { 112 return fName; 113 } 114 onISize()115 virtual SkISize onISize() SK_OVERRIDE { 116 return SkISize::Make(950, 950); 117 } 118 onDraw(SkCanvas * canvas)119 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 120 canvas->scale(1.5f, 1.5f); 121 canvas->translate(50,50); 122 123 const float blurRadii[] = { 1,5,10,20 }; 124 const int cornerRadii[] = { 1,5,10,20 }; 125 const SkRect r = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100)); 126 for (size_t i = 0; i < SK_ARRAY_COUNT(blurRadii); ++i) { 127 SkAutoCanvasRestore autoRestore(canvas, true); 128 canvas->translate(0, (r.height() + SkIntToScalar(50)) * i); 129 for (size_t j = 0; j < SK_ARRAY_COUNT(cornerRadii); ++j) { 130 SkMaskFilter* filter = SkBlurMaskFilter::Create( 131 kNormal_SkBlurStyle, 132 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(blurRadii[i])), 133 SkBlurMaskFilter::kHighQuality_BlurFlag); 134 SkPaint paint; 135 paint.setColor(SK_ColorBLACK); 136 paint.setMaskFilter(filter)->unref(); 137 138 SkRRect rrect; 139 rrect.setRectXY(r, SkIntToScalar(cornerRadii[j]), SkIntToScalar(cornerRadii[j])); 140 canvas->drawRRect(rrect, paint); 141 canvas->translate(r.width() + SkIntToScalar(50), 0); 142 } 143 } 144 } 145 private: 146 const SkString fName; 147 148 typedef skiagm::GM INHERITED; 149 }; 150 151 // Create one with dimensions/rounded corners based on the skp 152 // 153 // TODO(scroggo): Disabled in an attempt to rememdy 154 // https://code.google.com/p/skia/issues/detail?id=1801 ('Win7 Test bots all failing GenerateGMs: 155 // ran wrong number of tests') 156 //DEF_GM(return new BlurRoundRectGM(600, 5514, 6);) 157 158 // Rounded rect with two opposite corners with large radii, the other two 159 // small. 160 DEF_GM(return new BlurRoundRectGM(100, 100);) 161 162 DEF_GM(return new SimpleBlurRoundRectGM();) 163