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 22 SkLayerDrawLooper::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 29 SkLayerDrawLooper::SkLayerDrawLooper() 30 : fRecs(nullptr), 31 fCount(0) { 32 } 33 34 SkLayerDrawLooper::~SkLayerDrawLooper() { 35 Rec* rec = fRecs; 36 while (rec) { 37 Rec* next = rec->fNext; 38 delete rec; 39 rec = next; 40 } 41 } 42 43 SkLayerDrawLooper::Context* 44 SkLayerDrawLooper::makeContext(SkCanvas* canvas, SkArenaAlloc* alloc) const { 45 canvas->save(); 46 return alloc->make<LayerDrawLooperContext>(this); 47 } 48 49 static 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. 67 void 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? 137 static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) { 138 SkMatrix m = canvas->getTotalMatrix(); 139 m.postTranslate(dx, dy); 140 canvas->setMatrix(m); 141 } 142 143 SkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext( 144 const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {} 145 146 bool 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 168 bool 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 212 sk_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 245 void 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 262 sk_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 281 void 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 338 SkLayerDrawLooper::Builder::Builder() 339 : fRecs(nullptr), 340 fTopRec(nullptr), 341 fCount(0) { 342 } 343 344 SkLayerDrawLooper::Builder::~Builder() { 345 Rec* rec = fRecs; 346 while (rec) { 347 Rec* next = rec->fNext; 348 delete rec; 349 rec = next; 350 } 351 } 352 353 SkPaint* 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 367 void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) { 368 LayerInfo info; 369 370 info.fOffset.set(dx, dy); 371 (void)this->addLayer(info); 372 } 373 374 SkPaint* 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 391 sk_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 403 sk_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