Chromium Code Reviews| Index: src/core/SkRecordDraw.cpp |
| diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp |
| index a14b0316955dd0b1c93448c1bcd2410c5f74bae8..c796386f209b7d6ab50a3ab62decaf2e273b1a93 100644 |
| --- a/src/core/SkRecordDraw.cpp |
| +++ b/src/core/SkRecordDraw.cpp |
| @@ -160,6 +160,11 @@ private: |
| const SkPaint* paint; // Unowned. If set, adjusts the bounds of all ops in this block. |
| }; |
| + static bool PaintMayAffectTransparentBlack(const SkPaint* paint) { |
| + // FIXME: this is very conservative |
| + return paint && (paint->getImageFilter() || paint->getColorFilter()); |
| + } |
| + |
| template <typename T> void updateCTM(const T&) { /* most ops don't change the CTM */ } |
| void updateCTM(const Restore& op) { fCTM = &op.matrix; } |
| void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; } |
| @@ -173,7 +178,8 @@ private: |
| void updateClipBounds(const ClipRect& op) { fCurrentClipBounds = op.devBounds; } |
| void updateClipBounds(const ClipRegion& op) { fCurrentClipBounds = op.devBounds; } |
| void updateClipBounds(const SaveLayer& op) { |
| - if (op.bounds) { |
| + // Intersect the clip with the SaveLayer bounds, unless the paint affects transparent black. |
| + if (op.bounds && !PaintMayAffectTransparentBlack(op.paint)) { |
|
mtklein
2014/08/22 15:45:58
Just reading again:
"Since the bounds we pass to
|
| fCurrentClipBounds.intersect(this->adjustAndMap(*op.bounds, op.paint)); |
| } |
| } |
| @@ -208,15 +214,20 @@ private: |
| // We're done the Save block. Apply the block's bounds to all control ops inside it. |
| SaveBounds sb; |
| fSaveStack.pop(&sb); |
| + |
| + // If the paint affects transparent black, we can't trust any of our calculated bounds. |
| + const SkIRect& bounds = |
| + PaintMayAffectTransparentBlack(sb.paint) ? fCurrentClipBounds : sb.bounds; |
| + |
| while (sb.controlOps --> 0) { |
| - this->popControl(sb.bounds); |
| + this->popControl(bounds); |
| } |
| // This whole Save block may be part another Save block. |
| - this->updateSaveBounds(sb.bounds); |
| + this->updateSaveBounds(bounds); |
| // If called from a real Restore (not a phony one for balance), it'll need the bounds. |
| - return sb.bounds; |
| + return bounds; |
| } |
| void pushControl() { |