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 uint32_t onGetFlags() const SK_OVERRIDE { 129 return kSkipTiled_Flag; 130 } 131 132 virtual SkString onShortName() { 133 return SkString("pathfill"); 134 } 135 136 virtual SkISize onISize() { 137 return SkISize::Make(640, 480); 138 } 139 140 virtual void onDraw(SkCanvas* canvas) { 141 SkPaint paint; 142 paint.setAntiAlias(true); 143 144 for (size_t i = 0; i < N; i++) { 145 canvas->drawPath(fPath[i], paint); 146 canvas->translate(SkIntToScalar(0), fDY[i]); 147 } 148 } 149 150 private: 151 typedef skiagm::GM INHERITED; 152 }; 153 154 // test inverse-fill w/ a clip that completely excludes the geometry 155 class PathInverseFillGM : public skiagm::GM { 156 SkPath fPath[N]; 157 SkScalar fDY[N]; 158 public: 159 PathInverseFillGM() { 160 for (size_t i = 0; i < N; i++) { 161 fDY[i] = gProcs[i](&fPath[i]); 162 } 163 } 164 165 protected: 166 virtual uint32_t onGetFlags() const SK_OVERRIDE { 167 return kSkipTiled_Flag; 168 } 169 170 virtual SkString onShortName() { 171 return SkString("pathinvfill"); 172 } 173 174 virtual SkISize onISize() { 175 return SkISize::Make(450, 220); 176 } 177 178 static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint, 179 const SkRect* clip, SkScalar top, const SkScalar bottom) { 180 canvas->save(); 181 if (clip) { 182 SkRect r = *clip; 183 r.fTop = top; 184 r.fBottom = bottom; 185 canvas->clipRect(r); 186 } 187 canvas->drawPath(path, paint); 188 canvas->restore(); 189 } 190 191 virtual void onDraw(SkCanvas* canvas) { 192 SkPath path; 193 194 path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40)); 195 path.toggleInverseFillType(); 196 197 SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) }; 198 199 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 200 201 for (int doclip = 0; doclip <= 1; ++doclip) { 202 for (int aa = 0; aa <= 1; ++aa) { 203 SkPaint paint; 204 paint.setAntiAlias(SkToBool(aa)); 205 206 canvas->save(); 207 canvas->clipRect(clipR); 208 209 const SkRect* clipPtr = doclip ? &clipR : NULL; 210 211 show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY()); 212 show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom); 213 214 canvas->restore(); 215 canvas->translate(SkIntToScalar(110), 0); 216 } 217 } 218 } 219 220 private: 221 typedef skiagm::GM INHERITED; 222 }; 223 224 /////////////////////////////////////////////////////////////////////////////// 225 226 static skiagm::GM* MyFactory(void*) { return new PathFillGM; } 227 static skiagm::GMRegistry reg(MyFactory); 228 229 static skiagm::GM* F1(void*) { return new PathInverseFillGM; } 230 static skiagm::GMRegistry gR1(F1); 231