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