1 /* 2 * Copyright 2011 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 #include "gm.h" 8 #include "SkCanvas.h" 9 #include "SkPaint.h" 10 #include "SkRandom.h" 11 12 namespace skiagm { 13 14 class QuadPathGM : public GM { 15 public: 16 QuadPathGM() {} 17 18 protected: 19 virtual uint32_t onGetFlags() const SK_OVERRIDE { 20 return kSkipTiled_Flag; 21 } 22 23 SkString onShortName() { 24 return SkString("quadpath"); 25 } 26 27 SkISize onISize() { return SkISize::Make(1240, 390); } 28 29 void drawPath(SkPath& path,SkCanvas* canvas,SkColor color, 30 const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join, 31 SkPaint::Style style, SkPath::FillType fill, 32 SkScalar strokeWidth) { 33 path.setFillType(fill); 34 SkPaint paint; 35 paint.setStrokeCap(cap); 36 paint.setStrokeWidth(strokeWidth); 37 paint.setStrokeJoin(join); 38 paint.setColor(color); 39 paint.setStyle(style); 40 canvas->save(); 41 canvas->clipRect(clip); 42 canvas->drawPath(path, paint); 43 canvas->restore(); 44 } 45 46 virtual void onDraw(SkCanvas* canvas) { 47 struct FillAndName { 48 SkPath::FillType fFill; 49 const char* fName; 50 }; 51 static const FillAndName gFills[] = { 52 {SkPath::kWinding_FillType, "Winding"}, 53 {SkPath::kEvenOdd_FillType, "Even / Odd"}, 54 {SkPath::kInverseWinding_FillType, "Inverse Winding"}, 55 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}, 56 }; 57 struct StyleAndName { 58 SkPaint::Style fStyle; 59 const char* fName; 60 }; 61 static const StyleAndName gStyles[] = { 62 {SkPaint::kFill_Style, "Fill"}, 63 {SkPaint::kStroke_Style, "Stroke"}, 64 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, 65 }; 66 struct CapAndName { 67 SkPaint::Cap fCap; 68 SkPaint::Join fJoin; 69 const char* fName; 70 }; 71 static const CapAndName gCaps[] = { 72 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"}, 73 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"}, 74 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"} 75 }; 76 struct PathAndName { 77 SkPath fPath; 78 const char* fName; 79 }; 80 PathAndName path; 81 path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1); 82 path.fPath.quadTo(50*SK_Scalar1, 20*SK_Scalar1, 83 75*SK_Scalar1, 10*SK_Scalar1); 84 path.fName = "moveTo-quad"; 85 86 SkPaint titlePaint; 87 titlePaint.setColor(SK_ColorBLACK); 88 titlePaint.setAntiAlias(true); 89 titlePaint.setLCDRenderText(true); 90 titlePaint.setTextSize(15 * SK_Scalar1); 91 const char title[] = "Quad Drawn Into Rectangle Clips With " 92 "Indicated Style, Fill and Linecaps, with stroke width 10"; 93 canvas->drawText(title, strlen(title), 94 20 * SK_Scalar1, 95 20 * SK_Scalar1, 96 titlePaint); 97 98 SkLCGRandom rand; 99 SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1); 100 canvas->save(); 101 canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1); 102 canvas->save(); 103 for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) { 104 if (0 < cap) { 105 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0); 106 } 107 canvas->save(); 108 for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) { 109 if (0 < fill) { 110 canvas->translate(0, rect.height() + 40 * SK_Scalar1); 111 } 112 canvas->save(); 113 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) { 114 if (0 < style) { 115 canvas->translate(rect.width() + 40 * SK_Scalar1, 0); 116 } 117 118 SkColor color = 0xff007000; 119 this->drawPath(path.fPath, canvas, color, rect, 120 gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle, 121 gFills[fill].fFill, SK_Scalar1*10); 122 123 SkPaint rectPaint; 124 rectPaint.setColor(SK_ColorBLACK); 125 rectPaint.setStyle(SkPaint::kStroke_Style); 126 rectPaint.setStrokeWidth(-1); 127 rectPaint.setAntiAlias(true); 128 canvas->drawRect(rect, rectPaint); 129 130 SkPaint labelPaint; 131 labelPaint.setColor(color); 132 labelPaint.setAntiAlias(true); 133 labelPaint.setLCDRenderText(true); 134 labelPaint.setTextSize(10 * SK_Scalar1); 135 canvas->drawText(gStyles[style].fName, 136 strlen(gStyles[style].fName), 137 0, rect.height() + 12 * SK_Scalar1, 138 labelPaint); 139 canvas->drawText(gFills[fill].fName, 140 strlen(gFills[fill].fName), 141 0, rect.height() + 24 * SK_Scalar1, 142 labelPaint); 143 canvas->drawText(gCaps[cap].fName, 144 strlen(gCaps[cap].fName), 145 0, rect.height() + 36 * SK_Scalar1, 146 labelPaint); 147 } 148 canvas->restore(); 149 } 150 canvas->restore(); 151 } 152 canvas->restore(); 153 canvas->restore(); 154 } 155 156 private: 157 typedef GM INHERITED; 158 }; 159 160 class QuadClosePathGM : public GM { 161 public: 162 QuadClosePathGM() {} 163 164 protected: 165 virtual uint32_t onGetFlags() const SK_OVERRIDE { 166 return kSkipTiled_Flag; 167 } 168 169 SkString onShortName() { 170 return SkString("quadclosepath"); 171 } 172 173 SkISize onISize() { return SkISize::Make(1240, 390); } 174 175 void drawPath(SkPath& path,SkCanvas* canvas,SkColor color, 176 const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join, 177 SkPaint::Style style, SkPath::FillType fill, 178 SkScalar strokeWidth) { 179 path.setFillType(fill); 180 SkPaint paint; 181 paint.setStrokeCap(cap); 182 paint.setStrokeWidth(strokeWidth); 183 paint.setStrokeJoin(join); 184 paint.setColor(color); 185 paint.setStyle(style); 186 canvas->save(); 187 canvas->clipRect(clip); 188 canvas->drawPath(path, paint); 189 canvas->restore(); 190 } 191 192 virtual void onDraw(SkCanvas* canvas) { 193 struct FillAndName { 194 SkPath::FillType fFill; 195 const char* fName; 196 }; 197 static const FillAndName gFills[] = { 198 {SkPath::kWinding_FillType, "Winding"}, 199 {SkPath::kEvenOdd_FillType, "Even / Odd"}, 200 {SkPath::kInverseWinding_FillType, "Inverse Winding"}, 201 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}, 202 }; 203 struct StyleAndName { 204 SkPaint::Style fStyle; 205 const char* fName; 206 }; 207 static const StyleAndName gStyles[] = { 208 {SkPaint::kFill_Style, "Fill"}, 209 {SkPaint::kStroke_Style, "Stroke"}, 210 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, 211 }; 212 struct CapAndName { 213 SkPaint::Cap fCap; 214 SkPaint::Join fJoin; 215 const char* fName; 216 }; 217 static const CapAndName gCaps[] = { 218 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"}, 219 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"}, 220 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"} 221 }; 222 struct PathAndName { 223 SkPath fPath; 224 const char* fName; 225 }; 226 PathAndName path; 227 path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1); 228 path.fPath.quadTo(50*SK_Scalar1, 20*SK_Scalar1, 229 75*SK_Scalar1, 10*SK_Scalar1); 230 path.fPath.close(); 231 path.fName = "moveTo-quad-close"; 232 233 SkPaint titlePaint; 234 titlePaint.setColor(SK_ColorBLACK); 235 titlePaint.setAntiAlias(true); 236 titlePaint.setLCDRenderText(true); 237 titlePaint.setTextSize(15 * SK_Scalar1); 238 const char title[] = "Quad Closed Drawn Into Rectangle Clips With " 239 "Indicated Style, Fill and Linecaps, with stroke width 10"; 240 canvas->drawText(title, strlen(title), 241 20 * SK_Scalar1, 242 20 * SK_Scalar1, 243 titlePaint); 244 245 SkLCGRandom rand; 246 SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1); 247 canvas->save(); 248 canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1); 249 canvas->save(); 250 for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) { 251 if (0 < cap) { 252 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0); 253 } 254 canvas->save(); 255 for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) { 256 if (0 < fill) { 257 canvas->translate(0, rect.height() + 40 * SK_Scalar1); 258 } 259 canvas->save(); 260 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) { 261 if (0 < style) { 262 canvas->translate(rect.width() + 40 * SK_Scalar1, 0); 263 } 264 265 SkColor color = 0xff007000; 266 this->drawPath(path.fPath, canvas, color, rect, 267 gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle, 268 gFills[fill].fFill, SK_Scalar1*10); 269 270 SkPaint rectPaint; 271 rectPaint.setColor(SK_ColorBLACK); 272 rectPaint.setStyle(SkPaint::kStroke_Style); 273 rectPaint.setStrokeWidth(-1); 274 rectPaint.setAntiAlias(true); 275 canvas->drawRect(rect, rectPaint); 276 277 SkPaint labelPaint; 278 labelPaint.setColor(color); 279 labelPaint.setAntiAlias(true); 280 labelPaint.setLCDRenderText(true); 281 labelPaint.setTextSize(10 * SK_Scalar1); 282 canvas->drawText(gStyles[style].fName, 283 strlen(gStyles[style].fName), 284 0, rect.height() + 12 * SK_Scalar1, 285 labelPaint); 286 canvas->drawText(gFills[fill].fName, 287 strlen(gFills[fill].fName), 288 0, rect.height() + 24 * SK_Scalar1, 289 labelPaint); 290 canvas->drawText(gCaps[cap].fName, 291 strlen(gCaps[cap].fName), 292 0, rect.height() + 36 * SK_Scalar1, 293 labelPaint); 294 } 295 canvas->restore(); 296 } 297 canvas->restore(); 298 } 299 canvas->restore(); 300 canvas->restore(); 301 } 302 303 private: 304 typedef GM INHERITED; 305 }; 306 307 ////////////////////////////////////////////////////////////////////////////// 308 309 static GM* QuadPathFactory(void*) { return new QuadPathGM; } 310 static GMRegistry regQuadPath(QuadPathFactory); 311 312 static GM* QuadClosePathFactory(void*) { return new QuadClosePathGM; } 313 static GMRegistry regQuadClosePath(QuadClosePathFactory); 314 315 } 316