pathfill.cpp revision 7704754049cac4794f27496efa90acea963b8881
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.h" 9#include "SkPath.h" 10 11typedef SkScalar (*MakePathProc)(SkPath*); 12 13static SkScalar make_frame(SkPath* path) { 14 SkRect r = { SkIntToScalar(10), SkIntToScalar(10), 15 SkIntToScalar(630), SkIntToScalar(470) }; 16 path->addRoundRect(r, SkIntToScalar(15), SkIntToScalar(15)); 17 18 SkPaint paint; 19 paint.setStyle(SkPaint::kStroke_Style); 20 paint.setStrokeWidth(SkIntToScalar(5)); 21 paint.getFillPath(*path, path); 22 return SkIntToScalar(15); 23} 24 25static SkScalar make_triangle(SkPath* path) { 26 constexpr int gCoord[] = { 27 10, 20, 15, 5, 30, 30 28 }; 29 path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1])); 30 path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3])); 31 path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5])); 32 path->close(); 33 path->offset(SkIntToScalar(10), SkIntToScalar(0)); 34 return SkIntToScalar(30); 35} 36 37static SkScalar make_rect(SkPath* path) { 38 SkRect r = { SkIntToScalar(10), SkIntToScalar(10), 39 SkIntToScalar(30), SkIntToScalar(30) }; 40 path->addRect(r); 41 path->offset(SkIntToScalar(10), SkIntToScalar(0)); 42 return SkIntToScalar(30); 43} 44 45static SkScalar make_oval(SkPath* path) { 46 SkRect r = { SkIntToScalar(10), SkIntToScalar(10), 47 SkIntToScalar(30), SkIntToScalar(30) }; 48 path->addOval(r); 49 path->offset(SkIntToScalar(10), SkIntToScalar(0)); 50 return SkIntToScalar(30); 51} 52 53static SkScalar make_sawtooth(SkPath* path, int teeth) { 54 SkScalar x = SkIntToScalar(20); 55 SkScalar y = SkIntToScalar(20); 56 const SkScalar x0 = x; 57 const SkScalar dx = SkIntToScalar(5); 58 const SkScalar dy = SkIntToScalar(10); 59 60 path->moveTo(x, y); 61 for (int i = 0; i < teeth; i++) { 62 x += dx; 63 path->lineTo(x, y - dy); 64 x += dx; 65 path->lineTo(x, y + dy); 66 } 67 path->lineTo(x, y + (2 * dy)); 68 path->lineTo(x0, y + (2 * dy)); 69 path->close(); 70 return SkIntToScalar(30); 71} 72 73static SkScalar make_sawtooth_3(SkPath* path) { return make_sawtooth(path, 3); } 74static SkScalar make_sawtooth_32(SkPath* path) { return make_sawtooth(path, 32); } 75 76static SkScalar make_house(SkPath* path) { 77 path->moveTo(21, 23); 78 path->lineTo(21, 11.534f); 79 path->lineTo(22.327f, 12.741f); 80 path->lineTo(23.673f, 11.261f); 81 path->lineTo(12, 0.648f); 82 path->lineTo(8, 4.285f); 83 path->lineTo(8, 2); 84 path->lineTo(4, 2); 85 path->lineTo(4, 7.921f); 86 path->lineTo(0.327f, 11.26f); 87 path->lineTo(1.673f, 12.74f); 88 path->lineTo(3, 11.534f); 89 path->lineTo(3, 23); 90 path->lineTo(11, 23); 91 path->lineTo(11, 18); 92 path->lineTo(13, 18); 93 path->lineTo(13, 23); 94 path->lineTo(21, 23); 95 path->close(); 96 path->lineTo(9, 16); 97 path->lineTo(9, 21); 98 path->lineTo(5, 21); 99 path->lineTo(5, 9.715f); 100 path->lineTo(12, 3.351f); 101 path->lineTo(19, 9.715f); 102 path->lineTo(19, 21); 103 path->lineTo(15, 21); 104 path->lineTo(15, 16); 105 path->lineTo(9, 16); 106 path->close(); 107 path->offset(20, 0); 108 return SkIntToScalar(30); 109} 110 111static SkScalar make_star(SkPath* path, int n) { 112 const SkScalar c = SkIntToScalar(45); 113 const SkScalar r = SkIntToScalar(20); 114 115 SkScalar rad = -SK_ScalarPI / 2; 116 const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n; 117 118 path->moveTo(c, c - r); 119 for (int i = 1; i < n; i++) { 120 rad += drad; 121 SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV); 122 path->lineTo(c + SkScalarMul(cosV, r), c + SkScalarMul(sinV, r)); 123 } 124 path->close(); 125 return r * 2 * 6 / 5; 126} 127 128static SkScalar make_star_5(SkPath* path) { return make_star(path, 5); } 129static SkScalar make_star_13(SkPath* path) { return make_star(path, 13); } 130 131// We don't expect any output from this path. 132static SkScalar make_line(SkPath* path) { 133 path->moveTo(SkIntToScalar(30), SkIntToScalar(30)); 134 path->lineTo(SkIntToScalar(120), SkIntToScalar(40)); 135 path->close(); 136 path->moveTo(SkIntToScalar(150), SkIntToScalar(30)); 137 path->lineTo(SkIntToScalar(150), SkIntToScalar(30)); 138 path->lineTo(SkIntToScalar(300), SkIntToScalar(40)); 139 path->close(); 140 return SkIntToScalar(40); 141} 142 143static SkScalar make_info(SkPath* path) { 144 path->moveTo(24, 4); 145 path->cubicTo(12.94999980926514f, 146 4, 147 4, 148 12.94999980926514f, 149 4, 150 24); 151 path->cubicTo(4, 152 35.04999923706055f, 153 12.94999980926514f, 154 44, 155 24, 156 44); 157 path->cubicTo(35.04999923706055f, 158 44, 159 44, 160 35.04999923706055f, 161 44, 162 24); 163 path->cubicTo(44, 164 12.95000076293945f, 165 35.04999923706055f, 166 4, 167 24, 168 4); 169 path->close(); 170 path->moveTo(26, 34); 171 path->lineTo(22, 34); 172 path->lineTo(22, 22); 173 path->lineTo(26, 22); 174 path->lineTo(26, 34); 175 path->close(); 176 path->moveTo(26, 18); 177 path->lineTo(22, 18); 178 path->lineTo(22, 14); 179 path->lineTo(26, 14); 180 path->lineTo(26, 18); 181 path->close(); 182 183 return SkIntToScalar(44); 184} 185 186constexpr MakePathProc gProcs[] = { 187 make_frame, 188 make_triangle, 189 make_rect, 190 make_oval, 191 make_sawtooth_32, 192 make_star_5, 193 make_star_13, 194 make_line, 195 make_house, 196 make_sawtooth_3, 197}; 198 199#define N SK_ARRAY_COUNT(gProcs) 200 201class PathFillGM : public skiagm::GM { 202 SkPath fPath[N]; 203 SkScalar fDY[N]; 204 SkPath fInfoPath; 205protected: 206 void onOnceBeforeDraw() override { 207 for (size_t i = 0; i < N; i++) { 208 fDY[i] = gProcs[i](&fPath[i]); 209 } 210 211 (void) make_info(&fInfoPath); 212 } 213 214 215 SkString onShortName() override { 216 return SkString("pathfill"); 217 } 218 219 SkISize onISize() override { 220 return SkISize::Make(640, 480); 221 } 222 223 void onDraw(SkCanvas* canvas) override { 224 SkPaint paint; 225 paint.setAntiAlias(true); 226 227 for (size_t i = 0; i < N; i++) { 228 canvas->drawPath(fPath[i], paint); 229 canvas->translate(SkIntToScalar(0), fDY[i]); 230 } 231 232 canvas->scale(0.300000011920929f, 0.300000011920929f); 233 canvas->translate(50, 50); 234 canvas->drawPath(fInfoPath, paint); 235 } 236 237private: 238 typedef skiagm::GM INHERITED; 239}; 240 241// test inverse-fill w/ a clip that completely excludes the geometry 242class PathInverseFillGM : public skiagm::GM { 243 SkPath fPath[N]; 244 SkScalar fDY[N]; 245protected: 246 void onOnceBeforeDraw() override { 247 for (size_t i = 0; i < N; i++) { 248 fDY[i] = gProcs[i](&fPath[i]); 249 } 250 } 251 252 SkString onShortName() override { 253 return SkString("pathinvfill"); 254 } 255 256 SkISize onISize() override { 257 return SkISize::Make(450, 220); 258 } 259 260 static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint, 261 const SkRect* clip, SkScalar top, const SkScalar bottom) { 262 canvas->save(); 263 if (clip) { 264 SkRect r = *clip; 265 r.fTop = top; 266 r.fBottom = bottom; 267 canvas->clipRect(r); 268 } 269 canvas->drawPath(path, paint); 270 canvas->restore(); 271 } 272 273 void onDraw(SkCanvas* canvas) override { 274 SkPath path; 275 276 path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40)); 277 path.toggleInverseFillType(); 278 279 SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) }; 280 281 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 282 283 for (int doclip = 0; doclip <= 1; ++doclip) { 284 for (int aa = 0; aa <= 1; ++aa) { 285 SkPaint paint; 286 paint.setAntiAlias(SkToBool(aa)); 287 288 canvas->save(); 289 canvas->clipRect(clipR); 290 291 const SkRect* clipPtr = doclip ? &clipR : nullptr; 292 293 show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY()); 294 show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom); 295 296 canvas->restore(); 297 canvas->translate(SkIntToScalar(110), 0); 298 } 299 } 300 } 301 302private: 303 typedef skiagm::GM INHERITED; 304}; 305 306DEF_SIMPLE_GM(rotatedcubicpath, canvas, 200, 200) { 307 SkPaint p; 308 p.setAntiAlias(true); 309 p.setStyle(SkPaint::kFill_Style); 310 311 canvas->translate(50, 50); 312 SkPath path; 313 path.moveTo(48,-23); 314 path.cubicTo(48,-29.5, 6,-30, 6,-30); 315 path.cubicTo(6,-30, 2,0, 2,0); 316 path.cubicTo(2,0, 44,-21.5, 48,-23); 317 path.close(); 318 319 p.setColor(SK_ColorBLUE); 320 canvas->drawPath(path, p); 321 322 // Rotated path, which is not antialiased on GPU 323 p.setColor(SK_ColorRED); 324 canvas->rotate(90); 325 canvas->drawPath(path, p); 326} 327 328/////////////////////////////////////////////////////////////////////////////// 329 330DEF_GM( return new PathFillGM; ) 331DEF_GM( return new PathInverseFillGM; ) 332