1 2/* 3 * Copyright 2013 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9#include "gm.h" 10#include "SkTArray.h" 11#include "SkRandom.h" 12#include "SkMatrix.h" 13#include "SkBlurMaskFilter.h" 14#include "SkGradientShader.h" 15#include "SkBlurDrawLooper.h" 16#include "SkRect.h" 17#include "SkRRect.h" 18 19namespace skiagm { 20 21class RoundRectGM : public GM { 22public: 23 RoundRectGM() { 24 this->setBGColor(0xFF000000); 25 this->makePaints(); 26 this->makeMatrices(); 27 } 28 29protected: 30 31 SkString onShortName() override { 32 return SkString("roundrects"); 33 } 34 35 SkISize onISize() override { 36 return SkISize::Make(1200, 900); 37 } 38 39 void makePaints() { 40 { 41 // no AA 42 SkPaint p; 43 fPaints.push_back(p); 44 } 45 46 { 47 // AA 48 SkPaint p; 49 p.setAntiAlias(true); 50 fPaints.push_back(p); 51 } 52 53 { 54 // AA with stroke style 55 SkPaint p; 56 p.setAntiAlias(true); 57 p.setStyle(SkPaint::kStroke_Style); 58 p.setStrokeWidth(SkIntToScalar(5)); 59 fPaints.push_back(p); 60 } 61 62 { 63 // AA with stroke style, width = 0 64 SkPaint p; 65 p.setAntiAlias(true); 66 p.setStyle(SkPaint::kStroke_Style); 67 fPaints.push_back(p); 68 } 69 70 { 71 // AA with stroke and fill style 72 SkPaint p; 73 p.setAntiAlias(true); 74 p.setStyle(SkPaint::kStrokeAndFill_Style); 75 p.setStrokeWidth(SkIntToScalar(3)); 76 fPaints.push_back(p); 77 } 78 } 79 80 void makeMatrices() { 81 { 82 SkMatrix m; 83 m.setIdentity(); 84 fMatrices.push_back(m); 85 } 86 87 { 88 SkMatrix m; 89 m.setScale(SkIntToScalar(3), SkIntToScalar(2)); 90 fMatrices.push_back(m); 91 } 92 93 { 94 SkMatrix m; 95 m.setScale(SkIntToScalar(2), SkIntToScalar(2)); 96 fMatrices.push_back(m); 97 } 98 99 { 100 SkMatrix m; 101 m.setScale(SkIntToScalar(1), SkIntToScalar(2)); 102 fMatrices.push_back(m); 103 } 104 105 { 106 SkMatrix m; 107 m.setScale(SkIntToScalar(4), SkIntToScalar(1)); 108 fMatrices.push_back(m); 109 } 110 111 { 112 SkMatrix m; 113 m.setRotate(SkIntToScalar(90)); 114 fMatrices.push_back(m); 115 } 116 117 { 118 SkMatrix m; 119 m.setSkew(SkIntToScalar(2), SkIntToScalar(3)); 120 fMatrices.push_back(m); 121 } 122 123 { 124 SkMatrix m; 125 m.setRotate(SkIntToScalar(60)); 126 fMatrices.push_back(m); 127 } 128 } 129 130 SkColor genColor(SkRandom* rand) { 131 SkScalar hsv[3]; 132 hsv[0] = rand->nextRangeF(0.0f, 360.0f); 133 hsv[1] = rand->nextRangeF(0.75f, 1.0f); 134 hsv[2] = rand->nextRangeF(0.75f, 1.0f); 135 136 return SkHSVToColor(hsv); 137 } 138 139 void onDraw(SkCanvas* canvas) override { 140 SkRandom rand(1); 141 canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1); 142 SkRect rect = SkRect::MakeLTRB(-20, -30, 20, 30); 143 SkRRect circleRect; 144 circleRect.setRectXY(rect, 5, 5); 145 146 const SkScalar kXStart = 60.0f; 147 const SkScalar kYStart = 80.0f; 148 const int kXStep = 150; 149 const int kYStep = 160; 150 int maxX = fMatrices.count(); 151 152 SkPaint rectPaint; 153 rectPaint.setAntiAlias(true); 154 rectPaint.setStyle(SkPaint::kStroke_Style); 155 rectPaint.setStrokeWidth(SkIntToScalar(0)); 156 rectPaint.setColor(SK_ColorLTGRAY); 157 158 int testCount = 0; 159 for (int i = 0; i < fPaints.count(); ++i) { 160 for (int j = 0; j < fMatrices.count(); ++j) { 161 canvas->save(); 162 SkMatrix mat = fMatrices[j]; 163 // position the roundrect, and make it at off-integer coords. 164 mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) + 165 SK_Scalar1 / 4, 166 kYStart + SK_Scalar1 * kYStep * (testCount / maxX) + 167 3 * SK_Scalar1 / 4); 168 canvas->concat(mat); 169 170 SkColor color = genColor(&rand); 171 fPaints[i].setColor(color); 172 173 canvas->drawRect(rect, rectPaint); 174 canvas->drawRRect(circleRect, fPaints[i]); 175 176 canvas->restore(); 177 178 ++testCount; 179 } 180 } 181 182 // special cases 183 184 // non-scaled tall and skinny roundrect 185 for (int i = 0; i < fPaints.count(); ++i) { 186 SkRect rect = SkRect::MakeLTRB(-20, -60, 20, 60); 187 SkRRect ellipseRect; 188 ellipseRect.setRectXY(rect, 5, 10); 189 190 canvas->save(); 191 // position the roundrect, and make it at off-integer coords. 192 canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4, 193 kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4); 194 195 SkColor color = genColor(&rand); 196 fPaints[i].setColor(color); 197 198 canvas->drawRect(rect, rectPaint); 199 canvas->drawRRect(ellipseRect, fPaints[i]); 200 canvas->restore(); 201 } 202 203 // non-scaled wide and short roundrect 204 for (int i = 0; i < fPaints.count(); ++i) { 205 SkRect rect = SkRect::MakeLTRB(-80, -30, 80, 30); 206 SkRRect ellipseRect; 207 ellipseRect.setRectXY(rect, 20, 5); 208 209 canvas->save(); 210 // position the roundrect, and make it at off-integer coords. 211 canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4, 212 kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + 213 SK_ScalarHalf * kYStep); 214 215 SkColor color = genColor(&rand); 216 fPaints[i].setColor(color); 217 218 canvas->drawRect(rect, rectPaint); 219 canvas->drawRRect(ellipseRect, fPaints[i]); 220 canvas->restore(); 221 } 222 223 // super skinny roundrect 224 for (int i = 0; i < fPaints.count(); ++i) { 225 SkRect rect = SkRect::MakeLTRB(0, -60, 1, 60); 226 SkRRect circleRect; 227 circleRect.setRectXY(rect, 5, 5); 228 229 canvas->save(); 230 // position the roundrect, and make it at off-integer coords. 231 canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4, 232 kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4); 233 234 SkColor color = genColor(&rand); 235 fPaints[i].setColor(color); 236 237 canvas->drawRRect(circleRect, fPaints[i]); 238 canvas->restore(); 239 } 240 241 // super short roundrect 242 for (int i = 0; i < fPaints.count(); ++i) { 243 SkRect rect = SkRect::MakeLTRB(-80, -1, 80, 0); 244 SkRRect circleRect; 245 circleRect.setRectXY(rect, 5, 5); 246 247 canvas->save(); 248 // position the roundrect, and make it at off-integer coords. 249 canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4, 250 kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + 251 SK_ScalarHalf * kYStep); 252 253 SkColor color = genColor(&rand); 254 fPaints[i].setColor(color); 255 256 canvas->drawRRect(circleRect, fPaints[i]); 257 canvas->restore(); 258 } 259 260 // radial gradient 261 SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0)); 262 SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN }; 263 SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 }; 264 SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(center, 265 SkIntToScalar(20), 266 colors, 267 pos, 268 SK_ARRAY_COUNT(colors), 269 SkShader::kClamp_TileMode)); 270 271 for (int i = 0; i < fPaints.count(); ++i) { 272 canvas->save(); 273 // position the path, and make it at off-integer coords. 274 canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4, 275 kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + 276 SK_ScalarHalf * kYStep); 277 278 SkColor color = genColor(&rand); 279 fPaints[i].setColor(color); 280 fPaints[i].setShader(shader); 281 282 canvas->drawRect(rect, rectPaint); 283 canvas->drawRRect(circleRect, fPaints[i]); 284 285 fPaints[i].setShader(NULL); 286 287 canvas->restore(); 288 } 289 290 // strokes and radii 291 { 292 SkScalar radii[][2] = { 293 {10,10}, 294 {5,15}, 295 {5,15}, 296 {5,15} 297 }; 298 299 SkScalar strokeWidths[] = { 300 20, 10, 20, 40 301 }; 302 303 for (int i = 0; i < 4; ++i) { 304 SkRRect circleRect; 305 circleRect.setRectXY(rect, radii[i][0], radii[i][1]); 306 307 canvas->save(); 308 // position the roundrect, and make it at off-integer coords. 309 canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4, 310 kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + 311 SK_ScalarHalf * kYStep); 312 313 SkColor color = genColor(&rand); 314 315 SkPaint p; 316 p.setAntiAlias(true); 317 p.setStyle(SkPaint::kStroke_Style); 318 p.setStrokeWidth(strokeWidths[i]); 319 p.setColor(color); 320 321 canvas->drawRRect(circleRect, p); 322 canvas->restore(); 323 } 324 } 325 326 } 327 328private: 329 SkTArray<SkPaint> fPaints; 330 SkTArray<SkMatrix> fMatrices; 331 332 typedef GM INHERITED; 333}; 334 335////////////////////////////////////////////////////////////////////////////// 336 337static GM* MyFactory(void*) { return new RoundRectGM; } 338static GMRegistry reg(MyFactory); 339 340} 341