extend savelayer_maskfilter to also have an imagefilter

Bug: skia:7597
Change-Id: I8af9c9f841c301212a4a452f9b42d03a20e36417
Reviewed-on: https://skia-review.googlesource.com/105220
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2018-02-07 11:59:57 -05:00 committed by Skia Commit-Bot
parent eac2090b46
commit 2179b78ef2
3 changed files with 53 additions and 33 deletions

View File

@ -165,6 +165,8 @@ DEF_SIMPLE_GM(combinemaskfilter, canvas, 560, 510) {
}
#include "SkSurface.h"
#include "SkBlurImageFilter.h"
#include "SkBlurMaskFilter.h"
static sk_sp<SkImage> make_circle_image(SkCanvas* canvas, SkScalar radius, int margin) {
const int n = SkScalarCeilToInt(radius) * 2 + margin * 2;
auto surf = sk_tool_utils::makeSurface(canvas, SkImageInfo::MakeN32Premul(n, n));
@ -174,25 +176,47 @@ static sk_sp<SkImage> make_circle_image(SkCanvas* canvas, SkScalar radius, int m
return surf->makeImageSnapshot();
}
DEF_SIMPLE_GM(savelayer_maskfilter, canvas, 220, 220) {
auto image = make_circle_image(canvas, 50, 1);
DEF_SIMPLE_GM(savelayer_maskfilter, canvas, 450, 675) {
auto layerImage = GetResourceAsImage("images/mandrill_128.png");
auto maskImage = make_circle_image(canvas, 50, 1);
SkRect r = SkRect::MakeWH(102, 102);
SkPaint paint;
paint.setMaskFilter(SkShaderMaskFilter::Make(image->makeShader()));
SkPaint overlayPaint;
overlayPaint.setStyle(SkPaint::kStroke_Style);
// test that the maskfilter sees these changes to the ctm
canvas->translate(10, 10);
canvas->scale(2, 2);
canvas->saveLayer(&r, &paint);
canvas->drawColor(SK_ColorRED);
canvas->restore();
sk_sp<SkMaskFilter> mfs[] = {
SkShaderMaskFilter::Make(maskImage->makeShader()),
SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 3.5f),
nullptr,
};
mfs[2] = SkMaskFilter::MakeCompose(mfs[1], mfs[0]);
// now draw the expected circle to blend on top of the red one
paint.reset();
paint.setAntiAlias(true);
paint.setColor(0x800000FF);
canvas->drawRect(r, paint);
// Important that we test with and without an imagefilter attached to the layer,
// as cpu and gpu backends treat these differently (w/ or w/o a SkSpecialImage)
const sk_sp<SkImageFilter> imfs[] = {nullptr, SkBlurImageFilter::Make(3.5f, 3.5f, nullptr)};
for (auto mf : mfs) {
SkPaint layerPaint;
layerPaint.setMaskFilter(mf);
canvas->save();
for (auto imf : imfs) {
layerPaint.setImageFilter(imf);
canvas->saveLayer(&r, &layerPaint);
canvas->drawImage(layerImage, 0, 0, nullptr);
canvas->restore();
// now draw the (approximage) expected bounds of the mask
canvas->drawRect(r.makeOutset(1, 1), overlayPaint);
canvas->translate(r.width() + 10, 0);
}
canvas->restore();
canvas->translate(0, r.height() + 10);
}
}

View File

@ -379,12 +379,9 @@ void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPain
SkASSERT(!origPaint.getImageFilter());
// todo: can we unify with similar adjustment in SkGpuDevice?
const SkPaint* paint = &origPaint;
SkTLazy<SkPaint> lazyP;
if (origPaint.getMaskFilter()) {
lazyP.set(origPaint);
lazyP.get()->setMaskFilter(origPaint.getMaskFilter()->makeWithLocalMatrix(this->ctm()));
paint = lazyP.get();
SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
if (paint->getMaskFilter()) {
paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm()));
}
BDDraw(this).drawSprite(static_cast<SkBitmapDevice*>(device)->fBitmap, x, y, *paint);
@ -443,6 +440,10 @@ void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPain
y += offset.y();
}
if (paint->getMaskFilter()) {
paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm()));
}
if (!clipImage) {
SkBitmap resultBM;
if (src->getROPixels(&resultBM)) {

View File

@ -1086,6 +1086,12 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special1, int left, int top, const
const GrPixelConfig config = proxy->config();
SkPaint tmpUnfiltered(paint);
if (tmpUnfiltered.getMaskFilter()) {
SkMatrix ctm = this->ctm();
ctm.postTranslate(-SkIntToScalar(left + offset.fX), -SkIntToScalar(top + offset.fY));
tmpUnfiltered.setMaskFilter(tmpUnfiltered.getMaskFilter()->makeWithLocalMatrix(ctm));
}
tmpUnfiltered.setImageFilter(nullptr);
auto fp = GrSimpleTextureEffect::Make(std::move(proxy), SkMatrix::I());
@ -1108,7 +1114,7 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special1, int left, int top, const
fRenderTargetContext->fillRectToRect(
this->clip(),
std::move(grPaint),
GrAA(paint.isAntiAlias()),
GrAA(tmpUnfiltered.isAntiAlias()),
SkMatrix::I(),
SkRect::Make(SkIRect::MakeXYWH(left + offset.fX, top + offset.fY, subset.width(),
subset.height())),
@ -1259,8 +1265,8 @@ sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() {
}
void SkGpuDevice::drawDevice(SkBaseDevice* device,
int left, int top, const SkPaint& origPaint) {
SkASSERT(!origPaint.getImageFilter());
int left, int top, const SkPaint& paint) {
SkASSERT(!paint.getImageFilter());
ASSERT_SINGLE_OWNER
// clear of the source device must occur before CHECK_SHOULD_DRAW
@ -1273,18 +1279,7 @@ void SkGpuDevice::drawDevice(SkBaseDevice* device,
return;
}
// todo: can we unify with similar adjustment in SkBitmapDevice?
const SkPaint* paint = &origPaint;
SkTLazy<SkPaint> lazyP;
if (origPaint.getMaskFilter()) {
SkMatrix ctm = this->ctm();
ctm.postTranslate(-SkIntToScalar(left), -SkIntToScalar(top));
lazyP.set(origPaint);
lazyP.get()->setMaskFilter(origPaint.getMaskFilter()->makeWithLocalMatrix(ctm));
paint = lazyP.get();
}
this->drawSpecial(srcImg.get(), left, top, *paint, nullptr, SkMatrix::I());
this->drawSpecial(srcImg.get(), left, top, paint, nullptr, SkMatrix::I());
}
void SkGpuDevice::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint& paint) {