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