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