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