OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "gm.h" | 8 #include "gm.h" |
9 #include "SkAnimTimer.h" | 9 #include "SkAnimTimer.h" |
10 #include "SkBlurMaskFilter.h" | 10 #include "SkBlurMaskFilter.h" |
11 #include "SkGaussianEdgeShader.h" | 11 #include "SkGaussianEdgeShader.h" |
| 12 #include "SkRRectsGaussianEdgeShader.h" |
12 #include "SkPath.h" | 13 #include "SkPath.h" |
13 #include "SkPathOps.h" | 14 #include "SkPathOps.h" |
14 #include "SkRRect.h" | 15 #include "SkRRect.h" |
15 #include "SkStroke.h" | 16 #include "SkStroke.h" |
16 | 17 |
17 constexpr int kNumCols = 2; | 18 constexpr int kNumCols = 2; |
18 constexpr int kNumRows = 5; | 19 constexpr int kNumRows = 5; |
19 constexpr int kCellSize = 128; | 20 constexpr int kCellSize = 128; |
20 constexpr SkScalar kPad = 8.0f; | 21 constexpr SkScalar kPad = 8.0f; |
21 constexpr SkScalar kPeriod = 8.0f; | 22 constexpr SkScalar kPeriod = 8.0f; |
22 constexpr int kClipOffset = 32; | 23 constexpr int kClipOffset = 32; |
23 | 24 |
24 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 25 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
25 typedef SkPath (*PFDrawMthd)(SkCanvas*, const SkRect&, bool); | 26 |
26 | 27 class Object { |
27 static SkPath draw_rrect(SkCanvas* canvas, const SkRect& r, bool stroked) { | 28 public: |
28 SkRRect rr = SkRRect::MakeRectXY(r, 2*kPad, 2*kPad); | 29 virtual ~Object() {} |
29 | 30 virtual bool asRRect(SkRRect* rr) const = 0; |
30 SkPaint paint; | 31 virtual SkPath asPath() const = 0; |
31 paint.setAntiAlias(true); | 32 virtual void draw(SkCanvas* canvas, const SkPaint& paint) const = 0; |
32 if (stroked) { | 33 virtual void clip(SkCanvas* canvas) const = 0; |
| 34 virtual bool contains(const SkRect& r) const = 0; |
| 35 virtual const SkRect& bounds() const = 0; |
| 36 }; |
| 37 |
| 38 typedef Object* (*PFMakeMthd)(const SkRect& r); |
| 39 |
| 40 class RRect : public Object { |
| 41 public: |
| 42 RRect(const SkRect& r) { |
| 43 fRRect = SkRRect::MakeRectXY(r, 4*kPad, 4*kPad); |
| 44 } |
| 45 |
| 46 bool asRRect(SkRRect* rr) const override { |
| 47 *rr = fRRect; |
| 48 return true; |
| 49 } |
| 50 |
| 51 SkPath asPath() const override { |
| 52 SkPath p; |
| 53 p.addRRect(fRRect); |
| 54 return p; |
| 55 } |
| 56 |
| 57 void draw(SkCanvas* canvas, const SkPaint& paint) const override { |
| 58 canvas->drawRRect(fRRect, paint); |
| 59 } |
| 60 |
| 61 void clip(SkCanvas* canvas) const override { |
| 62 canvas->clipRRect(fRRect); |
| 63 } |
| 64 |
| 65 bool contains(const SkRect& r) const override { |
| 66 return fRRect.contains(r); |
| 67 } |
| 68 |
| 69 const SkRect& bounds() const override { |
| 70 return fRRect.getBounds(); |
| 71 } |
| 72 |
| 73 static Object* Make(const SkRect& r) { |
| 74 return new RRect(r); |
| 75 } |
| 76 |
| 77 private: |
| 78 SkRRect fRRect; |
| 79 }; |
| 80 |
| 81 class StrokedRRect : public Object { |
| 82 public: |
| 83 StrokedRRect(const SkRect& r) { |
| 84 fRRect = SkRRect::MakeRectXY(r, 2*kPad, 2*kPad); |
| 85 fStrokedBounds = r.makeOutset(kPad, kPad); |
| 86 } |
| 87 |
| 88 bool asRRect(SkRRect* rr) const override { |
| 89 return false; |
| 90 } |
| 91 |
| 92 SkPath asPath() const override { |
| 93 // In this case we want the outline of the stroked rrect |
| 94 SkPaint paint; |
| 95 paint.setAntiAlias(true); |
33 paint.setStyle(SkPaint::kStroke_Style); | 96 paint.setStyle(SkPaint::kStroke_Style); |
34 paint.setColor(SK_ColorRED); | 97 paint.setStrokeWidth(kPad); |
35 } else { | 98 |
36 // G channel is an F6.2 radius | |
37 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | |
38 paint.setShader(SkGaussianEdgeShader::Make()); | |
39 } | |
40 canvas->drawRRect(rr, paint); | |
41 | |
42 SkPath p; | |
43 p.addRoundRect(r, 2*kPad, 2*kPad); | |
44 return p; | |
45 } | |
46 | |
47 static SkPath draw_stroked_rrect(SkCanvas* canvas, const SkRect& r, bool stroked
) { | |
48 SkRect insetRect = r; | |
49 insetRect.inset(kPad, kPad); | |
50 SkRRect rr = SkRRect::MakeRectXY(insetRect, 2*kPad, 2*kPad); | |
51 | |
52 SkPaint paint; | |
53 paint.setAntiAlias(true); | |
54 paint.setStyle(SkPaint::kStroke_Style); | |
55 paint.setStrokeWidth(kPad); | |
56 | |
57 if (stroked) { | |
58 // In this case we want to draw a stroked representation of the stroked
rrect | |
59 SkPath p, stroked; | 99 SkPath p, stroked; |
60 p.addRRect(rr); | 100 p.addRRect(fRRect); |
61 SkStroke stroke(paint); | 101 SkStroke stroke(paint); |
62 stroke.strokePath(p, &stroked); | 102 stroke.strokePath(p, &stroked); |
63 | 103 return stroked; |
64 paint.setStrokeWidth(0); | 104 } |
65 paint.setColor(SK_ColorRED); | 105 |
66 canvas->drawPath(stroked, paint); | 106 void draw(SkCanvas* canvas, const SkPaint& paint) const override { |
67 } else { | 107 SkPaint stroke(paint); |
68 // G channel is an F6.2 radius | 108 stroke.setStyle(SkPaint::kStroke_Style); |
69 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | 109 stroke.setStrokeWidth(kPad); |
70 paint.setShader(SkGaussianEdgeShader::Make()); | 110 |
71 | 111 canvas->drawRRect(fRRect, stroke); |
72 canvas->drawRRect(rr, paint); | 112 } |
73 } | 113 |
74 | 114 void clip(SkCanvas* canvas) const override { |
75 SkPath p; | 115 canvas->clipPath(this->asPath()); |
76 insetRect.outset(kPad/2.0f, kPad/2.0f); | 116 } |
77 p.addRoundRect(insetRect, 2*kPad, 2*kPad); | 117 |
78 return p; | 118 bool contains(const SkRect& r) const override { |
79 } | 119 return false; |
80 | 120 } |
81 static SkPath draw_oval(SkCanvas* canvas, const SkRect& r, bool stroked) { | 121 |
82 SkRRect rr = SkRRect::MakeOval(r); | 122 const SkRect& bounds() const override { |
83 | 123 return fStrokedBounds; |
84 SkPaint paint; | 124 } |
85 paint.setAntiAlias(true); | 125 |
86 if (stroked) { | 126 static Object* Make(const SkRect& r) { |
87 paint.setStyle(SkPaint::kStroke_Style); | 127 return new StrokedRRect(r); |
88 paint.setColor(SK_ColorRED); | 128 } |
89 } else { | 129 |
90 // G channel is an F6.2 radius | 130 private: |
91 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | 131 SkRRect fRRect; |
92 paint.setShader(SkGaussianEdgeShader::Make()); | 132 SkRect fStrokedBounds; |
93 } | 133 }; |
94 canvas->drawRRect(rr, paint); | 134 |
95 | 135 class Oval : public Object { |
96 SkPath p; | 136 public: |
97 p.addOval(r); | 137 Oval(const SkRect& r) { |
98 return p; | 138 fRRect = SkRRect::MakeOval(r); |
99 } | 139 } |
100 | 140 |
101 static SkPath draw_square(SkCanvas* canvas, const SkRect& r, bool stroked) { | 141 bool asRRect(SkRRect* rr) const override { |
102 SkPaint paint; | 142 *rr = fRRect; |
103 paint.setAntiAlias(true); | 143 return true; |
104 if (stroked) { | 144 } |
105 paint.setStyle(SkPaint::kStroke_Style); | 145 |
106 paint.setColor(SK_ColorRED); | 146 SkPath asPath() const override { |
107 } else { | 147 SkPath p; |
108 // G channel is an F6.2 radius | 148 p.addRRect(fRRect); |
109 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | 149 return p; |
110 paint.setShader(SkGaussianEdgeShader::Make()); | 150 } |
111 } | 151 |
112 canvas->drawRect(r, paint); | 152 void draw(SkCanvas* canvas, const SkPaint& paint) const override { |
113 | 153 canvas->drawRRect(fRRect, paint); |
114 SkPath p; | 154 } |
115 p.addRect(r); | 155 |
116 return p; | 156 void clip(SkCanvas* canvas) const override { |
117 } | 157 canvas->clipRRect(fRRect); |
118 | 158 } |
119 static SkPath draw_pentagon(SkCanvas* canvas, const SkRect& r, bool stroked) { | 159 |
120 SkPath p; | 160 bool contains(const SkRect& r) const override { |
121 | 161 return fRRect.contains(r); |
122 SkPoint points[5] = { | 162 } |
123 { 0.000000f, -1.000000f }, | 163 |
124 { -0.951056f, -0.309017f }, | 164 const SkRect& bounds() const override { |
125 { -0.587785f, 0.809017f }, | 165 return fRRect.getBounds(); |
126 { 0.587785f, 0.809017f }, | 166 } |
127 { 0.951057f, -0.309017f }, | 167 |
128 }; | 168 static Object* Make(const SkRect& r) { |
129 | 169 return new Oval(r); |
130 SkScalar height = r.height()/2.0f; | 170 } |
131 SkScalar width = r.width()/2.0f; | 171 |
132 | 172 private: |
133 p.moveTo(r.centerX() + points[0].fX * width, r.centerY() + points[0].fY * he
ight); | 173 SkRRect fRRect; |
134 p.lineTo(r.centerX() + points[1].fX * width, r.centerY() + points[1].fY * he
ight); | 174 }; |
135 p.lineTo(r.centerX() + points[2].fX * width, r.centerY() + points[2].fY * he
ight); | 175 |
136 p.lineTo(r.centerX() + points[3].fX * width, r.centerY() + points[3].fY * he
ight); | 176 class Rect : public Object { |
137 p.lineTo(r.centerX() + points[4].fX * width, r.centerY() + points[4].fY * he
ight); | 177 public: |
138 p.close(); | 178 Rect(const SkRect& r) : fRect(r) { } |
139 | 179 |
140 SkPaint paint; | 180 bool asRRect(SkRRect* rr) const override { |
141 paint.setAntiAlias(true); | 181 *rr = SkRRect::MakeRect(fRect); |
142 if (stroked) { | 182 return true; |
143 paint.setStyle(SkPaint::kStroke_Style); | 183 } |
144 paint.setColor(SK_ColorRED); | 184 |
145 } else { | 185 SkPath asPath() const override { |
146 // G channel is an F6.2 radius | 186 SkPath p; |
147 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | 187 p.addRect(fRect); |
148 // This currently goes through the GrAAConvexPathRenderer and produces a | 188 return p; |
149 // AAConvexPathBatch (i.e., it doesn't have a analytic distance) | 189 } |
150 // paint.setShader(SkGaussianEdgeShader::Make()); | 190 |
151 } | 191 void draw(SkCanvas* canvas, const SkPaint& paint) const override { |
152 canvas->drawPath(p, paint); | 192 canvas->drawRect(fRect, paint); |
153 | 193 } |
154 return p; | 194 |
155 } | 195 void clip(SkCanvas* canvas) const override { |
156 | 196 canvas->clipRect(fRect); |
157 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 197 } |
158 typedef void (*PFClipMthd)(SkCanvas* canvas, const SkPoint&, SkScalar); | 198 |
159 | 199 bool contains(const SkRect& r) const override { |
160 static void circle_clip(SkCanvas* canvas, const SkPoint& center, SkScalar rad) { | 200 return fRect.contains(r); |
161 SkRect r = SkRect::MakeLTRB(center.fX - rad, center.fY - rad, center.fX + ra
d, center.fY + rad); | 201 } |
162 SkRRect rr = SkRRect::MakeOval(r); | 202 |
163 | 203 const SkRect& bounds() const override { |
164 canvas->clipRRect(rr); | 204 return fRect; |
165 } | 205 } |
166 | 206 |
167 static void square_clip(SkCanvas* canvas, const SkPoint& center, SkScalar size)
{ | 207 static Object* Make(const SkRect& r) { |
168 SkScalar newSize = SK_ScalarRoot2Over2 * size; | 208 return new Rect(r); |
169 SkRect r = SkRect::MakeLTRB(center.fX - newSize, center.fY - newSize, | 209 } |
170 center.fX + newSize, center.fY + newSize); | 210 |
171 | 211 private: |
172 canvas->clipRect(r); | 212 SkRect fRect; |
173 } | 213 }; |
174 | 214 |
175 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 215 class Pentagon : public Object { |
176 // These are stand alone methods (rather than just, say, returning the SkPath fo
r the clip | 216 public: |
177 // object) so that we can catch the clip-contains-victim case. | 217 Pentagon(const SkRect& r) { |
178 typedef SkPath (*PFGeometricClipMthd)(const SkPoint&, SkScalar, const SkPath&); | 218 SkPoint points[5] = { |
179 | 219 { 0.000000f, -1.000000f }, |
180 static SkPath circle_geometric_clip(const SkPoint& center, SkScalar rad, const S
kPath& victim) { | 220 { -0.951056f, -0.309017f }, |
181 const SkRect bound = victim.getBounds(); | 221 { -0.587785f, 0.809017f }, |
182 SkPoint pts[4]; | 222 { 0.587785f, 0.809017f }, |
183 bound.toQuad(pts); | 223 { 0.951057f, -0.309017f }, |
184 | 224 }; |
185 bool clipContainsVictim = true; | 225 |
186 for (int i = 0; i < 4; ++i) { | 226 SkScalar height = r.height()/2.0f; |
187 SkScalar distSq = (pts[i].fX - center.fX) * (pts[i].fX - center.fX) + | 227 SkScalar width = r.width()/2.0f; |
188 (pts[i].fY - center.fY) * (pts[i].fY - center.fY); | 228 |
189 if (distSq >= rad*rad) { | 229 fPath.moveTo(r.centerX() + points[0].fX * width, r.centerY() + points[0]
.fY * height); |
190 clipContainsVictim = false; | 230 fPath.lineTo(r.centerX() + points[1].fX * width, r.centerY() + points[1]
.fY * height); |
191 } | 231 fPath.lineTo(r.centerX() + points[2].fX * width, r.centerY() + points[2]
.fY * height); |
192 } | 232 fPath.lineTo(r.centerX() + points[3].fX * width, r.centerY() + points[3]
.fY * height); |
193 | 233 fPath.lineTo(r.centerX() + points[4].fX * width, r.centerY() + points[4]
.fY * height); |
194 if (clipContainsVictim) { | 234 fPath.close(); |
195 return victim; | 235 } |
196 } | 236 |
197 | 237 bool asRRect(SkRRect* rr) const override { |
198 // Add victim contains clip test? | 238 return false; |
199 | 239 } |
200 SkPath clipPath; | 240 |
201 clipPath.addCircle(center.fX, center.fY, rad); | 241 SkPath asPath() const override { return fPath; } |
202 | 242 |
203 SkPath result; | 243 void draw(SkCanvas* canvas, const SkPaint& paint) const override { |
204 SkAssertResult(Op(clipPath, victim, kIntersect_SkPathOp, &result)); | 244 canvas->drawPath(fPath, paint); |
205 | 245 } |
206 return result; | 246 |
207 } | 247 void clip(SkCanvas* canvas) const override { |
208 | 248 canvas->clipPath(this->asPath()); |
209 static SkPath square_geometric_clip(const SkPoint& center, SkScalar size, const
SkPath& victim) { | 249 } |
210 SkScalar newSize = SK_ScalarRoot2Over2 * size; | 250 |
211 SkRect r = SkRect::MakeLTRB(center.fX - newSize, center.fY - newSize, | 251 bool contains(const SkRect& r) const override { |
212 center.fX + newSize, center.fY + newSize); | 252 return false; |
213 | 253 } |
214 const SkRect bound = victim.getBounds(); | 254 |
215 | 255 const SkRect& bounds() const override { |
216 if (r.contains(bound)) { | 256 return fPath.getBounds(); |
217 return victim; | 257 } |
218 } | 258 |
219 | 259 static Object* Make(const SkRect& r) { |
220 // Add victim contains clip test? | 260 return new Pentagon(r); |
221 | 261 } |
222 SkPath clipPath; | 262 |
223 clipPath.addRect(r); | 263 private: |
224 | 264 SkPath fPath; |
225 SkPath result; | 265 }; |
226 SkAssertResult(Op(clipPath, victim, kIntersect_SkPathOp, &result)); | |
227 | |
228 return result; | |
229 } | |
230 | 266 |
231 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 267 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
232 namespace skiagm { | 268 namespace skiagm { |
233 | 269 |
234 // This GM attempts to mimic Android's reveal animation | 270 // This GM attempts to mimic Android's reveal animation |
235 class RevealGM : public GM { | 271 class RevealGM : public GM { |
236 public: | 272 public: |
237 RevealGM() : fFraction(0.5f), fDrawWithGaussianEdge(true) { | 273 enum Mode { |
| 274 kGaussianEdge_Mode, |
| 275 kBlurMask_Mode, |
| 276 kRRectsGaussianEdge_Mode, |
| 277 |
| 278 kLast_Mode = kRRectsGaussianEdge_Mode |
| 279 }; |
| 280 |
| 281 static const int kModeCount = kLast_Mode + 1; |
| 282 |
| 283 RevealGM() : fFraction(0.5f), fMode(kRRectsGaussianEdge_Mode) { |
238 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); | 284 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); |
239 } | 285 } |
240 | 286 |
241 protected: | 287 protected: |
242 | 288 |
243 SkString onShortName() override { | 289 SkString onShortName() override { |
244 return SkString("reveal"); | 290 return SkString("reveal"); |
245 } | 291 } |
246 | 292 |
247 SkISize onISize() override { | 293 SkISize onISize() override { |
248 return SkISize::Make(kNumCols * kCellSize, kNumRows * kCellSize); | 294 return SkISize::Make(kNumCols * kCellSize, kNumRows * kCellSize); |
249 } | 295 } |
250 | 296 |
251 void onDraw(SkCanvas* canvas) override { | 297 void onDraw(SkCanvas* canvas) override { |
252 PFClipMthd clips[kNumCols] = { circle_clip, square_clip }; | 298 PFMakeMthd clipMakes[kNumCols] = { Oval::Make, Rect::Make }; |
253 PFGeometricClipMthd geometricClips[kNumCols] = { | 299 PFMakeMthd drawMakes[kNumRows] = { |
254 circle_geometric_clip, | 300 RRect::Make, StrokedRRect::Make, Oval::Make, Rect::Make, Pentagon::M
ake |
255 square_geometric_clip | |
256 }; | |
257 PFDrawMthd draws[kNumRows] = { | |
258 draw_rrect, | |
259 draw_stroked_rrect, | |
260 draw_oval, | |
261 draw_square, | |
262 draw_pentagon | |
263 }; | 301 }; |
264 | 302 |
265 SkPaint strokePaint; | 303 SkPaint strokePaint; |
266 strokePaint.setColor(SK_ColorGREEN); | 304 strokePaint.setColor(SK_ColorGREEN); |
267 strokePaint.setStyle(SkPaint::kStroke_Style); | 305 strokePaint.setStyle(SkPaint::kStroke_Style); |
268 strokePaint.setStrokeWidth(0.0f); | 306 strokePaint.setStrokeWidth(0.0f); |
269 | 307 |
270 for (int y = 0; y < kNumRows; ++y) { | 308 for (int y = 0; y < kNumRows; ++y) { |
271 for (int x = 0; x < kNumCols; ++x) { | 309 for (int x = 0; x < kNumCols; ++x) { |
272 SkRect cell = SkRect::MakeXYWH(SkIntToScalar(x*kCellSize), | 310 SkRect cell = SkRect::MakeXYWH(SkIntToScalar(x*kCellSize), |
273 SkIntToScalar(y*kCellSize), | 311 SkIntToScalar(y*kCellSize), |
274 SkIntToScalar(kCellSize), | 312 SkIntToScalar(kCellSize), |
275 SkIntToScalar(kCellSize)); | 313 SkIntToScalar(kCellSize)); |
276 | 314 |
| 315 canvas->save(); |
| 316 canvas->clipRect(cell); |
| 317 |
277 cell.inset(kPad, kPad); | 318 cell.inset(kPad, kPad); |
278 SkPoint clipCenter = SkPoint::Make(cell.centerX() - kClipOffset, | 319 SkPoint clipCenter = SkPoint::Make(cell.centerX() - kClipOffset, |
279 cell.centerY() + kClipOffset)
; | 320 cell.centerY() + kClipOffset)
; |
| 321 SkScalar curSize = kCellSize * fFraction; |
| 322 const SkRect clipRect = SkRect::MakeLTRB(clipCenter.fX - curSize
, |
| 323 clipCenter.fY - curSize
, |
| 324 clipCenter.fX + curSize
, |
| 325 clipCenter.fY + curSize
); |
280 | 326 |
281 SkScalar curSize = kCellSize * fFraction; | 327 SkAutoTDelete<Object> clipObj((*clipMakes[x])(clipRect)); |
| 328 SkAutoTDelete<Object> drawObj((*drawMakes[y])(cell)); |
282 | 329 |
283 // The goal is to replace this clipped draw (which clips the | 330 // The goal is to replace this clipped draw (which clips the |
284 // shadow) with a draw using the geometric clip | 331 // shadow) with a draw using the geometric clip |
285 if (fDrawWithGaussianEdge) { | 332 if (kGaussianEdge_Mode == fMode) { |
286 canvas->save(); | 333 canvas->save(); |
287 (*clips[x])(canvas, clipCenter, curSize); | 334 clipObj->clip(canvas); |
288 (*draws[y])(canvas, cell, false); | 335 |
| 336 // Draw with GaussianEdgeShader |
| 337 SkPaint paint; |
| 338 paint.setAntiAlias(true); |
| 339 // G channel is an F6.2 radius |
| 340 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(
4*kPad), 0)); |
| 341 paint.setShader(SkGaussianEdgeShader::Make()); |
| 342 drawObj->draw(canvas, paint); |
289 canvas->restore(); | 343 canvas->restore(); |
290 } | 344 } else if (kBlurMask_Mode == fMode) { |
| 345 SkPath clippedPath; |
291 | 346 |
292 SkPath drawnPath = (*draws[y])(canvas, cell, true); | 347 if (clipObj->contains(drawObj->bounds())) { |
| 348 clippedPath = drawObj->asPath(); |
| 349 } else { |
| 350 SkPath drawnPath = drawObj->asPath(); |
| 351 SkPath clipPath = clipObj->asPath(); |
293 | 352 |
294 if (!fDrawWithGaussianEdge) { | 353 SkAssertResult(Op(clipPath, drawnPath, kIntersect_SkPath
Op, &clippedPath)); |
295 SkPath clippedPath = (*geometricClips[x])(clipCenter, curSiz
e, drawnPath); | 354 } |
296 SkASSERT(clippedPath.isConvex()); | |
297 | 355 |
298 SkPaint blurPaint; | 356 SkPaint blurPaint; |
299 blurPaint.setAntiAlias(true); | 357 blurPaint.setAntiAlias(true); |
300 blurPaint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlu
rStyle, 3.0f)); | 358 blurPaint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlu
rStyle, 3.0f)); |
301 canvas->drawPath(clippedPath, blurPaint); | 359 canvas->drawPath(clippedPath, blurPaint); |
| 360 } else { |
| 361 SkASSERT(kRRectsGaussianEdge_Mode == fMode); |
| 362 |
| 363 SkRect cover = drawObj->bounds(); |
| 364 SkAssertResult(cover.intersect(clipObj->bounds())); |
| 365 |
| 366 SkPaint paint; |
| 367 |
| 368 SkRRect clipRR, drawnRR; |
| 369 |
| 370 if (clipObj->asRRect(&clipRR) && drawObj->asRRect(&drawnRR))
{ |
| 371 paint.setShader(SkRRectsGaussianEdgeShader::Make(clipRR,
drawnRR, |
| 372 kPad, 0
.0f)); |
| 373 } |
| 374 |
| 375 canvas->drawRect(cover, paint); |
302 } | 376 } |
| 377 |
| 378 // Draw the clip and draw objects for reference |
| 379 SkPaint strokePaint; |
| 380 strokePaint.setStyle(SkPaint::kStroke_Style); |
| 381 strokePaint.setStrokeWidth(0); |
| 382 strokePaint.setColor(SK_ColorRED); |
| 383 canvas->drawPath(drawObj->asPath(), strokePaint); |
| 384 strokePaint.setColor(SK_ColorGREEN); |
| 385 canvas->drawPath(clipObj->asPath(), strokePaint); |
| 386 |
| 387 canvas->restore(); |
303 } | 388 } |
304 } | 389 } |
305 } | 390 } |
306 | 391 |
307 bool onHandleKey(SkUnichar uni) override { | 392 bool onHandleKey(SkUnichar uni) override { |
308 switch (uni) { | 393 switch (uni) { |
309 case 'C': | 394 case 'C': |
310 fDrawWithGaussianEdge = !fDrawWithGaussianEdge; | 395 fMode = (Mode)((fMode + 1) % kModeCount); |
311 return true; | 396 return true; |
312 } | 397 } |
313 | 398 |
314 return false; | 399 return false; |
315 } | 400 } |
316 | 401 |
317 bool onAnimate(const SkAnimTimer& timer) override { | 402 bool onAnimate(const SkAnimTimer& timer) override { |
318 fFraction = timer.pingPong(kPeriod, 0.0f, 0.0f, 1.0f); | 403 fFraction = timer.pingPong(kPeriod, 0.0f, 0.0f, 1.0f); |
319 return true; | 404 return true; |
320 } | 405 } |
321 | 406 |
322 private: | 407 private: |
323 SkScalar fFraction; | 408 SkScalar fFraction; |
324 bool fDrawWithGaussianEdge; | 409 Mode fMode; |
325 | 410 |
326 typedef GM INHERITED; | 411 typedef GM INHERITED; |
327 }; | 412 }; |
328 | 413 |
329 ////////////////////////////////////////////////////////////////////////////// | 414 ////////////////////////////////////////////////////////////////////////////// |
330 | 415 |
331 DEF_GM(return new RevealGM;) | 416 DEF_GM(return new RevealGM;) |
332 } | 417 } |
OLD | NEW |