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 "SkBlurMaskFilter.h" |
| 10 #include "SkRRect.h" |
| 11 #include "sk_tool_utils.h" |
| 12 |
| 13 static SkRect offset_center_to(const SkIRect& src, SkScalar x, SkScalar y) { |
| 14 SkScalar halfW = 0.5f * src.width(); |
| 15 SkScalar halfH = 0.5f * src.height(); |
| 16 |
| 17 return SkRect::MakeLTRB(x - halfW, y - halfH, x + halfW, y + halfH); |
| 18 } |
| 19 |
| 20 static void draw_rrect(SkCanvas* canvas, const SkRRect& rr, const SkRRect& occRR
) { |
| 21 const SkScalar kBlurSigma = 5.0f; |
| 22 |
| 23 SkRect occRect; |
| 24 SkColor strokeColor; |
| 25 |
| 26 { |
| 27 SkRect occRect1 = sk_tool_utils::compute_central_occluder(occRR); |
| 28 SkRect occRect2 = sk_tool_utils::compute_widest_occluder(occRR); |
| 29 SkRect occRect3 = sk_tool_utils::compute_tallest_occluder(occRR); |
| 30 |
| 31 SkScalar area1 = occRect1.width() * occRect1.height(); |
| 32 SkScalar area2 = occRect2.width() * occRect2.height(); |
| 33 SkScalar area3 = occRect3.width() * occRect3.height(); |
| 34 |
| 35 if (area1 >= area2 && area1 >= area3) { |
| 36 strokeColor = SK_ColorRED; |
| 37 occRect = occRect1; |
| 38 } else if (area2 > area3) { |
| 39 strokeColor = SK_ColorYELLOW; |
| 40 occRect = occRect2; |
| 41 } else { |
| 42 strokeColor = SK_ColorCYAN; |
| 43 occRect = occRect3; |
| 44 } |
| 45 } |
| 46 |
| 47 // draw the blur |
| 48 SkPaint paint; |
| 49 paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kBlurSigma))
; //, occRect)); |
| 50 canvas->drawRRect(rr, paint); |
| 51 |
| 52 // draw the stroked geometry of the full occluder |
| 53 SkPaint stroke; |
| 54 stroke.setStyle(SkPaint::kStroke_Style); |
| 55 stroke.setColor(SK_ColorBLUE); |
| 56 canvas->drawRRect(occRR, stroke); |
| 57 |
| 58 // draw the geometry of the occluding rect |
| 59 stroke.setColor(strokeColor); |
| 60 canvas->drawRect(occRect, stroke); |
| 61 } |
| 62 |
| 63 static void draw_45(SkCanvas* canvas, SkRRect::Corner corner, |
| 64 SkScalar dist, const SkPoint& center) { |
| 65 SkRRect::Corner left = SkRRect::kUpperLeft_Corner, right = SkRRect::kUpperLe
ft_Corner; |
| 66 SkVector dir = { 0, 0 }; |
| 67 |
| 68 static const SkScalar kSize = 64.0f / SK_ScalarSqrt2; |
| 69 |
| 70 switch (corner) { |
| 71 case SkRRect::kUpperLeft_Corner: |
| 72 left = SkRRect::kUpperRight_Corner; |
| 73 right = SkRRect::kLowerLeft_Corner; |
| 74 |
| 75 dir.set(-SK_ScalarRoot2Over2, -SK_ScalarRoot2Over2); |
| 76 break; |
| 77 case SkRRect::kUpperRight_Corner: |
| 78 left = SkRRect::kUpperLeft_Corner; |
| 79 right = SkRRect::kLowerRight_Corner; |
| 80 dir.set(SK_ScalarRoot2Over2, -SK_ScalarRoot2Over2); |
| 81 break; |
| 82 case SkRRect::kLowerRight_Corner: |
| 83 left = SkRRect::kLowerLeft_Corner; |
| 84 right = SkRRect::kUpperRight_Corner; |
| 85 dir.set(SK_ScalarRoot2Over2, SK_ScalarRoot2Over2); |
| 86 break; |
| 87 case SkRRect::kLowerLeft_Corner: |
| 88 left = SkRRect::kLowerRight_Corner; |
| 89 right = SkRRect::kUpperLeft_Corner; |
| 90 dir.set(-SK_ScalarRoot2Over2, SK_ScalarRoot2Over2); |
| 91 break; |
| 92 default: |
| 93 SkFAIL("Invalid shape."); |
| 94 } |
| 95 |
| 96 SkRect r = SkRect::MakeWH(kSize, kSize); |
| 97 // UL, UR, LR, LL |
| 98 SkVector radii[4] = { { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f
, 0.0f } }; |
| 99 radii[left] = SkVector::Make(kSize, kSize); |
| 100 radii[right] = SkVector::Make(kSize, kSize); |
| 101 SkRRect rr; |
| 102 rr.setRectRadii( |
| 103 offset_center_to(r.roundOut(), center.fX + dist*dir.fX, center.fY +
dist*dir.fY), |
| 104 radii); |
| 105 |
| 106 SkRRect occRR; |
| 107 dist -= 10.0f; |
| 108 occRR.setRectRadii( |
| 109 offset_center_to(r.roundOut(), center.fX + dist*dir.fX, center.fY +
dist*dir.fY), |
| 110 radii); |
| 111 |
| 112 draw_rrect(canvas, rr, occRR); |
| 113 } |
| 114 |
| 115 static void draw_45_simple(SkCanvas* canvas, const SkVector& v, |
| 116 SkScalar dist, const SkPoint& center) { |
| 117 SkIRect r = SkIRect::MakeWH(64, 64); |
| 118 SkRRect rr = SkRRect::MakeRectXY( |
| 119 offset_center_to(r, center.fX + dist*v.fX, center.fY
+ dist*v.fY), |
| 120 8, 8); |
| 121 |
| 122 dist -= 10.0f; |
| 123 SkRRect occRR = SkRRect::MakeRectXY( |
| 124 offset_center_to(r, center.fX + dist*v.fX, center.fY
+ dist*v.fY), |
| 125 8, 8); |
| 126 |
| 127 draw_rrect(canvas, rr, occRR); |
| 128 } |
| 129 |
| 130 static void draw_90(SkCanvas* canvas, const SkVector& v, SkScalar dist, const Sk
Point& center) { |
| 131 static const int kWidth = 25; |
| 132 |
| 133 SkIRect r; |
| 134 if (fabs(v.fX) < fabs(v.fY)) { |
| 135 r = SkIRect::MakeWH(kWidth, 64); |
| 136 } else { |
| 137 r = SkIRect::MakeWH(64, kWidth); |
| 138 } |
| 139 SkRRect rr = SkRRect::MakeOval( |
| 140 offset_center_to(r, center.fX + dist*v.fX, center.fY
+ dist*v.fY)); |
| 141 |
| 142 dist -= 10.0f; |
| 143 SkRRect occRR = SkRRect::MakeOval( |
| 144 offset_center_to(r, center.fX + dist*v.fX, center.fY
+ dist*v.fY)); |
| 145 |
| 146 draw_rrect(canvas, rr, occRR); |
| 147 } |
| 148 |
| 149 static void draw_90_simple(SkCanvas* canvas, const SkVector& v, |
| 150 SkScalar dist, const SkPoint& center) { |
| 151 static const int kLength = 128; |
| 152 static const int kWidth = 32; |
| 153 |
| 154 SkIRect r; |
| 155 if (fabs(v.fX) < fabs(v.fY)) { |
| 156 r = SkIRect::MakeWH(kLength, kWidth); |
| 157 } else { |
| 158 r = SkIRect::MakeWH(kWidth, kLength); |
| 159 } |
| 160 SkRRect rr = SkRRect::MakeRectXY( |
| 161 offset_center_to(r, center.fX + dist*v.fX, center.fY
+ dist*v.fY), |
| 162 8, 8); |
| 163 |
| 164 dist -= 10.0f; |
| 165 SkRRect occRR = SkRRect::MakeRectXY( |
| 166 offset_center_to(r, center.fX + dist*v.fX, center.fY
+ dist*v.fY), |
| 167 8, 8); |
| 168 |
| 169 draw_rrect(canvas, rr, occRR); |
| 170 } |
| 171 |
| 172 static void draw_30_60(SkCanvas* canvas, SkRRect::Corner corner, const SkVector&
v, |
| 173 SkScalar dist, const SkPoint& center) { |
| 174 SkRRect::Corner left = SkRRect::kUpperLeft_Corner, right = SkRRect::kUpperLe
ft_Corner; |
| 175 |
| 176 static const int kLength = 64; |
| 177 static const int kWidth = 30; |
| 178 |
| 179 switch (corner) { |
| 180 case SkRRect::kUpperLeft_Corner: |
| 181 left = SkRRect::kUpperRight_Corner; |
| 182 right = SkRRect::kLowerLeft_Corner; |
| 183 break; |
| 184 case SkRRect::kUpperRight_Corner: |
| 185 left = SkRRect::kUpperLeft_Corner; |
| 186 right = SkRRect::kLowerRight_Corner; |
| 187 break; |
| 188 case SkRRect::kLowerRight_Corner: |
| 189 left = SkRRect::kLowerLeft_Corner; |
| 190 right = SkRRect::kUpperRight_Corner; |
| 191 break; |
| 192 case SkRRect::kLowerLeft_Corner: |
| 193 left = SkRRect::kLowerRight_Corner; |
| 194 right = SkRRect::kUpperLeft_Corner; |
| 195 break; |
| 196 default: |
| 197 SkFAIL("Invalid shape."); |
| 198 } |
| 199 |
| 200 SkIRect r; |
| 201 if (fabs(v.fX) < fabs(v.fY)) { |
| 202 r = SkIRect::MakeWH(kLength, kWidth); |
| 203 } else { |
| 204 r = SkIRect::MakeWH(kWidth, kLength); |
| 205 } |
| 206 // UL, UR, LR, LL |
| 207 SkVector radii[4] = { { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f
, 0.0f } }; |
| 208 radii[left] = SkVector::Make(SkIntToScalar(kWidth), SkIntToScalar(kWidth)); |
| 209 radii[right] = SkVector::Make(SkIntToScalar(kWidth), SkIntToScalar(kWidth)); |
| 210 SkRRect rr; |
| 211 rr.setRectRadii(offset_center_to(r, center.fX + dist*v.fX, center.fY + dist*
v.fY), radii); |
| 212 |
| 213 dist -= 10.0f; |
| 214 SkRRect occRR; |
| 215 occRR.setRectRadii(offset_center_to(r, center.fX + dist*v.fX, center.fY + di
st*v.fY), radii); |
| 216 draw_rrect(canvas, rr, occRR); |
| 217 } |
| 218 |
| 219 namespace skiagm { |
| 220 |
| 221 class OccludedRRectBlurGM : public GM { |
| 222 public: |
| 223 OccludedRRectBlurGM() { |
| 224 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); |
| 225 } |
| 226 |
| 227 protected: |
| 228 |
| 229 SkString onShortName() override { |
| 230 return SkString("occludedrrectblur"); |
| 231 } |
| 232 |
| 233 SkISize onISize() override { |
| 234 return SkISize::Make(kWidth, kHeight); |
| 235 } |
| 236 |
| 237 void onDraw(SkCanvas* canvas) override { |
| 238 const SkPoint center = SkPoint::Make(kWidth/2, kHeight/2); |
| 239 |
| 240 // outer-most big RR |
| 241 { |
| 242 SkIRect r = SkIRect::MakeWH(420, 420); |
| 243 SkRRect rr = SkRRect::MakeRectXY(offset_center_to(r, center.fX, cent
er.fY), 64, 64); |
| 244 draw_rrect(canvas, rr, rr); |
| 245 |
| 246 #if 1 |
| 247 // TODO: remove this. Until we actually start skipping the middle dr
aw we need this |
| 248 // to provide contrast |
| 249 SkPaint temp; |
| 250 temp.setColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); |
| 251 r.inset(32, 32); |
| 252 canvas->drawRect(offset_center_to(r, center.fX, center.fY), temp); |
| 253 #endif |
| 254 } |
| 255 |
| 256 // center circle |
| 257 { |
| 258 SkIRect r = SkIRect::MakeWH(32, 32); |
| 259 SkRRect rr = SkRRect::MakeOval(offset_center_to(r, center.fX, center
.fY)); |
| 260 draw_rrect(canvas, rr, rr); |
| 261 } |
| 262 |
| 263 draw_45(canvas, SkRRect::kUpperLeft_Corner, 64, center); |
| 264 draw_45(canvas, SkRRect::kUpperRight_Corner, 64, center); |
| 265 draw_45(canvas, SkRRect::kLowerRight_Corner, 64, center); |
| 266 draw_45(canvas, SkRRect::kLowerLeft_Corner, 64, center); |
| 267 |
| 268 draw_90(canvas, SkVector::Make(-1.0f, 0.0f), 64, center); |
| 269 draw_90(canvas, SkVector::Make(0.0f, -1.0f), 64, center); |
| 270 draw_90(canvas, SkVector::Make(1.0f, 0.0f), 64, center); |
| 271 draw_90(canvas, SkVector::Make(0.0f, 1.0f), 64, center); |
| 272 |
| 273 static const SkScalar kRoot3Over2 = 0.8660254037844386f; |
| 274 |
| 275 draw_30_60(canvas, SkRRect::kLowerLeft_Corner, |
| 276 SkVector::Make(0.5f, kRoot3Over2), 120, center); |
| 277 draw_30_60(canvas, SkRRect::kUpperRight_Corner, |
| 278 SkVector::Make(kRoot3Over2, 0.5f), 120, center); |
| 279 |
| 280 draw_30_60(canvas, SkRRect::kUpperLeft_Corner, |
| 281 SkVector::Make(-0.5f, kRoot3Over2), 120, center); |
| 282 draw_30_60(canvas, SkRRect::kLowerRight_Corner, |
| 283 SkVector::Make(-kRoot3Over2, 0.5f), 120, center); |
| 284 |
| 285 draw_30_60(canvas, SkRRect::kLowerLeft_Corner, |
| 286 SkVector::Make(-0.5f, -kRoot3Over2), 120, center); |
| 287 draw_30_60(canvas, SkRRect::kUpperRight_Corner, |
| 288 SkVector::Make(-kRoot3Over2, -0.5f), 120, center); |
| 289 |
| 290 draw_30_60(canvas, SkRRect::kUpperLeft_Corner, |
| 291 SkVector::Make(0.5f, -kRoot3Over2), 120, center); |
| 292 draw_30_60(canvas, SkRRect::kLowerRight_Corner, |
| 293 SkVector::Make(kRoot3Over2, -0.5f), 120, center); |
| 294 |
| 295 draw_45_simple(canvas, SkVector::Make(-SK_ScalarRoot2Over2, -SK_ScalarRo
ot2Over2), |
| 296 190, center); |
| 297 draw_45_simple(canvas, SkVector::Make(SK_ScalarRoot2Over2, -SK_ScalarRoo
t2Over2), |
| 298 190, center); |
| 299 draw_45_simple(canvas, SkVector::Make(SK_ScalarRoot2Over2, SK_ScalarRoot
2Over2), |
| 300 190, center); |
| 301 draw_45_simple(canvas, SkVector::Make(-SK_ScalarRoot2Over2, SK_ScalarRoo
t2Over2), |
| 302 190, center); |
| 303 |
| 304 draw_90_simple(canvas, SkVector::Make(-1.0f, 0.0f), 150, center); |
| 305 draw_90_simple(canvas, SkVector::Make(0.0f, -1.0f), 150, center); |
| 306 draw_90_simple(canvas, SkVector::Make(1.0f, 0.0f), 150, center); |
| 307 draw_90_simple(canvas, SkVector::Make(0.0f, 1.0f), 150, center); |
| 308 } |
| 309 |
| 310 private: |
| 311 static const int kWidth = 440; |
| 312 static const int kHeight = 440; |
| 313 |
| 314 typedef GM INHERITED; |
| 315 }; |
| 316 |
| 317 ////////////////////////////////////////////////////////////////////////////// |
| 318 |
| 319 DEF_GM(return new OccludedRRectBlurGM;) |
| 320 } |
OLD | NEW |