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