123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717 |
- /*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "src/core/SkMaskFilterBase.h"
- #include "include/core/SkPath.h"
- #include "include/core/SkRRect.h"
- #include "src/core/SkAutoMalloc.h"
- #include "src/core/SkBlitter.h"
- #include "src/core/SkBlurPriv.h"
- #include "src/core/SkCachedData.h"
- #include "src/core/SkCoverageModePriv.h"
- #include "src/core/SkDraw.h"
- #include "src/core/SkRasterClip.h"
- #include "src/core/SkReadBuffer.h"
- #include "src/core/SkWriteBuffer.h"
- #if SK_SUPPORT_GPU
- #include "src/gpu/GrFragmentProcessor.h"
- #include "src/gpu/GrTextureProxy.h"
- #include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
- #include "src/gpu/text/GrSDFMaskFilter.h"
- #endif
- SkMaskFilterBase::NinePatch::~NinePatch() {
- if (fCache) {
- SkASSERT((const void*)fMask.fImage == fCache->data());
- fCache->unref();
- } else {
- SkMask::FreeImage(fMask.fImage);
- }
- }
- bool SkMaskFilterBase::asABlur(BlurRec*) const {
- return false;
- }
- static void extractMaskSubset(const SkMask& src, SkMask* dst) {
- SkASSERT(src.fBounds.contains(dst->fBounds));
- const int dx = dst->fBounds.left() - src.fBounds.left();
- const int dy = dst->fBounds.top() - src.fBounds.top();
- dst->fImage = src.fImage + dy * src.fRowBytes + dx;
- dst->fRowBytes = src.fRowBytes;
- dst->fFormat = src.fFormat;
- }
- static void blitClippedMask(SkBlitter* blitter, const SkMask& mask,
- const SkIRect& bounds, const SkIRect& clipR) {
- SkIRect r;
- if (r.intersect(bounds, clipR)) {
- blitter->blitMask(mask, r);
- }
- }
- static void blitClippedRect(SkBlitter* blitter, const SkIRect& rect, const SkIRect& clipR) {
- SkIRect r;
- if (r.intersect(rect, clipR)) {
- blitter->blitRect(r.left(), r.top(), r.width(), r.height());
- }
- }
- #if 0
- static void dump(const SkMask& mask) {
- for (int y = mask.fBounds.top(); y < mask.fBounds.bottom(); ++y) {
- for (int x = mask.fBounds.left(); x < mask.fBounds.right(); ++x) {
- SkDebugf("%02X", *mask.getAddr8(x, y));
- }
- SkDebugf("\n");
- }
- SkDebugf("\n");
- }
- #endif
- static void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR,
- const SkIPoint& center, bool fillCenter,
- const SkIRect& clipR, SkBlitter* blitter) {
- int cx = center.x();
- int cy = center.y();
- SkMask m;
- // top-left
- m.fBounds = mask.fBounds;
- m.fBounds.fRight = cx;
- m.fBounds.fBottom = cy;
- if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
- extractMaskSubset(mask, &m);
- m.fBounds.offsetTo(outerR.left(), outerR.top());
- blitClippedMask(blitter, m, m.fBounds, clipR);
- }
- // top-right
- m.fBounds = mask.fBounds;
- m.fBounds.fLeft = cx + 1;
- m.fBounds.fBottom = cy;
- if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
- extractMaskSubset(mask, &m);
- m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), outerR.top());
- blitClippedMask(blitter, m, m.fBounds, clipR);
- }
- // bottom-left
- m.fBounds = mask.fBounds;
- m.fBounds.fRight = cx;
- m.fBounds.fTop = cy + 1;
- if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
- extractMaskSubset(mask, &m);
- m.fBounds.offsetTo(outerR.left(), outerR.bottom() - m.fBounds.height());
- blitClippedMask(blitter, m, m.fBounds, clipR);
- }
- // bottom-right
- m.fBounds = mask.fBounds;
- m.fBounds.fLeft = cx + 1;
- m.fBounds.fTop = cy + 1;
- if (m.fBounds.width() > 0 && m.fBounds.height() > 0) {
- extractMaskSubset(mask, &m);
- m.fBounds.offsetTo(outerR.right() - m.fBounds.width(),
- outerR.bottom() - m.fBounds.height());
- blitClippedMask(blitter, m, m.fBounds, clipR);
- }
- SkIRect innerR;
- innerR.set(outerR.left() + cx - mask.fBounds.left(),
- outerR.top() + cy - mask.fBounds.top(),
- outerR.right() + (cx + 1 - mask.fBounds.right()),
- outerR.bottom() + (cy + 1 - mask.fBounds.bottom()));
- if (fillCenter) {
- blitClippedRect(blitter, innerR, clipR);
- }
- const int innerW = innerR.width();
- size_t storageSize = (innerW + 1) * (sizeof(int16_t) + sizeof(uint8_t));
- SkAutoSMalloc<4*1024> storage(storageSize);
- int16_t* runs = (int16_t*)storage.get();
- uint8_t* alpha = (uint8_t*)(runs + innerW + 1);
- SkIRect r;
- // top
- r.set(innerR.left(), outerR.top(), innerR.right(), innerR.top());
- if (r.intersect(clipR)) {
- int startY = SkMax32(0, r.top() - outerR.top());
- int stopY = startY + r.height();
- int width = r.width();
- for (int y = startY; y < stopY; ++y) {
- runs[0] = width;
- runs[width] = 0;
- alpha[0] = *mask.getAddr8(cx, mask.fBounds.top() + y);
- blitter->blitAntiH(r.left(), outerR.top() + y, alpha, runs);
- }
- }
- // bottom
- r.set(innerR.left(), innerR.bottom(), innerR.right(), outerR.bottom());
- if (r.intersect(clipR)) {
- int startY = outerR.bottom() - r.bottom();
- int stopY = startY + r.height();
- int width = r.width();
- for (int y = startY; y < stopY; ++y) {
- runs[0] = width;
- runs[width] = 0;
- alpha[0] = *mask.getAddr8(cx, mask.fBounds.bottom() - y - 1);
- blitter->blitAntiH(r.left(), outerR.bottom() - y - 1, alpha, runs);
- }
- }
- // left
- r.set(outerR.left(), innerR.top(), innerR.left(), innerR.bottom());
- if (r.intersect(clipR)) {
- SkMask m;
- m.fImage = mask.getAddr8(mask.fBounds.left() + r.left() - outerR.left(),
- mask.fBounds.top() + cy);
- m.fBounds = r;
- m.fRowBytes = 0; // so we repeat the scanline for our height
- m.fFormat = SkMask::kA8_Format;
- blitter->blitMask(m, r);
- }
- // right
- r.set(innerR.right(), innerR.top(), outerR.right(), innerR.bottom());
- if (r.intersect(clipR)) {
- SkMask m;
- m.fImage = mask.getAddr8(mask.fBounds.right() - outerR.right() + r.left(),
- mask.fBounds.top() + cy);
- m.fBounds = r;
- m.fRowBytes = 0; // so we repeat the scanline for our height
- m.fFormat = SkMask::kA8_Format;
- blitter->blitMask(m, r);
- }
- }
- static void draw_nine(const SkMask& mask, const SkIRect& outerR, const SkIPoint& center,
- bool fillCenter, const SkRasterClip& clip, SkBlitter* blitter) {
- // if we get here, we need to (possibly) resolve the clip and blitter
- SkAAClipBlitterWrapper wrapper(clip, blitter);
- blitter = wrapper.getBlitter();
- SkRegion::Cliperator clipper(wrapper.getRgn(), outerR);
- if (!clipper.done()) {
- const SkIRect& cr = clipper.rect();
- do {
- draw_nine_clipped(mask, outerR, center, fillCenter, cr, blitter);
- clipper.next();
- } while (!clipper.done());
- }
- }
- static int countNestedRects(const SkPath& path, SkRect rects[2]) {
- if (path.isNestedFillRects(rects)) {
- return 2;
- }
- return path.isRect(&rects[0]);
- }
- bool SkMaskFilterBase::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix,
- const SkRasterClip& clip, SkBlitter* blitter) const {
- // Attempt to speed up drawing by creating a nine patch. If a nine patch
- // cannot be used, return false to allow our caller to recover and perform
- // the drawing another way.
- NinePatch patch;
- patch.fMask.fImage = nullptr;
- if (kTrue_FilterReturn != this->filterRRectToNine(devRRect, matrix,
- clip.getBounds(),
- &patch)) {
- SkASSERT(nullptr == patch.fMask.fImage);
- return false;
- }
- draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, true, clip, blitter);
- return true;
- }
- bool SkMaskFilterBase::filterPath(const SkPath& devPath, const SkMatrix& matrix,
- const SkRasterClip& clip, SkBlitter* blitter,
- SkStrokeRec::InitStyle style) const {
- SkRect rects[2];
- int rectCount = 0;
- if (SkStrokeRec::kFill_InitStyle == style) {
- rectCount = countNestedRects(devPath, rects);
- }
- if (rectCount > 0) {
- NinePatch patch;
- switch (this->filterRectsToNine(rects, rectCount, matrix, clip.getBounds(), &patch)) {
- case kFalse_FilterReturn:
- SkASSERT(nullptr == patch.fMask.fImage);
- return false;
- case kTrue_FilterReturn:
- draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, 1 == rectCount, clip,
- blitter);
- return true;
- case kUnimplemented_FilterReturn:
- SkASSERT(nullptr == patch.fMask.fImage);
- // fall through
- break;
- }
- }
- SkMask srcM, dstM;
- if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), this, &matrix, &srcM,
- SkMask::kComputeBoundsAndRenderImage_CreateMode,
- style)) {
- return false;
- }
- SkAutoMaskFreeImage autoSrc(srcM.fImage);
- if (!this->filterMask(&dstM, srcM, matrix, nullptr)) {
- return false;
- }
- SkAutoMaskFreeImage autoDst(dstM.fImage);
- // if we get here, we need to (possibly) resolve the clip and blitter
- SkAAClipBlitterWrapper wrapper(clip, blitter);
- blitter = wrapper.getBlitter();
- SkRegion::Cliperator clipper(wrapper.getRgn(), dstM.fBounds);
- if (!clipper.done()) {
- const SkIRect& cr = clipper.rect();
- do {
- blitter->blitMask(dstM, cr);
- clipper.next();
- } while (!clipper.done());
- }
- return true;
- }
- SkMaskFilterBase::FilterReturn
- SkMaskFilterBase::filterRRectToNine(const SkRRect&, const SkMatrix&,
- const SkIRect& clipBounds, NinePatch*) const {
- return kUnimplemented_FilterReturn;
- }
- SkMaskFilterBase::FilterReturn
- SkMaskFilterBase::filterRectsToNine(const SkRect[], int count, const SkMatrix&,
- const SkIRect& clipBounds, NinePatch*) const {
- return kUnimplemented_FilterReturn;
- }
- #if SK_SUPPORT_GPU
- std::unique_ptr<GrFragmentProcessor>
- SkMaskFilterBase::asFragmentProcessor(const GrFPArgs& args) const {
- auto fp = this->onAsFragmentProcessor(args);
- if (fp) {
- SkASSERT(this->hasFragmentProcessor());
- } else {
- SkASSERT(!this->hasFragmentProcessor());
- }
- return fp;
- }
- bool SkMaskFilterBase::hasFragmentProcessor() const {
- return this->onHasFragmentProcessor();
- }
- std::unique_ptr<GrFragmentProcessor>
- SkMaskFilterBase::onAsFragmentProcessor(const GrFPArgs&) const {
- return nullptr;
- }
- bool SkMaskFilterBase::onHasFragmentProcessor() const { return false; }
- bool SkMaskFilterBase::canFilterMaskGPU(const GrShape& shape,
- const SkIRect& devSpaceShapeBounds,
- const SkIRect& clipBounds,
- const SkMatrix& ctm,
- SkIRect* maskRect) const {
- return false;
- }
- bool SkMaskFilterBase::directFilterMaskGPU(GrRecordingContext*,
- GrRenderTargetContext*,
- GrPaint&&,
- const GrClip&,
- const SkMatrix& viewMatrix,
- const GrShape&) const {
- return false;
- }
- sk_sp<GrTextureProxy> SkMaskFilterBase::filterMaskGPU(GrRecordingContext*,
- sk_sp<GrTextureProxy> srcProxy,
- const SkMatrix& ctm,
- const SkIRect& maskRect) const {
- return nullptr;
- }
- #endif
- void SkMaskFilterBase::computeFastBounds(const SkRect& src, SkRect* dst) const {
- SkMask srcM, dstM;
- srcM.fBounds = src.roundOut();
- srcM.fRowBytes = 0;
- srcM.fFormat = SkMask::kA8_Format;
- SkIPoint margin; // ignored
- if (this->filterMask(&dstM, srcM, SkMatrix::I(), &margin)) {
- dst->set(dstM.fBounds);
- } else {
- dst->set(srcM.fBounds);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- 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);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- class SkMatrixMF : public SkMaskFilterBase {
- public:
- SkMatrixMF(sk_sp<SkMaskFilter> filter, const SkMatrix& lm)
- : fFilter(std::move(filter))
- , fLM(lm)
- {}
- bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix& ctm,
- SkIPoint* margin) const override {
- return as_MFB(fFilter)->filterMask(dst, src, SkMatrix::Concat(ctm, fLM), margin);
- }
- void computeFastBounds(const SkRect& src, SkRect* dst) const override {
- *dst = src;
- SkRect tmp;
- fLM.mapRect(&tmp, src);
- as_MFB(fFilter)->computeFastBounds(tmp, dst);
- }
- SkMask::Format getFormat() const override { return as_MFB(fFilter)->getFormat(); }
- SK_FLATTENABLE_HOOKS(SkMatrixMF)
- protected:
- #if SK_SUPPORT_GPU
- std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs& args) const override{
- return as_MFB(fFilter)->asFragmentProcessor(GrFPArgs::WithPostLocalMatrix(args, fLM));
- }
- bool onHasFragmentProcessor() const override {
- return as_MFB(fFilter)->hasFragmentProcessor();
- }
- #endif
- private:
- sk_sp<SkMaskFilter> fFilter;
- const SkMatrix fLM;
- void flatten(SkWriteBuffer& buffer) const override {
- buffer.writeMatrix(fLM);
- buffer.writeFlattenable(fFilter.get());
- }
- friend class SkMaskFilter;
- typedef SkMaskFilterBase INHERITED;
- };
- sk_sp<SkFlattenable> SkMatrixMF::CreateProc(SkReadBuffer& buffer) {
- SkMatrix m;
- buffer.readMatrix(&m);
- auto filter = buffer.readMaskFilter();
- return filter ? filter->makeWithMatrix(m) : nullptr;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- 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));
- }
- sk_sp<SkMaskFilter> SkMaskFilter::makeWithMatrix(const SkMatrix& lm) const {
- sk_sp<SkMaskFilter> me = sk_ref_sp(const_cast<SkMaskFilter*>(this));
- if (lm.isIdentity()) {
- return me;
- }
- return sk_sp<SkMaskFilter>(new SkMatrixMF(std::move(me), lm));
- }
- void SkMaskFilter::RegisterFlattenables() {
- SK_REGISTER_FLATTENABLE(SkMatrixMF);
- SK_REGISTER_FLATTENABLE(SkComposeMF);
- SK_REGISTER_FLATTENABLE(SkCombineMF);
- sk_register_blur_maskfilter_createproc();
- #if SK_SUPPORT_GPU
- gr_register_sdf_maskfilter_createproc();
- #endif
- }
|