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