1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "gm.h" 9 10 typedef SkScalar (*MakePathProc)(SkPath*); 11 12 static SkScalar make_frame(SkPath* path) { 13 SkRect r = { SkIntToScalar(10), SkIntToScalar(10), 14 SkIntToScalar(630), SkIntToScalar(470) }; 15 path->addRoundRect(r, SkIntToScalar(15), SkIntToScalar(15)); 16 17 SkPaint paint; 18 paint.setStyle(SkPaint::kStroke_Style); 19 paint.setStrokeWidth(SkIntToScalar(5)); 20 paint.getFillPath(*path, path); 21 return SkIntToScalar(15); 22 } 23 24 static SkScalar make_triangle(SkPath* path) { 25 static const int gCoord[] = { 26 10, 20, 15, 5, 30, 30 27 }; 28 path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1])); 29 path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3])); 30 path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5])); 31 path->close(); 32 path->offset(SkIntToScalar(10), SkIntToScalar(0)); 33 return SkIntToScalar(30); 34 } 35 36 static SkScalar make_rect(SkPath* path) { 37 SkRect r = { SkIntToScalar(10), SkIntToScalar(10), 38 SkIntToScalar(30), SkIntToScalar(30) }; 39 path->addRect(r); 40 path->offset(SkIntToScalar(10), SkIntToScalar(0)); 41 return SkIntToScalar(30); 42 } 43 44 static SkScalar make_oval(SkPath* path) { 45 SkRect r = { SkIntToScalar(10), SkIntToScalar(10), 46 SkIntToScalar(30), SkIntToScalar(30) }; 47 path->addOval(r); 48 path->offset(SkIntToScalar(10), SkIntToScalar(0)); 49 return SkIntToScalar(30); 50 } 51 52 static SkScalar make_sawtooth(SkPath* path) { 53 SkScalar x = SkIntToScalar(20); 54 SkScalar y = SkIntToScalar(20); 55 const SkScalar x0 = x; 56 const SkScalar dx = SK_Scalar1 * 5; 57 const SkScalar dy = SK_Scalar1 * 10; 58 59 path->moveTo(x, y); 60 for (int i = 0; i < 32; i++) { 61 x += dx; 62 path->lineTo(x, y - dy); 63 x += dx; 64 path->lineTo(x, y + dy); 65 } 66 path->lineTo(x, y + (2 * dy)); 67 path->lineTo(x0, y + (2 * dy)); 68 path->close(); 69 return SkIntToScalar(30); 70 } 71 72 static SkScalar make_star(SkPath* path, int n) { 73 const SkScalar c = SkIntToScalar(45); 74 const SkScalar r = SkIntToScalar(20); 75 76 SkScalar rad = -SK_ScalarPI / 2; 77 const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n; 78 79 path->moveTo(c, c - r); 80 for (int i = 1; i < n; i++) { 81 rad += drad; 82 SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV); 83 path->lineTo(c + SkScalarMul(cosV, r), c + SkScalarMul(sinV, r)); 84 } 85 path->close(); 86 return r * 2 * 6 / 5; 87 } 88 89 static SkScalar make_star_5(SkPath* path) { return make_star(path, 5); } 90 static SkScalar make_star_13(SkPath* path) { return make_star(path, 13); } 91 92 // We don't expect any output from this path. 93 static SkScalar make_line(SkPath* path) { 94 path->moveTo(SkIntToScalar(30), SkIntToScalar(30)); 95 path->lineTo(SkIntToScalar(120), SkIntToScalar(40)); 96 path->close(); 97 path->moveTo(SkIntToScalar(150), SkIntToScalar(30)); 98 path->lineTo(SkIntToScalar(150), SkIntToScalar(30)); 99 path->lineTo(SkIntToScalar(300), SkIntToScalar(40)); 100 path->close(); 101 return SkIntToScalar(40); 102 } 103 104 static const MakePathProc gProcs[] = { 105 make_frame, 106 make_triangle, 107 make_rect, 108 make_oval, 109 make_sawtooth, 110 make_star_5, 111 make_star_13, 112 make_line, 113 }; 114 115 #define N SK_ARRAY_COUNT(gProcs) 116 117 class PathFillGM : public skiagm::GM { 118 SkPath fPath[N]; 119 SkScalar fDY[N]; 120 public: 121 PathFillGM() { 122 for (size_t i = 0; i < N; i++) { 123 fDY[i] = gProcs[i](&fPath[i]); 124 } 125 } 126 127 protected: 128 virtual SkString onShortName() { 129 return SkString("pathfill"); 130 } 131 132 virtual SkISize onISize() { 133 return SkISize::Make(640, 480); 134 } 135 136 virtual void onDraw(SkCanvas* canvas) { 137 SkPaint paint; 138 paint.setAntiAlias(true); 139 140 for (size_t i = 0; i < N; i++) { 141 canvas->drawPath(fPath[i], paint); 142 canvas->translate(SkIntToScalar(0), fDY[i]); 143 } 144 } 145 146 private: 147 typedef skiagm::GM INHERITED; 148 }; 149 150 // test inverse-fill w/ a clip that completely excludes the geometry 151 class PathInverseFillGM : public skiagm::GM { 152 SkPath fPath[N]; 153 SkScalar fDY[N]; 154 public: 155 PathInverseFillGM() { 156 for (size_t i = 0; i < N; i++) { 157 fDY[i] = gProcs[i](&fPath[i]); 158 } 159 } 160 161 protected: 162 virtual SkString onShortName() { 163 return SkString("pathinvfill"); 164 } 165 166 virtual SkISize onISize() { 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 virtual void onDraw(SkCanvas* canvas) { 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 : NULL; 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 static skiagm::GM* MyFactory(void*) { return new PathFillGM; } 219 static skiagm::GMRegistry reg(MyFactory); 220 221 static skiagm::GM* F1(void*) { return new PathInverseFillGM; } 222 static skiagm::GMRegistry gR1(F1); 223