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:
parent
273f107a2d
commit
52653731d5
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user