Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 #include "SkClipStack.h" | 8 #include "SkClipStack.h" |
| 9 #include "SkPath.h" | 9 #include "SkPath.h" |
| 10 #include "SkThread.h" | 10 #include "SkThread.h" |
| 11 | 11 |
| 12 #include <new> | 12 #include <new> |
| 13 | 13 |
| 14 | 14 |
| 15 // 0-2 are reserved for invalid, empty & wide-open | 15 // 0-2 are reserved for invalid, empty & wide-open |
| 16 static const int32_t kFirstUnreservedGenID = 3; | 16 static const int32_t kFirstUnreservedGenID = 3; |
| 17 int32_t SkClipStack::gGenID = kFirstUnreservedGenID; | 17 int32_t SkClipStack::gGenID = kFirstUnreservedGenID; |
| 18 | 18 |
| 19 bool SkClipStack::Element::operator== (const Element& element) const { | |
| 20 if (this == &element) { | |
| 21 return true; | |
| 22 } | |
| 23 if (fOp != element.fOp || | |
| 24 fType != element.fType || | |
| 25 fDoAA != element.fDoAA || | |
| 26 fSaveCount != element.fSaveCount) { | |
| 27 return false; | |
| 28 } | |
| 29 switch (fType) { | |
| 30 case kPath_Type: | |
| 31 return fPath == element.fPath; | |
| 32 case kRRect_Type: | |
| 33 return fRRect == element.fRRect; | |
| 34 case kRect_Type: | |
| 35 return fRect == element.fRect; | |
| 36 case kEmpty_Type: | |
| 37 return true; | |
| 38 default: | |
| 39 SkDEBUGFAIL("Unexpected type."); | |
| 40 return false; | |
| 41 } | |
| 42 } | |
| 43 | |
| 19 void SkClipStack::Element::invertShapeFillType() { | 44 void SkClipStack::Element::invertShapeFillType() { |
| 20 switch (fType) { | 45 switch (fType) { |
| 21 case kRect_Type: | 46 case kRect_Type: |
| 22 fPath.reset(); | 47 fPath.reset(); |
| 23 fPath.addRect(fRect); | 48 fPath.addRect(fRect); |
| 24 fPath.setFillType(SkPath::kInverseWinding_FillType); | 49 fPath.setFillType(SkPath::kInverseEvenOdd_FillType); |
|
robertphillips
2014/02/14 20:36:01
Do we really care about setting fRect to be empty?
bsalomon
2014/02/14 21:20:57
I guess not
| |
| 50 fRect.setEmpty(); | |
| 51 fType = kPath_Type; | |
| 52 break; | |
| 53 case kRRect_Type: | |
| 54 fPath.reset(); | |
| 55 fPath.addRRect(fRRect); | |
| 56 fPath.setFillType(SkPath::kInverseEvenOdd_FillType); | |
|
robertphillips
2014/02/14 20:36:01
Same for rrect?
bsalomon
2014/02/14 21:20:57
Done.
| |
| 57 fRRect.setEmpty(); | |
| 25 fType = kPath_Type; | 58 fType = kPath_Type; |
| 26 break; | 59 break; |
| 27 case kPath_Type: | 60 case kPath_Type: |
| 28 fPath.toggleInverseFillType(); | 61 fPath.toggleInverseFillType(); |
| 29 case kEmpty_Type: | 62 case kEmpty_Type: |
|
robertphillips
2014/02/14 20:36:01
Probably
bsalomon
2014/02/14 21:20:57
Agreed, but don't want to conflate any regressions
| |
| 63 // Should this set to an empty, inverse filled path? | |
| 30 break; | 64 break; |
| 31 } | 65 } |
| 32 } | 66 } |
| 67 | |
| 68 void SkClipStack::Element::initPath(int saveCount, const SkPath& path, SkRegion: :Op op, | |
| 69 bool doAA) { | |
| 70 if (!path.isInverseFillType()) { | |
| 71 if (SkPath::kNone_PathAsRect != path.asRect()) { | |
| 72 this->initRect(saveCount, path.getBounds(), op, doAA); | |
| 73 return; | |
| 74 } | |
| 75 SkRect ovalRect; | |
| 76 if (path.isOval(&ovalRect)) { | |
| 77 SkRRect rrect; | |
| 78 rrect.setOval(ovalRect); | |
| 79 this->initRRect(saveCount, rrect, op, doAA); | |
| 80 return; | |
| 81 } | |
| 82 } | |
| 83 fPath = path; | |
| 84 fType = kPath_Type; | |
| 85 this->initCommon(saveCount, op, doAA); | |
| 86 } | |
| 87 | |
| 88 void SkClipStack::Element::asPath(SkPath* path) const { | |
| 89 switch (fType) { | |
| 90 case kEmpty_Type: | |
| 91 path->reset(); | |
| 92 break; | |
| 93 case kRect_Type: | |
| 94 path->reset(); | |
| 95 path->addRect(fRect); | |
| 96 break; | |
| 97 case kRRect_Type: | |
| 98 path->reset(); | |
| 99 path->addRRect(fRRect); | |
| 100 break; | |
| 101 case kPath_Type: | |
| 102 *path = fPath; | |
| 103 break; | |
| 104 } | |
| 105 } | |
| 33 | 106 |
| 34 void SkClipStack::Element::checkEmpty() const { | 107 void SkClipStack::Element::checkEmpty() const { |
| 35 SkASSERT(fFiniteBound.isEmpty()); | 108 SkASSERT(fFiniteBound.isEmpty()); |
| 36 SkASSERT(kNormal_BoundsType == fFiniteBoundType); | 109 SkASSERT(kNormal_BoundsType == fFiniteBoundType); |
| 37 SkASSERT(!fIsIntersectionOfRects); | 110 SkASSERT(!fIsIntersectionOfRects); |
| 38 SkASSERT(kEmptyGenID == fGenID); | 111 SkASSERT(kEmptyGenID == fGenID); |
| 39 SkASSERT(fPath.isEmpty()); | 112 SkASSERT(fPath.isEmpty()); |
| 40 } | 113 } |
| 41 | 114 |
| 42 bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op o p) const { | 115 bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op o p) const { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 // that aren't set are whatever isn't set in the previous | 166 // that aren't set are whatever isn't set in the previous |
| 94 // clip and whatever this clip carves out | 167 // clip and whatever this clip carves out |
| 95 fFiniteBound.join(prevFinite); | 168 fFiniteBound.join(prevFinite); |
| 96 fFiniteBoundType = kInsideOut_BoundsType; | 169 fFiniteBoundType = kInsideOut_BoundsType; |
| 97 break; | 170 break; |
| 98 case kPrev_InvCur_FillCombo: | 171 case kPrev_InvCur_FillCombo: |
| 99 // In this case everything outside of this clip's bound | 172 // In this case everything outside of this clip's bound |
| 100 // is erased, so the only pixels that can remain set | 173 // is erased, so the only pixels that can remain set |
| 101 // occur w/in the intersection of the two finite bounds | 174 // occur w/in the intersection of the two finite bounds |
| 102 if (!fFiniteBound.intersect(prevFinite)) { | 175 if (!fFiniteBound.intersect(prevFinite)) { |
| 103 fFiniteBound.setEmpty(); | 176 this->setEmpty(); |
| 104 fGenID = kEmptyGenID; | 177 } else { |
| 178 fFiniteBoundType = kNormal_BoundsType; | |
| 105 } | 179 } |
| 106 fFiniteBoundType = kNormal_BoundsType; | |
| 107 break; | 180 break; |
| 108 case kPrev_Cur_FillCombo: | 181 case kPrev_Cur_FillCombo: |
| 109 // The most conservative result bound is that of the | 182 // The most conservative result bound is that of the |
| 110 // prior clip. This could be wildly incorrect if the | 183 // prior clip. This could be wildly incorrect if the |
| 111 // second clip either exactly matches the first clip | 184 // second clip either exactly matches the first clip |
| 112 // (which should yield the empty set) or reduces the | 185 // (which should yield the empty set) or reduces the |
| 113 // size of the prior bound (e.g., if the second clip | 186 // size of the prior bound (e.g., if the second clip |
| 114 // exactly matched the bottom half of the prior clip). | 187 // exactly matched the bottom half of the prior clip). |
| 115 // We ignore these two possibilities. | 188 // We ignore these two possibilities. |
| 116 fFiniteBound = prevFinite; | 189 fFiniteBound = prevFinite; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 198 // are within the current clip | 271 // are within the current clip |
| 199 break; | 272 break; |
| 200 case kPrev_InvCur_FillCombo: | 273 case kPrev_InvCur_FillCombo: |
| 201 // In this case the only pixels that will remain writeable | 274 // In this case the only pixels that will remain writeable |
| 202 // are with the previous clip | 275 // are with the previous clip |
| 203 fFiniteBound = prevFinite; | 276 fFiniteBound = prevFinite; |
| 204 fFiniteBoundType = kNormal_BoundsType; | 277 fFiniteBoundType = kNormal_BoundsType; |
| 205 break; | 278 break; |
| 206 case kPrev_Cur_FillCombo: | 279 case kPrev_Cur_FillCombo: |
| 207 if (!fFiniteBound.intersect(prevFinite)) { | 280 if (!fFiniteBound.intersect(prevFinite)) { |
| 208 fFiniteBound.setEmpty(); | 281 this->setEmpty(); |
| 209 fGenID = kEmptyGenID; | |
| 210 } | 282 } |
| 211 break; | 283 break; |
| 212 default: | 284 default: |
| 213 SkDEBUGFAIL("SkClipStack::Element::combineBoundsIntersection Invalid fill combination"); | 285 SkDEBUGFAIL("SkClipStack::Element::combineBoundsIntersection Invalid fill combination"); |
| 214 break; | 286 break; |
| 215 } | 287 } |
| 216 } | 288 } |
| 217 | 289 |
| 218 // a mirror of combineBoundsDiff | 290 // a mirror of combineBoundsDiff |
| 219 void SkClipStack::Element::combineBoundsRevDiff(int combination, const SkRect& p revFinite) { | 291 void SkClipStack::Element::combineBoundsRevDiff(int combination, const SkRect& p revFinite) { |
| 220 | 292 |
| 221 switch (combination) { | 293 switch (combination) { |
| 222 case kInvPrev_InvCur_FillCombo: | 294 case kInvPrev_InvCur_FillCombo: |
| 223 // The only pixels that can survive are in the | 295 // The only pixels that can survive are in the |
| 224 // previous bound since the extensions to infinity in | 296 // previous bound since the extensions to infinity in |
| 225 // both clips cancel out | 297 // both clips cancel out |
| 226 fFiniteBound = prevFinite; | 298 fFiniteBound = prevFinite; |
| 227 fFiniteBoundType = kNormal_BoundsType; | 299 fFiniteBoundType = kNormal_BoundsType; |
| 228 break; | 300 break; |
| 229 case kInvPrev_Cur_FillCombo: | 301 case kInvPrev_Cur_FillCombo: |
| 230 if (!fFiniteBound.intersect(prevFinite)) { | 302 if (!fFiniteBound.intersect(prevFinite)) { |
| 231 fFiniteBound.setEmpty(); | 303 this->setEmpty(); |
| 232 fGenID = kEmptyGenID; | 304 } else { |
| 305 fFiniteBoundType = kNormal_BoundsType; | |
| 233 } | 306 } |
| 234 fFiniteBoundType = kNormal_BoundsType; | |
| 235 break; | 307 break; |
| 236 case kPrev_InvCur_FillCombo: | 308 case kPrev_InvCur_FillCombo: |
| 237 fFiniteBound.join(prevFinite); | 309 fFiniteBound.join(prevFinite); |
| 238 fFiniteBoundType = kInsideOut_BoundsType; | 310 fFiniteBoundType = kInsideOut_BoundsType; |
| 239 break; | 311 break; |
| 240 case kPrev_Cur_FillCombo: | 312 case kPrev_Cur_FillCombo: |
| 241 // Fall through - as with the kDifference_Op case, the | 313 // Fall through - as with the kDifference_Op case, the |
| 242 // most conservative result bound is the bound of the | 314 // most conservative result bound is the bound of the |
| 243 // current clip. The prior clip could reduce the size of this | 315 // current clip. The prior clip could reduce the size of this |
| 244 // bound (as in the kDifference_Op case) but we are ignoring | 316 // bound (as in the kDifference_Op case) but we are ignoring |
| 245 // those cases. | 317 // those cases. |
| 246 break; | 318 break; |
| 247 default: | 319 default: |
| 248 SkDEBUGFAIL("SkClipStack::Element::combineBoundsRevDiff Invalid fill combination"); | 320 SkDEBUGFAIL("SkClipStack::Element::combineBoundsRevDiff Invalid fill combination"); |
| 249 break; | 321 break; |
| 250 } | 322 } |
| 251 } | 323 } |
| 252 | 324 |
| 253 void SkClipStack::Element::updateBoundAndGenID(const Element* prior) { | 325 void SkClipStack::Element::updateBoundAndGenID(const Element* prior) { |
| 254 // We set this first here but we may overwrite it later if we determine that the clip is | 326 // We set this first here but we may overwrite it later if we determine that the clip is |
| 255 // either wide-open or empty. | 327 // either wide-open or empty. |
| 256 fGenID = GetNextGenID(); | 328 fGenID = GetNextGenID(); |
| 257 | 329 |
| 258 // First, optimistically update the current Element's bound information | 330 // First, optimistically update the current Element's bound information |
| 259 // with the current clip's bound | 331 // with the current clip's bound |
| 260 fIsIntersectionOfRects = false; | 332 fIsIntersectionOfRects = false; |
| 261 if (kRect_Type == fType) { | 333 switch (fType) { |
| 262 fFiniteBound = fRect; | 334 case kRect_Type: |
| 263 fFiniteBoundType = kNormal_BoundsType; | 335 fFiniteBound = fRect; |
| 336 fFiniteBoundType = kNormal_BoundsType; | |
| 264 | 337 |
| 265 if (SkRegion::kReplace_Op == fOp || | 338 if (SkRegion::kReplace_Op == fOp || |
| 266 (SkRegion::kIntersect_Op == fOp && NULL == prior) || | 339 (SkRegion::kIntersect_Op == fOp && NULL == prior) || |
| 267 (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects && | 340 (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects && |
| 268 prior->rectRectIntersectAllowed(fRect, fDoAA))) { | 341 prior->rectRectIntersectAllowed(fRect, fDoAA))) { |
| 269 fIsIntersectionOfRects = true; | 342 fIsIntersectionOfRects = true; |
| 270 } | 343 } |
| 344 break; | |
| 345 case kRRect_Type: | |
| 346 fFiniteBound = fRRect.getBounds(); | |
| 347 fFiniteBoundType = kNormal_BoundsType; | |
| 348 break; | |
| 349 case kPath_Type: | |
| 350 fFiniteBound = fPath.getBounds(); | |
| 271 | 351 |
| 272 } else { | 352 if (fPath.isInverseFillType()) { |
| 273 SkASSERT(kPath_Type == fType); | 353 fFiniteBoundType = kInsideOut_BoundsType; |
| 274 | 354 } else { |
| 275 fFiniteBound = fPath.getBounds(); | 355 fFiniteBoundType = kNormal_BoundsType; |
| 276 | 356 } |
| 277 if (fPath.isInverseFillType()) { | 357 break; |
| 278 fFiniteBoundType = kInsideOut_BoundsType; | 358 case kEmpty_Type: |
| 279 } else { | 359 SkDEBUGFAIL("We shouldn't get here with an empty element."); |
| 280 fFiniteBoundType = kNormal_BoundsType; | 360 break; |
| 281 } | |
| 282 } | 361 } |
| 283 | 362 |
| 284 if (!fDoAA) { | 363 if (!fDoAA) { |
| 285 // Here we mimic a non-anti-aliased scanline system. If there is | 364 // Here we mimic a non-anti-aliased scanline system. If there is |
| 286 // no anti-aliasing we can integerize the bounding box to exclude | 365 // no anti-aliasing we can integerize the bounding box to exclude |
| 287 // fractional parts that won't be rendered. | 366 // fractional parts that won't be rendered. |
| 288 // Note: the left edge is handled slightly differently below. We | 367 // Note: the left edge is handled slightly differently below. We |
| 289 // are a bit more generous in the rounding since we don't want to | 368 // are a bit more generous in the rounding since we don't want to |
| 290 // risk missing the left pixels when fLeft is very close to .5 | 369 // risk missing the left pixels when fLeft is very close to .5 |
| 291 fFiniteBound.set(SkScalarFloorToScalar(fFiniteBound.fLeft+0.45f), | 370 fFiniteBound.set(SkScalarFloorToScalar(fFiniteBound.fLeft+0.45f), |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 break; | 416 break; |
| 338 case SkRegion::kReverseDifference_Op: | 417 case SkRegion::kReverseDifference_Op: |
| 339 this->combineBoundsRevDiff(combination, prevFinite); | 418 this->combineBoundsRevDiff(combination, prevFinite); |
| 340 break; | 419 break; |
| 341 case SkRegion::kReplace_Op: | 420 case SkRegion::kReplace_Op: |
| 342 // Replace just ignores everything prior | 421 // Replace just ignores everything prior |
| 343 // The current clip's bound information is already filled in | 422 // The current clip's bound information is already filled in |
| 344 // so nothing to do | 423 // so nothing to do |
| 345 break; | 424 break; |
| 346 default: | 425 default: |
| 347 SkDebugf("SkRegion::Op error/n"); | 426 SkDebugf("SkRegion::Op error\n"); |
| 348 SkASSERT(0); | 427 SkASSERT(0); |
| 349 break; | 428 break; |
| 350 } | 429 } |
| 351 } | 430 } |
| 352 | 431 |
| 353 // This constant determines how many Element's are allocated together as a block in | 432 // This constant determines how many Element's are allocated together as a block in |
| 354 // the deque. As such it needs to balance allocating too much memory vs. | 433 // the deque. As such it needs to balance allocating too much memory vs. |
| 355 // incurring allocation/deallocation thrashing. It should roughly correspond to | 434 // incurring allocation/deallocation thrashing. It should roughly correspond to |
| 356 // the deepest save/restore stack we expect to see. | 435 // the deepest save/restore stack we expect to see. |
| 357 static const int kDefaultElementAllocCnt = 8; | 436 static const int kDefaultElementAllocCnt = 8; |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 521 } | 600 } |
| 522 } | 601 } |
| 523 if (SkRegion::kReplace_Op == element->getOp()) { | 602 if (SkRegion::kReplace_Op == element->getOp()) { |
| 524 break; | 603 break; |
| 525 } | 604 } |
| 526 element = iter.prev(); | 605 element = iter.prev(); |
| 527 } | 606 } |
| 528 return true; | 607 return true; |
| 529 } | 608 } |
| 530 | 609 |
| 531 void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) { | 610 void SkClipStack::pushElement(const Element& element) { |
| 532 | |
| 533 // Use reverse iterator instead of back because Rect path may need previous | 611 // Use reverse iterator instead of back because Rect path may need previous |
| 534 SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart); | 612 SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart); |
| 535 Element* element = (Element*) iter.prev(); | 613 Element* prior = (Element*) iter.prev(); |
| 536 | 614 |
| 537 if (NULL != element) { | 615 if (NULL != prior) { |
| 538 if (element->canBeIntersectedInPlace(fSaveCount, op)) { | 616 if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) { |
| 539 switch (element->fType) { | 617 switch (prior->fType) { |
| 540 case Element::kEmpty_Type: | 618 case Element::kEmpty_Type: |
| 541 element->checkEmpty(); | 619 prior->checkEmpty(); |
| 542 return; | 620 return; |
| 543 case Element::kRect_Type: | 621 case Element::kRect_Type: |
| 544 if (element->rectRectIntersectAllowed(rect, doAA)) { | 622 if (Element::kRect_Type == element.getType()) { |
| 545 if (!element->fRect.intersect(rect)) { | 623 if (prior->rectRectIntersectAllowed(element.getRect(), e lement.isAA())) { |
| 546 element->setEmpty(); | 624 if (!prior->fRect.intersect(element.getRect())) { |
| 625 prior->setEmpty(); | |
| 626 return; | |
| 627 } | |
| 628 | |
| 629 prior->fDoAA = element.isAA(); | |
| 630 Element* priorPrior = (Element*) iter.prev(); | |
| 631 prior->updateBoundAndGenID(priorPrior); | |
| 547 return; | 632 return; |
| 548 } | 633 } |
| 549 | 634 break; |
| 550 element->fDoAA = doAA; | |
| 551 Element* prev = (Element*) iter.prev(); | |
| 552 element->updateBoundAndGenID(prev); | |
| 553 return; | |
| 554 } | 635 } |
| 555 break; | 636 // fallthrough |
| 556 case Element::kPath_Type: | 637 default: |
| 557 if (!SkRect::Intersects(element->fPath.getBounds(), rect)) { | 638 if (!SkRect::Intersects(prior->getBounds(), element.getBound s())) { |
| 558 element->setEmpty(); | 639 prior->setEmpty(); |
| 559 return; | 640 return; |
| 560 } | 641 } |
| 561 break; | 642 break; |
| 562 } | 643 } |
| 563 } else if (SkRegion::kReplace_Op == op) { | 644 } else if (SkRegion::kReplace_Op == element.getOp()) { |
| 564 this->restoreTo(fSaveCount - 1); | 645 this->restoreTo(fSaveCount - 1); |
| 565 element = (Element*) fDeque.back(); | 646 prior = (Element*) fDeque.back(); |
| 566 } | 647 } |
| 567 } | 648 } |
| 568 new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA); | 649 Element* newElement = SkNEW_PLACEMENT_ARGS(fDeque.push_back(), Element, (ele ment)); |
| 569 ((Element*) fDeque.back())->updateBoundAndGenID(element); | 650 newElement->updateBoundAndGenID(prior); |
| 651 } | |
| 652 | |
| 653 void SkClipStack::clipDevRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { | |
| 654 Element element(fSaveCount, rrect, op, doAA); | |
| 655 this->pushElement(element); | |
| 656 } | |
| 657 | |
| 658 void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) { | |
| 659 Element element(fSaveCount, rect, op, doAA); | |
| 660 this->pushElement(element); | |
| 570 } | 661 } |
| 571 | 662 |
| 572 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 663 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
| 573 SkRect alt; | 664 Element element(fSaveCount, path, op, doAA); |
| 574 if (path.isRect(&alt) && !path.isInverseFillType()) { | 665 this->pushElement(element); |
| 575 return this->clipDevRect(alt, op, doAA); | |
| 576 } | |
| 577 | |
| 578 Element* element = (Element*)fDeque.back(); | |
| 579 if (NULL != element) { | |
| 580 if (element->canBeIntersectedInPlace(fSaveCount, op)) { | |
| 581 const SkRect& pathBounds = path.getBounds(); | |
| 582 switch (element->fType) { | |
| 583 case Element::kEmpty_Type: | |
| 584 element->checkEmpty(); | |
| 585 return; | |
| 586 case Element::kRect_Type: | |
| 587 if (!SkRect::Intersects(element->fRect, pathBounds)) { | |
| 588 element->setEmpty(); | |
| 589 return; | |
| 590 } | |
| 591 break; | |
| 592 case Element::kPath_Type: | |
| 593 if (!SkRect::Intersects(element->fPath.getBounds(), pathBoun ds)) { | |
| 594 element->setEmpty(); | |
| 595 return; | |
| 596 } | |
| 597 break; | |
| 598 } | |
| 599 } else if (SkRegion::kReplace_Op == op) { | |
| 600 this->restoreTo(fSaveCount - 1); | |
| 601 element = (Element*) fDeque.back(); | |
| 602 } | |
| 603 } | |
| 604 new (fDeque.push_back()) Element(fSaveCount, path, op, doAA); | |
| 605 ((Element*) fDeque.back())->updateBoundAndGenID(element); | |
| 606 } | 666 } |
| 607 | 667 |
| 608 void SkClipStack::clipEmpty() { | 668 void SkClipStack::clipEmpty() { |
| 609 | 669 |
| 610 Element* element = (Element*) fDeque.back(); | 670 Element* element = (Element*) fDeque.back(); |
| 611 | 671 |
| 612 if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kInter sect_Op)) { | 672 if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kInter sect_Op)) { |
| 673 element->setEmpty(); | |
|
robertphillips
2014/02/14 20:36:01
Seems like we don't really need this switch any mo
bsalomon
2014/02/14 21:20:57
Done.
| |
| 613 switch (element->fType) { | 674 switch (element->fType) { |
| 614 case Element::kEmpty_Type: | 675 case Element::kEmpty_Type: |
| 615 element->checkEmpty(); | 676 element->checkEmpty(); |
| 616 return; | 677 return; |
| 617 case Element::kRect_Type: | 678 default: |
| 618 case Element::kPath_Type: | |
| 619 element->setEmpty(); | 679 element->setEmpty(); |
| 620 return; | 680 return; |
| 621 } | 681 } |
| 622 } | 682 } |
| 623 new (fDeque.push_back()) Element(fSaveCount); | 683 new (fDeque.push_back()) Element(fSaveCount); |
| 624 | 684 |
| 625 ((Element*)fDeque.back())->fGenID = kEmptyGenID; | 685 ((Element*)fDeque.back())->fGenID = kEmptyGenID; |
| 626 } | 686 } |
| 627 | 687 |
| 628 bool SkClipStack::isWideOpen() const { | 688 bool SkClipStack::isWideOpen() const { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 730 return kWideOpenGenID; | 790 return kWideOpenGenID; |
| 731 } | 791 } |
| 732 | 792 |
| 733 const Element* back = static_cast<const Element*>(fDeque.back()); | 793 const Element* back = static_cast<const Element*>(fDeque.back()); |
| 734 if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.is Empty()) { | 794 if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.is Empty()) { |
| 735 return kWideOpenGenID; | 795 return kWideOpenGenID; |
| 736 } | 796 } |
| 737 | 797 |
| 738 return back->getGenID(); | 798 return back->getGenID(); |
| 739 } | 799 } |
| OLD | NEW |