OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 "SkRRect.h" | 8 #include "SkRRect.h" |
9 #include "SkMatrix.h" | 9 #include "SkMatrix.h" |
10 | 10 |
(...skipping 25 matching lines...) Expand all Loading... |
36 } | 36 } |
37 fType = kSimple_Type; | 37 fType = kSimple_Type; |
38 if (xRad >= SkScalarHalf(fRect.width()) && yRad >= SkScalarHalf(fRect.height
())) { | 38 if (xRad >= SkScalarHalf(fRect.width()) && yRad >= SkScalarHalf(fRect.height
())) { |
39 fType = kOval_Type; | 39 fType = kOval_Type; |
40 // TODO: assert that all the x&y radii are already W/2 & H/2 | 40 // TODO: assert that all the x&y radii are already W/2 & H/2 |
41 } | 41 } |
42 | 42 |
43 SkDEBUGCODE(this->validate();) | 43 SkDEBUGCODE(this->validate();) |
44 } | 44 } |
45 | 45 |
46 void SkRRect::setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad
, | |
47 SkScalar rightRad, SkScalar bottomRad) { | |
48 if (rect.isEmpty()) { | |
49 this->setEmpty(); | |
50 return; | |
51 } | |
52 | |
53 leftRad = SkMaxScalar(leftRad, 0); | |
54 topRad = SkMaxScalar(topRad, 0); | |
55 rightRad = SkMaxScalar(rightRad, 0); | |
56 bottomRad = SkMaxScalar(bottomRad, 0); | |
57 | |
58 SkScalar scale = SK_Scalar1; | |
59 if (leftRad + rightRad > rect.width()) { | |
60 scale = SkScalarDiv(rect.width(), leftRad + rightRad); | |
61 } | |
62 if (topRad + bottomRad > rect.height()) { | |
63 scale = SkMinScalar(scale, SkScalarDiv(rect.width(), leftRad + rightRad)
); | |
64 } | |
65 | |
66 if (scale < SK_Scalar1) { | |
67 leftRad = SkScalarMul(leftRad, scale); | |
68 topRad = SkScalarMul(topRad, scale); | |
69 rightRad = SkScalarMul(rightRad, scale); | |
70 bottomRad = SkScalarMul(bottomRad, scale); | |
71 } | |
72 | |
73 if (leftRad == rightRad && topRad == bottomRad) { | |
74 if (leftRad >= SkScalarHalf(rect.width()) && topRad >= SkScalarHalf(rect
.height())) { | |
75 fType = kOval_Type; | |
76 } else if (0 == leftRad || 0 == topRad) { | |
77 // If the left and (by equality check above) right radii are zero th
en it is a rect. | |
78 // Same goes for top/bottom. | |
79 fType = kRect_Type; | |
80 leftRad = 0; | |
81 topRad = 0; | |
82 rightRad = 0; | |
83 bottomRad = 0; | |
84 } else { | |
85 fType = kSimple_Type; | |
86 } | |
87 } else { | |
88 fType = kNinePatch_Type; | |
89 } | |
90 | |
91 fRect = rect; | |
92 fRadii[kUpperLeft_Corner].set(leftRad, topRad); | |
93 fRadii[kUpperRight_Corner].set(rightRad, topRad); | |
94 fRadii[kLowerRight_Corner].set(rightRad, bottomRad); | |
95 fRadii[kLowerLeft_Corner].set(leftRad, bottomRad); | |
96 | |
97 SkDEBUGCODE(this->validate();) | |
98 } | |
99 | |
100 | |
101 void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { | 46 void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { |
102 if (rect.isEmpty()) { | 47 if (rect.isEmpty()) { |
103 this->setEmpty(); | 48 this->setEmpty(); |
104 return; | 49 return; |
105 } | 50 } |
106 | 51 |
107 fRect = rect; | 52 fRect = rect; |
108 memcpy(fRadii, radii, sizeof(fRadii)); | 53 memcpy(fRadii, radii, sizeof(fRadii)); |
109 | 54 |
110 bool allCornersSquare = true; | 55 bool allCornersSquare = true; |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 | 193 |
249 // At this point we know all four corners of 'rect' are inside the | 194 // At this point we know all four corners of 'rect' are inside the |
250 // bounds of of this RR. Check to make sure all the corners are inside | 195 // bounds of of this RR. Check to make sure all the corners are inside |
251 // all the curves | 196 // all the curves |
252 return this->checkCornerContainment(rect.fLeft, rect.fTop) && | 197 return this->checkCornerContainment(rect.fLeft, rect.fTop) && |
253 this->checkCornerContainment(rect.fRight, rect.fTop) && | 198 this->checkCornerContainment(rect.fRight, rect.fTop) && |
254 this->checkCornerContainment(rect.fRight, rect.fBottom) && | 199 this->checkCornerContainment(rect.fRight, rect.fBottom) && |
255 this->checkCornerContainment(rect.fLeft, rect.fBottom); | 200 this->checkCornerContainment(rect.fLeft, rect.fBottom); |
256 } | 201 } |
257 | 202 |
258 static bool radii_are_nine_patch(const SkVector radii[4]) { | |
259 return radii[SkRRect::kUpperLeft_Corner].fX == radii[SkRRect::kLowerLeft_Cor
ner].fX && | |
260 radii[SkRRect::kUpperLeft_Corner].fY == radii[SkRRect::kUpperRight_Co
rner].fY && | |
261 radii[SkRRect::kUpperRight_Corner].fX == radii[SkRRect::kLowerRight_C
orner].fX && | |
262 radii[SkRRect::kLowerLeft_Corner].fY == radii[SkRRect::kLowerRight_Co
rner].fY; | |
263 } | |
264 | |
265 // There is a simplified version of this method in setRectXY | 203 // There is a simplified version of this method in setRectXY |
266 void SkRRect::computeType() const { | 204 void SkRRect::computeType() const { |
267 SkDEBUGCODE(this->validate();) | 205 SkDEBUGCODE(this->validate();) |
268 | 206 |
269 if (fRect.isEmpty()) { | 207 if (fRect.isEmpty()) { |
270 fType = kEmpty_Type; | 208 fType = kEmpty_Type; |
271 return; | 209 return; |
272 } | 210 } |
273 | 211 |
274 bool allRadiiEqual = true; // are all x radii equal and all y radii? | 212 bool allRadiiEqual = true; // are all x radii equal and all y radii? |
(...skipping 18 matching lines...) Expand all Loading... |
293 if (allRadiiEqual) { | 231 if (allRadiiEqual) { |
294 if (fRadii[0].fX >= SkScalarHalf(fRect.width()) && | 232 if (fRadii[0].fX >= SkScalarHalf(fRect.width()) && |
295 fRadii[0].fY >= SkScalarHalf(fRect.height())) { | 233 fRadii[0].fY >= SkScalarHalf(fRect.height())) { |
296 fType = kOval_Type; | 234 fType = kOval_Type; |
297 } else { | 235 } else { |
298 fType = kSimple_Type; | 236 fType = kSimple_Type; |
299 } | 237 } |
300 return; | 238 return; |
301 } | 239 } |
302 | 240 |
303 if (radii_are_nine_patch(fRadii)) { | 241 fType = kComplex_Type; |
304 fType = kNinePatch_Type; | |
305 } else { | |
306 fType = kComplex_Type; | |
307 } | |
308 } | 242 } |
309 | 243 |
310 static bool matrix_only_scale_and_translate(const SkMatrix& matrix) { | 244 static bool matrix_only_scale_and_translate(const SkMatrix& matrix) { |
311 const SkMatrix::TypeMask m = (SkMatrix::TypeMask) (SkMatrix::kAffine_Mask | 245 const SkMatrix::TypeMask m = (SkMatrix::TypeMask) (SkMatrix::kAffine_Mask |
312 | SkMatrix::kPerspective_Mask); | 246 | SkMatrix::kPerspective_Mask); |
313 return (matrix.getType() & m) == 0; | 247 return (matrix.getType() & m) == 0; |
314 } | 248 } |
315 | 249 |
316 bool SkRRect::transform(const SkMatrix& matrix, SkRRect* dst) const { | 250 bool SkRRect::transform(const SkMatrix& matrix, SkRRect* dst) const { |
317 if (NULL == dst) { | 251 if (NULL == dst) { |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 } | 384 } |
451 | 385 |
452 if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) { | 386 if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) { |
453 allRadiiSame = false; | 387 allRadiiSame = false; |
454 } | 388 } |
455 | 389 |
456 if (0 != fRadii[i].fX && 0 != fRadii[i].fY) { | 390 if (0 != fRadii[i].fX && 0 != fRadii[i].fY) { |
457 allCornersSquare = false; | 391 allCornersSquare = false; |
458 } | 392 } |
459 } | 393 } |
460 bool patchesOfNine = radii_are_nine_patch(fRadii); | |
461 | 394 |
462 switch (fType) { | 395 switch (fType) { |
463 case kEmpty_Type: | 396 case kEmpty_Type: |
464 SkASSERT(fRect.isEmpty()); | 397 SkASSERT(fRect.isEmpty()); |
465 SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare); | 398 SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare); |
466 | 399 |
467 SkASSERT(0 == fRect.fLeft && 0 == fRect.fTop && | 400 SkASSERT(0 == fRect.fLeft && 0 == fRect.fTop && |
468 0 == fRect.fRight && 0 == fRect.fBottom); | 401 0 == fRect.fRight && 0 == fRect.fBottom); |
469 break; | 402 break; |
470 case kRect_Type: | 403 case kRect_Type: |
471 SkASSERT(!fRect.isEmpty()); | 404 SkASSERT(!fRect.isEmpty()); |
472 SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare); | 405 SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare); |
473 break; | 406 break; |
474 case kOval_Type: | 407 case kOval_Type: |
475 SkASSERT(!fRect.isEmpty()); | 408 SkASSERT(!fRect.isEmpty()); |
476 SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare); | 409 SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare); |
477 | 410 |
478 for (int i = 0; i < 4; ++i) { | 411 for (int i = 0; i < 4; ++i) { |
479 SkASSERT(SkScalarNearlyEqual(fRadii[i].fX, SkScalarHalf(fRect.wi
dth()))); | 412 SkASSERT(SkScalarNearlyEqual(fRadii[i].fX, SkScalarHalf(fRect.wi
dth()))); |
480 SkASSERT(SkScalarNearlyEqual(fRadii[i].fY, SkScalarHalf(fRect.he
ight()))); | 413 SkASSERT(SkScalarNearlyEqual(fRadii[i].fY, SkScalarHalf(fRect.he
ight()))); |
481 } | 414 } |
482 break; | 415 break; |
483 case kSimple_Type: | 416 case kSimple_Type: |
484 SkASSERT(!fRect.isEmpty()); | 417 SkASSERT(!fRect.isEmpty()); |
485 SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare); | 418 SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare); |
486 break; | 419 break; |
487 case kNinePatch_Type: | |
488 SkASSERT(!fRect.isEmpty()); | |
489 SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); | |
490 SkASSERT(patchesOfNine); | |
491 break; | |
492 case kComplex_Type: | 420 case kComplex_Type: |
493 SkASSERT(!fRect.isEmpty()); | 421 SkASSERT(!fRect.isEmpty()); |
494 SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); | 422 SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); |
495 SkASSERT(!patchesOfNine); | |
496 break; | 423 break; |
497 case kUnknown_Type: | 424 case kUnknown_Type: |
498 // no limits on this | 425 // no limits on this |
499 break; | 426 break; |
500 } | 427 } |
501 } | 428 } |
502 #endif // SK_DEBUG | 429 #endif // SK_DEBUG |
503 | 430 |
504 /////////////////////////////////////////////////////////////////////////////// | 431 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |