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