blob: 8627ae4b8e0fa530e3cfaecb32079c3685cede51 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#ifndef SkLayerDrawLooper_DEFINED
2#define SkLayerDrawLooper_DEFINED
3
4#include "SkDrawLooper.h"
reed@google.com0716c632011-04-12 18:32:06 +00005#include "SkXfermode.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00006
7struct SkPoint;
8
bsalomon@google.com8c3ff172011-04-15 15:42:24 +00009class SK_API SkLayerDrawLooper : public SkDrawLooper {
reed@android.com8a1c16f2008-12-17 15:59:43 +000010public:
11 SkLayerDrawLooper();
12 virtual ~SkLayerDrawLooper();
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +000013
reed@google.com0716c632011-04-12 18:32:06 +000014 /**
15 * Bits specifies which aspects of the layer's paint should replace the
16 * corresponding aspects on the draw's paint.
17 * kEntirePaint_Bits means use the layer's paint completely.
18 * 0 means ignore the layer's paint.
19 */
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +000020 enum Bits {
reed@google.com0716c632011-04-12 18:32:06 +000021 kStyle_Bit = 1 << 0, //!< use this layer's Style/stroke settings
22 kTextSkewX_Bit = 1 << 1, //!< use this layer's textskewx
23 kPathEffect_Bit = 1 << 2, //!< use this layer's patheffect
24 kMaskFilter_Bit = 1 << 3, //!< use this layer's maskfilter
25 kShader_Bit = 1 << 4, //!< use this layer's shader
26 kColorFilter_Bit = 1 << 5, //!< use this layer's colorfilter
27 kXfermode_Bit = 1 << 6, //!< use this layer's xfermode
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +000028
29 kEntirePaint_Bits = -1, //!< use this layer's paint entirely
30 };
31 typedef int32_t BitFlags;
reed@google.com0716c632011-04-12 18:32:06 +000032
33 /**
34 * Info for how to apply the layer's paint and offset.
35 *
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000036 * fFlagsMask selects which flags in the layer's paint should be applied.
37 * result = (draw-flags & ~fFlagsMask) | (layer-flags & fFlagsMask)
38 * In the extreme:
39 * If fFlagsMask is 0, we ignore all of the layer's flags
40 * If fFlagsMask is -1, we use all of the layer's flags
41 *
reed@google.com0716c632011-04-12 18:32:06 +000042 * fColorMode controls how we compute the final color for the layer:
43 * The layer's paint's color is treated as the SRC
44 * The draw's paint's color is treated as the DST
45 * final-color = Mode(layers-color, draws-color);
46 * Any SkXfermode::Mode will work. Two common choices are:
47 * kSrc_Mode: to use the layer's color, ignoring the draw's
48 * kDst_Mode: to just keep the draw's color, ignoring the layer's
49 */
bsalomon@google.com8c3ff172011-04-15 15:42:24 +000050 struct SK_API LayerInfo {
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000051 uint32_t fFlagsMask; // SkPaint::Flags
reed@google.com0716c632011-04-12 18:32:06 +000052 BitFlags fPaintBits;
53 SkXfermode::Mode fColorMode;
54 SkVector fOffset;
55 bool fPostTranslate; //!< applies to fOffset
56
57 /**
58 * Initial the LayerInfo. Defaults to settings that will draw the
59 * layer with no changes: e.g.
60 * fPaintBits == 0
61 * fColorMode == kDst_Mode
62 * fOffset == (0, 0)
63 */
64 LayerInfo();
65 };
66
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +000067 /**
68 * Call for each layer you want to add (from top to bottom).
69 * This returns a paint you can modify, but that ptr is only valid until
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000070 * the next call made to addLayer().
reed@android.com8a1c16f2008-12-17 15:59:43 +000071 */
reed@google.com0716c632011-04-12 18:32:06 +000072 SkPaint* addLayer(const LayerInfo&);
73
74 /**
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000075 * This layer will draw with the original paint, ad the specified offset
reed@google.com0716c632011-04-12 18:32:06 +000076 */
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000077 void addLayer(SkScalar dx, SkScalar dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +000078
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +000079 /**
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000080 * This layer will with the original paint and no offset.
reed@android.com8a1c16f2008-12-17 15:59:43 +000081 */
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000082 void addLayer() { this->addLayer(0, 0); }
reed@android.com8a1c16f2008-12-17 15:59:43 +000083
84 // overrides from SkDrawLooper
reed@google.com4e2b3d32011-04-07 14:18:59 +000085 virtual void init(SkCanvas*);
86 virtual bool next(SkCanvas*, SkPaint* paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +000087
88 // must be public for Registrar :(
89 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
90 return SkNEW_ARGS(SkLayerDrawLooper, (buffer));
91 }
92
93protected:
94 SkLayerDrawLooper(SkFlattenableReadBuffer&);
95
96 // overrides from SkFlattenable
97 virtual void flatten(SkFlattenableWriteBuffer& );
98 virtual Factory getFactory() { return CreateProc; }
99
100private:
101 struct Rec {
102 Rec* fNext;
103 SkPaint fPaint;
reed@google.com0716c632011-04-12 18:32:06 +0000104 LayerInfo fInfo;
105
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106 static Rec* Reverse(Rec*);
107 };
108 Rec* fRecs;
109 int fCount;
reed@google.com4e2b3d32011-04-07 14:18:59 +0000110
111 // state-machine during the init/next cycle
112 Rec* fCurrRec;
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +0000113
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000114 static void ApplyInfo(SkPaint* dst, const SkPaint& src, const LayerInfo&);
mike@reedtribe.org0e2810b2011-04-08 02:41:54 +0000115
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 class MyRegistrar : public SkFlattenable::Registrar {
117 public:
118 MyRegistrar();
119 };
120
121 typedef SkDrawLooper INHERITED;
122};
123
124
125#endif