Check for deferred saves in SkCanvas::clipShader

Before, in the new clip_shader_nested GM, without the
checkForDeferredSaves() call, the first clipShader() would end up
associated with the original save record, but the intervening scale()
call checked for deferred saves. This meant the second clipShader() was
associated with the new save record and would be removed during the
restore (although the first shader remained).

Change-Id: I62f33b821de810c68f62069201ae3429f520be8c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/293690
Auto-Submit: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
Michael Ludwig 2020-06-02 17:27:07 -04:00 committed by Skia Commit-Bot
parent 579c295b6b
commit 49203849a6
2 changed files with 29 additions and 0 deletions

View File

@ -19,6 +19,7 @@
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradientShader.h"
#include "src/core/SkClipOpPriv.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
@ -262,3 +263,30 @@ DEF_SIMPLE_GM(clip_shader_layer, canvas, 430, 320) {
canvas->drawColor(0xFFFF0000);
canvas->restore();
}
DEF_SIMPLE_GM(clip_shader_nested, canvas, 256, 256) {
float w = 64.f;
float h = 64.f;
const SkColor gradColors[] = {SK_ColorBLACK, SkColorSetARGB(128, 128, 128, 128)};
auto s = SkGradientShader::MakeRadial({0.5f * w, 0.5f * h}, 0.1f * w, gradColors, nullptr,
2, SkTileMode::kRepeat, 0, nullptr);
SkPaint p;
// A large black rect affected by two gradient clips
canvas->save();
canvas->clipShader(s);
canvas->scale(2.f, 2.f);
canvas->clipShader(s);
canvas->drawRect(SkRect::MakeWH(w, h), p);
canvas->restore();
canvas->translate(0.f, 2.f * h);
// A small red rect, with no clipping
canvas->save();
p.setColor(SK_ColorRED);
canvas->drawRect(SkRect::MakeWH(w, h), p);
canvas->restore();
}

View File

@ -1666,6 +1666,7 @@ void SkCanvas::clipShader(sk_sp<SkShader> sh, SkClipOp op) {
this->clipRect({0,0,0,0});
}
} else {
this->checkForDeferredSave();
this->onClipShader(std::move(sh), op);
}
}