remove unused maskfilter helpers: Combine, Compose

Change-Id: I8c6bf2c3539905c9c7bc9c29454322dbf944fe96
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/287823
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Mike Reed 2020-05-05 14:40:42 -04:00 committed by Skia Commit-Bot
parent 273f107a2d
commit 52653731d5
4 changed files with 3 additions and 422 deletions

View File

@ -8,6 +8,9 @@ Milestone 84
* <insert new release note here>
* Remove unused SkMaskFilter helpers: compbine, compose
Note: shadermaskfilter will likely be removed next (clipShader should serve)
* Add back SkCanvas::kPreserveLCDText_SaveLayerFlag to indicate that saveLayer()
will preserve LCD-text. All text in the layer must be drawn on opaque background
to ensure correct rendering.

View File

@ -40,24 +40,6 @@
#include <initializer_list>
static void draw_masked_image(SkCanvas* canvas, const SkImage* image, SkScalar x, SkScalar y,
const SkImage* mask, sk_sp<SkMaskFilter> outer, SkBlendMode mode) {
SkMatrix matrix = SkMatrix::MakeScale(SkIntToScalar(image->width()) / mask->width(),
SkIntToScalar(image->height() / mask->height()));
// The geometry of the drawImage is also translated by (x,y) so make the mask filter's
// coordinate system align with the rendered rectangle.
matrix.postTranslate(x, y);
SkPaint paint;
auto mf = SkShaderMaskFilter::Make(mask->makeShader(&matrix));
if (outer) {
mf = SkMaskFilter::MakeCompose(std::move(outer), std::move(mf));
}
paint.setMaskFilter(mf);
paint.setAntiAlias(true);
paint.setBlendMode(mode);
canvas->drawImage(image, x, y, &paint);
}
static sk_sp<SkShader> make_shader(const SkRect& r) {
const SkPoint pts[] = {
{ r.fLeft, r.fTop }, { r.fRight, r.fBottom },
@ -80,114 +62,3 @@ DEF_SIMPLE_GM(shadermaskfilter_gradient, canvas, 512, 512) {
paint.setAntiAlias(true);
canvas->drawOval(r, paint);
}
DEF_SIMPLE_GM_CAN_FAIL(shadermaskfilter_image, canvas, errorMsg, 560, 370) {
canvas->scale(1.25f, 1.25f);
auto image = GetResourceAsImage("images/mandrill_128.png");
auto mask = GetResourceAsImage("images/color_wheel.png");
if (!image || !mask) {
*errorMsg = "Could not load images. Did you forget to set the resourcePath?";
return skiagm::DrawResult::kFail;
}
auto blurmf = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5);
auto gradmf = SkShaderMaskFilter::Make(make_shader(SkRect::MakeIWH(mask->width(),
mask->height())));
const sk_sp<SkMaskFilter> array[] = { nullptr , blurmf, gradmf };
for (SkBlendMode mode : {SkBlendMode::kSrcOver, SkBlendMode::kSrcIn}) {
canvas->save();
for (sk_sp<SkMaskFilter> mf : array) {
draw_masked_image(canvas, image.get(), 10, 10, mask.get(), mf, mode);
canvas->translate(image->width() + 20.f, 0);
}
canvas->restore();
canvas->translate(0, image->height() + 20.f);
}
return skiagm::DrawResult::kOk;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
static sk_sp<SkMaskFilter> make_path_mf(const SkPath& path, unsigned alpha) {
SkPaint paint;
paint.setAntiAlias(true);
paint.setAlpha(alpha);
SkPictureRecorder recorder;
recorder.beginRecording(1000, 1000)->drawPath(path, paint);
auto shader = recorder.finishRecordingAsPicture()->makeShader(SkTileMode::kClamp,
SkTileMode::kClamp);
return SkShaderMaskFilter::Make(shader);
}
typedef void (*MakePathsProc)(const SkRect&, SkPath*, SkPath*);
const char* gCoverageName[] = {
"union", "sect", "diff", "rev-diff", "xor"
};
DEF_SIMPLE_GM(combinemaskfilter, canvas, 560, 510) {
const SkRect r = { 0, 0, 100, 100 };
SkPaint paint;
paint.setColor(SK_ColorRED);
SkFont font;
font.setSize(20);
const SkRect r2 = r.makeOutset(1.5f, 1.5f);
SkPaint strokePaint;
strokePaint.setStyle(SkPaint::kStroke_Style);
auto proc0 = [](const SkRect& r, SkPath* pathA, SkPath* pathB) {
pathA->moveTo(r.fLeft, r.fBottom);
pathA->lineTo(r.fRight, r.fTop);
pathA->lineTo(r.fRight, r.fBottom);
pathB->moveTo(r.fLeft, r.fTop);
pathB->lineTo(r.fRight, r.fBottom);
pathB->lineTo(r.fLeft, r.fBottom);
};
auto proc1 = [](const SkRect& r, SkPath* pathA, SkPath* pathB) {
pathA->addCircle(r.width()*0.25f, r.height()*0.25f, r.width()*0.5f);
pathB->addCircle(r.width()*0.75f, r.height()*0.75f, r.width()*0.5f);
};
MakePathsProc procs[] = { proc0, proc1 };
sk_sp<SkMaskFilter> mfA[2], mfB[2];
for (int i = 0; i < 2; ++i) {
SkPath a, b;
procs[i](r, &a, &b);
mfA[i] = make_path_mf(a, 1 * 0xFF / 3);
mfB[i] = make_path_mf(b, 2 * 0xFF / 3);
}
canvas->translate(10, 10 + 20);
canvas->save();
for (int i = 0; i < 5; ++i) {
SkTextUtils::DrawString(canvas, gCoverageName[i], r.width()*0.5f, -10, font, SkPaint(),
SkTextUtils::kCenter_Align);
SkCoverageMode cmode = static_cast<SkCoverageMode>(i);
canvas->save();
// esp. on gpu side, its valuable to exercise modes that do and do-not convolve coverage
// with alpha. SrcOver and SrcIn have these properties, but also happen to "look" the same
// for this test.
const SkBlendMode bmodes[] = { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn };
SkASSERT( SkBlendMode_SupportsCoverageAsAlpha(bmodes[0])); // test as-alpha
SkASSERT(!SkBlendMode_SupportsCoverageAsAlpha(bmodes[1])); // test not-as-alpha
for (auto bmode : bmodes) {
paint.setBlendMode(bmode);
for (int j = 0; j < 2; ++j) {
paint.setMaskFilter(SkMaskFilter::MakeCombine(mfA[j], mfB[j], cmode));
canvas->drawRect(r2, strokePaint);
canvas->drawRect(r, paint);
canvas->translate(0, r.height() + 10);
}
canvas->translate(0, 40);
}
canvas->restore();
canvas->translate(r.width() + 10, 0);
}
canvas->restore();
}

View File

@ -32,18 +32,6 @@ public:
static sk_sp<SkMaskFilter> MakeBlur(SkBlurStyle style, SkScalar sigma,
bool respectCTM = true);
/**
* Construct a maskfilter whose effect is to first apply the inner filter and then apply
* the outer filter to the result of the inner's. Returns nullptr on failure.
*/
static sk_sp<SkMaskFilter> MakeCompose(sk_sp<SkMaskFilter> outer, sk_sp<SkMaskFilter> inner);
/**
* Compose two maskfilters together using a coverage mode. Returns nullptr on failure.
*/
static sk_sp<SkMaskFilter> MakeCombine(sk_sp<SkMaskFilter> filterA, sk_sp<SkMaskFilter> filterB,
SkCoverageMode mode);
static SkFlattenable::Type GetFlattenableType() {
return kSkMaskFilter_Type;
}

View File

@ -366,288 +366,7 @@ void SkMaskFilterBase::computeFastBounds(const SkRect& src, SkRect* dst) const {
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T> static inline T join(const T& a, const T& b) {
T r = a;
r.join(b);
return r;
}
template <typename T> static inline T sect(const T& a, const T& b) {
T r = a;
return r.intersect(b) ? r : T::MakeEmpty();
}
class SkComposeMF : public SkMaskFilterBase {
public:
SkComposeMF(sk_sp<SkMaskFilter> outer, sk_sp<SkMaskFilter> inner)
: fOuter(std::move(outer))
, fInner(std::move(inner))
{
SkASSERT(as_MFB(fOuter)->getFormat() == SkMask::kA8_Format);
SkASSERT(as_MFB(fInner)->getFormat() == SkMask::kA8_Format);
}
bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, SkIPoint*) const override;
void computeFastBounds(const SkRect& src, SkRect* dst) const override {
SkRect tmp;
as_MFB(fInner)->computeFastBounds(src, &tmp);
as_MFB(fOuter)->computeFastBounds(tmp, dst);
}
SkMask::Format getFormat() const override { return SkMask::kA8_Format; }
protected:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs& args) const override{
std::unique_ptr<GrFragmentProcessor> array[2] = {
as_MFB(fInner)->asFragmentProcessor(args),
as_MFB(fOuter)->asFragmentProcessor(args),
};
if (!array[0] || !array[1]) {
return nullptr;
}
return GrFragmentProcessor::RunInSeries(array, 2);
}
bool onHasFragmentProcessor() const override {
return as_MFB(fInner)->hasFragmentProcessor() && as_MFB(fOuter)->hasFragmentProcessor();
}
#endif
private:
SK_FLATTENABLE_HOOKS(SkComposeMF)
sk_sp<SkMaskFilter> fOuter;
sk_sp<SkMaskFilter> fInner;
void flatten(SkWriteBuffer&) const override;
friend class SkMaskFilter;
typedef SkMaskFilterBase INHERITED;
};
bool SkComposeMF::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& ctm,
SkIPoint* margin) const {
SkIPoint innerMargin;
SkMask innerMask;
if (!as_MFB(fInner)->filterMask(&innerMask, src, ctm, &innerMargin)) {
return false;
}
if (!as_MFB(fOuter)->filterMask(dst, innerMask, ctm, margin)) {
return false;
}
if (margin) {
margin->fX += innerMargin.fX;
margin->fY += innerMargin.fY;
}
sk_free(innerMask.fImage);
return true;
}
void SkComposeMF::flatten(SkWriteBuffer & buffer) const {
buffer.writeFlattenable(fOuter.get());
buffer.writeFlattenable(fInner.get());
}
sk_sp<SkFlattenable> SkComposeMF::CreateProc(SkReadBuffer& buffer) {
auto outer = buffer.readMaskFilter();
auto inner = buffer.readMaskFilter();
if (!buffer.validate(outer && inner)) {
return nullptr;
}
return SkMaskFilter::MakeCompose(std::move(outer), std::move(inner));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class SkCombineMF : public SkMaskFilterBase {
public:
SkCombineMF(sk_sp<SkMaskFilter> dst, sk_sp<SkMaskFilter> src, SkCoverageMode mode)
: fDst(std::move(dst))
, fSrc(std::move(src))
, fMode(mode)
{
SkASSERT(as_MFB(fSrc)->getFormat() == SkMask::kA8_Format);
SkASSERT(as_MFB(fDst)->getFormat() == SkMask::kA8_Format);
}
bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, SkIPoint*) const override;
void computeFastBounds(const SkRect& src, SkRect* dst) const override {
SkRect srcR, dstR;
as_MFB(fSrc)->computeFastBounds(src, &srcR);
as_MFB(fDst)->computeFastBounds(src, &dstR);
*dst = join(srcR, dstR);
}
SkMask::Format getFormat() const override { return SkMask::kA8_Format; }
SK_FLATTENABLE_HOOKS(SkCombineMF)
protected:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs& args) const override{
auto src = as_MFB(fSrc)->asFragmentProcessor(args);
auto dst = as_MFB(fDst)->asFragmentProcessor(args);
if (!src || !dst) {
return nullptr;
}
return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(src), std::move(dst),
SkUncorrelatedCoverageModeToBlendMode(fMode));
}
bool onHasFragmentProcessor() const override {
return as_MFB(fSrc)->hasFragmentProcessor() && as_MFB(fDst)->hasFragmentProcessor();
}
#endif
private:
sk_sp<SkMaskFilter> fDst;
sk_sp<SkMaskFilter> fSrc;
SkCoverageMode fMode;
void flatten(SkWriteBuffer&) const override;
friend class SkMaskFilter;
typedef SkMaskFilterBase INHERITED;
};
#include "src/core/SkSafeMath.h"
class DrawIntoMask : public SkDraw {
public:
// we ignore the offset of the mask->fBounds
DrawIntoMask(SkMask* mask) {
int w = mask->fBounds.width();
int h = mask->fBounds.height();
size_t size = SkSafeMath::Mul(w, h);
mask->fFormat = SkMask::kA8_Format;
mask->fImage = SkMask::AllocImage(size, SkMask::kZeroInit_Alloc);
mask->fRowBytes = w;
SkAssertResult(fDst.reset(*mask));
fMatrixStorage.reset();
fMatrix = &fMatrixStorage;
fRCStorage.setRect({ 0, 0, w, h });
fRC = &fRCStorage;
}
void drawAsBitmap(const SkMask& m, const SkPaint& p) {
SkBitmap b;
b.installMaskPixels(m);
this->drawSprite(b, m.fBounds.fLeft, m.fBounds.fTop, p);
}
private:
SkMatrix fMatrixStorage;
SkRasterClip fRCStorage;
};
static SkIRect join(const SkIRect& src, const SkIRect& dst, SkCoverageMode mode) {
switch (mode) {
case SkCoverageMode::kUnion: return join(src, dst);
case SkCoverageMode::kIntersect: return sect(src, dst);
case SkCoverageMode::kDifference: return src;
case SkCoverageMode::kReverseDifference: return dst;
case SkCoverageMode::kXor: return join(src, dst);
}
// not reached
return { 0, 0, 0, 0 };
}
bool SkCombineMF::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& ctm,
SkIPoint* margin) const {
SkIPoint srcP, dstP;
SkMask srcM, dstM;
if (!as_MFB(fSrc)->filterMask(&srcM, src, ctm, &srcP)) {
return false;
}
if (!as_MFB(fDst)->filterMask(&dstM, src, ctm, &dstP)) {
return false;
}
dst->fBounds = join(srcM.fBounds, dstM.fBounds, fMode);
dst->fFormat = SkMask::kA8_Format;
if (src.fImage == nullptr) {
dst->fImage = nullptr;
return true;
}
DrawIntoMask md(dst);
SkPaint p;
p.setBlendMode(SkBlendMode::kSrc);
dstM.fBounds.offset(-dst->fBounds.fLeft, -dst->fBounds.fTop);
md.drawAsBitmap(dstM, p);
p.setBlendMode(SkUncorrelatedCoverageModeToBlendMode(fMode));
srcM.fBounds.offset(-dst->fBounds.fLeft, -dst->fBounds.fTop);
md.drawAsBitmap(srcM, p);
sk_free(srcM.fImage);
sk_free(dstM.fImage);
return true;
}
void SkCombineMF::flatten(SkWriteBuffer & buffer) const {
buffer.writeFlattenable(fDst.get());
buffer.writeFlattenable(fSrc.get());
buffer.write32(static_cast<uint32_t>(fMode));
}
sk_sp<SkFlattenable> SkCombineMF::CreateProc(SkReadBuffer& buffer) {
auto dst = buffer.readMaskFilter();
auto src = buffer.readMaskFilter();
SkCoverageMode mode = buffer.read32LE(SkCoverageMode::kLast);
if (!buffer.validate(dst && src)) {
return nullptr;
}
return SkMaskFilter::MakeCombine(std::move(dst), std::move(src), mode);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkMaskFilter> SkMaskFilter::MakeCompose(sk_sp<SkMaskFilter> outer,
sk_sp<SkMaskFilter> inner) {
if (!outer) {
return inner;
}
if (!inner) {
return outer;
}
if (as_MFB(inner)->getFormat() != SkMask::kA8_Format ||
as_MFB(outer)->getFormat() != SkMask::kA8_Format) {
return nullptr;
}
return sk_sp<SkMaskFilter>(new SkComposeMF(std::move(outer), std::move(inner)));
}
sk_sp<SkMaskFilter> SkMaskFilter::MakeCombine(sk_sp<SkMaskFilter> dst, sk_sp<SkMaskFilter> src,
SkCoverageMode mode) {
if (!dst) {
return src;
}
if (!src) {
return dst;
}
if (as_MFB(dst)->getFormat() != SkMask::kA8_Format ||
as_MFB(src)->getFormat() != SkMask::kA8_Format) {
return nullptr;
}
return sk_sp<SkMaskFilter>(new SkCombineMF(std::move(dst), std::move(src), mode));
}
void SkMaskFilter::RegisterFlattenables() {
SK_REGISTER_FLATTENABLE(SkComposeMF);
SK_REGISTER_FLATTENABLE(SkCombineMF);
sk_register_blur_maskfilter_createproc();
#if SK_SUPPORT_GPU
gr_register_sdf_maskfilter_createproc();