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