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