pathfill.cpp revision 5ee6491b7a1e7c177abc0186c2749ebe1f71fcf7
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#include "SkPicture.h" 10#include "SkRectShape.h" 11#include "SkGroupShape.h" 12 13typedef SkScalar (*MakePathProc)(SkPath*); 14 15static SkScalar make_frame(SkPath* path) { 16 SkRect r = { SkIntToScalar(10), SkIntToScalar(10), 17 SkIntToScalar(630), SkIntToScalar(470) }; 18 path->addRoundRect(r, SkIntToScalar(15), SkIntToScalar(15)); 19 20 SkPaint paint; 21 paint.setStyle(SkPaint::kStroke_Style); 22 paint.setStrokeWidth(SkIntToScalar(5)); 23 paint.getFillPath(*path, path); 24 return SkIntToScalar(15); 25} 26 27static SkScalar make_triangle(SkPath* path) { 28 static const int gCoord[] = { 29 10, 20, 15, 5, 30, 30 30 }; 31 path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1])); 32 path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3])); 33 path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5])); 34 path->close(); 35 path->offset(SkIntToScalar(10), SkIntToScalar(0)); 36 return SkIntToScalar(30); 37} 38 39static SkScalar make_rect(SkPath* path) { 40 SkRect r = { SkIntToScalar(10), SkIntToScalar(10), 41 SkIntToScalar(30), SkIntToScalar(30) }; 42 path->addRect(r); 43 path->offset(SkIntToScalar(10), SkIntToScalar(0)); 44 return SkIntToScalar(30); 45} 46 47static SkScalar make_oval(SkPath* path) { 48 SkRect r = { SkIntToScalar(10), SkIntToScalar(10), 49 SkIntToScalar(30), SkIntToScalar(30) }; 50 path->addOval(r); 51 path->offset(SkIntToScalar(10), SkIntToScalar(0)); 52 return SkIntToScalar(30); 53} 54 55static SkScalar make_sawtooth(SkPath* path) { 56 SkScalar x = SkIntToScalar(20); 57 SkScalar y = SkIntToScalar(20); 58 const SkScalar x0 = x; 59 const SkScalar dx = SK_Scalar1 * 5; 60 const SkScalar dy = SK_Scalar1 * 10; 61 62 path->moveTo(x, y); 63 for (int i = 0; i < 32; i++) { 64 x += dx; 65 path->lineTo(x, y - dy); 66 x += dx; 67 path->lineTo(x, y + dy); 68 } 69 path->lineTo(x, y + (2 * dy)); 70 path->lineTo(x0, y + (2 * dy)); 71 path->close(); 72 return SkIntToScalar(30); 73} 74 75static SkScalar make_star(SkPath* path, int n) { 76 const SkScalar c = SkIntToScalar(45); 77 const SkScalar r = SkIntToScalar(20); 78 79 SkScalar rad = -SK_ScalarPI / 2; 80 const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n; 81 82 path->moveTo(c, c - r); 83 for (int i = 1; i < n; i++) { 84 rad += drad; 85 SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV); 86 path->lineTo(c + SkScalarMul(cosV, r), c + SkScalarMul(sinV, r)); 87 } 88 path->close(); 89 return r * 2 * 6 / 5; 90} 91 92static SkScalar make_star_5(SkPath* path) { return make_star(path, 5); } 93static SkScalar make_star_13(SkPath* path) { return make_star(path, 13); } 94 95// We don't expect any output from this path. 96static SkScalar make_line(SkPath* path) { 97 path->moveTo(SkIntToScalar(30), SkIntToScalar(30)); 98 path->lineTo(SkIntToScalar(120), SkIntToScalar(40)); 99 path->close(); 100 path->moveTo(SkIntToScalar(150), SkIntToScalar(30)); 101 path->lineTo(SkIntToScalar(150), SkIntToScalar(30)); 102 path->lineTo(SkIntToScalar(300), SkIntToScalar(40)); 103 path->close(); 104 return SkIntToScalar(40); 105} 106 107static const MakePathProc gProcs[] = { 108 make_frame, 109 make_triangle, 110 make_rect, 111 make_oval, 112 make_sawtooth, 113 make_star_5, 114 make_star_13, 115 make_line, 116}; 117 118#define N SK_ARRAY_COUNT(gProcs) 119 120class PathFillGM : public skiagm::GM { 121 SkPath fPath[N]; 122 SkScalar fDY[N]; 123public: 124 PathFillGM() { 125 for (size_t i = 0; i < N; i++) { 126 fDY[i] = gProcs[i](&fPath[i]); 127 } 128 } 129 130protected: 131 virtual SkString onShortName() { 132 return SkString("pathfill"); 133 } 134 135 virtual SkISize onISize() { 136 return SkISize::Make(640, 480); 137 } 138 139 virtual void onDraw(SkCanvas* canvas) { 140 SkPaint paint; 141 paint.setAntiAlias(true); 142 143 for (size_t i = 0; i < N; i++) { 144 canvas->drawPath(fPath[i], paint); 145 canvas->translate(SkIntToScalar(0), fDY[i]); 146 } 147 } 148 149private: 150 typedef skiagm::GM INHERITED; 151}; 152 153// test inverse-fill w/ a clip that completely excludes the geometry 154class PathInverseFillGM : public skiagm::GM { 155 SkPath fPath[N]; 156 SkScalar fDY[N]; 157public: 158 PathInverseFillGM() { 159 for (size_t i = 0; i < N; i++) { 160 fDY[i] = gProcs[i](&fPath[i]); 161 } 162 } 163 164protected: 165 virtual SkString onShortName() { 166 return SkString("pathinvfill"); 167 } 168 169 virtual SkISize onISize() { 170 return SkISize::Make(450, 220); 171 } 172 173 static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint, 174 const SkRect* clip, SkScalar top, const SkScalar bottom) { 175 canvas->save(); 176 if (clip) { 177 SkRect r = *clip; 178 r.fTop = top; 179 r.fBottom = bottom; 180 canvas->clipRect(r); 181 } 182 canvas->drawPath(path, paint); 183 canvas->restore(); 184 } 185 186 virtual void onDraw(SkCanvas* canvas) { 187 SkPath path; 188 189 path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40)); 190 path.toggleInverseFillType(); 191 192 SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) }; 193 194 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 195 196 for (int doclip = 0; doclip <= 1; ++doclip) { 197 for (int aa = 0; aa <= 1; ++aa) { 198 SkPaint paint; 199 paint.setAntiAlias(SkToBool(aa)); 200 201 canvas->save(); 202 canvas->clipRect(clipR); 203 204 const SkRect* clipPtr = doclip ? &clipR : NULL; 205 206 show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY()); 207 show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom); 208 209 canvas->restore(); 210 canvas->translate(SkIntToScalar(110), 0); 211 } 212 } 213 } 214 215private: 216 typedef skiagm::GM INHERITED; 217}; 218 219/////////////////////////////////////////////////////////////////////////////// 220 221static skiagm::GM* MyFactory(void*) { return new PathFillGM; } 222static skiagm::GMRegistry reg(MyFactory); 223 224static skiagm::GM* F1(void*) { return new PathInverseFillGM; } 225static skiagm::GMRegistry gR1(F1); 226 227