Home | History | Annotate | Download | only in effects
      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 SkLayerDrawLooper_DEFINED
      9 #define SkLayerDrawLooper_DEFINED
     10 
     11 #include "SkDrawLooper.h"
     12 #include "SkPaint.h"
     13 #include "SkPoint.h"
     14 #include "SkXfermode.h"
     15 
     16 class SK_API SkLayerDrawLooper : public SkDrawLooper {
     17 public:
     18     virtual ~SkLayerDrawLooper();
     19 
     20     /**
     21      *  Bits specifies which aspects of the layer's paint should replace the
     22      *  corresponding aspects on the draw's paint.
     23      *  kEntirePaint_Bits means use the layer's paint completely.
     24      *  0 means ignore the layer's paint... except for fColorMode, which is
     25      *  always applied.
     26      */
     27     enum Bits {
     28         kStyle_Bit      = 1 << 0,   //!< use this layer's Style/stroke settings
     29         kTextSkewX_Bit  = 1 << 1,   //!< use this layer's textskewx
     30         kPathEffect_Bit = 1 << 2,   //!< use this layer's patheffect
     31         kMaskFilter_Bit = 1 << 3,   //!< use this layer's maskfilter
     32         kShader_Bit     = 1 << 4,   //!< use this layer's shader
     33         kColorFilter_Bit = 1 << 5,  //!< use this layer's colorfilter
     34         kXfermode_Bit   = 1 << 6,   //!< use this layer's xfermode
     35 
     36         /**
     37          *  Use the layer's paint entirely, with these exceptions:
     38          *  - We never override the draw's paint's text_encoding, since that is
     39          *    used to interpret the text/len parameters in draw[Pos]Text.
     40          *  - Color is always computed using the LayerInfo's fColorMode.
     41          */
     42         kEntirePaint_Bits = -1
     43 
     44     };
     45     typedef int32_t BitFlags;
     46 
     47     /**
     48      *  Info for how to apply the layer's paint and offset.
     49      *
     50      *  fColorMode controls how we compute the final color for the layer:
     51      *      The layer's paint's color is treated as the SRC
     52      *      The draw's paint's color is treated as the DST
     53      *      final-color = Mode(layers-color, draws-color);
     54      *  Any SkXfermode::Mode will work. Two common choices are:
     55      *      kSrc_Mode: to use the layer's color, ignoring the draw's
     56      *      kDst_Mode: to just keep the draw's color, ignoring the layer's
     57      */
     58     struct SK_API LayerInfo {
     59         BitFlags            fPaintBits;
     60         SkXfermode::Mode    fColorMode;
     61         SkVector            fOffset;
     62         bool                fPostTranslate; //!< applies to fOffset
     63 
     64         /**
     65          *  Initial the LayerInfo. Defaults to settings that will draw the
     66          *  layer with no changes: e.g.
     67          *      fPaintBits == 0
     68          *      fColorMode == kDst_Mode
     69          *      fOffset == (0, 0)
     70          */
     71         LayerInfo();
     72     };
     73 
     74     SkDrawLooper::Context* createContext(SkCanvas*, void* storage) const override;
     75 
     76     size_t contextSize() const override { return sizeof(LayerDrawLooperContext); }
     77 
     78     bool asABlurShadow(BlurShadowRec* rec) const override;
     79 
     80     SK_TO_STRING_OVERRIDE()
     81 
     82     Factory getFactory() const override { return CreateProc; }
     83     static SkFlattenable* CreateProc(SkReadBuffer& buffer);
     84 
     85 protected:
     86     SkLayerDrawLooper();
     87 
     88     void flatten(SkWriteBuffer&) const override;
     89 
     90 private:
     91     struct Rec {
     92         Rec*    fNext;
     93         SkPaint fPaint;
     94         LayerInfo fInfo;
     95     };
     96     Rec*    fRecs;
     97     int     fCount;
     98 
     99     // state-machine during the init/next cycle
    100     class LayerDrawLooperContext : public SkDrawLooper::Context {
    101     public:
    102         explicit LayerDrawLooperContext(const SkLayerDrawLooper* looper);
    103 
    104     protected:
    105         bool next(SkCanvas*, SkPaint* paint) override;
    106 
    107     private:
    108         Rec* fCurrRec;
    109 
    110         static void ApplyInfo(SkPaint* dst, const SkPaint& src, const LayerInfo&);
    111     };
    112 
    113     typedef SkDrawLooper INHERITED;
    114 
    115 public:
    116     class SK_API Builder {
    117     public:
    118         Builder();
    119         ~Builder();
    120 
    121         /**
    122          *  Call for each layer you want to add (from top to bottom).
    123          *  This returns a paint you can modify, but that ptr is only valid until
    124          *  the next call made to addLayer().
    125          */
    126         SkPaint* addLayer(const LayerInfo&);
    127 
    128         /**
    129          *  This layer will draw with the original paint, at the specified offset
    130          */
    131         void addLayer(SkScalar dx, SkScalar dy);
    132 
    133         /**
    134          *  This layer will with the original paint and no offset.
    135          */
    136         void addLayer() { this->addLayer(0, 0); }
    137 
    138         /// Similar to addLayer, but adds a layer to the top.
    139         SkPaint* addLayerOnTop(const LayerInfo&);
    140 
    141         /**
    142           * Pass list of layers on to newly built looper and return it. This will
    143           * also reset the builder, so it can be used to build another looper.
    144           */
    145         SkLayerDrawLooper* detachLooper();
    146 
    147     private:
    148         Rec* fRecs;
    149         Rec* fTopRec;
    150         int  fCount;
    151     };
    152 };
    153 
    154 #endif
    155