SkLayerDrawLooper.h revision 0f10f7bf1fb43ca6346dc220a076773b1f19a367
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 16class SK_API SkLayerDrawLooper : public SkDrawLooper { 17public: 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 107protected: 108 virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; 109 110private: 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 141public: 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 181