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 "sk_tool_utils.h" 9 #include "SkCanvas.h" 10 #include "SkPaint.h" 11 #include "SkPath.h" 12 #include "SkRandom.h" 13 14 namespace skiagm { 15 16 class EmptyPathGM : public GM { 17 public: 18 EmptyPathGM() {} 19 20 protected: 21 SkString onShortName() { 22 return SkString("emptypath"); 23 } 24 25 SkISize onISize() { return SkISize::Make(600, 280); } 26 27 void drawEmpty(SkCanvas* canvas, 28 SkColor color, 29 const SkRect& clip, 30 SkPaint::Style style, 31 SkPath::FillType fill) { 32 SkPath path; 33 path.setFillType(fill); 34 SkPaint paint; 35 paint.setColor(color); 36 paint.setStyle(style); 37 canvas->save(); 38 canvas->clipRect(clip); 39 canvas->drawPath(path, paint); 40 canvas->restore(); 41 } 42 43 virtual void onDraw(SkCanvas* canvas) { 44 struct FillAndName { 45 SkPath::FillType fFill; 46 const char* fName; 47 }; 48 constexpr FillAndName gFills[] = { 49 {SkPath::kWinding_FillType, "Winding"}, 50 {SkPath::kEvenOdd_FillType, "Even / Odd"}, 51 {SkPath::kInverseWinding_FillType, "Inverse Winding"}, 52 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}, 53 }; 54 struct StyleAndName { 55 SkPaint::Style fStyle; 56 const char* fName; 57 }; 58 constexpr StyleAndName gStyles[] = { 59 {SkPaint::kFill_Style, "Fill"}, 60 {SkPaint::kStroke_Style, "Stroke"}, 61 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, 62 }; 63 64 SkPaint titlePaint; 65 titlePaint.setColor(SK_ColorBLACK); 66 titlePaint.setAntiAlias(true); 67 sk_tool_utils::set_portable_typeface(&titlePaint); 68 titlePaint.setTextSize(15 * SK_Scalar1); 69 const char title[] = "Empty Paths Drawn Into Rectangle Clips With " 70 "Indicated Style and Fill"; 71 canvas->drawString(title, 72 20 * SK_Scalar1, 73 20 * SK_Scalar1, 74 titlePaint); 75 76 SkRandom rand; 77 SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1); 78 int i = 0; 79 canvas->save(); 80 canvas->translate(10 * SK_Scalar1, 0); 81 canvas->save(); 82 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) { 83 for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) { 84 if (0 == i % 4) { 85 canvas->restore(); 86 canvas->translate(0, rect.height() + 40 * SK_Scalar1); 87 canvas->save(); 88 } else { 89 canvas->translate(rect.width() + 40 * SK_Scalar1, 0); 90 } 91 ++i; 92 93 94 SkColor color = rand.nextU(); 95 color = 0xff000000 | color; // force solid 96 color = sk_tool_utils::color_to_565(color); 97 this->drawEmpty(canvas, color, rect, 98 gStyles[style].fStyle, gFills[fill].fFill); 99 100 SkPaint rectPaint; 101 rectPaint.setColor(SK_ColorBLACK); 102 rectPaint.setStyle(SkPaint::kStroke_Style); 103 rectPaint.setStrokeWidth(-1); 104 rectPaint.setAntiAlias(true); 105 canvas->drawRect(rect, rectPaint); 106 107 SkPaint labelPaint; 108 labelPaint.setColor(color); 109 labelPaint.setAntiAlias(true); 110 sk_tool_utils::set_portable_typeface(&labelPaint); 111 labelPaint.setTextSize(12 * SK_Scalar1); 112 canvas->drawString(gStyles[style].fName, 113 0, rect.height() + 15 * SK_Scalar1, 114 labelPaint); 115 canvas->drawString(gFills[fill].fName, 116 0, rect.height() + 28 * SK_Scalar1, 117 labelPaint); 118 } 119 } 120 canvas->restore(); 121 canvas->restore(); 122 } 123 124 private: 125 typedef GM INHERITED; 126 }; 127 DEF_GM( return new EmptyPathGM; ) 128 129 ////////////////////////////////////////////////////////////////////////////// 130 131 static void make_path_move(SkPath* path, const SkPoint pts[3]) { 132 for (int i = 0; i < 3; ++i) { 133 path->moveTo(pts[i]); 134 } 135 } 136 137 static void make_path_move_close(SkPath* path, const SkPoint pts[3]) { 138 for (int i = 0; i < 3; ++i) { 139 path->moveTo(pts[i]); 140 path->close(); 141 } 142 } 143 144 static void make_path_move_line(SkPath* path, const SkPoint pts[3]) { 145 for (int i = 0; i < 3; ++i) { 146 path->moveTo(pts[i]); 147 path->lineTo(pts[i]); 148 } 149 } 150 151 typedef void (*MakePathProc)(SkPath*, const SkPoint pts[3]); 152 153 static void make_path_move_mix(SkPath* path, const SkPoint pts[3]) { 154 path->moveTo(pts[0]); 155 path->moveTo(pts[1]); path->close(); 156 path->moveTo(pts[2]); path->lineTo(pts[2]); 157 } 158 159 class EmptyStrokeGM : public GM { 160 SkPoint fPts[3]; 161 162 public: 163 EmptyStrokeGM() { 164 fPts[0].set(40, 40); 165 fPts[1].set(80, 40); 166 fPts[2].set(120, 40); 167 } 168 169 protected: 170 SkString onShortName() override { 171 return SkString("emptystroke"); 172 } 173 174 SkISize onISize() override { return SkISize::Make(200, 240); } 175 176 void onDraw(SkCanvas* canvas) override { 177 const MakePathProc procs[] = { 178 make_path_move, // expect red red red 179 make_path_move_close, // expect black black black 180 make_path_move_line, // expect black black black 181 make_path_move_mix, // expect red black black, 182 }; 183 184 SkPaint strokePaint; 185 strokePaint.setStyle(SkPaint::kStroke_Style); 186 strokePaint.setStrokeWidth(21); 187 strokePaint.setStrokeCap(SkPaint::kSquare_Cap); 188 189 SkPaint dotPaint; 190 dotPaint.setColor(SK_ColorRED); 191 strokePaint.setStyle(SkPaint::kStroke_Style); 192 dotPaint.setStrokeWidth(7); 193 194 for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) { 195 SkPath path; 196 procs[i](&path, fPts); 197 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, fPts, dotPaint); 198 canvas->drawPath(path, strokePaint); 199 canvas->translate(0, 40); 200 } 201 } 202 203 private: 204 typedef GM INHERITED; 205 }; 206 DEF_GM( return new EmptyStrokeGM; ) 207 208 } 209