Home | History | Annotate | Download | only in core
      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;
     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;
     49         virtual void purge() {}
     50         virtual void purgeByKeys(const Key[], int) {}
     51     };
     52 
     53     class Context {
     54     public:
     55         Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache)
     56             : fCTM(ctm)
     57             , fClipBounds(clipBounds)
     58             , fCache(cache)
     59         {}
     60 
     61         const SkMatrix& ctm() const { return fCTM; }
     62         const SkIRect& clipBounds() const { return fClipBounds; }
     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         };
     80         CropRect() {}
     81         explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge)
     82             : fRect(rect), fFlags(flags) {}
     83         uint32_t flags() const { return fFlags; }
     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:
    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:
    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      */
    201     bool isColorFilterNode(SkColorFilter** filterPtr) const {
    202         return this->onIsColorFilterNode(filterPtr);
    203     }
    204 
    205     // DEPRECATED : use isColorFilterNode() instead
    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      */
    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      */
    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      */
    243     bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
    244 
    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()
    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      */
    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 
    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