1 /*
2  * Copyright 2011 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 SkImageFilter_DEFINED
9 #define SkImageFilter_DEFINED
10 
11 #include "../private/SkTArray.h"
12 #include "../private/SkTemplates.h"
13 #include "../private/SkMutex.h"
14 #include "SkFilterQuality.h"
15 #include "SkFlattenable.h"
16 #include "SkMatrix.h"
17 #include "SkRect.h"
18 #include "SkSurfaceProps.h"
19 
20 class GrFragmentProcessor;
21 class GrTexture;
22 class SkBaseDevice;
23 class SkBitmap;
24 class SkColorFilter;
25 struct SkIPoint;
26 class SkSpecialImage;
27 
28 /**
29  *  Base class for image filters. If one is installed in the paint, then
30  *  all drawing occurs as usual, but it is as if the drawing happened into an
31  *  offscreen (before the xfermode is applied). This offscreen bitmap will
32  *  then be handed to the imagefilter, who in turn creates a new bitmap which
33  *  is what will finally be drawn to the device (using the original xfermode).
34  */
35 class SK_API SkImageFilter : public SkFlattenable {
36 public:
37     // This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to
38     // (result, offset).
39     class Cache : public SkRefCnt {
40     public:
41         struct Key;
~Cache()42         virtual ~Cache() {}
43         static Cache* Create(size_t maxBytes);
44         static Cache* Get();
45         virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0;
46         virtual SkSpecialImage* get(const Key& key, SkIPoint* offset) const = 0;
47         virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0;
48         virtual void set(const Key& key, SkSpecialImage* image, const SkIPoint& offset) = 0;
purge()49         virtual void purge() {}
purgeByKeys(const Key[],int)50         virtual void purgeByKeys(const Key[], int) {}
51     };
52 
53     class Context {
54     public:
Context(const SkMatrix & ctm,const SkIRect & clipBounds,Cache * cache)55         Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache)
56             : fCTM(ctm)
57             , fClipBounds(clipBounds)
58             , fCache(cache)
59         {}
60 
ctm()61         const SkMatrix& ctm() const { return fCTM; }
clipBounds()62         const SkIRect& clipBounds() const { return fClipBounds; }
cache()63         Cache* cache() const { return fCache; }
64 
65     private:
66         SkMatrix        fCTM;
67         SkIRect         fClipBounds;
68         Cache*          fCache;
69     };
70 
71     class CropRect {
72     public:
73         enum CropEdge {
74             kHasLeft_CropEdge   = 0x01,
75             kHasTop_CropEdge    = 0x02,
76             kHasWidth_CropEdge  = 0x04,
77             kHasHeight_CropEdge = 0x08,
78             kHasAll_CropEdge    = 0x0F,
79         };
CropRect()80         CropRect() {}
81         explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge)
fRect(rect)82             : fRect(rect), fFlags(flags) {}
flags()83         uint32_t flags() const { return fFlags; }
rect()84         const SkRect& rect() const { return fRect; }
85 #ifndef SK_IGNORE_TO_STRING
86         void toString(SkString* str) const;
87 #endif
88 
89         /**
90          *  Apply this cropRect to the imageBounds. If a given edge of the cropRect is not
91          *  set, then the corresponding edge from imageBounds will be used.
92          *
93          *  Note: imageBounds is in "device" space, as the output cropped rectangle will be,
94          *  so the matrix is ignored for those. It is only applied the croprect's bounds.
95          */
96         void applyTo(const SkIRect& imageBounds, const SkMatrix&, SkIRect* cropped) const;
97 
98     private:
99         SkRect fRect;
100         uint32_t fFlags;
101     };
102 
103     enum TileUsage {
104         kPossible_TileUsage,    //!< the created device may be drawn tiled
105         kNever_TileUsage,       //!< the created device will never be drawn tiled
106     };
107 
108     class Proxy {
109     public:
~Proxy()110         virtual ~Proxy() {}
111 
112         virtual SkBaseDevice* createDevice(int width, int height,
113                                            TileUsage usage = kNever_TileUsage) = 0;
114 
115         // Returns true if the proxy handled the filter itself. If this returns
116         // false then the filter's code will be called.
117         virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
118                                  const SkImageFilter::Context&,
119                                  SkBitmap* result, SkIPoint* offset) = 0;
120     };
121 
122     class DeviceProxy : public Proxy {
123     public:
DeviceProxy(SkBaseDevice * device)124         DeviceProxy(SkBaseDevice* device) : fDevice(device) {}
125 
126         SkBaseDevice* createDevice(int width, int height,
127                                    TileUsage usage = kNever_TileUsage) override;
128 
129         // Returns true if the proxy handled the filter itself. If this returns
130         // false then the filter's code will be called.
131         bool filterImage(const SkImageFilter*, const SkBitmap& src, const SkImageFilter::Context&,
132                          SkBitmap* result, SkIPoint* offset) override;
133 
134     private:
135         SkBaseDevice* fDevice;
136     };
137 
138     /**
139      *  Request a new (result) image to be created from the src image.
140      *  If the src has no pixels (isNull()) then the request just wants to
141      *  receive the config and width/height of the result.
142      *
143      *  The matrix is the current matrix on the canvas.
144      *
145      *  Offset is the amount to translate the resulting image relative to the
146      *  src when it is drawn. This is an out-param.
147      *
148      *  If the result image cannot be created, return false, in which case both
149      *  the result and offset parameters will be ignored by the caller.
150      */
151     bool filterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
152                                SkBitmap* result, SkIPoint* offset) const;
153 
154     enum MapDirection {
155         kForward_MapDirection,
156         kReverse_MapDirection
157     };
158     /**
159      * Map a device-space rect recursively forward or backward through the
160      * filter DAG. kForward_MapDirection is used to determine which pixels of
161      * the destination canvas a source image rect would touch after filtering.
162      * kBackward_MapDirection is used to determine which rect of the source
163      * image would be required to fill the given rect (typically, clip bounds).
164      * Used for clipping and temp-buffer allocations, so the result need not
165      * be exact, but should never be smaller than the real answer. The default
166      * implementation recursively unions all input bounds, or returns false if
167      * no inputs.
168      */
169     bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst,
170                       MapDirection = kReverse_MapDirection) const;
171 
172     /**
173      *  Returns true if the filter can be processed on the GPU.  This is most
174      *  often used for multi-pass effects, where intermediate results must be
175      *  rendered to textures.  For single-pass effects, use asFragmentProcessor().
176      *  The default implementation returns asFragmentProcessor(NULL, NULL, SkMatrix::I(),
177      *  SkIRect()).
178      */
179     virtual bool canFilterImageGPU() const;
180 
181     /**
182      *  Process this image filter on the GPU.  This is most often used for
183      *  multi-pass effects, where intermediate results must be rendered to
184      *  textures.  For single-pass effects, use asFragmentProcessor().  src is the
185      *  source image for processing, as a texture-backed bitmap.  result is
186      *  the destination bitmap, which should contain a texture-backed pixelref
187      *  on success.  offset is the amount to translate the resulting image
188      *  relative to the src when it is drawn. The default implementation does
189      *  single-pass processing using asFragmentProcessor().
190      */
191     virtual bool filterImageGPUDeprecated(Proxy*, const SkBitmap& src, const Context&,
192                                           SkBitmap* result, SkIPoint* offset) const;
193 
194     /**
195      *  Returns whether this image filter is a color filter and puts the color filter into the
196      *  "filterPtr" parameter if it can. Does nothing otherwise.
197      *  If this returns false, then the filterPtr is unchanged.
198      *  If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
199      *  (i.e. it may not be set to NULL).
200      */
isColorFilterNode(SkColorFilter ** filterPtr)201     bool isColorFilterNode(SkColorFilter** filterPtr) const {
202         return this->onIsColorFilterNode(filterPtr);
203     }
204 
205     // DEPRECATED : use isColorFilterNode() instead
asColorFilter(SkColorFilter ** filterPtr)206     bool asColorFilter(SkColorFilter** filterPtr) const {
207         return this->isColorFilterNode(filterPtr);
208     }
209 
210     /**
211      *  Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
212      *  replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
213      *  same way.
214      */
215     bool asAColorFilter(SkColorFilter** filterPtr) const;
216 
217     /**
218      *  Returns the number of inputs this filter will accept (some inputs can
219      *  be NULL).
220      */
countInputs()221     int countInputs() const { return fInputCount; }
222 
223     /**
224      *  Returns the input filter at a given index, or NULL if no input is
225      *  connected.  The indices used are filter-specific.
226      */
getInput(int i)227     SkImageFilter* getInput(int i) const {
228         SkASSERT(i < fInputCount);
229         return fInputs[i];
230     }
231 
232     /**
233      *  Returns whether any edges of the crop rect have been set. The crop
234      *  rect is set at construction time, and determines which pixels from the
235      *  input image will be processed, and which pixels in the output image will be allowed.
236      *  The size of the crop rect should be
237      *  used as the size of the destination image. The origin of this rect
238      *  should be used to offset access to the input images, and should also
239      *  be added to the "offset" parameter in onFilterImage and
240      *  filterImageGPU(). (The latter ensures that the resulting buffer is
241      *  drawn in the correct location.)
242      */
cropRectIsSet()243     bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
244 
getCropRect()245     CropRect getCropRect() const { return fCropRect; }
246 
247     // Default impl returns union of all input bounds.
248     virtual void computeFastBounds(const SkRect&, SkRect*) const;
249 
250     // Can this filter DAG compute the resulting bounds of an object-space rectangle?
251     virtual bool canComputeFastBounds() const;
252 
253     /**
254      *  If this filter can be represented by another filter + a localMatrix, return that filter,
255      *  else return null.
256      */
257     SkImageFilter* newWithLocalMatrix(const SkMatrix& matrix) const;
258 
259     /**
260      * Create an SkMatrixImageFilter, which transforms its input by the given matrix.
261      */
262     static SkImageFilter* CreateMatrixFilter(const SkMatrix& matrix,
263                                              SkFilterQuality,
264                                              SkImageFilter* input = NULL);
265 
266 #if SK_SUPPORT_GPU
267     // Helper function which invokes GPU filter processing on the
268     // input at the specified "index". If the input is null, it leaves
269     // "result" and "offset" untouched, and returns true. If the input
270     // has a GPU implementation, it will be invoked directly.
271     // Otherwise, the filter will be processed in software and
272     // uploaded to the GPU.
273     bool filterInputGPUDeprecated(int index, SkImageFilter::Proxy* proxy,
274                                   const SkBitmap& src, const Context&,
275                                   SkBitmap* result, SkIPoint* offset) const;
276 #endif
277 
278     SK_TO_STRING_PUREVIRT()
SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)279     SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
280 
281 protected:
282     class Common {
283     public:
284         Common() {}
285         ~Common();
286 
287         /**
288          *  Attempt to unflatten the cropRect and the expected number of input filters.
289          *  If any number of input filters is valid, pass -1.
290          *  If this fails (i.e. corrupt buffer or contents) then return false and common will
291          *  be left uninitialized.
292          *  If this returns true, then inputCount() is the number of found input filters, each
293          *  of which may be NULL or a valid imagefilter.
294          */
295         bool unflatten(SkReadBuffer&, int expectedInputs);
296 
297         const CropRect& cropRect() const { return fCropRect; }
298         int             inputCount() const { return fInputs.count(); }
299         SkImageFilter** inputs() const { return fInputs.get(); }
300 
301         SkImageFilter*  getInput(int index) const { return fInputs[index]; }
302 
303         // If the caller wants a copy of the inputs, call this and it will transfer ownership
304         // of the unflattened input filters to the caller. This is just a short-cut for copying
305         // the inputs, calling ref() on each, and then waiting for Common's destructor to call
306         // unref() on each.
307         void detachInputs(SkImageFilter** inputs);
308 
309     private:
310         CropRect fCropRect;
311         // most filters accept at most 2 input-filters
312         SkAutoSTArray<2, SkImageFilter*> fInputs;
313 
314         void allocInputs(int count);
315     };
316 
317     SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL);
318 
319     virtual ~SkImageFilter();
320 
321     /**
322      *  Constructs a new SkImageFilter read from an SkReadBuffer object.
323      *
324      *  @param inputCount    The exact number of inputs expected for this SkImageFilter object.
325      *                       -1 can be used if the filter accepts any number of inputs.
326      *  @param rb            SkReadBuffer object from which the SkImageFilter is read.
327      */
328     explicit SkImageFilter(int inputCount, SkReadBuffer& rb);
329 
330     void flatten(SkWriteBuffer&) const override;
331 
332     /**
333      *  This is the virtual which should be overridden by the derived class
334      *  to perform image filtering.
335      *
336      *  src is the original primitive bitmap. If the filter has a connected
337      *  input, it should recurse on that input and use that in place of src.
338      *
339      *  The matrix is the current matrix on the canvas.
340      *
341      *  Offset is the amount to translate the resulting image relative to the
342      *  src when it is drawn. This is an out-param.
343      *
344      *  If the result image cannot be created, this should false, in which
345      *  case both the result and offset parameters will be ignored by the
346      *  caller.
347      */
348     virtual bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
349                                          SkBitmap* result, SkIPoint* offset) const;
350 
351     /**
352      * This function recurses into its inputs with the given clip rect (first
353      * argument), calls filterBounds() with the given map direction on each,
354      * and unions the result (third argument). If the rect cannot be mapped,
355      * false is returned and the destination rect is left unchanged.
356      * If a derived class has special recursion requirements (e.g., it has an
357      * input which does not participate in bounds computation), it can be
358      * overridden here.
359      *
360      * Note that this function is *not* responsible for mapping the rect for
361      * this node's filter bounds requirements (i.e., calling
362      * onFilterNodeBounds()); that is handled by filterBounds().
363      */
364     virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const;
365 
366     /**
367      * Performs a forwards or reverse mapping of the given rect to accommodate
368      * this filter's margin requirements. kForward_MapDirection is used to
369      * determine the destination pixels which would be touched by filtering
370      * the given given source rect (e.g., given source bitmap bounds,
371      * determine the optimal bounds of the filtered offscreen bitmap).
372      * kReverse_MapDirection is used to determine which pixels of the
373      * input(s) would be required to fill the given destination rect
374      * (e.g., clip bounds). NOTE: these operations may not be the
375      * inverse of the other. For example, blurring expands the given rect
376      * in both forward and reverse directions. Unlike
377      * onFilterBounds(), this function is non-recursive.
378      */
379     virtual void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const;
380 
381     // Helper function which invokes filter processing on the input at the
382     // specified "index". If the input is null, it leaves "result" and
383     // "offset" untouched, and returns true. If the input is non-null, it
384     // calls filterImage() on that input, and returns true on success.
385     // i.e., return !getInput(index) || getInput(index)->filterImage(...);
386     bool filterInputDeprecated(int index, Proxy*, const SkBitmap& src, const Context&,
387                                SkBitmap* result, SkIPoint* offset) const;
388 
389     /**
390      *  Return true (and return a ref'd colorfilter) if this node in the DAG is just a
391      *  colorfilter w/o CropRect constraints.
392      */
onIsColorFilterNode(SkColorFilter **)393     virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const {
394         return false;
395     }
396 
397     /** Given a "srcBounds" rect, computes destination bounds for this
398      *  destination bounds for this filter. "dstBounds" are computed by
399      *  transforming the crop rect by the context's CTM, applying it to the
400      *  initial bounds, and intersecting the result with the context's clip
401      *  bounds.  "srcBounds" (if non-null) are computed by intersecting the
402      *  initial bounds with "dstBounds", to ensure that we never sample
403      *  outside of the crop rect (this restriction may be relaxed in the
404      *  future).
405      */
406     bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const;
407 
408     /** A variant of the above call which takes the original source bitmap and
409      *  source offset. If the resulting crop rect is not entirely contained by
410      *  the source bitmap's bounds, it creates a new bitmap in "result" and
411      *  pads the edges with transparent black. In that case, the srcOffset is
412      *  modified to be the same as the bounds, since no further adjustment is
413      *  needed by the caller. This version should only be used by filters
414      *  which are not capable of processing a smaller source bitmap into a
415      *  larger destination.
416      */
417     bool applyCropRectDeprecated(const Context&, Proxy* proxy, const SkBitmap& src,
418                                  SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* result) const;
419 
420     /**
421      *  Returns true if the filter can be expressed a single-pass
422      *  GrProcessor, used to process this filter on the GPU, or false if
423      *  not.
424      *
425      *  If effect is non-NULL, a new GrProcessor instance is stored
426      *  in it.  The caller assumes ownership of the stage, and it is up to the
427      *  caller to unref it.
428      *
429      *  The effect can assume its vertexCoords space maps 1-to-1 with texels
430      *  in the texture.  "matrix" is a transformation to apply to filter
431      *  parameters before they are used in the effect. Note that this function
432      *  will be called with (NULL, NULL, SkMatrix::I()) to query for support,
433      *  so returning "true" indicates support for all possible matrices.
434      */
435     virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
436                                      const SkIRect& bounds) const;
437 
438     /**
439      *  Creates a modified Context for use when recursing up the image filter DAG.
440      *  The clip bounds are adjusted to accommodate any margins that this
441      *  filter requires by calling this node's
442      *  onFilterNodeBounds(..., kReverse_MapDirection).
443      */
444     Context mapContext(const Context& ctx) const;
445 
446 private:
447     friend class SkGraphics;
448     static void PurgeCache();
449 
usesSrcInput()450     bool usesSrcInput() const { return fUsesSrcInput; }
451 
452     typedef SkFlattenable INHERITED;
453     int fInputCount;
454     SkImageFilter** fInputs;
455     bool fUsesSrcInput;
456     CropRect fCropRect;
457     uint32_t fUniqueID; // Globally unique
458     mutable SkTArray<Cache::Key> fCacheKeys;
459     mutable SkMutex fMutex;
460 };
461 
462 /**
463  *  Helper to unflatten the common data, and return NULL if we fail.
464  */
465 #define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
466     Common localVar;                                                \
467     do {                                                            \
468         if (!localVar.unflatten(buffer, expectedCount)) {           \
469             return NULL;                                            \
470         }                                                           \
471     } while (0)
472 
473 #endif
474