skia2/gm/crbug_1174354.cpp
Brian Salomon 6d25f9d068 Fix downsampled blur with clamp mode.
Ensure the extra border added to the downsampled image doesn't filter in
values from outside the source bounds.

Bug: chromium:1174354
Change-Id: I6c62eeaa57ce4e5341eab24985553f87ab0df666
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/378322
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
2021-03-03 14:15:31 +00:00

58 lines
2.5 KiB
C++

/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/effects/SkGradientShader.h"
#include "include/effects/SkImageFilters.h"
static void draw_bg_blur(SkCanvas* canvas, SkIRect rect, float sigma) {
// First create an intermediate layer that has an opaque area that we blur with transparency
// all around it. We want to make sure the transparency doesn't affect the blur of the opaque
// content.
auto outsetRect = SkRect::Make(rect).makeOutset(10, 10);
canvas->saveLayer(outsetRect, nullptr);
SkColor colors[] = {SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN};
float cx = (rect.left() + rect.right() )/2.f;
float cy = (rect.top() + rect.bottom())/2.f;
auto g = SkGradientShader::MakeSweep(cx,
cy,
colors,
nullptr,
3,
SkTileMode::kMirror,
0,
45,
0,
nullptr);
SkPaint paint;
paint.setShader(std::move(g));
canvas->drawRect(SkRect::Make(rect), paint);
// Now do the bg-blur into another save-layer that should only read the opaque region.
SkCanvas::SaveLayerRec rec;
auto blur = SkImageFilters::Blur(sigma, sigma, SkTileMode::kClamp, nullptr, rect);
rec.fBounds = &outsetRect;
rec.fBackdrop = blur.get();
canvas->saveLayer(rec);
canvas->restore();
canvas->restore();
}
DEF_SIMPLE_GM(crbug_1174354, canvas, 70, 250) {
// The initial fix for crbug.com/1156805 had an issue where the border added to the downsampled
// texture that was used as input to the blur could actually bring in transparency when there
// wasn't any within the original src bounds. It was populated the border using a filtering draw
// from the full res source that could read from outside the pixels surrounding the original src
// bounds.
draw_bg_blur(canvas, SkIRect::MakeXYWH(10, 10, 50, 50), 5);
draw_bg_blur(canvas, SkIRect::MakeXYWH(10, 70, 50, 50), 15);
draw_bg_blur(canvas, SkIRect::MakeXYWH(10, 130, 50, 50), 30);
draw_bg_blur(canvas, SkIRect::MakeXYWH(10, 190, 50, 50), 70);
}