aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2018-01-23 15:29:32 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-23 21:14:20 +0000
commit80747ef591ff3c09c2b610eb21258132d1ff4ef5 (patch)
treee7472d73f966f9400b0e52cb02ad9e8515de32c3
parenta7701e032bcc55a73360aa8d1b53ceef566de991 (diff)
move the guts of SkMaskFilter.h into SkMaskFilterBase.h
Bug: skia: Change-Id: I29ad0960156562867429542d3cfbf3d639529cab Reviewed-on: https://skia-review.googlesource.com/98802 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Brian Salomon <bsalomon@google.com>
-rw-r--r--include/core/SkMaskFilter.h231
-rw-r--r--include/effects/SkBlurMaskFilter.h3
-rw-r--r--include/effects/SkRRectsGaussianEdgeMaskFilter.h1
-rw-r--r--include/effects/SkTableMaskFilter.h39
-rw-r--r--src/core/SkBitmap.cpp5
-rw-r--r--src/core/SkBlitter.cpp4
-rw-r--r--src/core/SkDraw.cpp13
-rw-r--r--src/core/SkMaskFilter.cpp88
-rw-r--r--src/core/SkMaskFilterBase.h251
-rw-r--r--src/core/SkPaint.cpp4
-rw-r--r--src/core/SkReadBuffer.h4
-rw-r--r--src/core/SkScalerContext.cpp4
-rw-r--r--src/effects/SkBlurMaskFilter.cpp7
-rw-r--r--src/effects/SkEmbossMaskFilter.h4
-rw-r--r--src/effects/SkLayerDrawLooper.cpp5
-rw-r--r--src/effects/SkRRectsGaussianEdgeMaskFilter.cpp3
-rw-r--r--src/effects/SkShaderMaskFilter.cpp3
-rw-r--r--src/effects/SkTableMaskFilter.cpp58
-rw-r--r--src/gpu/GrBlurUtils.cpp10
-rw-r--r--src/gpu/SkGpuDevice.cpp4
-rw-r--r--src/gpu/SkGpuDevice_drawTexture.cpp18
-rw-r--r--src/gpu/SkGr.cpp4
-rw-r--r--src/gpu/text/GrAtlasTextBlob.cpp3
-rw-r--r--src/gpu/text/GrAtlasTextBlob.h8
-rw-r--r--src/gpu/text/GrAtlasTextContext.cpp5
-rw-r--r--src/gpu/text/GrTextBlobCache.h2
-rw-r--r--src/pdf/SkPDFDevice.cpp4
-rw-r--r--src/xps/SkXPSDevice.cpp4
-rw-r--r--tests/BlurTest.cpp9
-rw-r--r--tests/FlattenDrawableTest.cpp15
-rw-r--r--tools/debugger/SkDrawCommand.cpp6
31 files changed, 441 insertions, 378 deletions
diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h
index 3e10dc9ad3..55bf8bf4d5 100644
--- a/include/core/SkMaskFilter.h
+++ b/include/core/SkMaskFilter.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -9,245 +8,19 @@
#ifndef SkMaskFilter_DEFINED
#define SkMaskFilter_DEFINED
-#include "SkBlurTypes.h"
#include "SkFlattenable.h"
-#include "SkMask.h"
-#include "SkPaint.h"
-#include "SkStrokeRec.h"
-class GrClip;
-class GrContext;
-struct GrFPArgs;
-class GrRenderTargetContext;
-class GrPaint;
-class GrFragmentProcessor;
-class GrRenderTarget;
-class GrResourceProvider;
-class GrTexture;
-class GrTextureProxy;
-class SkBitmap;
-class SkBlitter;
-class SkCachedData;
-class SkMatrix;
-class SkPath;
-class SkRasterClip;
-class SkRRect;
+class SkString;
/** \class SkMaskFilter
SkMaskFilter is the base class for object that perform transformations on
- an alpha-channel mask before drawing it. A subclass of SkMaskFilter may be
- installed into a SkPaint. Once there, each time a primitive is drawn, it
- is first scan converted into a SkMask::kA8_Format mask, and handed to the
- filter, calling its filterMask() method. If this returns true, then the
- new mask is used to render into the device.
-
- Blur and emboss are implemented as subclasses of SkMaskFilter.
+ the mask before drawing it. An example subclass is Blur.
*/
class SK_API SkMaskFilter : public SkFlattenable {
public:
- /** Returns the format of the resulting mask that this subclass will return
- when its filterMask() method is called.
- */
- virtual SkMask::Format getFormat() const = 0;
-
- /** Create a new mask by filter the src mask.
- If src.fImage == null, then do not allocate or create the dst image
- but do fill out the other fields in dstMask.
- If you do allocate a dst image, use SkMask::AllocImage()
- If this returns false, dst mask is ignored.
- @param dst the result of the filter. If src.fImage == null, dst should not allocate its image
- @param src the original image to be filtered.
- @param matrix the CTM
- @param margin if not null, return the buffer dx/dy need when calculating the effect. Used when
- drawing a clipped object to know how much larger to allocate the src before
- applying the filter. If returning false, ignore this parameter.
- @return true if the dst mask was correctly created.
- */
- virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
- SkIPoint* margin) const;
-
-#if SK_SUPPORT_GPU
- /**
- * Returns a processor if the filter can be expressed a single-pass GrProcessor without
- * requiring an explicit input mask. Per-pixel, the effect receives the incoming mask's
- * coverage as the input color and outputs the filtered covereage value. This means that each
- * pixel's filtered coverage must only depend on the unfiltered mask value for that pixel and
- * not on surrounding values.
- */
- std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs& args) const;
-
- /**
- * Returns true iff asFragmentProcessor() will return a processor
- */
- bool hasFragmentProcessor() const;
-
- /**
- * If asFragmentProcessor() fails the filter may be implemented on the GPU by a subclass
- * overriding filterMaskGPU (declared below). That code path requires constructing a
- * src mask as input. Since that is a potentially expensive operation, the subclass must also
- * override this function to indicate whether filterTextureMaskGPU would succeeed if the mask
- * were to be created.
- *
- * 'maskRect' returns the device space portion of the mask that the filter needs. The mask
- * passed into 'filterMaskGPU' should have the same extent as 'maskRect' but be
- * translated to the upper-left corner of the mask (i.e., (maskRect.fLeft, maskRect.fTop)
- * appears at (0, 0) in the mask).
- *
- * Logically, how this works is:
- * canFilterMaskGPU is called
- * if (it returns true)
- * the returned mask rect is used for quick rejecting
- * either directFilterMaskGPU or directFilterRRectMaskGPU is then called
- * if (neither of them handle the blur)
- * the mask rect is used to generate the mask
- * filterMaskGPU is called to filter the mask
- *
- * TODO: this should work as:
- * if (canFilterMaskGPU(devShape, ...)) // rect, rrect, drrect, path
- * filterMaskGPU(devShape, ...)
- * this would hide the RRect special case and the mask generation
- */
- virtual bool canFilterMaskGPU(const SkRRect& devRRect,
- const SkIRect& clipBounds,
- const SkMatrix& ctm,
- SkRect* maskRect) const;
-
- /**
- * Try to directly render the mask filter into the target. Returns true if drawing was
- * successful. If false is returned then paint is unmodified.
- */
- virtual bool directFilterMaskGPU(GrContext*,
- GrRenderTargetContext* renderTargetContext,
- GrPaint&& paint,
- const GrClip&,
- const SkMatrix& viewMatrix,
- const SkStrokeRec& strokeRec,
- const SkPath& path) const;
- /**
- * Try to directly render a rounded rect mask filter into the target. Returns
- * true if drawing was successful. If false is returned then paint is unmodified.
- */
- virtual bool directFilterRRectMaskGPU(GrContext*,
- GrRenderTargetContext* renderTargetContext,
- GrPaint&& paint,
- const GrClip&,
- const SkMatrix& viewMatrix,
- const SkStrokeRec& strokeRec,
- const SkRRect& rrect,
- const SkRRect& devRRect) const;
-
- /**
- * This function is used to implement filters that require an explicit src mask. It should only
- * be called if canFilterMaskGPU returned true and the maskRect param should be the output from
- * that call.
- * Implementations are free to get the GrContext from the src texture in order to create
- * additional textures and perform multiple passes.
- */
- virtual sk_sp<GrTextureProxy> filterMaskGPU(GrContext*,
- sk_sp<GrTextureProxy> srcProxy,
- const SkMatrix& ctm,
- const SkIRect& maskRect) const;
-#endif
-
- /**
- * The fast bounds function is used to enable the paint to be culled early
- * in the drawing pipeline. This function accepts the current bounds of the
- * paint as its src param and the filter adjust those bounds using its
- * current mask and returns the result using the dest param. Callers are
- * allowed to provide the same struct for both src and dest so each
- * implementation must accomodate that behavior.
- *
- * The default impl calls filterMask with the src mask having no image,
- * but subclasses may override this if they can compute the rect faster.
- */
- virtual void computeFastBounds(const SkRect& src, SkRect* dest) const;
-
- struct BlurRec {
- SkScalar fSigma;
- SkBlurStyle fStyle;
- SkBlurQuality fQuality;
- };
- /**
- * If this filter can be represented by a BlurRec, return true and (if not null) fill in the
- * provided BlurRec parameter. If this effect cannot be represented as a BlurRec, return false
- * and ignore the BlurRec parameter.
- */
- virtual bool asABlur(BlurRec*) const;
-
SK_TO_STRING_PUREVIRT()
SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter)
-
-protected:
- SkMaskFilter() {}
-
-#if SK_SUPPORT_GPU
- virtual std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs&) const;
- virtual bool onHasFragmentProcessor() const;
-#endif
-
- enum FilterReturn {
- kFalse_FilterReturn,
- kTrue_FilterReturn,
- kUnimplemented_FilterReturn
- };
-
- class NinePatch : ::SkNoncopyable {
- public:
- NinePatch() : fCache(nullptr) { }
- ~NinePatch();
-
- SkMask fMask; // fBounds must have [0,0] in its top-left
- SkIRect fOuterRect; // width/height must be >= fMask.fBounds'
- SkIPoint fCenter; // identifies center row/col for stretching
- SkCachedData* fCache;
- };
-
- /**
- * Override if your subclass can filter a rect, and return the answer as
- * a ninepatch mask to be stretched over the returned outerRect. On success
- * return kTrue_FilterReturn. On failure (e.g. out of memory) return
- * kFalse_FilterReturn. If the normal filterMask() entry-point should be
- * called (the default) return kUnimplemented_FilterReturn.
- *
- * By convention, the caller will take the center rol/col from the returned
- * mask as the slice it can replicate horizontally and vertically as we
- * stretch the mask to fit inside outerRect. It is an error for outerRect
- * to be smaller than the mask's bounds. This would imply that the width
- * and height of the mask should be odd. This is not required, just that
- * the caller will call mask.fBounds.centerX() and centerY() to find the
- * strips that will be replicated.
- */
- virtual FilterReturn filterRectsToNine(const SkRect[], int count,
- const SkMatrix&,
- const SkIRect& clipBounds,
- NinePatch*) const;
- /**
- * Similar to filterRectsToNine, except it performs the work on a round rect.
- */
- virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&,
- const SkIRect& clipBounds,
- NinePatch*) const;
-
-private:
- friend class SkDraw;
-
- /** Helper method that, given a path in device space, will rasterize it into a kA8_Format mask
- and then call filterMask(). If this returns true, the specified blitter will be called
- to render that mask. Returns false if filterMask() returned false.
- This method is not exported to java.
- */
- bool filterPath(const SkPath& devPath, const SkMatrix& ctm, const SkRasterClip&, SkBlitter*,
- SkStrokeRec::InitStyle) const;
-
- /** Helper method that, given a roundRect in device space, will rasterize it into a kA8_Format
- mask and then call filterMask(). If this returns true, the specified blitter will be called
- to render that mask. Returns false if filterMask() returned false.
- */
- bool filterRRect(const SkRRect& devRRect, const SkMatrix& ctm, const SkRasterClip&,
- SkBlitter*) const;
-
- typedef SkFlattenable INHERITED;
};
#endif
diff --git a/include/effects/SkBlurMaskFilter.h b/include/effects/SkBlurMaskFilter.h
index 8b032e50ee..af074ffff3 100644
--- a/include/effects/SkBlurMaskFilter.h
+++ b/include/effects/SkBlurMaskFilter.h
@@ -10,9 +10,12 @@
// we include this since our callers will need to at least be able to ref/unref
#include "SkMaskFilter.h"
+#include "SkRect.h"
#include "SkScalar.h"
#include "SkBlurTypes.h"
+class SkRRect;
+
class SK_API SkBlurMaskFilter {
public:
/**
diff --git a/include/effects/SkRRectsGaussianEdgeMaskFilter.h b/include/effects/SkRRectsGaussianEdgeMaskFilter.h
index d9e30248e2..cd7effc118 100644
--- a/include/effects/SkRRectsGaussianEdgeMaskFilter.h
+++ b/include/effects/SkRRectsGaussianEdgeMaskFilter.h
@@ -9,6 +9,7 @@
#define SkRRectsGaussianEdgeMaskFilter_DEFINED
#include "SkMaskFilter.h"
+#include "SkScalar.h"
class SkRRect;
diff --git a/include/effects/SkTableMaskFilter.h b/include/effects/SkTableMaskFilter.h
index f226dd1760..eb6ccb08b1 100644
--- a/include/effects/SkTableMaskFilter.h
+++ b/include/effects/SkTableMaskFilter.h
@@ -16,7 +16,7 @@
Applies a table lookup on each of the alpha values in the mask.
Helper methods create some common tables (e.g. gamma, clipping)
*/
-class SK_API SkTableMaskFilter : public SkMaskFilter {
+class SK_API SkTableMaskFilter {
public:
/** Utility that sets the gamma table
*/
@@ -27,40 +27,11 @@ public:
*/
static void MakeClipTable(uint8_t table[256], uint8_t min, uint8_t max);
- static SkMaskFilter* Create(const uint8_t table[256]) {
- return new SkTableMaskFilter(table);
- }
+ static SkMaskFilter* Create(const uint8_t table[256]);
+ static SkMaskFilter* CreateGamma(SkScalar gamma);
+ static SkMaskFilter* CreateClip(uint8_t min, uint8_t max);
- static SkMaskFilter* CreateGamma(SkScalar gamma) {
- uint8_t table[256];
- MakeGammaTable(table, gamma);
- return new SkTableMaskFilter(table);
- }
-
- static SkMaskFilter* CreateClip(uint8_t min, uint8_t max) {
- uint8_t table[256];
- MakeClipTable(table, min, max);
- return new SkTableMaskFilter(table);
- }
-
- SkMask::Format getFormat() const override;
- bool filterMask(SkMask*, const SkMask&, const SkMatrix&, SkIPoint*) const override;
-
- SK_TO_STRING_OVERRIDE()
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTableMaskFilter)
-
-protected:
- ~SkTableMaskFilter() override;
-
- void flatten(SkWriteBuffer&) const override;
-
-private:
- SkTableMaskFilter();
- explicit SkTableMaskFilter(const uint8_t table[256]);
-
- uint8_t fTable[256];
-
- typedef SkMaskFilter INHERITED;
+ SkTableMaskFilter() = delete;
};
#endif
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index c438ecd2a2..0e88e03b06 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -16,6 +16,7 @@
#include "SkImageInfoPriv.h"
#include "SkMallocPixelRef.h"
#include "SkMask.h"
+#include "SkMaskFilterBase.h"
#include "SkMath.h"
#include "SkPixelRef.h"
#include "SkPixmapPriv.h"
@@ -543,7 +544,7 @@ bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
// compute our (larger?) dst bounds if we have a filter
if (filter) {
identity.reset();
- if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
+ if (!as_MFB(filter)->filterMask(&dstM, srcM, identity, nullptr)) {
goto NO_FILTER_CASE;
}
dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
@@ -567,7 +568,7 @@ bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
SkAutoMaskFreeImage srcCleanup(srcM.fImage);
GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
- if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
+ if (!as_MFB(filter)->filterMask(&dstM, srcM, identity, nullptr)) {
goto NO_FILTER_CASE;
}
SkAutoMaskFreeImage dstCleanup(dstM.fImage);
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index 1f21e28dad..f4de215972 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -13,7 +13,7 @@
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkMask.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkPaintPriv.h"
#include "SkShaderBase.h"
#include "SkString.h"
@@ -946,7 +946,7 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
if (origPaint.getMaskFilter() != nullptr &&
- origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
+ as_MFB(origPaint.getMaskFilter())->getFormat() == SkMask::k3D_Format) {
shader3D = sk_make_sp<Sk3DShader>(sk_ref_sp(shader));
// we know we haven't initialized lazyPaint yet, so just do it
paint.writable()->setShader(shader3D);
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 20ce379cd6..3e4722be4d 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -18,7 +18,7 @@
#include "SkDraw.h"
#include "SkDrawProcs.h"
#include "SkFindAndPlaceGlyph.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkMatrix.h"
#include "SkMatrixUtils.h"
#include "SkPaint.h"
@@ -842,7 +842,7 @@ void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
SkMask dstM;
if (paint.getMaskFilter() &&
- paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, nullptr)) {
+ as_MFB(paint.getMaskFilter())->filterMask(&dstM, srcM, *fMatrix, nullptr)) {
mask = &dstM;
}
SkAutoMaskFreeImage ami(dstM.fImage);
@@ -922,7 +922,8 @@ void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
SkRRect devRRect;
if (rrect.transform(*fMatrix, &devRRect)) {
SkAutoBlitterChoose blitter(fDst, *fMatrix, paint);
- if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, blitter.get())) {
+ if (as_MFB(paint.getMaskFilter())->filterRRect(devRRect, *fMatrix,
+ *fRC, blitter.get())) {
return; // filterRRect() called the blitter, so we're done
}
}
@@ -959,7 +960,7 @@ void SkDraw::drawDevPath(const SkPath& devPath, const SkPaint& paint, bool drawC
SkRect pathBounds = devPath.getBounds().makeOutset(1, 1);
if (paint.getMaskFilter()) {
- paint.getMaskFilter()->computeFastBounds(pathBounds, &pathBounds);
+ as_MFB(paint.getMaskFilter())->computeFastBounds(pathBounds, &pathBounds);
// Need to outset the path to work-around a bug in blurmaskfilter. When that is fixed
// we can remove this hack. See skbug.com/5542
@@ -984,7 +985,7 @@ void SkDraw::drawDevPath(const SkPath& devPath, const SkPaint& paint, bool drawC
if (paint.getMaskFilter()) {
SkStrokeRec::InitStyle style = doFill ? SkStrokeRec::kFill_InitStyle
: SkStrokeRec::kHairline_InitStyle;
- if (paint.getMaskFilter()->filterPath(devPath, *fMatrix, *fRC, blitter, style)) {
+ if (as_MFB(paint.getMaskFilter())->filterPath(devPath, *fMatrix, *fRC, blitter, style)) {
return; // filterPath() called the blitter, so we're done
}
}
@@ -1659,7 +1660,7 @@ static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
srcM.fBounds = *bounds;
srcM.fFormat = SkMask::kA8_Format;
- if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
+ if (!as_MFB(filter)->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
return false;
}
}
diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp
index 75d29e12a8..64767e7efa 100644
--- a/src/core/SkMaskFilter.cpp
+++ b/src/core/SkMaskFilter.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkAutoMalloc.h"
#include "SkBlitter.h"
@@ -20,7 +20,7 @@
#include "GrFragmentProcessor.h"
#endif
-SkMaskFilter::NinePatch::~NinePatch() {
+SkMaskFilterBase::NinePatch::~NinePatch() {
if (fCache) {
SkASSERT((const void*)fMask.fImage == fCache->data());
fCache->unref();
@@ -29,12 +29,12 @@ SkMaskFilter::NinePatch::~NinePatch() {
}
}
-bool SkMaskFilter::filterMask(SkMask*, const SkMask&, const SkMatrix&,
+bool SkMaskFilterBase::filterMask(SkMask*, const SkMask&, const SkMatrix&,
SkIPoint*) const {
return false;
}
-bool SkMaskFilter::asABlur(BlurRec*) const {
+bool SkMaskFilterBase::asABlur(BlurRec*) const {
return false;
}
@@ -213,8 +213,8 @@ static int countNestedRects(const SkPath& path, SkRect rects[2]) {
return path.isRect(&rects[0]);
}
-bool SkMaskFilter::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix,
- const SkRasterClip& clip, SkBlitter* blitter) const {
+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.
@@ -230,9 +230,9 @@ bool SkMaskFilter::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix,
return true;
}
-bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
- const SkRasterClip& clip, SkBlitter* blitter,
- SkStrokeRec::InitStyle style) const {
+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) {
@@ -289,20 +289,21 @@ bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
return true;
}
-SkMaskFilter::FilterReturn
-SkMaskFilter::filterRRectToNine(const SkRRect&, const SkMatrix&,
- const SkIRect& clipBounds, NinePatch*) const {
+SkMaskFilterBase::FilterReturn
+SkMaskFilterBase::filterRRectToNine(const SkRRect&, const SkMatrix&,
+ const SkIRect& clipBounds, NinePatch*) const {
return kUnimplemented_FilterReturn;
}
-SkMaskFilter::FilterReturn
-SkMaskFilter::filterRectsToNine(const SkRect[], int count, const SkMatrix&,
- const SkIRect& clipBounds, NinePatch*) const {
+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> SkMaskFilter::asFragmentProcessor(const GrFPArgs& args) const {
+std::unique_ptr<GrFragmentProcessor>
+SkMaskFilterBase::asFragmentProcessor(const GrFPArgs& args) const {
SkASSERT(args.fLocalMatrix == nullptr);
auto fp = this->onAsFragmentProcessor(args);
if (fp) {
@@ -312,52 +313,53 @@ std::unique_ptr<GrFragmentProcessor> SkMaskFilter::asFragmentProcessor(const GrF
}
return fp;
}
-bool SkMaskFilter::hasFragmentProcessor() const {
+bool SkMaskFilterBase::hasFragmentProcessor() const {
return this->onHasFragmentProcessor();
}
-std::unique_ptr<GrFragmentProcessor> SkMaskFilter::onAsFragmentProcessor(const GrFPArgs&) const {
+std::unique_ptr<GrFragmentProcessor>
+SkMaskFilterBase::onAsFragmentProcessor(const GrFPArgs&) const {
return nullptr;
}
-bool SkMaskFilter::onHasFragmentProcessor() const { return false; }
+bool SkMaskFilterBase::onHasFragmentProcessor() const { return false; }
-bool SkMaskFilter::canFilterMaskGPU(const SkRRect& devRRect,
- const SkIRect& clipBounds,
- const SkMatrix& ctm,
- SkRect* maskRect) const {
+bool SkMaskFilterBase::canFilterMaskGPU(const SkRRect& devRRect,
+ const SkIRect& clipBounds,
+ const SkMatrix& ctm,
+ SkRect* maskRect) const {
return false;
}
-bool SkMaskFilter::directFilterMaskGPU(GrContext*,
- GrRenderTargetContext* renderTargetContext,
- GrPaint&&,
- const GrClip&,
- const SkMatrix& viewMatrix,
- const SkStrokeRec& strokeRec,
- const SkPath& path) const {
+bool SkMaskFilterBase::directFilterMaskGPU(GrContext*,
+ GrRenderTargetContext* renderTargetContext,
+ GrPaint&&,
+ const GrClip&,
+ const SkMatrix& viewMatrix,
+ const SkStrokeRec& strokeRec,
+ const SkPath& path) const {
return false;
}
-bool SkMaskFilter::directFilterRRectMaskGPU(GrContext*,
- GrRenderTargetContext* renderTargetContext,
- GrPaint&&,
- const GrClip&,
- const SkMatrix& viewMatrix,
- const SkStrokeRec& strokeRec,
- const SkRRect& rrect,
- const SkRRect& devRRect) const {
+bool SkMaskFilterBase::directFilterRRectMaskGPU(GrContext*,
+ GrRenderTargetContext* renderTargetContext,
+ GrPaint&&,
+ const GrClip&,
+ const SkMatrix& viewMatrix,
+ const SkStrokeRec& strokeRec,
+ const SkRRect& rrect,
+ const SkRRect& devRRect) const {
return false;
}
-sk_sp<GrTextureProxy> SkMaskFilter::filterMaskGPU(GrContext*,
- sk_sp<GrTextureProxy> srcProxy,
- const SkMatrix& ctm,
- const SkIRect& maskRect) const {
+sk_sp<GrTextureProxy> SkMaskFilterBase::filterMaskGPU(GrContext*,
+ sk_sp<GrTextureProxy> srcProxy,
+ const SkMatrix& ctm,
+ const SkIRect& maskRect) const {
return nullptr;
}
#endif
-void SkMaskFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
+void SkMaskFilterBase::computeFastBounds(const SkRect& src, SkRect* dst) const {
SkMask srcM, dstM;
srcM.fBounds = src.roundOut();
diff --git a/src/core/SkMaskFilterBase.h b/src/core/SkMaskFilterBase.h
new file mode 100644
index 0000000000..4b4b4258d6
--- /dev/null
+++ b/src/core/SkMaskFilterBase.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMaskFilterBase_DEFINED
+#define SkMaskFilterBase_DEFINED
+
+#include "SkBlurTypes.h"
+#include "SkFlattenable.h"
+#include "SkMask.h"
+#include "SkMaskFilter.h"
+#include "SkPaint.h"
+#include "SkStrokeRec.h"
+
+class GrClip;
+class GrContext;
+struct GrFPArgs;
+class GrRenderTargetContext;
+class GrPaint;
+class GrFragmentProcessor;
+class GrRenderTarget;
+class GrResourceProvider;
+class GrTexture;
+class GrTextureProxy;
+class SkBitmap;
+class SkBlitter;
+class SkCachedData;
+class SkMatrix;
+class SkPath;
+class SkRasterClip;
+class SkRRect;
+
+class SkMaskFilterBase : public SkMaskFilter {
+public:
+ /** Returns the format of the resulting mask that this subclass will return
+ when its filterMask() method is called.
+ */
+ virtual SkMask::Format getFormat() const = 0;
+
+ /** Create a new mask by filter the src mask.
+ If src.fImage == null, then do not allocate or create the dst image
+ but do fill out the other fields in dstMask.
+ If you do allocate a dst image, use SkMask::AllocImage()
+ If this returns false, dst mask is ignored.
+ @param dst the result of the filter. If src.fImage == null, dst should not allocate its image
+ @param src the original image to be filtered.
+ @param matrix the CTM
+ @param margin if not null, return the buffer dx/dy need when calculating the effect. Used when
+ drawing a clipped object to know how much larger to allocate the src before
+ applying the filter. If returning false, ignore this parameter.
+ @return true if the dst mask was correctly created.
+ */
+ virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
+ SkIPoint* margin) const;
+
+#if SK_SUPPORT_GPU
+ /**
+ * Returns a processor if the filter can be expressed a single-pass GrProcessor without
+ * requiring an explicit input mask. Per-pixel, the effect receives the incoming mask's
+ * coverage as the input color and outputs the filtered covereage value. This means that each
+ * pixel's filtered coverage must only depend on the unfiltered mask value for that pixel and
+ * not on surrounding values.
+ */
+ std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs& args) const;
+
+ /**
+ * Returns true iff asFragmentProcessor() will return a processor
+ */
+ bool hasFragmentProcessor() const;
+
+ /**
+ * If asFragmentProcessor() fails the filter may be implemented on the GPU by a subclass
+ * overriding filterMaskGPU (declared below). That code path requires constructing a
+ * src mask as input. Since that is a potentially expensive operation, the subclass must also
+ * override this function to indicate whether filterTextureMaskGPU would succeeed if the mask
+ * were to be created.
+ *
+ * 'maskRect' returns the device space portion of the mask that the filter needs. The mask
+ * passed into 'filterMaskGPU' should have the same extent as 'maskRect' but be
+ * translated to the upper-left corner of the mask (i.e., (maskRect.fLeft, maskRect.fTop)
+ * appears at (0, 0) in the mask).
+ *
+ * Logically, how this works is:
+ * canFilterMaskGPU is called
+ * if (it returns true)
+ * the returned mask rect is used for quick rejecting
+ * either directFilterMaskGPU or directFilterRRectMaskGPU is then called
+ * if (neither of them handle the blur)
+ * the mask rect is used to generate the mask
+ * filterMaskGPU is called to filter the mask
+ *
+ * TODO: this should work as:
+ * if (canFilterMaskGPU(devShape, ...)) // rect, rrect, drrect, path
+ * filterMaskGPU(devShape, ...)
+ * this would hide the RRect special case and the mask generation
+ */
+ virtual bool canFilterMaskGPU(const SkRRect& devRRect,
+ const SkIRect& clipBounds,
+ const SkMatrix& ctm,
+ SkRect* maskRect) const;
+
+ /**
+ * Try to directly render the mask filter into the target. Returns true if drawing was
+ * successful. If false is returned then paint is unmodified.
+ */
+ virtual bool directFilterMaskGPU(GrContext*,
+ GrRenderTargetContext* renderTargetContext,
+ GrPaint&& paint,
+ const GrClip&,
+ const SkMatrix& viewMatrix,
+ const SkStrokeRec& strokeRec,
+ const SkPath& path) const;
+ /**
+ * Try to directly render a rounded rect mask filter into the target. Returns
+ * true if drawing was successful. If false is returned then paint is unmodified.
+ */
+ virtual bool directFilterRRectMaskGPU(GrContext*,
+ GrRenderTargetContext* renderTargetContext,
+ GrPaint&& paint,
+ const GrClip&,
+ const SkMatrix& viewMatrix,
+ const SkStrokeRec& strokeRec,
+ const SkRRect& rrect,
+ const SkRRect& devRRect) const;
+
+ /**
+ * This function is used to implement filters that require an explicit src mask. It should only
+ * be called if canFilterMaskGPU returned true and the maskRect param should be the output from
+ * that call.
+ * Implementations are free to get the GrContext from the src texture in order to create
+ * additional textures and perform multiple passes.
+ */
+ virtual sk_sp<GrTextureProxy> filterMaskGPU(GrContext*,
+ sk_sp<GrTextureProxy> srcProxy,
+ const SkMatrix& ctm,
+ const SkIRect& maskRect) const;
+#endif
+
+ /**
+ * The fast bounds function is used to enable the paint to be culled early
+ * in the drawing pipeline. This function accepts the current bounds of the
+ * paint as its src param and the filter adjust those bounds using its
+ * current mask and returns the result using the dest param. Callers are
+ * allowed to provide the same struct for both src and dest so each
+ * implementation must accomodate that behavior.
+ *
+ * The default impl calls filterMask with the src mask having no image,
+ * but subclasses may override this if they can compute the rect faster.
+ */
+ virtual void computeFastBounds(const SkRect& src, SkRect* dest) const;
+
+ struct BlurRec {
+ SkScalar fSigma;
+ SkBlurStyle fStyle;
+ SkBlurQuality fQuality;
+ };
+ /**
+ * If this filter can be represented by a BlurRec, return true and (if not null) fill in the
+ * provided BlurRec parameter. If this effect cannot be represented as a BlurRec, return false
+ * and ignore the BlurRec parameter.
+ */
+ virtual bool asABlur(BlurRec*) const;
+
+protected:
+ SkMaskFilterBase() {}
+
+#if SK_SUPPORT_GPU
+ virtual std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs&) const;
+ virtual bool onHasFragmentProcessor() const;
+#endif
+
+ enum FilterReturn {
+ kFalse_FilterReturn,
+ kTrue_FilterReturn,
+ kUnimplemented_FilterReturn
+ };
+
+ class NinePatch : ::SkNoncopyable {
+ public:
+ NinePatch() : fCache(nullptr) { }
+ ~NinePatch();
+
+ SkMask fMask; // fBounds must have [0,0] in its top-left
+ SkIRect fOuterRect; // width/height must be >= fMask.fBounds'
+ SkIPoint fCenter; // identifies center row/col for stretching
+ SkCachedData* fCache;
+ };
+
+ /**
+ * Override if your subclass can filter a rect, and return the answer as
+ * a ninepatch mask to be stretched over the returned outerRect. On success
+ * return kTrue_FilterReturn. On failure (e.g. out of memory) return
+ * kFalse_FilterReturn. If the normal filterMask() entry-point should be
+ * called (the default) return kUnimplemented_FilterReturn.
+ *
+ * By convention, the caller will take the center rol/col from the returned
+ * mask as the slice it can replicate horizontally and vertically as we
+ * stretch the mask to fit inside outerRect. It is an error for outerRect
+ * to be smaller than the mask's bounds. This would imply that the width
+ * and height of the mask should be odd. This is not required, just that
+ * the caller will call mask.fBounds.centerX() and centerY() to find the
+ * strips that will be replicated.
+ */
+ virtual FilterReturn filterRectsToNine(const SkRect[], int count,
+ const SkMatrix&,
+ const SkIRect& clipBounds,
+ NinePatch*) const;
+ /**
+ * Similar to filterRectsToNine, except it performs the work on a round rect.
+ */
+ virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&,
+ const SkIRect& clipBounds,
+ NinePatch*) const;
+
+private:
+ friend class SkDraw;
+
+ /** Helper method that, given a path in device space, will rasterize it into a kA8_Format mask
+ and then call filterMask(). If this returns true, the specified blitter will be called
+ to render that mask. Returns false if filterMask() returned false.
+ This method is not exported to java.
+ */
+ bool filterPath(const SkPath& devPath, const SkMatrix& ctm, const SkRasterClip&, SkBlitter*,
+ SkStrokeRec::InitStyle) const;
+
+ /** Helper method that, given a roundRect in device space, will rasterize it into a kA8_Format
+ mask and then call filterMask(). If this returns true, the specified blitter will be called
+ to render that mask. Returns false if filterMask() returned false.
+ */
+ bool filterRRect(const SkRRect& devRRect, const SkMatrix& ctm, const SkRasterClip&,
+ SkBlitter*) const;
+
+ typedef SkFlattenable INHERITED;
+};
+
+inline SkMaskFilterBase* as_MFB(SkMaskFilter* mf) {
+ return static_cast<SkMaskFilterBase*>(mf);
+}
+
+inline const SkMaskFilterBase* as_MFB(const SkMaskFilter* mf) {
+ return static_cast<const SkMaskFilterBase*>(mf);
+}
+
+inline const SkMaskFilterBase* as_MFB(const sk_sp<SkMaskFilter>& mf) {
+ return static_cast<SkMaskFilterBase*>(mf.get());
+}
+
+#endif
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 3cfa690b1e..0686c3b017 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1967,7 +1967,7 @@ const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
*storage = src->makeOutset(radius, radius);
if (this->getMaskFilter()) {
- this->getMaskFilter()->computeFastBounds(*storage, storage);
+ as_MFB(this->getMaskFilter())->computeFastBounds(*storage, storage);
}
if (this->getImageFilter()) {
@@ -2034,7 +2034,7 @@ void SkPaint::toString(SkString* str) const {
SkMaskFilter* maskFilter = this->getMaskFilter();
if (maskFilter) {
str->append("<dt>MaskFilter:</dt><dd>");
- maskFilter->toString(str);
+ as_MFB(maskFilter)->toString(str);
str->append("</dd>");
}
diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h
index 34c3c50fa3..4e0453a7aa 100644
--- a/src/core/SkReadBuffer.h
+++ b/src/core/SkReadBuffer.h
@@ -13,7 +13,7 @@
#include "SkSerialProcs.h"
#include "SkDrawLooper.h"
#include "SkImageFilter.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkPath.h"
#include "SkPathEffect.h"
#include "SkPicture.h"
@@ -143,7 +143,7 @@ public:
sk_sp<SkColorFilter> readColorFilter() { return this->readFlattenable<SkColorFilter>(); }
sk_sp<SkDrawLooper> readDrawLooper() { return this->readFlattenable<SkDrawLooper>(); }
sk_sp<SkImageFilter> readImageFilter() { return this->readFlattenable<SkImageFilter>(); }
- sk_sp<SkMaskFilter> readMaskFilter() { return this->readFlattenable<SkMaskFilter>(); }
+ sk_sp<SkMaskFilter> readMaskFilter() { return this->readFlattenable<SkMaskFilterBase>(); }
sk_sp<SkPathEffect> readPathEffect() { return this->readFlattenable<SkPathEffect>(); }
sk_sp<SkShader> readShader() { return this->readFlattenable<SkShaderBase>(); }
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index fafaf367eb..d082232986 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -175,7 +175,7 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) {
fRec.getMatrixFrom2x2(&matrix);
src.fImage = nullptr; // only want the bounds from the filter
- if (fMaskFilter->filterMask(&dst, src, matrix, nullptr)) {
+ if (as_MFB(fMaskFilter)->filterMask(&dst, src, matrix, nullptr)) {
if (dst.fBounds.isEmpty() || !dst.fBounds.is16Bit()) {
goto SK_ERROR;
}
@@ -504,7 +504,7 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
fRec.getMatrixFrom2x2(&matrix);
- if (fMaskFilter->filterMask(&dstM, srcM, matrix, nullptr)) {
+ if (as_MFB(fMaskFilter)->filterMask(&dstM, srcM, matrix, nullptr)) {
int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
int dstRB = origGlyph.rowBytes();
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index 0d67b4a18f..d730d62d14 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -8,6 +8,7 @@
#include "SkBlurMaskFilter.h"
#include "SkBlurMask.h"
#include "SkGpuBlurUtils.h"
+#include "SkMaskFilterBase.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkMaskFilter.h"
@@ -40,7 +41,7 @@ SkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) {
return SkBlurMask::ConvertRadiusToSigma(radius);
}
-class SkBlurMaskFilterImpl : public SkMaskFilter {
+class SkBlurMaskFilterImpl : public SkMaskFilterBase {
public:
SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, const SkRect& occluder, uint32_t flags);
@@ -459,7 +460,7 @@ static SkCachedData* add_cached_rects(SkMask* mask, SkScalar sigma, SkBlurStyle
static const bool c_analyticBlurRRect{true};
#endif
-SkMaskFilter::FilterReturn
+SkMaskFilterBase::FilterReturn
SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& matrix,
const SkIRect& clipBounds,
NinePatch* patch) const {
@@ -596,7 +597,7 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
// Use the faster analytic blur approach for ninepatch rects
static const bool c_analyticBlurNinepatch{true};
-SkMaskFilter::FilterReturn
+SkMaskFilterBase::FilterReturn
SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
const SkMatrix& matrix,
const SkIRect& clipBounds,
diff --git a/src/effects/SkEmbossMaskFilter.h b/src/effects/SkEmbossMaskFilter.h
index 29b70ad1f9..89bb5c8921 100644
--- a/src/effects/SkEmbossMaskFilter.h
+++ b/src/effects/SkEmbossMaskFilter.h
@@ -8,13 +8,13 @@
#ifndef SkEmbossMaskFilter_DEFINED
#define SkEmbossMaskFilter_DEFINED
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
/** \class SkEmbossMaskFilter
This mask filter creates a 3D emboss look, by specifying a light and blur amount.
*/
-class SK_API SkEmbossMaskFilter : public SkMaskFilter {
+class SK_API SkEmbossMaskFilter : public SkMaskFilterBase {
public:
struct Light {
SkScalar fDirection[3]; // x,y,z
diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp
index 7dff657c52..17aa7a123d 100644
--- a/src/effects/SkLayerDrawLooper.cpp
+++ b/src/effects/SkLayerDrawLooper.cpp
@@ -10,6 +10,7 @@
#include "SkCanvas.h"
#include "SkColorSpaceXformer.h"
#include "SkColor.h"
+#include "SkMaskFilterBase.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkLayerDrawLooper.h"
@@ -181,8 +182,8 @@ bool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const {
if (nullptr == mf) {
return false;
}
- SkMaskFilter::BlurRec maskBlur;
- if (!mf->asABlur(&maskBlur)) {
+ SkMaskFilterBase::BlurRec maskBlur;
+ if (!as_MFB(mf)->asABlur(&maskBlur)) {
return false;
}
diff --git a/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp b/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp
index 09739c0813..850e440099 100644
--- a/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp
+++ b/src/effects/SkRRectsGaussianEdgeMaskFilter.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "SkMaskFilterBase.h"
#include "SkRRectsGaussianEdgeMaskFilter.h"
#include "SkReadBuffer.h"
#include "SkRRect.h"
@@ -19,7 +20,7 @@
* The round rects must have the same radii at each corner and the x&y radii
* must also be equal.
*/
-class SkRRectsGaussianEdgeMaskFilterImpl : public SkMaskFilter {
+class SkRRectsGaussianEdgeMaskFilterImpl : public SkMaskFilterBase {
public:
SkRRectsGaussianEdgeMaskFilterImpl(const SkRRect& first, const SkRRect& second,
SkScalar radius)
diff --git a/src/effects/SkShaderMaskFilter.cpp b/src/effects/SkShaderMaskFilter.cpp
index 8693751899..f2088fce72 100644
--- a/src/effects/SkShaderMaskFilter.cpp
+++ b/src/effects/SkShaderMaskFilter.cpp
@@ -6,12 +6,13 @@
*/
#include "SkCanvas.h"
+#include "SkMaskFilterBase.h"
#include "SkReadBuffer.h"
#include "SkShaderMaskFilter.h"
#include "SkShader.h"
#include "SkString.h"
-class SkShaderMF : public SkMaskFilter {
+class SkShaderMF : public SkMaskFilterBase {
public:
SkShaderMF(sk_sp<SkShader> shader) : fShader(std::move(shader)) {}
diff --git a/src/effects/SkTableMaskFilter.cpp b/src/effects/SkTableMaskFilter.cpp
index a3b4038a2f..5006f04cb0 100644
--- a/src/effects/SkTableMaskFilter.cpp
+++ b/src/effects/SkTableMaskFilter.cpp
@@ -5,26 +5,48 @@
* found in the LICENSE file.
*/
-
#include "SkFixed.h"
#include "SkReadBuffer.h"
#include "SkString.h"
#include "SkTableMaskFilter.h"
#include "SkWriteBuffer.h"
-SkTableMaskFilter::SkTableMaskFilter() {
+class SkTableMaskFilterImpl : public SkMaskFilterBase {
+public:
+ explicit SkTableMaskFilterImpl(const uint8_t table[256]);
+
+ SkMask::Format getFormat() const override;
+ bool filterMask(SkMask*, const SkMask&, const SkMatrix&, SkIPoint*) const override;
+
+ SK_TO_STRING_OVERRIDE()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTableMaskFilterImpl)
+
+protected:
+ ~SkTableMaskFilterImpl() override;
+
+ void flatten(SkWriteBuffer&) const override;
+
+private:
+ SkTableMaskFilterImpl();
+
+ uint8_t fTable[256];
+
+ typedef SkMaskFilter INHERITED;
+};
+
+SkTableMaskFilterImpl::SkTableMaskFilterImpl() {
for (int i = 0; i < 256; i++) {
fTable[i] = i;
}
}
-SkTableMaskFilter::SkTableMaskFilter(const uint8_t table[256]) {
+SkTableMaskFilterImpl::SkTableMaskFilterImpl(const uint8_t table[256]) {
memcpy(fTable, table, sizeof(fTable));
}
-SkTableMaskFilter::~SkTableMaskFilter() {}
+SkTableMaskFilterImpl::~SkTableMaskFilterImpl() {}
-bool SkTableMaskFilter::filterMask(SkMask* dst, const SkMask& src,
+bool SkTableMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
const SkMatrix&, SkIPoint* margin) const {
if (src.fFormat != SkMask::kA8_Format) {
return false;
@@ -66,24 +88,40 @@ bool SkTableMaskFilter::filterMask(SkMask* dst, const SkMask& src,
return true;
}
-SkMask::Format SkTableMaskFilter::getFormat() const {
+SkMask::Format SkTableMaskFilterImpl::getFormat() const {
return SkMask::kA8_Format;
}
-void SkTableMaskFilter::flatten(SkWriteBuffer& wb) const {
+void SkTableMaskFilterImpl::flatten(SkWriteBuffer& wb) const {
wb.writeByteArray(fTable, 256);
}
-sk_sp<SkFlattenable> SkTableMaskFilter::CreateProc(SkReadBuffer& buffer) {
+sk_sp<SkFlattenable> SkTableMaskFilterImpl::CreateProc(SkReadBuffer& buffer) {
uint8_t table[256];
if (!buffer.readByteArray(table, 256)) {
return nullptr;
}
- return sk_sp<SkFlattenable>(Create(table));
+ return sk_sp<SkFlattenable>(SkTableMaskFilter::Create(table));
}
///////////////////////////////////////////////////////////////////////////////
+SkMaskFilter* SkTableMaskFilter::Create(const uint8_t table[256]) {
+ return new SkTableMaskFilterImpl(table);
+}
+
+SkMaskFilter* SkTableMaskFilter::CreateGamma(SkScalar gamma) {
+ uint8_t table[256];
+ MakeGammaTable(table, gamma);
+ return new SkTableMaskFilterImpl(table);
+}
+
+SkMaskFilter* SkTableMaskFilter::CreateClip(uint8_t min, uint8_t max) {
+ uint8_t table[256];
+ MakeClipTable(table, min, max);
+ return new SkTableMaskFilterImpl(table);
+}
+
void SkTableMaskFilter::MakeGammaTable(uint8_t table[256], SkScalar gamma) {
const float dx = 1 / 255.0f;
const float g = SkScalarToFloat(gamma);
@@ -131,7 +169,7 @@ void SkTableMaskFilter::MakeClipTable(uint8_t table[256], uint8_t min,
}
#ifndef SK_IGNORE_TO_STRING
-void SkTableMaskFilter::toString(SkString* str) const {
+void SkTableMaskFilterImpl::toString(SkString* str) const {
str->append("SkTableMaskFilter: (");
str->append("table: ");
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index aff3647f6c..b79a38a884 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -17,7 +17,7 @@
#include "GrTextureProxy.h"
#include "SkDraw.h"
#include "SkGr.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkPaint.h"
#include "SkTLazy.h"
@@ -65,7 +65,7 @@ static bool sw_draw_with_mask_filter(GrContext* context,
}
SkAutoMaskFreeImage autoSrc(srcM.fImage);
- if (!filter->filterMask(&dstM, srcM, viewMatrix, nullptr)) {
+ if (!as_MFB(filter)->filterMask(&dstM, srcM, viewMatrix, nullptr)) {
return false;
}
// this will free-up dstM when we're done (allocated in filterMask())
@@ -144,7 +144,7 @@ static void draw_path_with_mask_filter(GrContext* context,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
- const SkMaskFilter* maskFilter,
+ const SkMaskFilterBase* maskFilter,
const GrStyle& style,
const SkPath* path,
bool pathIsMutable) {
@@ -252,7 +252,7 @@ void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
const GrStyle& style,
bool pathIsMutable) {
draw_path_with_mask_filter(context, renderTargetContext, clip, std::move(paint), aa, viewMatrix,
- mf, style, &path, pathIsMutable);
+ as_MFB(mf), style, &path, pathIsMutable);
}
void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
@@ -297,7 +297,7 @@ void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
return;
}
GrAA aa = GrAA(paint.isAntiAlias());
- SkMaskFilter* mf = paint.getMaskFilter();
+ SkMaskFilterBase* mf = as_MFB(paint.getMaskFilter());
if (mf && !mf->hasFragmentProcessor()) {
// The MaskFilter wasn't already handled in SkPaintToGrPaint
draw_path_with_mask_filter(context, renderTargetContext, clip, std::move(grPaint), aa,
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 3f7dcb41e0..080d993c68 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -28,7 +28,7 @@
#include "SkImageInfoPriv.h"
#include "SkImage_Base.h"
#include "SkLatticeIter.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkPathEffect.h"
#include "SkPicture.h"
#include "SkPictureData.h"
@@ -402,7 +402,7 @@ void SkGpuDevice::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
return;
}
- SkMaskFilter* mf = paint.getMaskFilter();
+ SkMaskFilterBase* mf = as_MFB(paint.getMaskFilter());
if (mf) {
if (mf->hasFragmentProcessor()) {
mf = nullptr; // already handled in SkPaintToGrPaint
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index 9e980cddb5..0798f1e012 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -15,7 +15,7 @@
#include "GrTextureMaker.h"
#include "SkDraw.h"
#include "SkGr.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "effects/GrBicubicEffect.h"
#include "effects/GrSimpleTextureEffect.h"
#include "effects/GrTextureDomain.h"
@@ -323,14 +323,14 @@ void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer,
viewMatrix.mapRectScaleTranslate(&devClippedDstRect, clippedDstRect);
SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
- if (mf->directFilterRRectMaskGPU(fContext.get(),
- fRenderTargetContext.get(),
- std::move(grPaint),
- this->clip(),
- viewMatrix,
- rec,
- SkRRect::MakeRect(clippedDstRect),
- SkRRect::MakeRect(devClippedDstRect))) {
+ if (as_MFB(mf)->directFilterRRectMaskGPU(fContext.get(),
+ fRenderTargetContext.get(),
+ std::move(grPaint),
+ this->clip(),
+ viewMatrix,
+ rec,
+ SkRRect::MakeRect(clippedDstRect),
+ SkRRect::MakeRect(devClippedDstRect))) {
return;
}
}
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 6b1c779ff8..4d3ce4752a 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -24,7 +24,7 @@
#include "SkConvertPixels.h"
#include "SkData.h"
#include "SkImageInfoPriv.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkMessageBus.h"
#include "SkMipMap.h"
#include "SkPM4fPriv.h"
@@ -477,7 +477,7 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context,
}
}
- SkMaskFilter* maskFilter = skPaint.getMaskFilter();
+ SkMaskFilterBase* maskFilter = as_MFB(skPaint.getMaskFilter());
if (maskFilter) {
if (auto mfFP = maskFilter->asFragmentProcessor(fpArgs)) {
grPaint->addCoverageFragmentProcessor(std::move(mfFP));
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index 69e5e775be..7fce4ba856 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -13,6 +13,7 @@
#include "SkColorFilter.h"
#include "SkDrawFilter.h"
#include "SkGlyphCache.h"
+#include "SkMaskFilterBase.h"
#include "SkTextBlobRunIterator.h"
#include "ops/GrAtlasTextOp.h"
@@ -152,7 +153,7 @@ void GrAtlasTextBlob::appendBigGlyph(GrGlyph* glyph, SkGlyphCache* cache, const
}
bool GrAtlasTextBlob::mustRegenerate(const GrTextUtils::Paint& paint,
- const SkMaskFilter::BlurRec& blurRec,
+ const SkMaskFilterBase::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
// If we have LCD text then our canonical color will be set to transparent, in this case we have
// to regenerate the blob on any color change
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index 94ec54a775..12a80c49d3 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -14,7 +14,7 @@
#include "GrMemoryPool.h"
#include "GrTextUtils.h"
#include "SkDescriptor.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkOpts.h"
#include "SkPathEffect.h"
#include "SkPoint3.h"
@@ -81,7 +81,7 @@ public:
};
void setupKey(const GrAtlasTextBlob::Key& key,
- const SkMaskFilter::BlurRec& blurRec,
+ const SkMaskFilterBase::BlurRec& blurRec,
const SkPaint& paint) {
fKey = key;
if (key.fHasBlur) {
@@ -190,7 +190,7 @@ public:
}
}
- bool mustRegenerate(const GrTextUtils::Paint&, const SkMaskFilter::BlurRec& blurRec,
+ bool mustRegenerate(const GrTextUtils::Paint&, const SkMaskFilterBase::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
// flush a GrAtlasTextBlob associated with a SkTextBlob
@@ -536,7 +536,7 @@ private:
GrGlyph** fGlyphs;
Run* fRuns;
GrMemoryPool* fPool;
- SkMaskFilter::BlurRec fBlurRec;
+ SkMaskFilterBase::BlurRec fBlurRec;
StrokeInfo fStrokeInfo;
SkTArray<BigGlyph> fBigGlyphs;
Key fKey;
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 4193c7d32c..41c46466ac 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -15,6 +15,7 @@
#include "SkGr.h"
#include "SkGraphics.h"
#include "SkMakeUnique.h"
+#include "SkMaskFilterBase.h"
#include "ops/GrMeshDrawOp.h"
// DF sizes and thresholds for usage of the small and medium sizes. For example, above
@@ -113,13 +114,13 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t
}
sk_sp<GrAtlasTextBlob> cacheBlob;
- SkMaskFilter::BlurRec blurRec;
+ SkMaskFilterBase::BlurRec blurRec;
GrAtlasTextBlob::Key key;
// It might be worth caching these things, but its not clear at this time
// TODO for animated mask filters, this will fill up our cache. We need a safeguard here
const SkMaskFilter* mf = skPaint.getMaskFilter();
bool canCache = !(skPaint.getPathEffect() ||
- (mf && !mf->asABlur(&blurRec)) ||
+ (mf && !as_MFB(mf)->asABlur(&blurRec)) ||
drawFilter);
SkScalerContextFlags scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo());
diff --git a/src/gpu/text/GrTextBlobCache.h b/src/gpu/text/GrTextBlobCache.h
index ac15124937..7a5c3a8c28 100644
--- a/src/gpu/text/GrTextBlobCache.h
+++ b/src/gpu/text/GrTextBlobCache.h
@@ -48,7 +48,7 @@ public:
sk_sp<GrAtlasTextBlob> makeCachedBlob(const SkTextBlob* blob,
const GrAtlasTextBlob::Key& key,
- const SkMaskFilter::BlurRec& blurRec,
+ const SkMaskFilterBase::BlurRec& blurRec,
const SkPaint& paint) {
sk_sp<GrAtlasTextBlob> cacheBlob(this->makeBlob(blob));
cacheBlob->setupKey(key, blurRec, paint);
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 0628b8f905..91f170d194 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -21,7 +21,7 @@
#include "SkImageFilterCache.h"
#include "SkJpegEncoder.h"
#include "SkMakeUnique.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkPDFBitmap.h"
#include "SkPDFCanon.h"
#include "SkPDFDocument.h"
@@ -841,7 +841,7 @@ void SkPDFDevice::internalDrawPathWithFilter(const SkClipStack& clipStack,
SkAutoMaskFreeImage srcAutoMaskFreeImage(sourceMask.fImage);
SkMask dstMask;
SkIPoint margin;
- if (!paint->getMaskFilter()->filterMask(&dstMask, sourceMask, ctm, &margin)) {
+ if (!as_MFB(paint->getMaskFilter())->filterMask(&dstMask, sourceMask, ctm, &margin)) {
return;
}
SkIRect dstMaskBounds = dstMask.fBounds;
diff --git a/src/xps/SkXPSDevice.cpp b/src/xps/SkXPSDevice.cpp
index dcf88aac00..94c6b79c32 100644
--- a/src/xps/SkXPSDevice.cpp
+++ b/src/xps/SkXPSDevice.cpp
@@ -34,7 +34,7 @@
#include "SkImage.h"
#include "SkImageEncoder.h"
#include "SkImagePriv.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkPaint.h"
#include "SkPathEffect.h"
#include "SkPathOps.h"
@@ -1615,7 +1615,7 @@ void SkXPSDevice::drawPath(const SkPath& platonicPath,
//[Mask -> Mask]
SkMask filteredMask;
- if (filter->filterMask(&filteredMask, rasteredMask, matrix, nullptr)) {
+ if (as_MFB(filter)->filterMask(&filteredMask, rasteredMask, matrix, nullptr)) {
mask = &filteredMask;
}
SkAutoMaskFreeImage filteredAmi(filteredMask.fImage);
diff --git a/tests/BlurTest.cpp b/tests/BlurTest.cpp
index 6c5ef269d7..d8d917fe8f 100644
--- a/tests/BlurTest.cpp
+++ b/tests/BlurTest.cpp
@@ -12,6 +12,7 @@
#include "SkColorFilter.h"
#include "SkEmbossMaskFilter.h"
#include "SkLayerDrawLooper.h"
+#include "SkMaskFilterBase.h"
#include "SkMath.h"
#include "SkPaint.h"
#include "SkPath.h"
@@ -456,8 +457,8 @@ DEF_TEST(BlurAsABlur, reporter) {
REPORTER_ASSERT(reporter, sigma <= 0);
} else {
REPORTER_ASSERT(reporter, sigma > 0);
- SkMaskFilter::BlurRec rec;
- bool success = mf->asABlur(&rec);
+ SkMaskFilterBase::BlurRec rec;
+ bool success = as_MFB(mf)->asABlur(&rec);
if (flags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
REPORTER_ASSERT(reporter, !success);
} else {
@@ -483,8 +484,8 @@ DEF_TEST(BlurAsABlur, reporter) {
const SkScalar sigma = sigmas[j];
auto mf(SkEmbossMaskFilter::Make(sigma, light));
if (mf) {
- SkMaskFilter::BlurRec rec;
- bool success = mf->asABlur(&rec);
+ SkMaskFilterBase::BlurRec rec;
+ bool success = as_MFB(mf)->asABlur(&rec);
REPORTER_ASSERT(reporter, !success);
}
}
diff --git a/tests/FlattenDrawableTest.cpp b/tests/FlattenDrawableTest.cpp
index 9df8ba0b5b..411b082dba 100644
--- a/tests/FlattenDrawableTest.cpp
+++ b/tests/FlattenDrawableTest.cpp
@@ -284,3 +284,18 @@ DEF_TEST(FlattenRecordedDrawable, r) {
REPORTER_ASSERT(r, out);
REPORTER_ASSERT(r, !strcmp("SkRecordedDrawable", out->getTypeName()));
}
+
+// be sure these constructs compile, don't assert, and return null
+DEF_TEST(Flattenable_EmptyDeserialze, reporter) {
+ auto data = SkData::MakeEmpty();
+
+ #define test(name) REPORTER_ASSERT(reporter, !name::Deserialize(data->data(), data->size()))
+ test(SkPathEffect);
+ test(SkMaskFilter);
+ test(SkShaderBase); // todo: make this just be shader!
+ test(SkColorFilter);
+ test(SkImageFilter);
+ test(SkDrawLooper);
+ #undef test
+}
+
diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp
index 34189fa6a4..c1f06773d3 100644
--- a/tools/debugger/SkDrawCommand.cpp
+++ b/tools/debugger/SkDrawCommand.cpp
@@ -15,7 +15,7 @@
#include "SkDashPathEffect.h"
#include "SkImageFilter.h"
#include "SkJsonWriteBuffer.h"
-#include "SkMaskFilter.h"
+#include "SkMaskFilterBase.h"
#include "SkObjectParser.h"
#include "SkPaintDefaults.h"
#include "SkPathEffect.h"
@@ -1071,8 +1071,8 @@ static void apply_paint_maskfilter(const SkPaint& paint, Json::Value* target,
UrlDataManager& urlDataManager) {
SkMaskFilter* maskFilter = paint.getMaskFilter();
if (maskFilter != nullptr) {
- SkMaskFilter::BlurRec blurRec;
- if (maskFilter->asABlur(&blurRec)) {
+ SkMaskFilterBase::BlurRec blurRec;
+ if (as_MFB(maskFilter)->asABlur(&blurRec)) {
Json::Value blur(Json::objectValue);
blur[SKDEBUGCANVAS_ATTRIBUTE_SIGMA] = Json::Value(blurRec.fSigma);
switch (blurRec.fStyle) {