Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2011 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkDrawLooper_DEFINED
     11 #define SkDrawLooper_DEFINED
     12 
     13 #include "SkBlurTypes.h"
     14 #include "SkFlattenable.h"
     15 #include "SkPoint.h"
     16 #include "SkColor.h"
     17 
     18 class SkCanvas;
     19 class SkPaint;
     20 struct SkRect;
     21 class SkString;
     22 
     23 /** \class SkDrawLooper
     24     Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are,
     25     and something is drawn to a canvas with that paint, the looper subclass will
     26     be called, allowing it to modify the canvas and/or paint for that draw call.
     27     More than that, via the next() method, the looper can modify the draw to be
     28     invoked multiple times (hence the name loop-er), allow it to perform effects
     29     like shadows or frame/fills, that require more than one pass.
     30 */
     31 class SK_API SkDrawLooper : public SkFlattenable {
     32 public:
     33     SK_DECLARE_INST_COUNT(SkDrawLooper)
     34 
     35     /**
     36      *  Holds state during a draw. Users call next() until it returns false.
     37      *
     38      *  Subclasses of SkDrawLooper should create a subclass of this object to
     39      *  hold state specific to their subclass.
     40      */
     41     class SK_API Context : ::SkNoncopyable {
     42     public:
     43         Context() {}
     44         virtual ~Context() {}
     45 
     46         /**
     47          *  Called in a loop on objects returned by SkDrawLooper::createContext().
     48          *  Each time true is returned, the object is drawn (possibly with a modified
     49          *  canvas and/or paint). When false is finally returned, drawing for the object
     50          *  stops.
     51          *
     52          *  On each call, the paint will be in its original state, but the
     53          *  canvas will be as it was following the previous call to next() or
     54          *  createContext().
     55          *
     56          *  The implementation must ensure that, when next() finally returns
     57          *  false, the canvas has been restored to the state it was
     58          *  initially, before createContext() was first called.
     59          */
     60         virtual bool next(SkCanvas* canvas, SkPaint* paint) = 0;
     61     };
     62 
     63     /**
     64      *  Called right before something is being drawn. Returns a Context
     65      *  whose next() method should be called until it returns false.
     66      *  The caller has to ensure that the storage pointer provides enough
     67      *  memory for the Context. The required size can be queried by calling
     68      *  contextSize(). It is also the caller's responsibility to destroy the
     69      *  object after use.
     70      */
     71     virtual Context* createContext(SkCanvas*, void* storage) const = 0;
     72 
     73     /**
     74       *  Returns the number of bytes needed to store subclasses of Context (belonging to the
     75       *  corresponding SkDrawLooper subclass).
     76       */
     77     virtual size_t contextSize() const = 0;
     78 
     79 
     80     /**
     81      * The fast bounds functions are used to enable the paint to be culled early
     82      * in the drawing pipeline. If a subclass can support this feature it must
     83      * return true for the canComputeFastBounds() function.  If that function
     84      * returns false then computeFastBounds behavior is undefined otherwise it
     85      * is expected to have the following behavior. Given the parent paint and
     86      * the parent's bounding rect the subclass must fill in and return the
     87      * storage rect, where the storage rect is with the union of the src rect
     88      * and the looper's bounding rect.
     89      */
     90     virtual bool canComputeFastBounds(const SkPaint& paint) const;
     91     virtual void computeFastBounds(const SkPaint& paint,
     92                                    const SkRect& src, SkRect* dst) const;
     93 
     94     struct BlurShadowRec {
     95         SkScalar        fSigma;
     96         SkVector        fOffset;
     97         SkColor         fColor;
     98         SkBlurStyle     fStyle;
     99         SkBlurQuality   fQuality;
    100     };
    101     /**
    102      *  If this looper can be interpreted as having two layers, such that
    103      *      1. The first layer (bottom most) just has a blur and translate
    104      *      2. The second layer has no modifications to either paint or canvas
    105      *      3. No other layers.
    106      *  then return true, and if not null, fill out the BlurShadowRec).
    107      *
    108      *  If any of the above are not met, return false and ignore the BlurShadowRec parameter.
    109      */
    110     virtual bool asABlurShadow(BlurShadowRec*) const;
    111 
    112     SK_TO_STRING_PUREVIRT()
    113     SK_DEFINE_FLATTENABLE_TYPE(SkDrawLooper)
    114 
    115 protected:
    116     SkDrawLooper() {}
    117 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
    118     SkDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {}
    119 #endif
    120 
    121 private:
    122     typedef SkFlattenable INHERITED;
    123 };
    124 
    125 #endif
    126