Chromium Code Reviews| Index: src/core/SkCanvas.cpp |
| =================================================================== |
| --- src/core/SkCanvas.cpp (revision 9298) |
| +++ src/core/SkCanvas.cpp (working copy) |
| @@ -1279,6 +1279,74 @@ |
| return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); |
| } |
| +bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op, |
|
reed1
2013/05/29 18:54:01
/**
* This *never* calls back through a virtual o
|
| + bool inverseFilled) { |
| + // This is for updating the clip conservatively using only bounds |
| + // information. |
| + // Contract: |
| + // The current clip must contain the true clip. The true |
| + // clip is the clip that would have normally been computed |
| + // by calls to clipPath and clipRRect |
| + // Objective: |
| + // Keep the current clip as small as possible without |
| + // breaking the contract, using only clip bounding rectangles |
| + // (for performance). |
| + if (inverseFilled) { |
| + switch (op) { |
| + case SkRegion::kIntersect_Op: |
| + case SkRegion::kDifference_Op: |
| + // These ops can only shrink the current clip. So leaving |
| + // the clip unchanges conservatively respects the contract. |
| + return this->getClipDeviceBounds(NULL); |
| + case SkRegion::kUnion_Op: |
| + case SkRegion::kReplace_Op: |
| + case SkRegion::kReverseDifference_Op: |
| + case SkRegion::kXOR_Op: |
| + { |
| + // These ops can grow the current clip up to the extents of |
| + // the input clip, which is inverse filled, so we just set |
| + // the current clip to the device bounds. |
| + SkRect deviceBounds; |
| + SkIRect deviceIBounds; |
| + this->getDevice()->getGlobalBounds(&deviceIBounds); |
| + deviceBounds = SkRect::MakeFromIRect(deviceIBounds); |
| + this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag); |
| + // set the clip in device space |
| + this->SkCanvas::setMatrix(SkMatrix::I()); |
| + bool result = this->SkCanvas::clipRect(deviceBounds, |
| + SkRegion::kReplace_Op, false); |
| + this->SkCanvas::restore(); //pop the matrix, but keep the clip |
| + return result; |
| + } |
| + default: |
| + SkASSERT(0); // unhandled op? |
| + } |
| + } else { |
| + // Not inverse filled |
| + switch (op) { |
| + case SkRegion::kIntersect_Op: |
| + case SkRegion::kUnion_Op: |
| + case SkRegion::kReplace_Op: |
| + return this->SkCanvas::clipRect(bounds, op, false); |
| + case SkRegion::kDifference_Op: |
| + // Difference can only shrink the current clip. |
| + // Leaving clip unchanged conservatively fullfills the contract. |
| + return this->getClipDeviceBounds(NULL); |
| + case SkRegion::kReverseDifference_Op: |
| + // To reverse, we swap in the bounds with a replace op. |
| + // As with difference, leave it unchanged. |
| + return this->SkCanvas::clipRect(bounds, SkRegion::kReplace_Op, false); |
| + case SkRegion::kXOR_Op: |
| + // Be conservative, based on (A XOR B) always included in (A union B), |
| + // which is always included in (bounds(A) union bounds(B)) |
| + return this->SkCanvas::clipRect(bounds, SkRegion::kUnion_Op, false); |
| + default: |
| + SkASSERT(0); // unhandled op? |
| + } |
| + } |
| + return true; |
| +} |
| + |
| bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { |
| AutoValidateClip avc(this); |