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 8#include "gm.h" 9#include "sk_tool_utils.h" 10#include "SkCanvas.h" 11#include "SkPaint.h" 12#include "SkPath.h" 13#include "SkRandom.h" 14 15namespace skiagm { 16 17class QuadPathGM : public GM { 18public: 19 QuadPathGM() {} 20 21protected: 22 23 SkString onShortName() override { 24 return SkString("quadpath"); 25 } 26 27 SkISize onISize() override { 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 void onDraw(SkCanvas* canvas) override { 47 struct FillAndName { 48 SkPath::FillType fFill; 49 const char* fName; 50 }; 51 constexpr 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 constexpr 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 constexpr 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.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->drawString(title, 94 20 * SK_Scalar1, 95 20 * SK_Scalar1, 96 titlePaint); 97 98 SkRandom 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 = sk_tool_utils::color_to_565(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 sk_tool_utils::set_portable_typeface(&labelPaint); 134 labelPaint.setTextSize(10 * SK_Scalar1); 135 canvas->drawString(gStyles[style].fName, 136 0, rect.height() + 12 * SK_Scalar1, 137 labelPaint); 138 canvas->drawString(gFills[fill].fName, 139 0, rect.height() + 24 * SK_Scalar1, 140 labelPaint); 141 canvas->drawString(gCaps[cap].fName, 142 0, rect.height() + 36 * SK_Scalar1, 143 labelPaint); 144 } 145 canvas->restore(); 146 } 147 canvas->restore(); 148 } 149 canvas->restore(); 150 canvas->restore(); 151 } 152 153private: 154 typedef GM INHERITED; 155}; 156 157class QuadClosePathGM : public GM { 158public: 159 QuadClosePathGM() {} 160 161protected: 162 163 SkString onShortName() override { 164 return SkString("quadclosepath"); 165 } 166 167 SkISize onISize() override { return SkISize::Make(1240, 390); } 168 169 void drawPath(SkPath& path,SkCanvas* canvas,SkColor color, 170 const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join, 171 SkPaint::Style style, SkPath::FillType fill, 172 SkScalar strokeWidth) { 173 path.setFillType(fill); 174 SkPaint paint; 175 paint.setStrokeCap(cap); 176 paint.setStrokeWidth(strokeWidth); 177 paint.setStrokeJoin(join); 178 paint.setColor(color); 179 paint.setStyle(style); 180 canvas->save(); 181 canvas->clipRect(clip); 182 canvas->drawPath(path, paint); 183 canvas->restore(); 184 } 185 186 void onDraw(SkCanvas* canvas) override { 187 struct FillAndName { 188 SkPath::FillType fFill; 189 const char* fName; 190 }; 191 constexpr FillAndName gFills[] = { 192 {SkPath::kWinding_FillType, "Winding"}, 193 {SkPath::kEvenOdd_FillType, "Even / Odd"}, 194 {SkPath::kInverseWinding_FillType, "Inverse Winding"}, 195 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}, 196 }; 197 struct StyleAndName { 198 SkPaint::Style fStyle; 199 const char* fName; 200 }; 201 constexpr StyleAndName gStyles[] = { 202 {SkPaint::kFill_Style, "Fill"}, 203 {SkPaint::kStroke_Style, "Stroke"}, 204 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, 205 }; 206 struct CapAndName { 207 SkPaint::Cap fCap; 208 SkPaint::Join fJoin; 209 const char* fName; 210 }; 211 constexpr CapAndName gCaps[] = { 212 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"}, 213 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"}, 214 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"} 215 }; 216 struct PathAndName { 217 SkPath fPath; 218 const char* fName; 219 }; 220 PathAndName path; 221 path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1); 222 path.fPath.quadTo(50*SK_Scalar1, 20*SK_Scalar1, 223 75*SK_Scalar1, 10*SK_Scalar1); 224 path.fPath.close(); 225 path.fName = "moveTo-quad-close"; 226 227 SkPaint titlePaint; 228 titlePaint.setColor(SK_ColorBLACK); 229 titlePaint.setAntiAlias(true); 230 sk_tool_utils::set_portable_typeface(&titlePaint); 231 titlePaint.setTextSize(15 * SK_Scalar1); 232 const char title[] = "Quad Closed Drawn Into Rectangle Clips With " 233 "Indicated Style, Fill and Linecaps, with stroke width 10"; 234 canvas->drawString(title, 235 20 * SK_Scalar1, 236 20 * SK_Scalar1, 237 titlePaint); 238 239 SkRandom rand; 240 SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1); 241 canvas->save(); 242 canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1); 243 canvas->save(); 244 for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) { 245 if (0 < cap) { 246 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0); 247 } 248 canvas->save(); 249 for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) { 250 if (0 < fill) { 251 canvas->translate(0, rect.height() + 40 * SK_Scalar1); 252 } 253 canvas->save(); 254 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) { 255 if (0 < style) { 256 canvas->translate(rect.width() + 40 * SK_Scalar1, 0); 257 } 258 259 SkColor color = sk_tool_utils::color_to_565(0xff007000); 260 this->drawPath(path.fPath, canvas, color, rect, 261 gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle, 262 gFills[fill].fFill, SK_Scalar1*10); 263 264 SkPaint rectPaint; 265 rectPaint.setColor(SK_ColorBLACK); 266 rectPaint.setStyle(SkPaint::kStroke_Style); 267 rectPaint.setStrokeWidth(-1); 268 rectPaint.setAntiAlias(true); 269 canvas->drawRect(rect, rectPaint); 270 271 SkPaint labelPaint; 272 labelPaint.setColor(color); 273 labelPaint.setAntiAlias(true); 274 sk_tool_utils::set_portable_typeface(&labelPaint); 275 labelPaint.setTextSize(10 * SK_Scalar1); 276 canvas->drawString(gStyles[style].fName, 277 0, rect.height() + 12 * SK_Scalar1, 278 labelPaint); 279 canvas->drawString(gFills[fill].fName, 280 0, rect.height() + 24 * SK_Scalar1, 281 labelPaint); 282 canvas->drawString(gCaps[cap].fName, 283 0, rect.height() + 36 * SK_Scalar1, 284 labelPaint); 285 } 286 canvas->restore(); 287 } 288 canvas->restore(); 289 } 290 canvas->restore(); 291 canvas->restore(); 292 } 293 294private: 295 typedef GM INHERITED; 296}; 297 298////////////////////////////////////////////////////////////////////////////// 299 300static GM* QuadPathFactory(void*) { return new QuadPathGM; } 301static GMRegistry regQuadPath(QuadPathFactory); 302 303static GM* QuadClosePathFactory(void*) { return new QuadClosePathGM; } 304static GMRegistry regQuadClosePath(QuadClosePathFactory); 305 306} 307