aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2014-10-01 12:48:58 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-01 12:48:58 -0700
commit8e393bf70ea2aab9ca31f52c15b518436c7b6055 (patch)
tree14099f16f1a9f7e16ee6cbde54d74066c9736daf /src
parent8324a6a27ee61c8f09f3dfcc972bed86d52df0ca (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.cpp39
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;
}