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 
contextSize()76     size_t contextSize() const override { return sizeof(LayerDrawLooperContext); }
77 
78     bool asABlurShadow(BlurShadowRec* rec) const override;
79 
SK_TO_STRING_OVERRIDE()80     SK_TO_STRING_OVERRIDE()
81 
82     Factory getFactory() const override { return CreateProc; }
83     static sk_sp<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          */
addLayer()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         sk_sp<SkDrawLooper> detach();
146 #ifdef SK_SUPPORT_LEGACY_MINOR_EFFECT_PTR
detachLooper()147         SkLayerDrawLooper* detachLooper() {
148             return (SkLayerDrawLooper*)this->detach().release();
149         }
150 #endif
151 
152     private:
153         Rec* fRecs;
154         Rec* fTopRec;
155         int  fCount;
156     };
157 };
158 
159 #endif
160