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 "SkFilterQuality.h"
     12 #include "SkFlattenable.h"
     13 #include "SkMatrix.h"
     14 #include "SkRect.h"
     15 #include "SkTemplates.h"
     16 
     17 class SkBitmap;
     18 class SkColorFilter;
     19 class SkBaseDevice;
     20 class SkSurfaceProps;
     21 struct SkIPoint;
     22 class GrFragmentProcessor;
     23 class GrTexture;
     24 
     25 /**
     26  *  Base class for image filters. If one is installed in the paint, then
     27  *  all drawing occurs as usual, but it is as if the drawing happened into an
     28  *  offscreen (before the xfermode is applied). This offscreen bitmap will
     29  *  then be handed to the imagefilter, who in turn creates a new bitmap which
     30  *  is what will finally be drawn to the device (using the original xfermode).
     31  */
     32 class SK_API SkImageFilter : public SkFlattenable {
     33 public:
     34     SK_DECLARE_INST_COUNT(SkImageFilter)
     35 
     36     class CropRect {
     37     public:
     38         enum CropEdge {
     39             kHasLeft_CropEdge   = 0x01,
     40             kHasTop_CropEdge    = 0x02,
     41             kHasRight_CropEdge  = 0x04,
     42             kHasBottom_CropEdge = 0x08,
     43             kHasAll_CropEdge    = 0x0F,
     44         };
     45         CropRect() {}
     46         explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {}
     47         uint32_t flags() const { return fFlags; }
     48         const SkRect& rect() const { return fRect; }
     49     private:
     50         SkRect fRect;
     51         uint32_t fFlags;
     52     };
     53 
     54     // This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to
     55     // (result, offset).
     56     class Cache : public SkRefCnt {
     57     public:
     58         struct Key;
     59         virtual ~Cache() {}
     60         static Cache* Create(size_t maxBytes);
     61         static Cache* Get();
     62         virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0;
     63         virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0;
     64     };
     65 
     66     class Context {
     67     public:
     68         Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache) :
     69             fCTM(ctm), fClipBounds(clipBounds), fCache(cache) {
     70         }
     71         const SkMatrix& ctm() const { return fCTM; }
     72         const SkIRect& clipBounds() const { return fClipBounds; }
     73         Cache* cache() const { return fCache; }
     74     private:
     75         SkMatrix fCTM;
     76         SkIRect  fClipBounds;
     77         Cache* fCache;
     78     };
     79 
     80     class Proxy {
     81     public:
     82         virtual ~Proxy() {};
     83 
     84         virtual SkBaseDevice* createDevice(int width, int height) = 0;
     85         // returns true if the proxy can handle this filter natively
     86         virtual bool canHandleImageFilter(const SkImageFilter*) = 0;
     87         // returns true if the proxy handled the filter itself. if this returns
     88         // false then the filter's code will be called.
     89         virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
     90                                  const Context&,
     91                                  SkBitmap* result, SkIPoint* offset) = 0;
     92         virtual const SkSurfaceProps* surfaceProps() const = 0;
     93     };
     94 
     95     /**
     96      *  Request a new (result) image to be created from the src image.
     97      *  If the src has no pixels (isNull()) then the request just wants to
     98      *  receive the config and width/height of the result.
     99      *
    100      *  The matrix is the current matrix on the canvas.
    101      *
    102      *  Offset is the amount to translate the resulting image relative to the
    103      *  src when it is drawn. This is an out-param.
    104      *
    105      *  If the result image cannot be created, return false, in which case both
    106      *  the result and offset parameters will be ignored by the caller.
    107      */
    108     bool filterImage(Proxy*, const SkBitmap& src, const Context&,
    109                      SkBitmap* result, SkIPoint* offset) const;
    110 
    111     /**
    112      *  Given the src bounds of an image, this returns the bounds of the result
    113      *  image after the filter has been applied.
    114      */
    115     bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const;
    116 
    117     /**
    118      *  Returns true if the filter can be processed on the GPU.  This is most
    119      *  often used for multi-pass effects, where intermediate results must be
    120      *  rendered to textures.  For single-pass effects, use asFragmentProcessor().
    121      *  The default implementation returns asFragmentProcessor(NULL, NULL, SkMatrix::I(),
    122      *  SkIRect()).
    123      */
    124     virtual bool canFilterImageGPU() const;
    125 
    126     /**
    127      *  Process this image filter on the GPU.  This is most often used for
    128      *  multi-pass effects, where intermediate results must be rendered to
    129      *  textures.  For single-pass effects, use asFragmentProcessor().  src is the
    130      *  source image for processing, as a texture-backed bitmap.  result is
    131      *  the destination bitmap, which should contain a texture-backed pixelref
    132      *  on success.  offset is the amount to translate the resulting image
    133      *  relative to the src when it is drawn. The default implementation does
    134      *  single-pass processing using asFragmentProcessor().
    135      */
    136     virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&,
    137                                 SkBitmap* result, SkIPoint* offset) const;
    138 
    139     /**
    140      *  Returns whether this image filter is a color filter and puts the color filter into the
    141      *  "filterPtr" parameter if it can. Does nothing otherwise.
    142      *  If this returns false, then the filterPtr is unchanged.
    143      *  If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
    144      *  (i.e. it may not be set to NULL).
    145      */
    146     bool isColorFilterNode(SkColorFilter** filterPtr) const {
    147         return this->onIsColorFilterNode(filterPtr);
    148     }
    149 
    150     // DEPRECATED : use isColorFilterNode() instead
    151     bool asColorFilter(SkColorFilter** filterPtr) const {
    152         return this->isColorFilterNode(filterPtr);
    153     }
    154 
    155     /**
    156      *  Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
    157      *  replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
    158      *  same way.
    159      */
    160     bool asAColorFilter(SkColorFilter** filterPtr) const {
    161         return this->countInputs() > 0 &&
    162                NULL == this->getInput(0) &&
    163                this->isColorFilterNode(filterPtr);
    164     }
    165 
    166     /**
    167      *  Returns the number of inputs this filter will accept (some inputs can
    168      *  be NULL).
    169      */
    170     int countInputs() const { return fInputCount; }
    171 
    172     /**
    173      *  Returns the input filter at a given index, or NULL if no input is
    174      *  connected.  The indices used are filter-specific.
    175      */
    176     SkImageFilter* getInput(int i) const {
    177         SkASSERT(i < fInputCount);
    178         return fInputs[i];
    179     }
    180 
    181     /**
    182      *  Returns whether any edges of the crop rect have been set. The crop
    183      *  rect is set at construction time, and determines which pixels from the
    184      *  input image will be processed. The size of the crop rect should be
    185      *  used as the size of the destination image. The origin of this rect
    186      *  should be used to offset access to the input images, and should also
    187      *  be added to the "offset" parameter in onFilterImage and
    188      *  filterImageGPU(). (The latter ensures that the resulting buffer is
    189      *  drawn in the correct location.)
    190      */
    191     bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
    192 
    193     // Default impl returns union of all input bounds.
    194     virtual void computeFastBounds(const SkRect&, SkRect*) const;
    195 
    196     /**
    197      * Create an SkMatrixImageFilter, which transforms its input by the given matrix.
    198      */
    199     static SkImageFilter* CreateMatrixFilter(const SkMatrix& matrix,
    200                                              SkFilterQuality,
    201                                              SkImageFilter* input = NULL);
    202 
    203 #if SK_SUPPORT_GPU
    204     /**
    205      * Wrap the given texture in a texture-backed SkBitmap.
    206      */
    207     static void WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result);
    208 
    209     /**
    210      * Recursively evaluate this filter on the GPU. If the filter has no GPU
    211      * implementation, it will be processed in software and uploaded to the GPU.
    212      */
    213     bool getInputResultGPU(SkImageFilter::Proxy* proxy, const SkBitmap& src, const Context&,
    214                            SkBitmap* result, SkIPoint* offset) const;
    215 #endif
    216 
    217     SK_TO_STRING_PUREVIRT()
    218     SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
    219 
    220 protected:
    221     class Common {
    222     public:
    223         Common() {}
    224         ~Common();
    225 
    226         /**
    227          *  Attempt to unflatten the cropRect and the expected number of input filters.
    228          *  If any number of input filters is valid, pass -1.
    229          *  If this fails (i.e. corrupt buffer or contents) then return false and common will
    230          *  be left uninitialized.
    231          *  If this returns true, then inputCount() is the number of found input filters, each
    232          *  of which may be NULL or a valid imagefilter.
    233          */
    234         bool unflatten(SkReadBuffer&, int expectedInputs);
    235 
    236         const CropRect& cropRect() const { return fCropRect; }
    237         int             inputCount() const { return fInputs.count(); }
    238         SkImageFilter** inputs() const { return fInputs.get(); }
    239 
    240         SkImageFilter*  getInput(int index) const { return fInputs[index]; }
    241 
    242         // If the caller wants a copy of the inputs, call this and it will transfer ownership
    243         // of the unflattened input filters to the caller. This is just a short-cut for copying
    244         // the inputs, calling ref() on each, and then waiting for Common's destructor to call
    245         // unref() on each.
    246         void detachInputs(SkImageFilter** inputs);
    247 
    248     private:
    249         CropRect fCropRect;
    250         // most filters accept at most 2 input-filters
    251         SkAutoSTArray<2, SkImageFilter*> fInputs;
    252 
    253         void allocInputs(int count);
    254     };
    255 
    256     SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL);
    257 
    258     virtual ~SkImageFilter();
    259 
    260     /**
    261      *  Constructs a new SkImageFilter read from an SkReadBuffer object.
    262      *
    263      *  @param inputCount    The exact number of inputs expected for this SkImageFilter object.
    264      *                       -1 can be used if the filter accepts any number of inputs.
    265      *  @param rb            SkReadBuffer object from which the SkImageFilter is read.
    266      */
    267     explicit SkImageFilter(int inputCount, SkReadBuffer& rb);
    268 
    269     void flatten(SkWriteBuffer&) const override;
    270 
    271     /**
    272      *  This is the virtual which should be overridden by the derived class
    273      *  to perform image filtering.
    274      *
    275      *  src is the original primitive bitmap. If the filter has a connected
    276      *  input, it should recurse on that input and use that in place of src.
    277      *
    278      *  The matrix is the current matrix on the canvas.
    279      *
    280      *  Offset is the amount to translate the resulting image relative to the
    281      *  src when it is drawn. This is an out-param.
    282      *
    283      *  If the result image cannot be created, this should false, in which
    284      *  case both the result and offset parameters will be ignored by the
    285      *  caller.
    286      */
    287     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
    288                                SkBitmap* result, SkIPoint* offset) const;
    289     // Given the bounds of the destination rect to be filled in device
    290     // coordinates (first parameter), and the CTM, compute (conservatively)
    291     // which rect of the source image would be required (third parameter).
    292     // Used for clipping and temp-buffer allocations, so the result need not
    293     // be exact, but should never be smaller than the real answer. The default
    294     // implementation recursively unions all input bounds, or returns false if
    295     // no inputs.
    296     virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const;
    297 
    298     /**
    299      *  Return true (and return a ref'd colorfilter) if this node in the DAG is just a
    300      *  colorfilter w/o CropRect constraints.
    301      */
    302     virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const {
    303         return false;
    304     }
    305 
    306     /** Computes source bounds as the src bitmap bounds offset by srcOffset.
    307      *  Apply the transformed crop rect to the bounds if any of the
    308      *  corresponding edge flags are set. Intersects the result against the
    309      *  context's clipBounds, and returns the result in "bounds". If there is
    310      *  no intersection, returns false and leaves "bounds" unchanged.
    311      */
    312     bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset,
    313                        SkIRect* bounds) const;
    314 
    315     /** Same as the above call, except that if the resulting crop rect is not
    316      *  entirely contained by the source bitmap's bounds, it creates a new
    317      *  bitmap in "result" and pads the edges with transparent black. In that
    318      *  case, the srcOffset is modified to be the same as the bounds, since no
    319      *  further adjustment is needed by the caller. This version should only
    320      *  be used by filters which are not capable of processing a smaller
    321      *  source bitmap into a larger destination.
    322      */
    323     bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, SkIPoint* srcOffset,
    324                        SkIRect* bounds, SkBitmap* result) const;
    325 
    326     /**
    327      *  Returns true if the filter can be expressed a single-pass
    328      *  GrProcessor, used to process this filter on the GPU, or false if
    329      *  not.
    330      *
    331      *  If effect is non-NULL, a new GrProcessor instance is stored
    332      *  in it.  The caller assumes ownership of the stage, and it is up to the
    333      *  caller to unref it.
    334      *
    335      *  The effect can assume its vertexCoords space maps 1-to-1 with texels
    336      *  in the texture.  "matrix" is a transformation to apply to filter
    337      *  parameters before they are used in the effect. Note that this function
    338      *  will be called with (NULL, NULL, SkMatrix::I()) to query for support,
    339      *  so returning "true" indicates support for all possible matrices.
    340      */
    341     virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
    342                                      const SkIRect& bounds) const;
    343 
    344 private:
    345     bool usesSrcInput() const { return fUsesSrcInput; }
    346 
    347     typedef SkFlattenable INHERITED;
    348     int fInputCount;
    349     SkImageFilter** fInputs;
    350     bool fUsesSrcInput;
    351     CropRect fCropRect;
    352     uint32_t fUniqueID; // Globally unique
    353 };
    354 
    355 /**
    356  *  Helper to unflatten the common data, and return NULL if we fail.
    357  */
    358 #define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
    359     Common localVar;                                                \
    360     do {                                                            \
    361         if (!localVar.unflatten(buffer, expectedCount)) {           \
    362             return NULL;                                            \
    363         }                                                           \
    364     } while (0)
    365 
    366 #endif
    367