diff options
author | mtklein <mtklein@chromium.org> | 2014-10-01 12:48:58 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-01 12:48:58 -0700 |
commit | 8e393bf70ea2aab9ca31f52c15b518436c7b6055 (patch) | |
tree | 14099f16f1a9f7e16ee6cbde54d74066c9736daf /src | |
parent | 8324a6a27ee61c8f09f3dfcc972bed86d52df0ca (diff) |
Don't adjust the bounds after a restore with the restore's paired saveLayer's paint.
It makes no sense for the paint from a saveLayer to effect anything outside its saveLayer/restore block. But as currently written, we'll adjust the clip bounds just after a restore by that paint.
Turns out the test I wrote for the last CL (which caused this bug) actually had the bug baked into its expectations. I've updated them and added some notes to explain.
BUG=418417
Review URL: https://codereview.chromium.org/623563002
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkRecordDraw.cpp | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index bdebcb7c15..c693b05c63 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -7,7 +7,6 @@ #include "SkRecordDraw.h" #include "SkPatchUtils.h" -#include "SkTLogic.h" void SkRecordDraw(const SkRecord& record, SkCanvas* canvas, @@ -181,26 +180,40 @@ private: const SkPaint* paint; // Unowned. If set, adjusts the bounds of all ops in this block. }; - template <typename T> void updateCTM(const T&) { /* most ops don't change the CTM */ } + // Only Restore and SetMatrix change the CTM. + template <typename T> void updateCTM(const T&) {} void updateCTM(const Restore& op) { fCTM = &op.matrix; } void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; } - // Most ops don't change the clip. Those that do generally have a field named devBounds. - SK_CREATE_MEMBER_DETECTOR(devBounds); + // Most ops don't change the clip. + template <typename T> void updateClipBounds(const T&) {} - template <typename T> - SK_WHEN(!HasMember_devBounds<T>, void) updateClipBounds(const T& op) {} + // Clip{Path,RRect,Rect,Region} obviously change the clip. They all know their bounds already. + void updateClipBounds(const ClipPath& op) { this->updateClipBoundsForClipOp(op.devBounds); } + void updateClipBounds(const ClipRRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } + void updateClipBounds(const ClipRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } + void updateClipBounds(const ClipRegion& op) { this->updateClipBoundsForClipOp(op.devBounds); } - // Each of the devBounds fields holds the state of the device bounds after the op. - // (So Restore's devBounds are those bounds saved by its paired Save or SaveLayer.) - template <typename T> - SK_WHEN(HasMember_devBounds<T>, void) updateClipBounds(const T& op) { - Bounds clip = SkRect::Make(op.devBounds); + // The bounds of clip ops need to be adjusted for the paints of saveLayers they're inside. + void updateClipBoundsForClipOp(const SkIRect& devBounds) { + Bounds clip = SkRect::Make(devBounds); // We don't call adjustAndMap() because as its last step it would intersect the adjusted // clip bounds with the previous clip, exactly what we can't do when the clip grows. fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip) ? clip : Bounds::MakeLargest(); } + // Restore holds the devBounds for the clip after the {save,saveLayer}/restore block completes. + void updateClipBounds(const Restore& op) { + // This is just like the clip ops above, but we need to skip the effects (if any) of our + // paired saveLayer (if it is one); it has not yet been popped off the save stack. Our + // devBounds reflect the state of the world after the saveLayer/restore block is done, + // so they are not affected by the saveLayer's paint. + const int kSavesToIgnore = 1; + Bounds clip = SkRect::Make(op.devBounds); + fCurrentClipBounds = + this->adjustForSaveLayerPaints(&clip, kSavesToIgnore) ? clip : Bounds::MakeLargest(); + } + // We also take advantage of SaveLayer bounds when present to further cut the clip down. void updateClipBounds(const SaveLayer& op) { if (op.bounds) { @@ -478,8 +491,8 @@ private: return true; } - bool adjustForSaveLayerPaints(SkRect* rect) const { - for (int i = fSaveStack.count() - 1; i >= 0; i--) { + bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const { + for (int i = fSaveStack.count() - 1 - savesToIgnore; i >= 0; i--) { if (!AdjustForPaint(fSaveStack[i].paint, rect)) { return false; } |