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