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  SkArenaAlloc;
     19 class  SkCanvas;
     20 class  SkColorSpaceXformer;
     21 class  SkPaint;
     22 struct SkRect;
     23 class  SkString;
     24 
     25 /** \class SkDrawLooper
     26     Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are,
     27     and something is drawn to a canvas with that paint, the looper subclass will
     28     be called, allowing it to modify the canvas and/or paint for that draw call.
     29     More than that, via the next() method, the looper can modify the draw to be
     30     invoked multiple times (hence the name loop-er), allow it to perform effects
     31     like shadows or frame/fills, that require more than one pass.
     32 */
     33 class SK_API SkDrawLooper : public SkFlattenable {
     34 public:
     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      */
     67     virtual Context* makeContext(SkCanvas*, SkArenaAlloc*) const = 0;
     68 
     69     /**
     70      * The fast bounds functions are used to enable the paint to be culled early
     71      * in the drawing pipeline. If a subclass can support this feature it must
     72      * return true for the canComputeFastBounds() function.  If that function
     73      * returns false then computeFastBounds behavior is undefined otherwise it
     74      * is expected to have the following behavior. Given the parent paint and
     75      * the parent's bounding rect the subclass must fill in and return the
     76      * storage rect, where the storage rect is with the union of the src rect
     77      * and the looper's bounding rect.
     78      */
     79     bool canComputeFastBounds(const SkPaint& paint) const;
     80     void computeFastBounds(const SkPaint& paint, const SkRect& src, SkRect* dst) const;
     81 
     82     struct BlurShadowRec {
     83         SkScalar        fSigma;
     84         SkVector        fOffset;
     85         SkColor         fColor;
     86         SkBlurStyle     fStyle;
     87         SkBlurQuality   fQuality;
     88     };
     89     /**
     90      *  If this looper can be interpreted as having two layers, such that
     91      *      1. The first layer (bottom most) just has a blur and translate
     92      *      2. The second layer has no modifications to either paint or canvas
     93      *      3. No other layers.
     94      *  then return true, and if not null, fill out the BlurShadowRec).
     95      *
     96      *  If any of the above are not met, return false and ignore the BlurShadowRec parameter.
     97      */
     98     virtual bool asABlurShadow(BlurShadowRec*) const;
     99 
    100     SK_TO_STRING_PUREVIRT()
    101     SK_DEFINE_FLATTENABLE_TYPE(SkDrawLooper)
    102 
    103 protected:
    104     sk_sp<SkDrawLooper> makeColorSpace(SkColorSpaceXformer* xformer) const {
    105         return this->onMakeColorSpace(xformer);
    106     }
    107     virtual sk_sp<SkDrawLooper> onMakeColorSpace(SkColorSpaceXformer*) const = 0;
    108 
    109     SkDrawLooper() {}
    110 
    111 private:
    112     friend class SkColorSpaceXformer;
    113 
    114     typedef SkFlattenable INHERITED;
    115 };
    116 
    117 #endif
    118