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 SkLayerDrawLooper::LayerInfo::LayerInfo() { 17 fFlagsMask = 0; // ignore our paint flags 18 fPaintBits = 0; // ignore our paint fields 19 fColorMode = SkXfermode::kDst_Mode; // ignore our color 20 fOffset.set(0, 0); 21 fPostTranslate = false; 22 } 23 24 SkLayerDrawLooper::SkLayerDrawLooper() 25 : fRecs(NULL), 26 fTopRec(NULL), 27 fCount(0), 28 fCurrRec(NULL) { 29 } 30 31 SkLayerDrawLooper::~SkLayerDrawLooper() { 32 Rec* rec = fRecs; 33 while (rec) { 34 Rec* next = rec->fNext; 35 SkDELETE(rec); 36 rec = next; 37 } 38 } 39 40 SkPaint* SkLayerDrawLooper::addLayer(const LayerInfo& info) { 41 fCount += 1; 42 43 Rec* rec = SkNEW(Rec); 44 rec->fNext = fRecs; 45 rec->fInfo = info; 46 fRecs = rec; 47 if (NULL == fTopRec) { 48 fTopRec = rec; 49 } 50 51 return &rec->fPaint; 52 } 53 54 void SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) { 55 LayerInfo info; 56 57 info.fOffset.set(dx, dy); 58 (void)this->addLayer(info); 59 } 60 61 SkPaint* SkLayerDrawLooper::addLayerOnTop(const LayerInfo& info) { 62 fCount += 1; 63 64 Rec* rec = SkNEW(Rec); 65 rec->fNext = NULL; 66 rec->fInfo = info; 67 if (NULL == fRecs) { 68 fRecs = rec; 69 } else { 70 SkASSERT(NULL != fTopRec); 71 fTopRec->fNext = rec; 72 } 73 fTopRec = rec; 74 75 return &rec->fPaint; 76 } 77 78 void SkLayerDrawLooper::init(SkCanvas* canvas) { 79 fCurrRec = fRecs; 80 canvas->save(SkCanvas::kMatrix_SaveFlag); 81 } 82 83 static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) { 84 switch (mode) { 85 case SkXfermode::kSrc_Mode: 86 return src; 87 case SkXfermode::kDst_Mode: 88 return dst; 89 default: { 90 SkPMColor pmS = SkPreMultiplyColor(src); 91 SkPMColor pmD = SkPreMultiplyColor(dst); 92 SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD); 93 return SkUnPreMultiply::PMColorToColor(result); 94 } 95 } 96 } 97 98 // Even with kEntirePaint_Bits, we always ensure that the master paint's 99 // text-encoding is respected, since that controls how we interpret the 100 // text/length parameters of a draw[Pos]Text call. 101 void SkLayerDrawLooper::ApplyInfo(SkPaint* dst, const SkPaint& src, 102 const LayerInfo& info) { 103 104 uint32_t mask = info.fFlagsMask; 105 dst->setFlags((dst->getFlags() & ~mask) | (src.getFlags() & mask)); 106 dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode)); 107 108 BitFlags bits = info.fPaintBits; 109 SkPaint::TextEncoding encoding = dst->getTextEncoding(); 110 111 if (0 == bits) { 112 return; 113 } 114 if (kEntirePaint_Bits == bits) { 115 // we've already computed these, so save it from the assignment 116 uint32_t f = dst->getFlags(); 117 SkColor c = dst->getColor(); 118 *dst = src; 119 dst->setFlags(f); 120 dst->setColor(c); 121 dst->setTextEncoding(encoding); 122 return; 123 } 124 125 if (bits & kStyle_Bit) { 126 dst->setStyle(src.getStyle()); 127 dst->setStrokeWidth(src.getStrokeWidth()); 128 dst->setStrokeMiter(src.getStrokeMiter()); 129 dst->setStrokeCap(src.getStrokeCap()); 130 dst->setStrokeJoin(src.getStrokeJoin()); 131 } 132 133 if (bits & kTextSkewX_Bit) { 134 dst->setTextSkewX(src.getTextSkewX()); 135 } 136 137 if (bits & kPathEffect_Bit) { 138 dst->setPathEffect(src.getPathEffect()); 139 } 140 if (bits & kMaskFilter_Bit) { 141 dst->setMaskFilter(src.getMaskFilter()); 142 } 143 if (bits & kShader_Bit) { 144 dst->setShader(src.getShader()); 145 } 146 if (bits & kColorFilter_Bit) { 147 dst->setColorFilter(src.getColorFilter()); 148 } 149 if (bits & kXfermode_Bit) { 150 dst->setXfermode(src.getXfermode()); 151 } 152 153 // we don't override these 154 #if 0 155 dst->setTypeface(src.getTypeface()); 156 dst->setTextSize(src.getTextSize()); 157 dst->setTextScaleX(src.getTextScaleX()); 158 dst->setRasterizer(src.getRasterizer()); 159 dst->setLooper(src.getLooper()); 160 dst->setTextEncoding(src.getTextEncoding()); 161 dst->setHinting(src.getHinting()); 162 #endif 163 } 164 165 // Should we add this to canvas? 166 static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) { 167 SkMatrix m = canvas->getTotalMatrix(); 168 m.postTranslate(dx, dy); 169 canvas->setMatrix(m); 170 } 171 172 bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) { 173 canvas->restore(); 174 if (NULL == fCurrRec) { 175 return false; 176 } 177 178 ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo); 179 180 canvas->save(SkCanvas::kMatrix_SaveFlag); 181 if (fCurrRec->fInfo.fPostTranslate) { 182 postTranslate(canvas, fCurrRec->fInfo.fOffset.fX, 183 fCurrRec->fInfo.fOffset.fY); 184 } else { 185 canvas->translate(fCurrRec->fInfo.fOffset.fX, fCurrRec->fInfo.fOffset.fY); 186 } 187 fCurrRec = fCurrRec->fNext; 188 189 return true; 190 } 191 192 /////////////////////////////////////////////////////////////////////////////// 193 194 void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const { 195 this->INHERITED::flatten(buffer); 196 197 #ifdef SK_DEBUG 198 { 199 Rec* rec = fRecs; 200 int count = 0; 201 while (rec) { 202 rec = rec->fNext; 203 count += 1; 204 } 205 SkASSERT(count == fCount); 206 } 207 #endif 208 209 buffer.writeInt(fCount); 210 211 Rec* rec = fRecs; 212 for (int i = 0; i < fCount; i++) { 213 buffer.writeInt(rec->fInfo.fFlagsMask); 214 buffer.writeInt(rec->fInfo.fPaintBits); 215 buffer.writeInt(rec->fInfo.fColorMode); 216 buffer.writePoint(rec->fInfo.fOffset); 217 buffer.writeBool(rec->fInfo.fPostTranslate); 218 buffer.writePaint(rec->fPaint); 219 rec = rec->fNext; 220 } 221 } 222 223 SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer) 224 : INHERITED(buffer), 225 fRecs(NULL), 226 fTopRec(NULL), 227 fCount(0), 228 fCurrRec(NULL) { 229 int count = buffer.readInt(); 230 231 for (int i = 0; i < count; i++) { 232 LayerInfo info; 233 info.fFlagsMask = buffer.readInt(); 234 info.fPaintBits = buffer.readInt(); 235 info.fColorMode = (SkXfermode::Mode)buffer.readInt(); 236 buffer.readPoint(&info.fOffset); 237 info.fPostTranslate = buffer.readBool(); 238 buffer.readPaint(this->addLayerOnTop(info)); 239 } 240 SkASSERT(count == fCount); 241 242 #ifdef SK_DEBUG 243 { 244 Rec* rec = fRecs; 245 int n = 0; 246 while (rec) { 247 rec = rec->fNext; 248 n += 1; 249 } 250 SkASSERT(count == n); 251 } 252 #endif 253 } 254 255 #ifdef SK_DEVELOPER 256 void 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