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 11 typedef SkScalar (*MakePathProc)(SkPath*); 12 13 static 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 25 static SkScalar make_triangle(SkPath* path) { 26 static const 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 37 static 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 45 static 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 53 static SkScalar make_sawtooth(SkPath* path) { 54 SkScalar x = SkIntToScalar(20); 55 SkScalar y = SkIntToScalar(20); 56 const SkScalar x0 = x; 57 const SkScalar dx = SK_Scalar1 * 5; 58 const SkScalar dy = SK_Scalar1 * 10; 59 60 path->moveTo(x, y); 61 for (int i = 0; i < 32; 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 73 static SkScalar make_star(SkPath* path, int n) { 74 const SkScalar c = SkIntToScalar(45); 75 const SkScalar r = SkIntToScalar(20); 76 77 SkScalar rad = -SK_ScalarPI / 2; 78 const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n; 79 80 path->moveTo(c, c - r); 81 for (int i = 1; i < n; i++) { 82 rad += drad; 83 SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV); 84 path->lineTo(c + SkScalarMul(cosV, r), c + SkScalarMul(sinV, r)); 85 } 86 path->close(); 87 return r * 2 * 6 / 5; 88 } 89 90 static SkScalar make_star_5(SkPath* path) { return make_star(path, 5); } 91 static SkScalar make_star_13(SkPath* path) { return make_star(path, 13); } 92 93 // We don't expect any output from this path. 94 static SkScalar make_line(SkPath* path) { 95 path->moveTo(SkIntToScalar(30), SkIntToScalar(30)); 96 path->lineTo(SkIntToScalar(120), SkIntToScalar(40)); 97 path->close(); 98 path->moveTo(SkIntToScalar(150), SkIntToScalar(30)); 99 path->lineTo(SkIntToScalar(150), SkIntToScalar(30)); 100 path->lineTo(SkIntToScalar(300), SkIntToScalar(40)); 101 path->close(); 102 return SkIntToScalar(40); 103 } 104 105 static const MakePathProc gProcs[] = { 106 make_frame, 107 make_triangle, 108 make_rect, 109 make_oval, 110 make_sawtooth, 111 make_star_5, 112 make_star_13, 113 make_line, 114 }; 115 116 #define N SK_ARRAY_COUNT(gProcs) 117 118 class PathFillGM : public skiagm::GM { 119 SkPath fPath[N]; 120 SkScalar fDY[N]; 121 protected: 122 void onOnceBeforeDraw() override { 123 for (size_t i = 0; i < N; i++) { 124 fDY[i] = gProcs[i](&fPath[i]); 125 } 126 } 127 128 129 SkString onShortName() override { 130 return SkString("pathfill"); 131 } 132 133 SkISize onISize() override { 134 return SkISize::Make(640, 480); 135 } 136 137 void onDraw(SkCanvas* canvas) override { 138 SkPaint paint; 139 paint.setAntiAlias(true); 140 141 for (size_t i = 0; i < N; i++) { 142 canvas->drawPath(fPath[i], paint); 143 canvas->translate(SkIntToScalar(0), fDY[i]); 144 } 145 } 146 147 private: 148 typedef skiagm::GM INHERITED; 149 }; 150 151 // test inverse-fill w/ a clip that completely excludes the geometry 152 class PathInverseFillGM : public skiagm::GM { 153 SkPath fPath[N]; 154 SkScalar fDY[N]; 155 protected: 156 void onOnceBeforeDraw() override { 157 for (size_t i = 0; i < N; i++) { 158 fDY[i] = gProcs[i](&fPath[i]); 159 } 160 } 161 162 SkString onShortName() override { 163 return SkString("pathinvfill"); 164 } 165 166 SkISize onISize() override { 167 return SkISize::Make(450, 220); 168 } 169 170 static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint, 171 const SkRect* clip, SkScalar top, const SkScalar bottom) { 172 canvas->save(); 173 if (clip) { 174 SkRect r = *clip; 175 r.fTop = top; 176 r.fBottom = bottom; 177 canvas->clipRect(r); 178 } 179 canvas->drawPath(path, paint); 180 canvas->restore(); 181 } 182 183 void onDraw(SkCanvas* canvas) override { 184 SkPath path; 185 186 path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40)); 187 path.toggleInverseFillType(); 188 189 SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) }; 190 191 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 192 193 for (int doclip = 0; doclip <= 1; ++doclip) { 194 for (int aa = 0; aa <= 1; ++aa) { 195 SkPaint paint; 196 paint.setAntiAlias(SkToBool(aa)); 197 198 canvas->save(); 199 canvas->clipRect(clipR); 200 201 const SkRect* clipPtr = doclip ? &clipR : nullptr; 202 203 show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY()); 204 show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom); 205 206 canvas->restore(); 207 canvas->translate(SkIntToScalar(110), 0); 208 } 209 } 210 } 211 212 private: 213 typedef skiagm::GM INHERITED; 214 }; 215 216 /////////////////////////////////////////////////////////////////////////////// 217 218 DEF_GM( return new PathFillGM; ) 219 DEF_GM( return new PathInverseFillGM; ) 220