SkLayerDrawLooper.cpp revision 8b0e8ac5f582de80356019406e2975079bf0829d
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 224SkLayerDrawLooper::SkLayerDrawLooper(SkReadBuffer& buffer) 225 : INHERITED(buffer), 226 fRecs(NULL), 227 fTopRec(NULL), 228 fCount(0), 229 fCurrRec(NULL) { 230 int count = buffer.readInt(); 231 232 for (int i = 0; i < count; i++) { 233 LayerInfo info; 234 info.fFlagsMask = buffer.readInt(); 235 info.fPaintBits = buffer.readInt(); 236 info.fColorMode = (SkXfermode::Mode)buffer.readInt(); 237 buffer.readPoint(&info.fOffset); 238 info.fPostTranslate = buffer.readBool(); 239 buffer.readPaint(this->addLayerOnTop(info)); 240 } 241 SkASSERT(count == fCount); 242 243#ifdef SK_DEBUG 244 { 245 Rec* rec = fRecs; 246 int n = 0; 247 while (rec) { 248 rec = rec->fNext; 249 n += 1; 250 } 251 SkASSERT(count == n); 252 } 253#endif 254} 255 256#ifdef SK_DEVELOPER 257void SkLayerDrawLooper::toString(SkString* str) const { 258 str->appendf("SkLayerDrawLooper (%d): ", fCount); 259 260 Rec* rec = fRecs; 261 for (int i = 0; i < fCount; i++) { 262 str->appendf("%d: ", i); 263 264 str->append("flagsMask: ("); 265 if (0 == rec->fInfo.fFlagsMask) { 266 str->append("None"); 267 } else { 268 bool needSeparator = false; 269 SkAddFlagToString(str, SkToBool(SkPaint::kAntiAlias_Flag & rec->fInfo.fFlagsMask), 270 "AntiAlias", &needSeparator); 271// SkAddFlagToString(str, SkToBool(SkPaint::kFilterBitmap_Flag & rec->fInfo.fFlagsMask), "FilterBitmap", &needSeparator); 272 SkAddFlagToString(str, SkToBool(SkPaint::kDither_Flag & rec->fInfo.fFlagsMask), 273 "Dither", &needSeparator); 274 SkAddFlagToString(str, SkToBool(SkPaint::kUnderlineText_Flag & rec->fInfo.fFlagsMask), 275 "UnderlineText", &needSeparator); 276 SkAddFlagToString(str, SkToBool(SkPaint::kStrikeThruText_Flag & rec->fInfo.fFlagsMask), 277 "StrikeThruText", &needSeparator); 278 SkAddFlagToString(str, SkToBool(SkPaint::kFakeBoldText_Flag & rec->fInfo.fFlagsMask), 279 "FakeBoldText", &needSeparator); 280 SkAddFlagToString(str, SkToBool(SkPaint::kLinearText_Flag & rec->fInfo.fFlagsMask), 281 "LinearText", &needSeparator); 282 SkAddFlagToString(str, SkToBool(SkPaint::kSubpixelText_Flag & rec->fInfo.fFlagsMask), 283 "SubpixelText", &needSeparator); 284 SkAddFlagToString(str, SkToBool(SkPaint::kDevKernText_Flag & rec->fInfo.fFlagsMask), 285 "DevKernText", &needSeparator); 286 SkAddFlagToString(str, SkToBool(SkPaint::kLCDRenderText_Flag & rec->fInfo.fFlagsMask), 287 "LCDRenderText", &needSeparator); 288 SkAddFlagToString(str, SkToBool(SkPaint::kEmbeddedBitmapText_Flag & rec->fInfo.fFlagsMask), 289 "EmbeddedBitmapText", &needSeparator); 290 SkAddFlagToString(str, SkToBool(SkPaint::kAutoHinting_Flag & rec->fInfo.fFlagsMask), 291 "Autohinted", &needSeparator); 292 SkAddFlagToString(str, SkToBool(SkPaint::kVerticalText_Flag & rec->fInfo.fFlagsMask), 293 "VerticalText", &needSeparator); 294 SkAddFlagToString(str, SkToBool(SkPaint::kGenA8FromLCD_Flag & rec->fInfo.fFlagsMask), 295 "GenA8FromLCD", &needSeparator); 296 } 297 str->append(") "); 298 299 str->append("paintBits: ("); 300 if (0 == rec->fInfo.fPaintBits) { 301 str->append("None"); 302 } else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) { 303 str->append("EntirePaint"); 304 } else { 305 bool needSeparator = false; 306 SkAddFlagToString(str, SkToBool(kStyle_Bit & rec->fInfo.fPaintBits), "Style", 307 &needSeparator); 308 SkAddFlagToString(str, SkToBool(kTextSkewX_Bit & rec->fInfo.fPaintBits), "TextSkewX", 309 &needSeparator); 310 SkAddFlagToString(str, SkToBool(kPathEffect_Bit & rec->fInfo.fPaintBits), "PathEffect", 311 &needSeparator); 312 SkAddFlagToString(str, SkToBool(kMaskFilter_Bit & rec->fInfo.fPaintBits), "MaskFilter", 313 &needSeparator); 314 SkAddFlagToString(str, SkToBool(kShader_Bit & rec->fInfo.fPaintBits), "Shader", 315 &needSeparator); 316 SkAddFlagToString(str, SkToBool(kColorFilter_Bit & rec->fInfo.fPaintBits), "ColorFilter", 317 &needSeparator); 318 SkAddFlagToString(str, SkToBool(kXfermode_Bit & rec->fInfo.fPaintBits), "Xfermode", 319 &needSeparator); 320 } 321 str->append(") "); 322 323 static const char* gModeStrings[SkXfermode::kLastMode+1] = { 324 "kClear", "kSrc", "kDst", "kSrcOver", "kDstOver", "kSrcIn", "kDstIn", 325 "kSrcOut", "kDstOut", "kSrcATop", "kDstATop", "kXor", "kPlus", 326 "kMultiply", "kScreen", "kOverlay", "kDarken", "kLighten", "kColorDodge", 327 "kColorBurn", "kHardLight", "kSoftLight", "kDifference", "kExclusion" 328 }; 329 330 str->appendf("mode: %s ", gModeStrings[rec->fInfo.fColorMode]); 331 332 str->append("offset: ("); 333 str->appendScalar(rec->fInfo.fOffset.fX); 334 str->append(", "); 335 str->appendScalar(rec->fInfo.fOffset.fY); 336 str->append(") "); 337 338 str->append("postTranslate: "); 339 if (rec->fInfo.fPostTranslate) { 340 str->append("true "); 341 } else { 342 str->append("false "); 343 } 344 345 rec->fPaint.toString(str); 346 rec = rec->fNext; 347 } 348} 349#endif 350