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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 * TODO: clean this guy up and possibly add to SkScalar.h | 110 * TODO: clean this guy up and possibly add to SkScalar.h |
111 */ | 111 */ |
112 static inline SkScalar SkScalarDecULP(SkScalar value) { | 112 static inline SkScalar SkScalarDecULP(SkScalar value) { |
113 #if SK_SCALAR_IS_FLOAT | 113 #if SK_SCALAR_IS_FLOAT |
114 return SkBits2Float(SkFloat2Bits(value) - 1); | 114 return SkBits2Float(SkFloat2Bits(value) - 1); |
115 #else | 115 #else |
116 #error "need impl for doubles" | 116 #error "need impl for doubles" |
117 #endif | 117 #endif |
118 } | 118 } |
119 | 119 |
120 static SkScalar clamp_radius_add(SkScalar rad, SkScalar min, SkScalar max) { | 120 /** |
robertphillips
2015/02/13 22:31:03
missing spaces here ?
| |
121 SkASSERT(rad <= max - min); | 121 * We need all combinations of predicates to be true to have a "safe" radius va lue. |
122 if (min + rad > max) { | 122 */ |
123 static SkScalar clamp_radius_check_predicates(SkScalar rad, SkScalar min, SkScal ar max) { | |
124 SkASSERT(min < max); | |
125 if (rad > max - min || min + rad > max || max - rad < min) { | |
123 rad = SkScalarDecULP(rad); | 126 rad = SkScalarDecULP(rad); |
124 } | 127 } |
125 return rad; | 128 return rad; |
126 } | |
127 | |
128 static SkScalar clamp_radius_sub(SkScalar rad, SkScalar min, SkScalar max) { | |
129 SkASSERT(rad <= max - min); | |
130 if (max - rad < min) { | |
131 rad = SkScalarDecULP(rad); | |
132 } | |
133 return rad; | |
134 } | 129 } |
135 | 130 |
136 void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { | 131 void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { |
137 if (rect.isEmpty() || !rect.isFinite()) { | 132 if (rect.isEmpty() || !rect.isFinite()) { |
138 this->setEmpty(); | 133 this->setEmpty(); |
139 return; | 134 return; |
140 } | 135 } |
141 | 136 |
142 if (!SkScalarsAreFinite(&radii[0].fX, 8)) { | 137 if (!SkScalarsAreFinite(&radii[0].fX, 8)) { |
143 this->setRect(rect); // devolve into a simple rect | 138 this->setRect(rect); // devolve into a simple rect |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 } | 199 } |
205 } | 200 } |
206 | 201 |
207 // skbug.com/3239 -- its possible that we can hit the following inconsistenc y: | 202 // skbug.com/3239 -- its possible that we can hit the following inconsistenc y: |
208 // rad == bounds.bottom - bounds.top | 203 // rad == bounds.bottom - bounds.top |
209 // bounds.bottom - radius < bounds.top | 204 // bounds.bottom - radius < bounds.top |
210 // YIKES | 205 // YIKES |
211 // We need to detect and "fix" this now, otherwise we can have the following wackiness: | 206 // We need to detect and "fix" this now, otherwise we can have the following wackiness: |
212 // path.addRRect(rrect); | 207 // path.addRRect(rrect); |
213 // rrect.rect() != path.getBounds() | 208 // rrect.rect() != path.getBounds() |
214 fRadii[0].fX = clamp_radius_add(fRadii[0].fX, rect.fLeft, rect.fRight); | 209 for (int i = 0; i < 4; ++i) { |
215 fRadii[0].fY = clamp_radius_add(fRadii[0].fY, rect.fTop, rect.fBottom); | 210 fRadii[i].fX = clamp_radius_check_predicates(fRadii[i].fX, rect.fLeft, r ect.fRight); |
216 fRadii[1].fX = clamp_radius_sub(fRadii[1].fX, rect.fLeft, rect.fRight); | 211 fRadii[i].fY = clamp_radius_check_predicates(fRadii[i].fY, rect.fTop, re ct.fBottom); |
217 fRadii[1].fY = clamp_radius_add(fRadii[1].fY, rect.fTop, rect.fBottom); | 212 } |
218 fRadii[2].fX = clamp_radius_sub(fRadii[2].fX, rect.fLeft, rect.fRight); | |
219 fRadii[2].fY = clamp_radius_sub(fRadii[2].fY, rect.fTop, rect.fBottom); | |
220 fRadii[3].fX = clamp_radius_add(fRadii[3].fX, rect.fLeft, rect.fRight); | |
221 fRadii[3].fY = clamp_radius_sub(fRadii[3].fY, rect.fTop, rect.fBottom); | |
222 | |
223 // At this point we're either oval, simple, or complex (not empty or rect). | 213 // At this point we're either oval, simple, or complex (not empty or rect). |
224 this->computeType(); | 214 this->computeType(); |
225 | 215 |
226 SkDEBUGCODE(this->validate();) | 216 SkDEBUGCODE(this->validate();) |
227 } | 217 } |
228 | 218 |
229 // This method determines if a point known to be inside the RRect's bounds is | 219 // This method determines if a point known to be inside the RRect's bounds is |
230 // inside all the corners. | 220 // inside all the corners. |
231 bool SkRRect::checkCornerContainment(SkScalar x, SkScalar y) const { | 221 bool SkRRect::checkCornerContainment(SkScalar x, SkScalar y) const { |
232 SkPoint canonicalPt; // (x,y) translated to one of the quadrants | 222 SkPoint canonicalPt; // (x,y) translated to one of the quadrants |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 // use SkMatrix::rectStaysRect() to check for a valid transformation. | 380 // use SkMatrix::rectStaysRect() to check for a valid transformation. |
391 if (!matrix_only_scale_and_translate(matrix)) { | 381 if (!matrix_only_scale_and_translate(matrix)) { |
392 return false; | 382 return false; |
393 } | 383 } |
394 | 384 |
395 SkRect newRect; | 385 SkRect newRect; |
396 if (!matrix.mapRect(&newRect, fRect)) { | 386 if (!matrix.mapRect(&newRect, fRect)) { |
397 return false; | 387 return false; |
398 } | 388 } |
399 | 389 |
390 // The matrix may have scaled us to zero (or due to float madness, we now ha ve collapsed | |
robertphillips
2015/02/13 22:31:03
',' -> ')' ?
| |
391 // some dimension of the rect, so we need to check for that. | |
392 if (newRect.isEmpty()) { | |
393 dst->setEmpty(); | |
394 return true; | |
395 } | |
396 | |
400 // At this point, this is guaranteed to succeed, so we can modify dst. | 397 // At this point, this is guaranteed to succeed, so we can modify dst. |
401 dst->fRect = newRect; | 398 dst->fRect = newRect; |
402 | 399 |
403 // Since the only transforms that were allowed are scale and translate, the type | 400 // Since the only transforms that were allowed are scale and translate, the type |
404 // remains unchanged. | 401 // remains unchanged. |
405 dst->fType = fType; | 402 dst->fType = fType; |
406 | 403 |
407 if (kOval_Type == fType) { | 404 if (kOval_Type == fType) { |
408 for (int i = 0; i < 4; ++i) { | 405 for (int i = 0; i < 4; ++i) { |
409 dst->fRadii[i].fX = SkScalarHalf(newRect.width()); | 406 dst->fRadii[i].fX = SkScalarHalf(newRect.width()); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
521 } | 518 } |
522 line.append("\n"); | 519 line.append("\n"); |
523 } | 520 } |
524 line.append("};"); | 521 line.append("};"); |
525 SkDebugf("%s\n", line.c_str()); | 522 SkDebugf("%s\n", line.c_str()); |
526 } | 523 } |
527 | 524 |
528 /////////////////////////////////////////////////////////////////////////////// | 525 /////////////////////////////////////////////////////////////////////////////// |
529 | 526 |
530 #ifdef SK_DEBUG | 527 #ifdef SK_DEBUG |
528 /** | |
529 * We need all combinations of predicates to be true to have a "safe" radius va lue. | |
530 */ | |
531 static void validate_radius_check_predicates(SkScalar rad, SkScalar min, SkScala r max) { | |
532 SkASSERT(min <= max); | |
533 SkASSERT(rad <= max - min); | |
534 SkASSERT(min + rad <= max); | |
535 SkASSERT(max - rad >= min); | |
536 } | |
537 | |
531 void SkRRect::validate() const { | 538 void SkRRect::validate() const { |
532 bool allRadiiZero = (0 == fRadii[0].fX && 0 == fRadii[0].fY); | 539 bool allRadiiZero = (0 == fRadii[0].fX && 0 == fRadii[0].fY); |
533 bool allCornersSquare = (0 == fRadii[0].fX || 0 == fRadii[0].fY); | 540 bool allCornersSquare = (0 == fRadii[0].fX || 0 == fRadii[0].fY); |
534 bool allRadiiSame = true; | 541 bool allRadiiSame = true; |
535 | 542 |
536 for (int i = 1; i < 4; ++i) { | 543 for (int i = 1; i < 4; ++i) { |
537 if (0 != fRadii[i].fX || 0 != fRadii[i].fY) { | 544 if (0 != fRadii[i].fX || 0 != fRadii[i].fY) { |
538 allRadiiZero = false; | 545 allRadiiZero = false; |
539 } | 546 } |
540 | 547 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
574 SkASSERT(!fRect.isEmpty()); | 581 SkASSERT(!fRect.isEmpty()); |
575 SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); | 582 SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); |
576 SkASSERT(patchesOfNine); | 583 SkASSERT(patchesOfNine); |
577 break; | 584 break; |
578 case kComplex_Type: | 585 case kComplex_Type: |
579 SkASSERT(!fRect.isEmpty()); | 586 SkASSERT(!fRect.isEmpty()); |
580 SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); | 587 SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare); |
581 SkASSERT(!patchesOfNine); | 588 SkASSERT(!patchesOfNine); |
582 break; | 589 break; |
583 } | 590 } |
591 | |
592 for (int i = 0; i < 4; ++i) { | |
593 validate_radius_check_predicates(fRadii[i].fX, fRect.fLeft, fRect.fRight ); | |
594 validate_radius_check_predicates(fRadii[i].fY, fRect.fTop, fRect.fBottom ); | |
595 } | |
584 } | 596 } |
585 #endif // SK_DEBUG | 597 #endif // SK_DEBUG |
586 | 598 |
587 /////////////////////////////////////////////////////////////////////////////// | 599 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |