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