SkLayerDrawLooper.cpp revision 091a594dbc4116ec2e54724432472bf37dae794a
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 "SkReadBuffer.h" 11#include "SkWriteBuffer.h" 12#include "SkLayerDrawLooper.h" 13#include "SkString.h" 14#include "SkStringUtils.h" 15#include "SkUnPreMultiply.h" 16 17SkLayerDrawLooper::LayerInfo::LayerInfo() { 18 fPaintBits = 0; // ignore our paint fields 19 fColorMode = SkXfermode::kDst_Mode; // ignore our color 20 fOffset.set(0, 0); 21 fPostTranslate = false; 22} 23 24SkLayerDrawLooper::SkLayerDrawLooper() 25 : fRecs(NULL), 26 fTopRec(NULL), 27 fCount(0) { 28} 29 30SkLayerDrawLooper::~SkLayerDrawLooper() { 31 Rec* rec = fRecs; 32 while (rec) { 33 Rec* next = rec->fNext; 34 SkDELETE(rec); 35 rec = next; 36 } 37} 38 39SkLayerDrawLooper::Context* SkLayerDrawLooper::createContext(SkCanvas* canvas, void* storage) const { 40 canvas->save(); 41 return SkNEW_PLACEMENT_ARGS(storage, LayerDrawLooperContext, (this)); 42} 43 44static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) { 45 switch (mode) { 46 case SkXfermode::kSrc_Mode: 47 return src; 48 case SkXfermode::kDst_Mode: 49 return dst; 50 default: { 51 SkPMColor pmS = SkPreMultiplyColor(src); 52 SkPMColor pmD = SkPreMultiplyColor(dst); 53 SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD); 54 return SkUnPreMultiply::PMColorToColor(result); 55 } 56 } 57} 58 59// Even with kEntirePaint_Bits, we always ensure that the master paint's 60// text-encoding is respected, since that controls how we interpret the 61// text/length parameters of a draw[Pos]Text call. 62void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo( 63 SkPaint* dst, const SkPaint& src, const LayerInfo& info) { 64 65 dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode)); 66 67 BitFlags bits = info.fPaintBits; 68 SkPaint::TextEncoding encoding = dst->getTextEncoding(); 69 70 if (0 == bits) { 71 return; 72 } 73 if (kEntirePaint_Bits == bits) { 74 // we've already computed these, so save it from the assignment 75 uint32_t f = dst->getFlags(); 76 SkColor c = dst->getColor(); 77 *dst = src; 78 dst->setFlags(f); 79 dst->setColor(c); 80 dst->setTextEncoding(encoding); 81 return; 82 } 83 84 if (bits & kStyle_Bit) { 85 dst->setStyle(src.getStyle()); 86 dst->setStrokeWidth(src.getStrokeWidth()); 87 dst->setStrokeMiter(src.getStrokeMiter()); 88 dst->setStrokeCap(src.getStrokeCap()); 89 dst->setStrokeJoin(src.getStrokeJoin()); 90 } 91 92 if (bits & kTextSkewX_Bit) { 93 dst->setTextSkewX(src.getTextSkewX()); 94 } 95 96 if (bits & kPathEffect_Bit) { 97 dst->setPathEffect(src.getPathEffect()); 98 } 99 if (bits & kMaskFilter_Bit) { 100 dst->setMaskFilter(src.getMaskFilter()); 101 } 102 if (bits & kShader_Bit) { 103 dst->setShader(src.getShader()); 104 } 105 if (bits & kColorFilter_Bit) { 106 dst->setColorFilter(src.getColorFilter()); 107 } 108 if (bits & kXfermode_Bit) { 109 dst->setXfermode(src.getXfermode()); 110 } 111 112 // we don't override these 113#if 0 114 dst->setTypeface(src.getTypeface()); 115 dst->setTextSize(src.getTextSize()); 116 dst->setTextScaleX(src.getTextScaleX()); 117 dst->setRasterizer(src.getRasterizer()); 118 dst->setLooper(src.getLooper()); 119 dst->setTextEncoding(src.getTextEncoding()); 120 dst->setHinting(src.getHinting()); 121#endif 122} 123 124// Should we add this to canvas? 125static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) { 126 SkMatrix m = canvas->getTotalMatrix(); 127 m.postTranslate(dx, dy); 128 canvas->setMatrix(m); 129} 130 131SkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext( 132 const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {} 133 134bool SkLayerDrawLooper::LayerDrawLooperContext::next(SkCanvas* canvas, 135 SkPaint* paint) { 136 canvas->restore(); 137 if (NULL == fCurrRec) { 138 return false; 139 } 140 141 ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo); 142 143 canvas->save(); 144 if (fCurrRec->fInfo.fPostTranslate) { 145 postTranslate(canvas, fCurrRec->fInfo.fOffset.fX, 146 fCurrRec->fInfo.fOffset.fY); 147 } else { 148 canvas->translate(fCurrRec->fInfo.fOffset.fX, 149 fCurrRec->fInfo.fOffset.fY); 150 } 151 fCurrRec = fCurrRec->fNext; 152 153 return true; 154} 155 156/////////////////////////////////////////////////////////////////////////////// 157 158void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const { 159 this->INHERITED::flatten(buffer); 160 161#ifdef SK_DEBUG 162 { 163 Rec* rec = fRecs; 164 int count = 0; 165 while (rec) { 166 rec = rec->fNext; 167 count += 1; 168 } 169 SkASSERT(count == fCount); 170 } 171#endif 172 173 buffer.writeInt(fCount); 174 175 Rec* rec = fRecs; 176 for (int i = 0; i < fCount; i++) { 177 // Legacy "flagsmask" field -- now ignored, remove when we bump version 178 buffer.writeInt(0); 179 180 buffer.writeInt(rec->fInfo.fPaintBits); 181 buffer.writeInt(rec->fInfo.fColorMode); 182 buffer.writePoint(rec->fInfo.fOffset); 183 buffer.writeBool(rec->fInfo.fPostTranslate); 184 buffer.writePaint(rec->fPaint); 185 rec = rec->fNext; 186 } 187} 188 189SkFlattenable* SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) { 190 int count = buffer.readInt(); 191 192 Builder builder; 193 for (int i = 0; i < count; i++) { 194 LayerInfo info; 195 // Legacy "flagsmask" field -- now ignored, remove when we bump version 196 (void)buffer.readInt(); 197 198 info.fPaintBits = buffer.readInt(); 199 info.fColorMode = (SkXfermode::Mode)buffer.readInt(); 200 buffer.readPoint(&info.fOffset); 201 info.fPostTranslate = buffer.readBool(); 202 buffer.readPaint(builder.addLayerOnTop(info)); 203 } 204 SkLayerDrawLooper* looper = builder.detachLooper(); 205 SkASSERT(count == looper->fCount); 206 207#ifdef SK_DEBUG 208 { 209 Rec* rec = looper->fRecs; 210 int n = 0; 211 while (rec) { 212 rec = rec->fNext; 213 n += 1; 214 } 215 SkASSERT(count == n); 216 } 217#endif 218 219 return looper; 220} 221 222#ifndef SK_IGNORE_TO_STRING 223void SkLayerDrawLooper::toString(SkString* str) const { 224 str->appendf("SkLayerDrawLooper (%d): ", fCount); 225 226 Rec* rec = fRecs; 227 for (int i = 0; i < fCount; i++) { 228 str->appendf("%d: paintBits: (", i); 229 if (0 == rec->fInfo.fPaintBits) { 230 str->append("None"); 231 } else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) { 232 str->append("EntirePaint"); 233 } else { 234 bool needSeparator = false; 235 SkAddFlagToString(str, SkToBool(kStyle_Bit & rec->fInfo.fPaintBits), "Style", 236 &needSeparator); 237 SkAddFlagToString(str, SkToBool(kTextSkewX_Bit & rec->fInfo.fPaintBits), "TextSkewX", 238 &needSeparator); 239 SkAddFlagToString(str, SkToBool(kPathEffect_Bit & rec->fInfo.fPaintBits), "PathEffect", 240 &needSeparator); 241 SkAddFlagToString(str, SkToBool(kMaskFilter_Bit & rec->fInfo.fPaintBits), "MaskFilter", 242 &needSeparator); 243 SkAddFlagToString(str, SkToBool(kShader_Bit & rec->fInfo.fPaintBits), "Shader", 244 &needSeparator); 245 SkAddFlagToString(str, SkToBool(kColorFilter_Bit & rec->fInfo.fPaintBits), "ColorFilter", 246 &needSeparator); 247 SkAddFlagToString(str, SkToBool(kXfermode_Bit & rec->fInfo.fPaintBits), "Xfermode", 248 &needSeparator); 249 } 250 str->append(") "); 251 252 static const char* gModeStrings[SkXfermode::kLastMode+1] = { 253 "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn", 254 "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus", 255 "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge", 256 "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion" 257 }; 258 259 str->appendf("mode: %s ", gModeStrings[rec->fInfo.fColorMode]); 260 261 str->append("offset: ("); 262 str->appendScalar(rec->fInfo.fOffset.fX); 263 str->append(", "); 264 str->appendScalar(rec->fInfo.fOffset.fY); 265 str->append(") "); 266 267 str->append("postTranslate: "); 268 if (rec->fInfo.fPostTranslate) { 269 str->append("true "); 270 } else { 271 str->append("false "); 272 } 273 274 rec->fPaint.toString(str); 275 rec = rec->fNext; 276 } 277} 278#endif 279 280SkLayerDrawLooper::Builder::Builder() 281 : fRecs(NULL), 282 fTopRec(NULL), 283 fCount(0) { 284} 285 286SkLayerDrawLooper::Builder::~Builder() { 287 Rec* rec = fRecs; 288 while (rec) { 289 Rec* next = rec->fNext; 290 SkDELETE(rec); 291 rec = next; 292 } 293} 294 295SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) { 296 fCount += 1; 297 298 Rec* rec = SkNEW(Rec); 299 rec->fNext = fRecs; 300 rec->fInfo = info; 301 fRecs = rec; 302 if (NULL == fTopRec) { 303 fTopRec = rec; 304 } 305 306 return &rec->fPaint; 307} 308 309void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) { 310 LayerInfo info; 311 312 info.fOffset.set(dx, dy); 313 (void)this->addLayer(info); 314} 315 316SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) { 317 fCount += 1; 318 319 Rec* rec = SkNEW(Rec); 320 rec->fNext = NULL; 321 rec->fInfo = info; 322 if (NULL == fRecs) { 323 fRecs = rec; 324 } else { 325 SkASSERT(NULL != fTopRec); 326 fTopRec->fNext = rec; 327 } 328 fTopRec = rec; 329 330 return &rec->fPaint; 331} 332 333SkLayerDrawLooper* SkLayerDrawLooper::Builder::detachLooper() { 334 SkLayerDrawLooper* looper = SkNEW(SkLayerDrawLooper); 335 looper->fCount = fCount; 336 looper->fRecs = fRecs; 337 338 fCount = 0; 339 fRecs = NULL; 340 fTopRec = NULL; 341 342 return looper; 343} 344