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