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