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