1 /*
2  * Copyright 2019 Google LLC
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 SkImageFilter_Base_DEFINED
9 #define SkImageFilter_Base_DEFINED
10 
11 #include "include/core/SkColorSpace.h"
12 #include "include/core/SkImageFilter.h"
13 #include "include/core/SkImageInfo.h"
14 #include "include/private/SkTArray.h"
15 
16 #include "src/core/SkImageFilterTypes.h"
17 
18 class GrFragmentProcessor;
19 class GrRecordingContext;
20 
21 // True base class that all SkImageFilter implementations need to extend from. This provides the
22 // actual API surface that Skia will use to compute the filtered images.
23 class SkImageFilter_Base : public SkImageFilter {
24 public:
25     SK_USE_FLUENT_IMAGE_FILTER_TYPES_IN_CLASS
26 
27     // DEPRECATED - Use skif::Context directly.
28     using Context = skif::Context;
29 
30     /**
31      *  Request a new filtered image to be created from the src image. The returned skif::Image
32      *  provides both the pixel data and the origin point that it should be drawn at, relative to
33      *  the layer space defined by the provided context.
34      *
35      *  If the result image cannot be created, or the result would be transparent black, returns
36      *  a skif::Image that has a null special image, in which its origin should be ignored.
37      *
38      *  TODO: Right now the imagefilters sometimes return empty result bitmaps/
39      *        specialimages. That doesn't seem quite right.
40      */
41     skif::FilterResult<For::kOutput> filterImage(const skif::Context& context) const;
42 
43     /**
44      *  Calculate the smallest-possible required layer bounds that would provide sufficient
45      *  information to correctly compute the image filter for every pixel in the desired output
46      *  bounds. The 'desiredOutput' is intended to represent either the root render target bounds,
47      *  or the device-space bounds of the current clip. If the bounds of the content that will be
48      *  drawn into the layer is known, 'knownContentBounds' should be provided, since it can be
49      *  used to restrict the size of the layer if the image filter DAG does not affect transparent
50      *  black.
51      *
52      *  The returned rect is in the layer space defined by 'mapping', so it directly represents
53      *  the size and location of the SkDevice created to rasterize the content prior to invoking the
54      *  image filter (assuming its CTM and basis matrix are configured to match 'mapping').
55      *
56      *  While this operation transforms an device-space output bounds to a layer-space input bounds,
57      *  it is not necessarily the inverse of getOutputBounds(). For instance, a blur needs to have
58      *  an outset margin when reading pixels at the edge (to satisfy its kernel), thus it expands
59      *  its required input rect to include every pixel that contributes to the desired output rect.
60 
61      *  @param mapping       The coordinate space mapping that defines both the transformation
62      *                       between local and layer, and layer to root device space, that will be
63      *                       used when the filter is later invoked.
64      *  @param desiredOutput The desired output boundary that needs to be covered by the filter's
65      *                       output (assuming that the filter is then invoked with a suitable input)
66      *  @param knownContentBounds
67      *                       Optional, the known layer-space bounds of the non-transparent content
68      *                       that would be rasterized in the source input image.
69      *
70      * @return The layer-space bounding box to use for an SkDevice when drawing the source image.
71      */
72     skif::LayerSpace<SkIRect> getInputBounds(
73             const skif::Mapping& mapping, const skif::DeviceSpace<SkRect>& desiredOutput,
74             const skif::ParameterSpace<SkRect>* knownContentBounds) const;
75 
76     /**
77      *  Calculate the device-space bounds of the output of this filter DAG, if it were to process
78      *  an image layer covering the 'contentBounds'. The 'mapping' defines how the content will be
79      *  transformed to layer space when it is drawn, and how the output filter image is then
80      *  transformed to the final device space (i.e. it specifies the mapping between the root device
81      *  space and the parameter space of the initially provided content).
82      *
83      *  While this operation transforms a parameter-space input bounds to an device-space output
84      *  bounds, it is not necessarily the inverse of getInputBounds(). For instance, a blur needs to
85      *  have an outset margin when reading pixels at the edge (to satisfy its kernel), so it will
86      *  generate a result larger than its input (so that the blur is visible) and, thus, expands its
87      *  output to include every pixel that it will touch.
88      *
89      *  @param mapping       The coordinate space mapping that defines both the transformation
90      *                       between local and layer, and layer to root device space, that will be
91      *                       used when the filter is later invoked.
92      *  @param contentBounds The local-space bounds of the non-transparent content that would be
93      *                       drawn into the source image prior to filtering with this DAG,  i.e.
94      *                       the same as 'knownContentBounds' in getInputBounds().
95      *
96      *  @return The root device-space bounding box of the filtered image, were it applied to
97      *          content contained by 'contentBounds' and then drawn with 'mapping' to the root
98      *          device (w/o any additional clipping).
99      */
100     skif::DeviceSpace<SkIRect> getOutputBounds(
101             const skif::Mapping& mapping, const skif::ParameterSpace<SkRect>& contentBounds) const;
102 
103     /**
104      *  Returns whether any edges of the crop rect have been set. The crop
105      *  rect is set at construction time, and determines which pixels from the
106      *  input image will be processed, and which pixels in the output image will be allowed.
107      *  The size of the crop rect should be
108      *  used as the size of the destination image. The origin of this rect
109      *  should be used to offset access to the input images, and should also
110      *  be added to the "offset" parameter in onFilterImage.
111      *
112      *  DEPRECATED - Remove once cropping is handled by a separate filter
113      */
cropRectIsSet()114     bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
115 
116     // DEPRECATED - Remove once cropping is handled by a separate filter
getCropRect()117     CropRect getCropRect() const { return fCropRect; }
118 
119     // Expose isolated node bounds behavior for SampleImageFilterDAG and debugging
filterNodeBounds(const SkIRect & srcRect,const SkMatrix & ctm,MapDirection dir,const SkIRect * inputRect)120     SkIRect filterNodeBounds(const SkIRect& srcRect, const SkMatrix& ctm,
121                              MapDirection dir, const SkIRect* inputRect) const {
122         return this->onFilterNodeBounds(srcRect, ctm, dir, inputRect);
123     }
124 
125     /**
126      *  ImageFilters can natively handle scaling and translate components in the CTM. Only some of
127      *  them can handle affine (or more complex) matrices. This call returns true iff the filter
128      *  and all of its (non-null) inputs can handle these more complex matrices.
129      */
130     bool canHandleComplexCTM() const;
131 
132     /**
133      * Return an image filter representing this filter applied with the given ctm. This will modify
134      * the DAG as needed if this filter does not support complex CTMs and 'ctm' is not simple. The
135      * ctm matrix will be decomposed such that ctm = A*B; B will be incorporated directly into the
136      * DAG and A must be the ctm set on the context passed to filterImage(). 'remainder' will be set
137      * to A.
138      *
139      * If this filter supports complex ctms, or 'ctm' is not complex, then A = ctm and B = I. When
140      * the filter does not support complex ctms, and the ctm is complex, then A represents the
141      * extracted simple portion of the ctm, and the complex portion is baked into a new DAG using a
142      * matrix filter.
143      *
144      * This will never return null.
145      *
146      * DEPRECATED - Should draw the results of filterImage() directly with the remainder matrix.
147      */
148     sk_sp<SkImageFilter> applyCTM(const SkMatrix& ctm, SkMatrix* remainder) const;
149 
uniqueID()150     uint32_t uniqueID() const { return fUniqueID; }
151 
152 protected:
153     class Common {
154     public:
155         /**
156          *  Attempt to unflatten the cropRect and the expected number of input filters.
157          *  If any number of input filters is valid, pass -1.
158          *  If this fails (i.e. corrupt buffer or contents) then return false and common will
159          *  be left uninitialized.
160          *  If this returns true, then inputCount() is the number of found input filters, each
161          *  of which may be NULL or a valid imagefilter.
162          */
163         bool unflatten(SkReadBuffer&, int expectedInputs);
164 
cropRect()165         const CropRect& cropRect() const { return fCropRect; }
inputCount()166         int inputCount() const { return fInputs.count(); }
inputs()167         sk_sp<SkImageFilter>* inputs() { return fInputs.begin(); }
168 
getInput(int index)169         sk_sp<SkImageFilter> getInput(int index) { return fInputs[index]; }
170 
171     private:
172         CropRect fCropRect;
173         // most filters accept at most 2 input-filters
174         SkSTArray<2, sk_sp<SkImageFilter>, true> fInputs;
175     };
176 
177     // Whether or not to recurse to child input filters for certain operations that walk the DAG.
178     enum class VisitChildren : bool {
179         kNo  = false,
180         kYes = true
181     };
182 
183     SkImageFilter_Base(sk_sp<SkImageFilter> const* inputs, int inputCount,
184                        const CropRect* cropRect);
185 
186     ~SkImageFilter_Base() override;
187 
188     void flatten(SkWriteBuffer&) const override;
189 
190     // DEPRECATED - Use the private context-only variant
191     virtual sk_sp<SkSpecialImage> onFilterImage(const Context&, SkIPoint* offset) const = 0;
192 
193     // DEPRECATED - Override onGetOutputLayerBounds and onGetInputLayerBounds instead. The
194     // node-specific and aggregation functions are no longer separated in the current API. A helper
195     // function is provided to do the default recursion for the common filter case.
196     virtual SkIRect onFilterBounds(const SkIRect&, const SkMatrix& ctm,
197                                    MapDirection, const SkIRect* inputRect) const;
198     virtual SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,
199                                        MapDirection, const SkIRect* inputRect) const;
200 
201     // DEPRECRATED - Call the Context-only getInputFilteredImage()
filterInput(int index,const Context & ctx,SkIPoint * offset)202     sk_sp<SkSpecialImage> filterInput(int index, const Context& ctx, SkIPoint* offset) const {
203         return this->getInputFilteredImage(index, ctx).imageAndOffset(offset);
204     }
205 
206     // Helper function to visit each of this filter's child filters and call their
207     // onGetInputLayerBounds with the provided 'desiredOutput' and 'contentBounds'. Automatically
208     // handles null input filters. Returns the union of all of the children's input bounds.
209     skif::LayerSpace<SkIRect> visitInputLayerBounds(
210             const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& desiredOutput,
211             const skif::LayerSpace<SkIRect>& contentBounds) const;
212     // Helper function to visit each of this filter's child filters and call their
213     // onGetOutputLayerBounds with the provided 'contentBounds'. Automatically handles null input
214     // filters.
215     skif::LayerSpace<SkIRect> visitOutputLayerBounds(
216             const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& contentBounds) const;
217 
218     // Helper function to help with recursing through the filter DAG. It invokes filter processing
219     // set to null, it returns the dynamic source image on the Context instead.
220     //
221     // Implementations must handle cases when the input filter was unable to compute an image and
222     // the returned skif::Image has a null SkSpecialImage. If the filter affect transparent black
223     // should explicitly handle nullptr results and press on. In the error case this behavior will
224     // produce a better result than nothing and is necessary for the clipped out case.
getInputFilteredImage(int index,const skif::Context & context)225     skif::FilterResult<For::kInput> getInputFilteredImage(int index,
226                                                           const skif::Context& context) const {
227         return this->filterInput<For::kInput>(index, context);
228     }
229     // Convenience that calls filterInput with index = 0 and the most specific usage.
getInputFilteredImage0(const skif::Context & context)230     skif::FilterResult<For::kInput0> getInputFilteredImage0(const skif::Context& context) const {
231         return this->filterInput<For::kInput0>(0, context);
232     }
233     // Convenience that calls filterInput with index = 1 and the most specific usage.
getInputFilteredImage1(const skif::Context & context)234     skif::FilterResult<For::kInput1> getInputFilteredImage1(const skif::Context& context) const {
235         return this->filterInput<For::kInput1>(1, context);
236     }
237 
238     // DEPRECATED - Remove once cropping is handled by a separate filter
getCropRectIfSet()239     const CropRect* getCropRectIfSet() const {
240         return this->cropRectIsSet() ? &fCropRect : nullptr;
241     }
242 
243     /** Given a "srcBounds" rect, computes destination bounds for this filter.
244      *  "dstBounds" are computed by transforming the crop rect by the context's
245      *  CTM, applying it to the initial bounds, and intersecting the result with
246      *  the context's clip bounds.  "srcBounds" (if non-null) are computed by
247      *  intersecting the initial bounds with "dstBounds", to ensure that we never
248      *  sample outside of the crop rect (this restriction may be relaxed in the
249      *  future).
250      *
251      *  DEPRECATED - Remove once cropping is handled by a separate filter, although it may be
252      *  necessary to provide a similar convenience function to compute the output bounds given the
253      *  images returned by filterInput().
254      */
255     bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const;
256 
257     /** A variant of the above call which takes the original source bitmap and
258      *  source offset. If the resulting crop rect is not entirely contained by
259      *  the source bitmap's bounds, it creates a new bitmap in "result" and
260      *  pads the edges with transparent black. In that case, the srcOffset is
261      *  modified to be the same as the bounds, since no further adjustment is
262      *  needed by the caller. This version should only be used by filters
263      *  which are not capable of processing a smaller source bitmap into a
264      *  larger destination.
265      *
266      *  DEPRECATED - Remove once cropping is handled by a separate filter.
267      */
268     sk_sp<SkSpecialImage> applyCropRectAndPad(const Context&, SkSpecialImage* src,
269                                               SkIPoint* srcOffset, SkIRect* bounds) const;
270 
271     /**
272      *  Creates a modified Context for use when recursing up the image filter DAG.
273      *  The clip bounds are adjusted to accommodate any margins that this
274      *  filter requires by calling this node's
275      *  onFilterNodeBounds(..., kReverse_MapDirection).
276      */
277     // TODO (michaelludwig) - I don't think this is necessary to keep as protected. Other than the
278     // real use case in recursing through the DAG for filterInput(), it feels wrong for blur and
279     // other filters to need to call it.
280     Context mapContext(const Context& ctx) const;
281 
282 #if SK_SUPPORT_GPU
283     static sk_sp<SkSpecialImage> DrawWithFP(GrRecordingContext* context,
284                                             std::unique_ptr<GrFragmentProcessor> fp,
285                                             const SkIRect& bounds,
286                                             SkColorType colorType,
287                                             const SkColorSpace* colorSpace,
288                                             GrProtected isProtected = GrProtected::kNo);
289 
290     /**
291      *  Returns a version of the passed-in image (possibly the original), that is in a colorspace
292      *  with the same gamut as the one from the OutputProperties. This allows filters that do many
293      *  texture samples to guarantee that any color space conversion has happened before running.
294      */
295     static sk_sp<SkSpecialImage> ImageToColorSpace(SkSpecialImage* src,
296                                                    SkColorType colorType,
297                                                    SkColorSpace* colorSpace);
298 #endif
299 
300     // If 'srcBounds' will sample outside the border of 'originalSrcBounds' (i.e., the sample
301     // will wrap around to the other side) we must preserve the far side of the src along that
302     // axis (e.g., if we will sample beyond the left edge of the src, the right side must be
303     // preserved for the repeat sampling to work).
304     // DEPRECATED - Remove once cropping is handled by a separate filter, that can also handle all
305     // tile modes (including repeat) properly
306     static SkIRect DetermineRepeatedSrcBound(const SkIRect& srcBounds,
307                                              const SkIVector& filterOffset,
308                                              const SkISize& filterSize,
309                                              const SkIRect& originalSrcBounds);
310 
311 private:
312     friend class SkImageFilter;
313     // For PurgeCache()
314     friend class SkGraphics;
315 
316     static void PurgeCache();
317 
318     void init(sk_sp<SkImageFilter> const* inputs, int inputCount, const CropRect* cropRect);
319 
320     // Configuration points for the filter implementation, marked private since they should not
321     // need to be invoked by the subclasses. These refer to the node's specific behavior and are
322     // not responsible for aggregating the behavior of the entire filter DAG.
323 
324     /**
325      *  Return true (and returns a ref'd colorfilter) if this node in the DAG is just a colorfilter
326      *  w/o CropRect constraints.
327      */
onIsColorFilterNode(SkColorFilter **)328     virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const { return false; }
329 
330     /**
331      *  Return true if this filter can map from its parameter space to a layer space described by an
332      *  arbitrary transformation matrix. If this returns false, the filter only needs to worry about
333      *  mapping from parameter to layer using a scale+translate matrix.
334      */
onCanHandleComplexCTM()335     virtual bool onCanHandleComplexCTM() const { return false; }
336 
337     /**
338      *  Return true if this filter would transform transparent black pixels to a color other than
339      *  transparent black. When false, optimizations can be taken to discard regions known to be
340      *  transparent black and thus process fewer pixels.
341      */
affectsTransparentBlack()342     virtual bool affectsTransparentBlack() const { return false; }
343 
344     /**
345      *  This is the virtual which should be overridden by the derived class to perform image
346      *  filtering. Subclasses are responsible for recursing to their input filters, although the
347      *  getFilteredInputX() functions are provided to handle all necessary details of this. If the
348      *  filter has a fixed number of inputs, the getFilterInput0() and getFilteredInput1() functions
349      *  ensure the returned filtered Images have the most specific input usage.
350      *
351      *  If the image cannot be created (either because of an error or if the result would be empty
352      *  because it was clipped out), this should return a filtered Image with a null SkSpecialImage.
353      *  In these situations, callers that do not affect transparent black can end early, since the
354      *  "transparent" implicit image would be unchanged. Callers that affect transparent black need
355      *  to safely handle these null and empty images and return an image filling the context's clip
356      *  bounds as if its input filtered image were transparent black.
357      */
358     virtual skif::FilterResult<For::kOutput> onFilterImage(const skif::Context& context) const;
359 
360     /**
361      *  Calculates the necessary input layer size in order for the final output of the filter to
362      *  cover the desired output bounds. The provided 'desiredOutput' represents the requested
363      *  input bounds for this node's parent filter node, i.e. this function answers "what does this
364      *  node require for input in order to satisfy (as its own output), the input needs of its
365      *  parent?".
366      *
367      *  If 'recurse' is true, this function is responsible for recursing to its child image filters
368      *  and accounting for what they require to meet this filter's input requirements. It is up to
369      *  the filter to determine how to aggregate these inputs, but a helper function is provided for
370      *  the common case where the final required layer size is the union of the child filters'
371      *  required inputs, evaluated on what this filter requires for itself. 'recurse' is kNo
372      *  when mapping Contexts while actually filtering images, since the child recursion is
373      *  happening at a higher level.
374      *
375      *  Unlike the public getInputBounds(), all internal bounds calculations are done in the shared
376      *  layer space defined by 'mapping'.
377      *
378      *  The default implementation assumes that current filter requires an input equal to
379      *  'desiredOutputBounds', and passes this down to its child filters, and returns the union of
380      *  their required inputs.
381      */
382     virtual skif::LayerSpace<SkIRect> onGetInputLayerBounds(
383             const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& desiredOutput,
384             const skif::LayerSpace<SkIRect>& contentBounds,
385             VisitChildren recurse = VisitChildren::kYes) const;
386 
387     /**
388      *  Calculates the output bounds that this filter node would touch when processing an input
389      *  sized to 'contentBounds'. This function is responsible for recursing to its child image
390      *  filters and accounting for what they output. It is up to the filter to determine how to
391      *  aggregate the outputs of its children, but a helper function is provided for the common
392      *  case where the filter output is the union of its child outputs.
393      *
394      *  Unlike the public getOutputBounds(), all internal bounds calculations are done in the
395      *  shared layer space defined by 'mapping'.
396      *
397      *  The default implementation assumes that the output of this filter is equal to the union of
398      *  the outputs of its child filters evaluated with 'contentBounds'.
399      */
400     // TODO (michaelludwig) - When layerMatrix = I, this function could be used to implement
401     // onComputeFastBounds() instead of making filters implement the essentially the same calcs x2
402     virtual skif::LayerSpace<SkIRect> onGetOutputLayerBounds(
403             const skif::Mapping& mapping, const skif::LayerSpace<SkIRect>& contentBounds) const;
404 
405     // The actual implementation of the protected getFilterInputX() functions, but don't expose the
406     // flexible templating to subclasses so it can't be abused.
407     template<skif::Usage kU>
408     skif::FilterResult<kU> filterInput(int index, const skif::Context& ctx) const;
409 
410     SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs;
411 
412     bool fUsesSrcInput;
413     CropRect fCropRect;
414     uint32_t fUniqueID; // Globally unique
415 
416     typedef SkImageFilter INHERITED;
417 };
418 
as_IFB(SkImageFilter * filter)419 static inline SkImageFilter_Base* as_IFB(SkImageFilter* filter) {
420     return static_cast<SkImageFilter_Base*>(filter);
421 }
422 
as_IFB(const sk_sp<SkImageFilter> & filter)423 static inline SkImageFilter_Base* as_IFB(const sk_sp<SkImageFilter>& filter) {
424     return static_cast<SkImageFilter_Base*>(filter.get());
425 }
426 
as_IFB(const SkImageFilter * filter)427 static inline const SkImageFilter_Base* as_IFB(const SkImageFilter* filter) {
428     return static_cast<const SkImageFilter_Base*>(filter);
429 }
430 
431 /**
432  *  Helper to unflatten the common data, and return nullptr if we fail.
433  */
434 #define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
435     Common localVar;                                                \
436     do {                                                            \
437         if (!localVar.unflatten(buffer, expectedCount)) {           \
438             return nullptr;                                         \
439         }                                                           \
440     } while (0)
441 
442 #endif // SkImageFilter_Base_DEFINED
443