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