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