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