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