SkLayerDrawLooper.cpp revision 3c898186c9082c535e589807752a0a9dc5d28aa0
1#include "SkCanvas.h" 2#include "SkColor.h" 3#include "SkLayerDrawLooper.h" 4#include "SkPaint.h" 5#include "SkUnPreMultiply.h" 6 7SkLayerDrawLooper::LayerInfo::LayerInfo() { 8 fFlagsMask = 0; // ignore our paint flags 9 fPaintBits = 0; // ignore our paint fields 10 fColorMode = SkXfermode::kDst_Mode; // ignore our color 11 fOffset.set(0, 0); 12 fPostTranslate = false; 13} 14 15SkLayerDrawLooper::SkLayerDrawLooper() 16 : fRecs(NULL), 17 fCount(0), 18 fCurrRec(NULL) { 19} 20 21SkLayerDrawLooper::~SkLayerDrawLooper() { 22 Rec* rec = fRecs; 23 while (rec) { 24 Rec* next = rec->fNext; 25 SkDELETE(rec); 26 rec = next; 27 } 28} 29 30SkPaint* SkLayerDrawLooper::addLayer(const LayerInfo& info) { 31 fCount += 1; 32 33 Rec* rec = SkNEW(Rec); 34 rec->fNext = fRecs; 35 rec->fInfo = info; 36 fRecs = rec; 37 38 return &rec->fPaint; 39} 40 41void SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) { 42 LayerInfo info; 43 44 info.fOffset.set(dx, dy); 45 (void)this->addLayer(info); 46} 47 48void SkLayerDrawLooper::init(SkCanvas* canvas) { 49 fCurrRec = fRecs; 50 canvas->save(SkCanvas::kMatrix_SaveFlag); 51} 52 53static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) { 54 switch (mode) { 55 case SkXfermode::kSrc_Mode: 56 return src; 57 case SkXfermode::kDst_Mode: 58 return dst; 59 default: { 60 SkPMColor pmS = SkPreMultiplyColor(src); 61 SkPMColor pmD = SkPreMultiplyColor(dst); 62 SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD); 63 return SkUnPreMultiply::PMColorToColor(result); 64 } 65 } 66} 67 68void SkLayerDrawLooper::ApplyInfo(SkPaint* dst, const SkPaint& src, 69 const LayerInfo& info) { 70 71 uint32_t mask = info.fFlagsMask; 72 dst->setFlags((dst->getFlags() & ~mask) | (src.getFlags() & mask)); 73 74 dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode)); 75 76 BitFlags bits = info.fPaintBits; 77 78 if (0 == bits) { 79 return; 80 } 81 if (kEntirePaint_Bits == bits) { 82 // we've already computed these, so save it from the assignment 83 uint32_t f = dst->getFlags(); 84 SkColor c = dst->getColor(); 85 *dst = src; 86 dst->setFlags(f); 87 dst->setColor(c); 88 return; 89 } 90 91 if (bits & kStyle_Bit) { 92 dst->setStyle(src.getStyle()); 93 dst->setStrokeWidth(src.getStrokeWidth()); 94 dst->setStrokeMiter(src.getStrokeMiter()); 95 dst->setStrokeCap(src.getStrokeCap()); 96 dst->setStrokeJoin(src.getStrokeJoin()); 97 } 98 99 if (bits & kTextSkewX_Bit) { 100 dst->setTextSkewX(src.getTextSkewX()); 101 } 102 103 if (bits & kPathEffect_Bit) { 104 dst->setPathEffect(src.getPathEffect()); 105 } 106 if (bits & kMaskFilter_Bit) { 107 dst->setMaskFilter(src.getMaskFilter()); 108 } 109 if (bits & kShader_Bit) { 110 dst->setShader(src.getShader()); 111 } 112 if (bits & kColorFilter_Bit) { 113 dst->setColorFilter(src.getColorFilter()); 114 } 115 if (bits & kXfermode_Bit) { 116 dst->setXfermode(src.getXfermode()); 117 } 118 119 // we never copy these 120#if 0 121 dst->setFlags(src.getFlags()); 122 dst->setTypeface(src.getTypeface()); 123 dst->setTextSize(src.getTextSize()); 124 dst->setTextScaleX(src.getTextScaleX()); 125 dst->setTextSkewX(src.getTextSkewX()); 126 dst->setRasterizer(src.getRasterizer()); 127 dst->setLooper(src.getLooper()); 128 dst->setTextEncoding(src.getTextEncoding()); 129 dst->setHinting(src.getHinting()); 130#endif 131} 132 133// Should we add this to canvas? 134static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) { 135 SkMatrix m = canvas->getTotalMatrix(); 136 m.postTranslate(dx, dy); 137 canvas->setMatrix(m); 138} 139 140bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) { 141 canvas->restore(); 142 if (NULL == fCurrRec) { 143 return false; 144 } 145 146 ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo); 147 148 canvas->save(SkCanvas::kMatrix_SaveFlag); 149 if (fCurrRec->fInfo.fPostTranslate) { 150 postTranslate(canvas, fCurrRec->fInfo.fOffset.fX, 151 fCurrRec->fInfo.fOffset.fY); 152 } else { 153 canvas->translate(fCurrRec->fInfo.fOffset.fX, fCurrRec->fInfo.fOffset.fY); 154 } 155 fCurrRec = fCurrRec->fNext; 156 157 return true; 158} 159 160SkLayerDrawLooper::Rec* SkLayerDrawLooper::Rec::Reverse(Rec* head) { 161 Rec* rec = head; 162 Rec* prev = NULL; 163 while (rec) { 164 Rec* next = rec->fNext; 165 rec->fNext = prev; 166 prev = rec; 167 rec = next; 168 } 169 return prev; 170} 171 172/////////////////////////////////////////////////////////////////////////////// 173 174void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) { 175 this->INHERITED::flatten(buffer); 176 177#ifdef SK_DEBUG 178 { 179 Rec* rec = fRecs; 180 int count = 0; 181 while (rec) { 182 rec = rec->fNext; 183 count += 1; 184 } 185 SkASSERT(count == fCount); 186 } 187#endif 188 189 buffer.writeInt(fCount); 190 191 Rec* rec = fRecs; 192 for (int i = 0; i < fCount; i++) { 193 buffer.writeInt(rec->fInfo.fPaintBits); 194 buffer.writeInt(rec->fInfo.fColorMode); 195 buffer.writeScalar(rec->fInfo.fOffset.fX); 196 buffer.writeScalar(rec->fInfo.fOffset.fY); 197 buffer.writeBool(rec->fInfo.fPostTranslate); 198 rec->fPaint.flatten(buffer); 199 rec = rec->fNext; 200 } 201} 202 203SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer) 204 : INHERITED(buffer), 205 fRecs(NULL), 206 fCount(0), 207 fCurrRec(NULL) { 208 int count = buffer.readInt(); 209 210 for (int i = 0; i < count; i++) { 211 LayerInfo info; 212 info.fPaintBits = buffer.readInt(); 213 info.fColorMode = (SkXfermode::Mode)buffer.readInt(); 214 info.fOffset.fX = buffer.readScalar(); 215 info.fOffset.fY = buffer.readScalar(); 216 info.fPostTranslate = buffer.readBool(); 217 this->addLayer(info)->unflatten(buffer); 218 } 219 SkASSERT(count == fCount); 220 221 // we're in reverse order, so fix it now 222 fRecs = Rec::Reverse(fRecs); 223 224#ifdef SK_DEBUG 225 { 226 Rec* rec = fRecs; 227 int n = 0; 228 while (rec) { 229 rec = rec->fNext; 230 n += 1; 231 } 232 SkASSERT(count == n); 233 } 234#endif 235} 236 237/////////////////////////////////////////////////////////////////////////////// 238 239static SkFlattenable::Registrar gReg("SkLayerDrawLooper", 240 SkLayerDrawLooper::CreateProc); 241