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 12namespace skiagm { 13 14class CubicPathGM : public GM { 15public: 16 CubicPathGM() {} 17 18protected: 19 SkString onShortName() { 20 return SkString("cubicpath"); 21 } 22 23 SkISize onISize() { return make_isize(1240, 390); } 24 25 void drawPath(SkPath& path,SkCanvas* canvas,SkColor color, 26 const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join, 27 SkPaint::Style style, SkPath::FillType fill, 28 SkScalar strokeWidth) { 29 path.setFillType(fill); 30 SkPaint paint; 31 paint.setStrokeCap(cap); 32 paint.setStrokeWidth(strokeWidth); 33 paint.setStrokeJoin(join); 34 paint.setColor(color); 35 paint.setStyle(style); 36 canvas->save(); 37 canvas->clipRect(clip); 38 canvas->drawPath(path, paint); 39 canvas->restore(); 40 } 41 42 virtual void onDraw(SkCanvas* canvas) { 43 struct FillAndName { 44 SkPath::FillType fFill; 45 const char* fName; 46 }; 47 static const FillAndName gFills[] = { 48 {SkPath::kWinding_FillType, "Winding"}, 49 {SkPath::kEvenOdd_FillType, "Even / Odd"}, 50 {SkPath::kInverseWinding_FillType, "Inverse Winding"}, 51 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}, 52 }; 53 struct StyleAndName { 54 SkPaint::Style fStyle; 55 const char* fName; 56 }; 57 static const StyleAndName gStyles[] = { 58 {SkPaint::kFill_Style, "Fill"}, 59 {SkPaint::kStroke_Style, "Stroke"}, 60 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, 61 }; 62 struct CapAndName { 63 SkPaint::Cap fCap; 64 SkPaint::Join fJoin; 65 const char* fName; 66 }; 67 static const CapAndName gCaps[] = { 68 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"}, 69 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"}, 70 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"} 71 }; 72 struct PathAndName { 73 SkPath fPath; 74 const char* fName; 75 }; 76 PathAndName path; 77 path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1); 78 path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1, 79 60*SK_Scalar1, 20*SK_Scalar1, 80 75*SK_Scalar1, 10*SK_Scalar1); 81 path.fName = "moveTo-cubic"; 82 83 SkPaint titlePaint; 84 titlePaint.setColor(SK_ColorBLACK); 85 titlePaint.setAntiAlias(true); 86 titlePaint.setLCDRenderText(true); 87 titlePaint.setTextSize(15 * SK_Scalar1); 88 const char title[] = "Cubic Drawn Into Rectangle Clips With " 89 "Indicated Style, Fill and Linecaps, with stroke width 10"; 90 canvas->drawText(title, strlen(title), 91 20 * SK_Scalar1, 92 20 * SK_Scalar1, 93 titlePaint); 94 95 SkRandom rand; 96 SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1); 97 canvas->save(); 98 canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1); 99 canvas->save(); 100 for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) { 101 if (0 < cap) { 102 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0); 103 } 104 canvas->save(); 105 for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) { 106 if (0 < fill) { 107 canvas->translate(0, rect.height() + 40 * SK_Scalar1); 108 } 109 canvas->save(); 110 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) { 111 if (0 < style) { 112 canvas->translate(rect.width() + 40 * SK_Scalar1, 0); 113 } 114 115 SkColor color = 0xff007000; 116 this->drawPath(path.fPath, canvas, color, rect, 117 gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle, 118 gFills[fill].fFill, SK_Scalar1*10); 119 120 SkPaint rectPaint; 121 rectPaint.setColor(SK_ColorBLACK); 122 rectPaint.setStyle(SkPaint::kStroke_Style); 123 rectPaint.setStrokeWidth(-1); 124 rectPaint.setAntiAlias(true); 125 canvas->drawRect(rect, rectPaint); 126 127 SkPaint labelPaint; 128 labelPaint.setColor(color); 129 labelPaint.setAntiAlias(true); 130 labelPaint.setLCDRenderText(true); 131 labelPaint.setTextSize(10 * SK_Scalar1); 132 canvas->drawText(gStyles[style].fName, 133 strlen(gStyles[style].fName), 134 0, rect.height() + 12 * SK_Scalar1, 135 labelPaint); 136 canvas->drawText(gFills[fill].fName, 137 strlen(gFills[fill].fName), 138 0, rect.height() + 24 * SK_Scalar1, 139 labelPaint); 140 canvas->drawText(gCaps[cap].fName, 141 strlen(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 CubicClosePathGM : public GM { 158public: 159 CubicClosePathGM() {} 160 161protected: 162 SkString onShortName() { 163 return SkString("cubicclosepath"); 164 } 165 166 SkISize onISize() { return make_isize(1240, 390); } 167 168 void drawPath(SkPath& path,SkCanvas* canvas,SkColor color, 169 const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join, 170 SkPaint::Style style, SkPath::FillType fill, 171 SkScalar strokeWidth) { 172 path.setFillType(fill); 173 SkPaint paint; 174 paint.setStrokeCap(cap); 175 paint.setStrokeWidth(strokeWidth); 176 paint.setStrokeJoin(join); 177 paint.setColor(color); 178 paint.setStyle(style); 179 canvas->save(); 180 canvas->clipRect(clip); 181 canvas->drawPath(path, paint); 182 canvas->restore(); 183 } 184 185 virtual void onDraw(SkCanvas* canvas) { 186 struct FillAndName { 187 SkPath::FillType fFill; 188 const char* fName; 189 }; 190 static const FillAndName gFills[] = { 191 {SkPath::kWinding_FillType, "Winding"}, 192 {SkPath::kEvenOdd_FillType, "Even / Odd"}, 193 {SkPath::kInverseWinding_FillType, "Inverse Winding"}, 194 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}, 195 }; 196 struct StyleAndName { 197 SkPaint::Style fStyle; 198 const char* fName; 199 }; 200 static const StyleAndName gStyles[] = { 201 {SkPaint::kFill_Style, "Fill"}, 202 {SkPaint::kStroke_Style, "Stroke"}, 203 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, 204 }; 205 struct CapAndName { 206 SkPaint::Cap fCap; 207 SkPaint::Join fJoin; 208 const char* fName; 209 }; 210 static const CapAndName gCaps[] = { 211 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"}, 212 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"}, 213 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"} 214 }; 215 struct PathAndName { 216 SkPath fPath; 217 const char* fName; 218 }; 219 PathAndName path; 220 path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1); 221 path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1, 222 60*SK_Scalar1, 20*SK_Scalar1, 223 75*SK_Scalar1, 10*SK_Scalar1); 224 path.fPath.close(); 225 path.fName = "moveTo-cubic-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[] = "Cubic 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 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 = 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 297private: 298 typedef GM INHERITED; 299}; 300 301////////////////////////////////////////////////////////////////////////////// 302 303static GM* CubicPathFactory(void*) { return new CubicPathGM; } 304static GMRegistry regCubicPath(CubicPathFactory); 305 306static GM* CubicClosePathFactory(void*) { return new CubicClosePathGM; } 307static GMRegistry regCubicClosePath(CubicClosePathFactory); 308 309} 310