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