xref: /aosp_15_r20/external/skia/src/core/SkMaskFilterBase.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2018 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkMaskFilterBase_DEFINED
9 #define SkMaskFilterBase_DEFINED
10 
11 #include "include/core/SkBlurTypes.h"
12 #include "include/core/SkFlattenable.h"
13 #include "include/core/SkMaskFilter.h"
14 #include "include/core/SkPaint.h"
15 #include "include/core/SkStrokeRec.h"
16 #include "include/private/base/SkNoncopyable.h"
17 #include "src/base/SkTLazy.h"
18 #include "src/core/SkMask.h"
19 
20 class GrClip;
21 struct GrFPArgs;
22 class GrFragmentProcessor;
23 class GrPaint;
24 class GrRecordingContext;
25 class GrRenderTarget;
26 namespace skgpu {
27 namespace ganesh {
28 class SurfaceDrawContext;
29 }
30 }  // namespace skgpu
31 class GrResourceProvider;
32 class GrStyledShape;
33 class GrSurfaceProxyView;
34 class GrTexture;
35 class GrTextureProxy;
36 
37 class SkBitmap;
38 class SkBlitter;
39 class SkCachedData;
40 class SkMatrix;
41 class SkPath;
42 class SkRasterClip;
43 class SkRRect;
44 
45 class SkMaskFilterBase : public SkMaskFilter {
46 public:
47     /** Returns the format of the resulting mask that this subclass will return
48         when its filterMask() method is called.
49     */
50     virtual SkMask::Format getFormat() const = 0;
51 
52     /** Create a new mask by filter the src mask.
53         If src.fImage == null, then do not allocate or create the dst image
54         but do fill out the other fields in dstMask.
55         If you do allocate a dst image, use SkMask::AllocImage()
56         If this returns false, dst mask is ignored.
57         @param  dst the result of the filter. If src.fImage == null, dst should not allocate its image
58         @param src the original image to be filtered.
59         @param matrix the CTM
60         @param margin   if not null, return the buffer dx/dy need when calculating the effect. Used when
61                         drawing a clipped object to know how much larger to allocate the src before
62                         applying the filter. If returning false, ignore this parameter.
63         @return true if the dst mask was correctly created.
64     */
65     virtual bool filterMask(SkMaskBuilder* dst, const SkMask& src, const SkMatrix&,
66                             SkIPoint* margin) const = 0;
67 
68     enum class Type {
69         kBlur,
70         kEmboss,
71         kSDF,
72         kShader,
73         kTable,
74     };
75 
76     virtual Type type() const = 0;
77 
78     /**
79      * The fast bounds function is used to enable the paint to be culled early
80      * in the drawing pipeline. This function accepts the current bounds of the
81      * paint as its src param and the filter adjust those bounds using its
82      * current mask and returns the result using the dest param. Callers are
83      * allowed to provide the same struct for both src and dest so each
84      * implementation must accommodate that behavior.
85      *
86      *  The default impl calls filterMask with the src mask having no image,
87      *  but subclasses may override this if they can compute the rect faster.
88      */
89     virtual void computeFastBounds(const SkRect& src, SkRect* dest) const;
90 
91     struct BlurRec {
92         SkScalar        fSigma;
93         SkBlurStyle     fStyle;
94     };
95     /**
96      *  If this filter can be represented by a BlurRec, return true and (if not null) fill in the
97      *  provided BlurRec parameter. If this effect cannot be represented as a BlurRec, return false
98      *  and ignore the BlurRec parameter.
99      */
100     virtual bool asABlur(BlurRec*) const;
101 
102     /**
103      * Return an SkImageFilter representation of this mask filter that SkCanvas can apply to an
104      * alpha-only image to produce an equivalent effect to running the mask filter directly.
105      */
106     virtual sk_sp<SkImageFilter> asImageFilter(const SkMatrix& ctm) const;
107 
GetFlattenableType()108     static SkFlattenable::Type GetFlattenableType() {
109         return kSkMaskFilter_Type;
110     }
111 
getFlattenableType()112     SkFlattenable::Type getFlattenableType() const override {
113         return kSkMaskFilter_Type;
114     }
115 
116 protected:
SkMaskFilterBase()117     SkMaskFilterBase() {}
118 
119     enum FilterReturn {
120         kFalse_FilterReturn,
121         kTrue_FilterReturn,
122         kUnimplemented_FilterReturn
123     };
124 
125     class NinePatch : ::SkNoncopyable {
126     public:
NinePatch(const SkMask & mask,SkIRect outerRect,SkIPoint center,SkCachedData * cache)127         NinePatch(const SkMask& mask, SkIRect outerRect, SkIPoint center, SkCachedData* cache)
128             : fMask(mask), fOuterRect(outerRect), fCenter(center), fCache(cache) {}
129         ~NinePatch();
130 
131         SkMask      fMask;      // fBounds must have [0,0] in its top-left
132         SkIRect     fOuterRect; // width/height must be >= fMask.fBounds'
133         SkIPoint    fCenter;    // identifies center row/col for stretching
134         SkCachedData* fCache = nullptr;
135     };
136 
137     /**
138      *  Override if your subclass can filter a rect, and return the answer as
139      *  a ninepatch mask to be stretched over the returned outerRect. On success
140      *  return kTrue_FilterReturn. On failure (e.g. out of memory) return
141      *  kFalse_FilterReturn. If the normal filterMask() entry-point should be
142      *  called (the default) return kUnimplemented_FilterReturn.
143      *
144      *  By convention, the caller will take the center rol/col from the returned
145      *  mask as the slice it can replicate horizontally and vertically as we
146      *  stretch the mask to fit inside outerRect. It is an error for outerRect
147      *  to be smaller than the mask's bounds. This would imply that the width
148      *  and height of the mask should be odd. This is not required, just that
149      *  the caller will call mask.fBounds.centerX() and centerY() to find the
150      *  strips that will be replicated.
151      */
152     virtual FilterReturn filterRectsToNine(const SkRect[], int count,
153                                            const SkMatrix&,
154                                            const SkIRect& clipBounds,
155                                            SkTLazy<NinePatch>*) const;
156     /**
157      *  Similar to filterRectsToNine, except it performs the work on a round rect.
158      */
159     virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&,
160                                            const SkIRect& clipBounds,
161                                            SkTLazy<NinePatch>*) const;
162 
163 private:
164     friend class SkDraw;
165     friend class SkDrawBase;
166 
167     /** Helper method that, given a path in device space, will rasterize it into a kA8_Format mask
168      and then call filterMask(). If this returns true, the specified blitter will be called
169      to render that mask. Returns false if filterMask() returned false.
170      This method is not exported to java.
171      */
172     bool filterPath(const SkPath& devPath, const SkMatrix& ctm, const SkRasterClip&, SkBlitter*,
173                     SkStrokeRec::InitStyle) const;
174 
175     /** Helper method that, given a roundRect in device space, will rasterize it into a kA8_Format
176      mask and then call filterMask(). If this returns true, the specified blitter will be called
177      to render that mask. Returns false if filterMask() returned false.
178      */
179     bool filterRRect(const SkRRect& devRRect, const SkMatrix& ctm, const SkRasterClip&,
180                      SkBlitter*) const;
181 
182     using INHERITED = SkFlattenable;
183 };
184 
as_MFB(SkMaskFilter * mf)185 inline SkMaskFilterBase* as_MFB(SkMaskFilter* mf) {
186     return static_cast<SkMaskFilterBase*>(mf);
187 }
188 
as_MFB(const SkMaskFilter * mf)189 inline const SkMaskFilterBase* as_MFB(const SkMaskFilter* mf) {
190     return static_cast<const SkMaskFilterBase*>(mf);
191 }
192 
as_MFB(const sk_sp<SkMaskFilter> & mf)193 inline const SkMaskFilterBase* as_MFB(const sk_sp<SkMaskFilter>& mf) {
194     return static_cast<SkMaskFilterBase*>(mf.get());
195 }
196 
197 // For RegisterFlattenables access to the blur mask filter implementation
198 extern void sk_register_blur_maskfilter_createproc();
199 
200 #endif
201