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 protected: 121 void onOnceBeforeDraw() override { 122 for (size_t i = 0; i < N; i++) { 123 fDY[i] = gProcs[i](&fPath[i]); 124 } 125 } 126 127 128 SkString onShortName() override { 129 return SkString("pathfill"); 130 } 131 132 SkISize onISize() override { 133 return SkISize::Make(640, 480); 134 } 135 136 void onDraw(SkCanvas* canvas) override { 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 protected: 155 void onOnceBeforeDraw() override { 156 for (size_t i = 0; i < N; i++) { 157 fDY[i] = gProcs[i](&fPath[i]); 158 } 159 } 160 161 SkString onShortName() override { 162 return SkString("pathinvfill"); 163 } 164 165 SkISize onISize() override { 166 return SkISize::Make(450, 220); 167 } 168 169 static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint, 170 const SkRect* clip, SkScalar top, const SkScalar bottom) { 171 canvas->save(); 172 if (clip) { 173 SkRect r = *clip; 174 r.fTop = top; 175 r.fBottom = bottom; 176 canvas->clipRect(r); 177 } 178 canvas->drawPath(path, paint); 179 canvas->restore(); 180 } 181 182 void onDraw(SkCanvas* canvas) override { 183 SkPath path; 184 185 path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40)); 186 path.toggleInverseFillType(); 187 188 SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) }; 189 190 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 191 192 for (int doclip = 0; doclip <= 1; ++doclip) { 193 for (int aa = 0; aa <= 1; ++aa) { 194 SkPaint paint; 195 paint.setAntiAlias(SkToBool(aa)); 196 197 canvas->save(); 198 canvas->clipRect(clipR); 199 200 const SkRect* clipPtr = doclip ? &clipR : NULL; 201 202 show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY()); 203 show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom); 204 205 canvas->restore(); 206 canvas->translate(SkIntToScalar(110), 0); 207 } 208 } 209 } 210 211 private: 212 typedef skiagm::GM INHERITED; 213 }; 214 215 /////////////////////////////////////////////////////////////////////////////// 216 217 static skiagm::GM* MyFactory(void*) { return new PathFillGM; } 218 static skiagm::GMRegistry reg(MyFactory); 219 220 static skiagm::GM* F1(void*) { return new PathInverseFillGM; } 221 static skiagm::GMRegistry gR1(F1); 222