| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2016 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #include "gm.h" | |
| 9 #include "SkAnimTimer.h" | |
| 10 #include "SkGaussianEdgeShader.h" | |
| 11 #include "SkPath.h" | |
| 12 #include "SkPathOps.h" | |
| 13 #include "SkRRect.h" | |
| 14 #include "SkStroke.h" | |
| 15 | |
| 16 constexpr int kNumCols = 2; | |
| 17 constexpr int kNumRows = 5; | |
| 18 constexpr int kCellSize = 128; | |
| 19 constexpr SkScalar kPad = 8.0f; | |
| 20 constexpr SkScalar kPeriod = 8.0f; | |
| 21 constexpr int kClipOffset = 32; | |
| 22 | |
| 23 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 24 typedef SkPath (*PFDrawMthd)(SkCanvas*, const SkRect&, bool); | |
| 25 | |
| 26 static SkPath draw_rrect(SkCanvas* canvas, const SkRect& r, bool stroked) { | |
| 27 SkRRect rr = SkRRect::MakeRectXY(r, 2*kPad, 2*kPad); | |
| 28 | |
| 29 SkPaint paint; | |
| 30 paint.setAntiAlias(true); | |
| 31 if (stroked) { | |
| 32 paint.setStyle(SkPaint::kStroke_Style); | |
| 33 paint.setColor(SK_ColorRED); | |
| 34 } else { | |
| 35 // G channel is an F6.2 radius | |
| 36 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | |
| 37 paint.setShader(SkGaussianEdgeShader::Make()); | |
| 38 } | |
| 39 canvas->drawRRect(rr, paint); | |
| 40 | |
| 41 SkPath p; | |
| 42 p.addRoundRect(r, 2*kPad, 2*kPad); | |
| 43 return p; | |
| 44 } | |
| 45 | |
| 46 static SkPath draw_stroked_rrect(SkCanvas* canvas, const SkRect& r, bool stroked
) { | |
| 47 SkRect insetRect = r; | |
| 48 insetRect.inset(kPad, kPad); | |
| 49 SkRRect rr = SkRRect::MakeRectXY(insetRect, 2*kPad, 2*kPad); | |
| 50 | |
| 51 SkPaint paint; | |
| 52 paint.setAntiAlias(true); | |
| 53 paint.setStyle(SkPaint::kStroke_Style); | |
| 54 paint.setStrokeWidth(kPad); | |
| 55 | |
| 56 if (stroked) { | |
| 57 // In this case we want to draw a stroked representation of the stroked
rrect | |
| 58 SkPath p, stroked; | |
| 59 p.addRRect(rr); | |
| 60 SkStroke stroke(paint); | |
| 61 stroke.strokePath(p, &stroked); | |
| 62 | |
| 63 paint.setStrokeWidth(0); | |
| 64 paint.setColor(SK_ColorRED); | |
| 65 canvas->drawPath(stroked, paint); | |
| 66 } else { | |
| 67 // G channel is an F6.2 radius | |
| 68 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | |
| 69 paint.setShader(SkGaussianEdgeShader::Make()); | |
| 70 | |
| 71 canvas->drawRRect(rr, paint); | |
| 72 } | |
| 73 | |
| 74 SkPath p; | |
| 75 insetRect.outset(kPad/2.0f, kPad/2.0f); | |
| 76 p.addRoundRect(insetRect, 2*kPad, 2*kPad); | |
| 77 return p; | |
| 78 } | |
| 79 | |
| 80 static SkPath draw_oval(SkCanvas* canvas, const SkRect& r, bool stroked) { | |
| 81 SkRRect rr = SkRRect::MakeOval(r); | |
| 82 | |
| 83 SkPaint paint; | |
| 84 paint.setAntiAlias(true); | |
| 85 if (stroked) { | |
| 86 paint.setStyle(SkPaint::kStroke_Style); | |
| 87 paint.setColor(SK_ColorRED); | |
| 88 } else { | |
| 89 // G channel is an F6.2 radius | |
| 90 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | |
| 91 paint.setShader(SkGaussianEdgeShader::Make()); | |
| 92 } | |
| 93 canvas->drawRRect(rr, paint); | |
| 94 | |
| 95 SkPath p; | |
| 96 p.addOval(r); | |
| 97 return p; | |
| 98 } | |
| 99 | |
| 100 static SkPath draw_square(SkCanvas* canvas, const SkRect& r, bool stroked) { | |
| 101 SkPaint paint; | |
| 102 paint.setAntiAlias(true); | |
| 103 if (stroked) { | |
| 104 paint.setStyle(SkPaint::kStroke_Style); | |
| 105 paint.setColor(SK_ColorRED); | |
| 106 } else { | |
| 107 // G channel is an F6.2 radius | |
| 108 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | |
| 109 paint.setShader(SkGaussianEdgeShader::Make()); | |
| 110 } | |
| 111 canvas->drawRect(r, paint); | |
| 112 | |
| 113 SkPath p; | |
| 114 p.addRect(r); | |
| 115 return p; | |
| 116 } | |
| 117 | |
| 118 static SkPath draw_pentagon(SkCanvas* canvas, const SkRect& r, bool stroked) { | |
| 119 SkPath p; | |
| 120 | |
| 121 SkPoint points[5] = { | |
| 122 { 0.000000f, -1.000000f }, | |
| 123 { -0.951056f, -0.309017f }, | |
| 124 { -0.587785f, 0.809017f }, | |
| 125 { 0.587785f, 0.809017f }, | |
| 126 { 0.951057f, -0.309017f }, | |
| 127 }; | |
| 128 | |
| 129 SkScalar height = r.height()/2.0f; | |
| 130 SkScalar width = r.width()/2.0f; | |
| 131 | |
| 132 p.moveTo(r.centerX() + points[0].fX * width, r.centerY() + points[0].fY * he
ight); | |
| 133 p.lineTo(r.centerX() + points[1].fX * width, r.centerY() + points[1].fY * he
ight); | |
| 134 p.lineTo(r.centerX() + points[2].fX * width, r.centerY() + points[2].fY * he
ight); | |
| 135 p.lineTo(r.centerX() + points[3].fX * width, r.centerY() + points[3].fY * he
ight); | |
| 136 p.lineTo(r.centerX() + points[4].fX * width, r.centerY() + points[4].fY * he
ight); | |
| 137 p.close(); | |
| 138 | |
| 139 SkPaint paint; | |
| 140 paint.setAntiAlias(true); | |
| 141 if (stroked) { | |
| 142 paint.setStyle(SkPaint::kStroke_Style); | |
| 143 paint.setColor(SK_ColorRED); | |
| 144 } else { | |
| 145 // G channel is an F6.2 radius | |
| 146 paint.setColor(SkColorSetARGB(255, 255, (unsigned char)(4*kPad), 0)); | |
| 147 // This currently goes through the GrAAConvexPathRenderer and produces a | |
| 148 // AAConvexPathBatch (i.e., it doesn't have a analytic distance) | |
| 149 // paint.setShader(SkGaussianEdgeShader::Make()); | |
| 150 } | |
| 151 canvas->drawPath(p, paint); | |
| 152 | |
| 153 return p; | |
| 154 } | |
| 155 | |
| 156 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 157 typedef void (*PFClipMthd)(SkCanvas* canvas, const SkPoint&, SkScalar); | |
| 158 | |
| 159 static void circle_clip(SkCanvas* canvas, const SkPoint& center, SkScalar rad) { | |
| 160 SkRect r = SkRect::MakeLTRB(center.fX - rad, center.fY - rad, center.fX + ra
d, center.fY + rad); | |
| 161 SkRRect rr = SkRRect::MakeOval(r); | |
| 162 | |
| 163 canvas->clipRRect(rr); | |
| 164 } | |
| 165 | |
| 166 static void square_clip(SkCanvas* canvas, const SkPoint& center, SkScalar size)
{ | |
| 167 SkScalar newSize = SK_ScalarRoot2Over2 * size; | |
| 168 SkRect r = SkRect::MakeLTRB(center.fX - newSize, center.fY - newSize, | |
| 169 center.fX + newSize, center.fY + newSize); | |
| 170 | |
| 171 canvas->clipRect(r); | |
| 172 } | |
| 173 | |
| 174 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 175 // These are stand alone methods (rather than just, say, returning the SkPath fo
r the clip | |
| 176 // object) so that we can catch the clip-contains-victim case. | |
| 177 typedef SkPath (*PFGeometricClipMthd)(const SkPoint&, SkScalar, const SkPath&); | |
| 178 | |
| 179 static SkPath circle_geometric_clip(const SkPoint& center, SkScalar rad, const S
kPath& victim) { | |
| 180 const SkRect bound = victim.getBounds(); | |
| 181 SkPoint pts[4]; | |
| 182 bound.toQuad(pts); | |
| 183 | |
| 184 bool clipContainsVictim = true; | |
| 185 for (int i = 0; i < 4; ++i) { | |
| 186 SkScalar distSq = (pts[i].fX - center.fX) * (pts[i].fX - center.fX) + | |
| 187 (pts[i].fY - center.fY) * (pts[i].fY - center.fY); | |
| 188 if (distSq >= rad*rad) { | |
| 189 clipContainsVictim = false; | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 if (clipContainsVictim) { | |
| 194 return victim; | |
| 195 } | |
| 196 | |
| 197 // Add victim contains clip test? | |
| 198 | |
| 199 SkPath clipPath; | |
| 200 clipPath.addCircle(center.fX, center.fY, rad); | |
| 201 | |
| 202 SkPath result; | |
| 203 SkAssertResult(Op(clipPath, victim, kIntersect_SkPathOp, &result)); | |
| 204 | |
| 205 return result; | |
| 206 } | |
| 207 | |
| 208 static SkPath square_geometric_clip(const SkPoint& center, SkScalar size, const
SkPath& victim) { | |
| 209 SkScalar newSize = SK_ScalarRoot2Over2 * size; | |
| 210 SkRect r = SkRect::MakeLTRB(center.fX - newSize, center.fY - newSize, | |
| 211 center.fX + newSize, center.fY + newSize); | |
| 212 | |
| 213 const SkRect bound = victim.getBounds(); | |
| 214 | |
| 215 if (r.contains(bound)) { | |
| 216 return victim; | |
| 217 } | |
| 218 | |
| 219 // Add victim contains clip test? | |
| 220 | |
| 221 SkPath clipPath; | |
| 222 clipPath.addRect(r); | |
| 223 | |
| 224 SkPath result; | |
| 225 SkAssertResult(Op(clipPath, victim, kIntersect_SkPathOp, &result)); | |
| 226 | |
| 227 return result; | |
| 228 } | |
| 229 | |
| 230 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
| 231 namespace skiagm { | |
| 232 | |
| 233 // This GM attempts to mimic Android's reveal animation | |
| 234 class RevealGM : public GM { | |
| 235 public: | |
| 236 RevealGM() : fFraction(0.5f) { | |
| 237 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); | |
| 238 } | |
| 239 | |
| 240 protected: | |
| 241 | |
| 242 SkString onShortName() override { | |
| 243 return SkString("reveal"); | |
| 244 } | |
| 245 | |
| 246 SkISize onISize() override { | |
| 247 return SkISize::Make(kNumCols * kCellSize, kNumRows * kCellSize); | |
| 248 } | |
| 249 | |
| 250 void onDraw(SkCanvas* canvas) override { | |
| 251 PFClipMthd clips[kNumCols] = { circle_clip, square_clip }; | |
| 252 PFGeometricClipMthd geometricClips[kNumCols] = { | |
| 253 circle_geometric_clip, | |
| 254 square_geometric_clip | |
| 255 }; | |
| 256 PFDrawMthd draws[kNumRows] = { | |
| 257 draw_rrect, | |
| 258 draw_stroked_rrect, | |
| 259 draw_oval, | |
| 260 draw_square, | |
| 261 draw_pentagon | |
| 262 }; | |
| 263 | |
| 264 SkPaint strokePaint; | |
| 265 strokePaint.setColor(SK_ColorGREEN); | |
| 266 strokePaint.setStyle(SkPaint::kStroke_Style); | |
| 267 strokePaint.setStrokeWidth(0.0f); | |
| 268 | |
| 269 for (int y = 0; y < kNumRows; ++y) { | |
| 270 for (int x = 0; x < kNumCols; ++x) { | |
| 271 SkRect cell = SkRect::MakeXYWH(SkIntToScalar(x*kCellSize), | |
| 272 SkIntToScalar(y*kCellSize), | |
| 273 SkIntToScalar(kCellSize), | |
| 274 SkIntToScalar(kCellSize)); | |
| 275 | |
| 276 cell.inset(kPad, kPad); | |
| 277 SkPoint clipCenter = SkPoint::Make(cell.centerX() - kClipOffset, | |
| 278 cell.centerY() + kClipOffset)
; | |
| 279 | |
| 280 SkScalar curSize = kCellSize * fFraction; | |
| 281 | |
| 282 // The goal is to replace this clipped draw (which clips the | |
| 283 // shadow) with a draw using the geometric clip | |
| 284 canvas->save(); | |
| 285 (*clips[x])(canvas, clipCenter, curSize); | |
| 286 (*draws[y])(canvas, cell, false); | |
| 287 canvas->restore(); | |
| 288 | |
| 289 SkPath drawnPath = (*draws[y])(canvas, cell, true); | |
| 290 SkPath clippedPath = (*geometricClips[x])(clipCenter, curSize, d
rawnPath); | |
| 291 canvas->drawPath(clippedPath, strokePaint); | |
| 292 } | |
| 293 } | |
| 294 } | |
| 295 | |
| 296 bool onAnimate(const SkAnimTimer& timer) override { | |
| 297 fFraction = timer.pingPong(kPeriod, 0.0f, 0.0f, 1.0f); | |
| 298 return true; | |
| 299 } | |
| 300 | |
| 301 private: | |
| 302 SkScalar fFraction; | |
| 303 | |
| 304 typedef GM INHERITED; | |
| 305 }; | |
| 306 | |
| 307 ////////////////////////////////////////////////////////////////////////////// | |
| 308 | |
| 309 DEF_GM(return new RevealGM;) | |
| 310 } | |
| OLD | NEW |