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