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