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