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