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 10typedef SkScalar (*MakePathProc)(SkPath*); 11 12static 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 24static 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 36static 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 44static 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 52static 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 72static 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 89static SkScalar make_star_5(SkPath* path) { return make_star(path, 5); } 90static SkScalar make_star_13(SkPath* path) { return make_star(path, 13); } 91 92// We don't expect any output from this path. 93static 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 104static 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 117class PathFillGM : public skiagm::GM { 118 SkPath fPath[N]; 119 SkScalar fDY[N]; 120protected: 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 146private: 147 typedef skiagm::GM INHERITED; 148}; 149 150// test inverse-fill w/ a clip that completely excludes the geometry 151class PathInverseFillGM : public skiagm::GM { 152 SkPath fPath[N]; 153 SkScalar fDY[N]; 154protected: 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 211private: 212 typedef skiagm::GM INHERITED; 213}; 214 215/////////////////////////////////////////////////////////////////////////////// 216 217static skiagm::GM* MyFactory(void*) { return new PathFillGM; } 218static skiagm::GMRegistry reg(MyFactory); 219 220static skiagm::GM* F1(void*) { return new PathInverseFillGM; } 221static skiagm::GMRegistry gR1(F1); 222