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