1 /* 2 * Copyright 2006 The Android Open Source Project 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 8 #include "SkMaskFilterBase.h" 9 10 #include "SkAutoMalloc.h" 11 #include "SkBlitter.h" 12 #include "SkCachedData.h" 13 #include "SkCoverageModePriv.h" 14 #include "SkDraw.h" 15 #include "SkPath.h" 16 #include "SkRRect.h" 17 #include "SkRasterClip.h" 18 #include "SkReadBuffer.h" 19 #include "SkWriteBuffer.h" 20 21 #if SK_SUPPORT_GPU 22 #include "GrTextureProxy.h" 23 #include "GrFragmentProcessor.h" 24 #include "effects/GrXfermodeFragmentProcessor.h" 25 #endif 26 27 SkMaskFilterBase::NinePatch::~NinePatch() { 28 if (fCache) { 29 SkASSERT((const void*)fMask.fImage == fCache->data()); 30 fCache->unref(); 31 } else { 32 SkMask::FreeImage(fMask.fImage); 33 } 34 } 35 36 bool SkMaskFilterBase::filterMask(SkMask*, const SkMask&, const SkMatrix&, 37 SkIPoint*) const { 38 return false; 39 } 40 41 bool SkMaskFilterBase::asABlur(BlurRec*) const { 42 return false; 43 } 44 45 static void extractMaskSubset(const SkMask& src, SkMask* dst) { 46 SkASSERT(src.fBounds.contains(dst->fBounds)); 47 48 const int dx = dst->fBounds.left() - src.fBounds.left(); 49 const int dy = dst->fBounds.top() - src.fBounds.top(); 50 dst->fImage = src.fImage + dy * src.fRowBytes + dx; 51 dst->fRowBytes = src.fRowBytes; 52 dst->fFormat = src.fFormat; 53 } 54 55 static void blitClippedMask(SkBlitter* blitter, const SkMask& mask, 56 const SkIRect& bounds, const SkIRect& clipR) { 57 SkIRect r; 58 if (r.intersect(bounds, clipR)) { 59 blitter->blitMask(mask, r); 60 } 61 } 62 63 static void blitClippedRect(SkBlitter* blitter, const SkIRect& rect, const SkIRect& clipR) { 64 SkIRect r; 65 if (r.intersect(rect, clipR)) { 66 blitter->blitRect(r.left(), r.top(), r.width(), r.height()); 67 } 68 } 69 70 #if 0 71 static void dump(const SkMask& mask) { 72 for (int y = mask.fBounds.top(); y < mask.fBounds.bottom(); ++y) { 73 for (int x = mask.fBounds.left(); x < mask.fBounds.right(); ++x) { 74 SkDebugf("%02X", *mask.getAddr8(x, y)); 75 } 76 SkDebugf("\n"); 77 } 78 SkDebugf("\n"); 79 } 80 #endif 81 82 static void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR, 83 const SkIPoint& center, bool fillCenter, 84 const SkIRect& clipR, SkBlitter* blitter) { 85 int cx = center.x(); 86 int cy = center.y(); 87 SkMask m; 88 89 // top-left 90 m.fBounds = mask.fBounds; 91 m.fBounds.fRight = cx; 92 m.fBounds.fBottom = cy; 93 if (m.fBounds.width() > 0 && m.fBounds.height() > 0) { 94 extractMaskSubset(mask, &m); 95 m.fBounds.offsetTo(outerR.left(), outerR.top()); 96 blitClippedMask(blitter, m, m.fBounds, clipR); 97 } 98 99 // top-right 100 m.fBounds = mask.fBounds; 101 m.fBounds.fLeft = cx + 1; 102 m.fBounds.fBottom = cy; 103 if (m.fBounds.width() > 0 && m.fBounds.height() > 0) { 104 extractMaskSubset(mask, &m); 105 m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), outerR.top()); 106 blitClippedMask(blitter, m, m.fBounds, clipR); 107 } 108 109 // bottom-left 110 m.fBounds = mask.fBounds; 111 m.fBounds.fRight = cx; 112 m.fBounds.fTop = cy + 1; 113 if (m.fBounds.width() > 0 && m.fBounds.height() > 0) { 114 extractMaskSubset(mask, &m); 115 m.fBounds.offsetTo(outerR.left(), outerR.bottom() - m.fBounds.height()); 116 blitClippedMask(blitter, m, m.fBounds, clipR); 117 } 118 119 // bottom-right 120 m.fBounds = mask.fBounds; 121 m.fBounds.fLeft = cx + 1; 122 m.fBounds.fTop = cy + 1; 123 if (m.fBounds.width() > 0 && m.fBounds.height() > 0) { 124 extractMaskSubset(mask, &m); 125 m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), 126 outerR.bottom() - m.fBounds.height()); 127 blitClippedMask(blitter, m, m.fBounds, clipR); 128 } 129 130 SkIRect innerR; 131 innerR.set(outerR.left() + cx - mask.fBounds.left(), 132 outerR.top() + cy - mask.fBounds.top(), 133 outerR.right() + (cx + 1 - mask.fBounds.right()), 134 outerR.bottom() + (cy + 1 - mask.fBounds.bottom())); 135 if (fillCenter) { 136 blitClippedRect(blitter, innerR, clipR); 137 } 138 139 const int innerW = innerR.width(); 140 size_t storageSize = (innerW + 1) * (sizeof(int16_t) + sizeof(uint8_t)); 141 SkAutoSMalloc<4*1024> storage(storageSize); 142 int16_t* runs = (int16_t*)storage.get(); 143 uint8_t* alpha = (uint8_t*)(runs + innerW + 1); 144 145 SkIRect r; 146 // top 147 r.set(innerR.left(), outerR.top(), innerR.right(), innerR.top()); 148 if (r.intersect(clipR)) { 149 int startY = SkMax32(0, r.top() - outerR.top()); 150 int stopY = startY + r.height(); 151 int width = r.width(); 152 for (int y = startY; y < stopY; ++y) { 153 runs[0] = width; 154 runs[width] = 0; 155 alpha[0] = *mask.getAddr8(cx, mask.fBounds.top() + y); 156 blitter->blitAntiH(r.left(), outerR.top() + y, alpha, runs); 157 } 158 } 159 // bottom 160 r.set(innerR.left(), innerR.bottom(), innerR.right(), outerR.bottom()); 161 if (r.intersect(clipR)) { 162 int startY = outerR.bottom() - r.bottom(); 163 int stopY = startY + r.height(); 164 int width = r.width(); 165 for (int y = startY; y < stopY; ++y) { 166 runs[0] = width; 167 runs[width] = 0; 168 alpha[0] = *mask.getAddr8(cx, mask.fBounds.bottom() - y - 1); 169 blitter->blitAntiH(r.left(), outerR.bottom() - y - 1, alpha, runs); 170 } 171 } 172 // left 173 r.set(outerR.left(), innerR.top(), innerR.left(), innerR.bottom()); 174 if (r.intersect(clipR)) { 175 SkMask m; 176 m.fImage = mask.getAddr8(mask.fBounds.left() + r.left() - outerR.left(), 177 mask.fBounds.top() + cy); 178 m.fBounds = r; 179 m.fRowBytes = 0; // so we repeat the scanline for our height 180 m.fFormat = SkMask::kA8_Format; 181 blitter->blitMask(m, r); 182 } 183 // right 184 r.set(innerR.right(), innerR.top(), outerR.right(), innerR.bottom()); 185 if (r.intersect(clipR)) { 186 SkMask m; 187 m.fImage = mask.getAddr8(mask.fBounds.right() - outerR.right() + r.left(), 188 mask.fBounds.top() + cy); 189 m.fBounds = r; 190 m.fRowBytes = 0; // so we repeat the scanline for our height 191 m.fFormat = SkMask::kA8_Format; 192 blitter->blitMask(m, r); 193 } 194 } 195 196 static void draw_nine(const SkMask& mask, const SkIRect& outerR, const SkIPoint& center, 197 bool fillCenter, const SkRasterClip& clip, SkBlitter* blitter) { 198 // if we get here, we need to (possibly) resolve the clip and blitter 199 SkAAClipBlitterWrapper wrapper(clip, blitter); 200 blitter = wrapper.getBlitter(); 201 202 SkRegion::Cliperator clipper(wrapper.getRgn(), outerR); 203 204 if (!clipper.done()) { 205 const SkIRect& cr = clipper.rect(); 206 do { 207 draw_nine_clipped(mask, outerR, center, fillCenter, cr, blitter); 208 clipper.next(); 209 } while (!clipper.done()); 210 } 211 } 212 213 static int countNestedRects(const SkPath& path, SkRect rects[2]) { 214 if (path.isNestedFillRects(rects)) { 215 return 2; 216 } 217 return path.isRect(&rects[0]); 218 } 219 220 bool SkMaskFilterBase::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix, 221 const SkRasterClip& clip, SkBlitter* blitter) const { 222 // Attempt to speed up drawing by creating a nine patch. If a nine patch 223 // cannot be used, return false to allow our caller to recover and perform 224 // the drawing another way. 225 NinePatch patch; 226 patch.fMask.fImage = nullptr; 227 if (kTrue_FilterReturn != this->filterRRectToNine(devRRect, matrix, 228 clip.getBounds(), 229 &patch)) { 230 SkASSERT(nullptr == patch.fMask.fImage); 231 return false; 232 } 233 draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, true, clip, blitter); 234 return true; 235 } 236 237 bool SkMaskFilterBase::filterPath(const SkPath& devPath, const SkMatrix& matrix, 238 const SkRasterClip& clip, SkBlitter* blitter, 239 SkStrokeRec::InitStyle style) const { 240 SkRect rects[2]; 241 int rectCount = 0; 242 if (SkStrokeRec::kFill_InitStyle == style) { 243 rectCount = countNestedRects(devPath, rects); 244 } 245 if (rectCount > 0) { 246 NinePatch patch; 247 248 switch (this->filterRectsToNine(rects, rectCount, matrix, clip.getBounds(), &patch)) { 249 case kFalse_FilterReturn: 250 SkASSERT(nullptr == patch.fMask.fImage); 251 return false; 252 253 case kTrue_FilterReturn: 254 draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, 1 == rectCount, clip, 255 blitter); 256 return true; 257 258 case kUnimplemented_FilterReturn: 259 SkASSERT(nullptr == patch.fMask.fImage); 260 // fall through 261 break; 262 } 263 } 264 265 SkMask srcM, dstM; 266 267 if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), this, &matrix, &srcM, 268 SkMask::kComputeBoundsAndRenderImage_CreateMode, 269 style)) { 270 return false; 271 } 272 SkAutoMaskFreeImage autoSrc(srcM.fImage); 273 274 if (!this->filterMask(&dstM, srcM, matrix, nullptr)) { 275 return false; 276 } 277 SkAutoMaskFreeImage autoDst(dstM.fImage); 278 279 // if we get here, we need to (possibly) resolve the clip and blitter 280 SkAAClipBlitterWrapper wrapper(clip, blitter); 281 blitter = wrapper.getBlitter(); 282 283 SkRegion::Cliperator clipper(wrapper.getRgn(), dstM.fBounds); 284 285 if (!clipper.done()) { 286 const SkIRect& cr = clipper.rect(); 287 do { 288 blitter->blitMask(dstM, cr); 289 clipper.next(); 290 } while (!clipper.done()); 291 } 292 293 return true; 294 } 295 296 SkMaskFilterBase::FilterReturn 297 SkMaskFilterBase::filterRRectToNine(const SkRRect&, const SkMatrix&, 298 const SkIRect& clipBounds, NinePatch*) const { 299 return kUnimplemented_FilterReturn; 300 } 301 302 SkMaskFilterBase::FilterReturn 303 SkMaskFilterBase::filterRectsToNine(const SkRect[], int count, const SkMatrix&, 304 const SkIRect& clipBounds, NinePatch*) const { 305 return kUnimplemented_FilterReturn; 306 } 307 308 #if SK_SUPPORT_GPU 309 std::unique_ptr<GrFragmentProcessor> 310 SkMaskFilterBase::asFragmentProcessor(const GrFPArgs& args) const { 311 auto fp = this->onAsFragmentProcessor(args); 312 if (fp) { 313 SkASSERT(this->hasFragmentProcessor()); 314 } else { 315 SkASSERT(!this->hasFragmentProcessor()); 316 } 317 return fp; 318 } 319 bool SkMaskFilterBase::hasFragmentProcessor() const { 320 return this->onHasFragmentProcessor(); 321 } 322 323 std::unique_ptr<GrFragmentProcessor> 324 SkMaskFilterBase::onAsFragmentProcessor(const GrFPArgs&) const { 325 return nullptr; 326 } 327 bool SkMaskFilterBase::onHasFragmentProcessor() const { return false; } 328 329 bool SkMaskFilterBase::canFilterMaskGPU(const SkRRect& devRRect, 330 const SkIRect& clipBounds, 331 const SkMatrix& ctm, 332 SkRect* maskRect) const { 333 return false; 334 } 335 336 bool SkMaskFilterBase::directFilterMaskGPU(GrContext*, 337 GrRenderTargetContext* renderTargetContext, 338 GrPaint&&, 339 const GrClip&, 340 const SkMatrix& viewMatrix, 341 const SkStrokeRec& strokeRec, 342 const SkPath& path) const { 343 return false; 344 } 345 346 bool SkMaskFilterBase::directFilterRRectMaskGPU(GrContext*, 347 GrRenderTargetContext* renderTargetContext, 348 GrPaint&&, 349 const GrClip&, 350 const SkMatrix& viewMatrix, 351 const SkStrokeRec& strokeRec, 352 const SkRRect& rrect, 353 const SkRRect& devRRect) const { 354 return false; 355 } 356 357 sk_sp<GrTextureProxy> SkMaskFilterBase::filterMaskGPU(GrContext*, 358 sk_sp<GrTextureProxy> srcProxy, 359 const SkMatrix& ctm, 360 const SkIRect& maskRect) const { 361 return nullptr; 362 } 363 #endif 364 365 void SkMaskFilterBase::computeFastBounds(const SkRect& src, SkRect* dst) const { 366 SkMask srcM, dstM; 367 368 srcM.fBounds = src.roundOut(); 369 srcM.fRowBytes = 0; 370 srcM.fFormat = SkMask::kA8_Format; 371 372 SkIPoint margin; // ignored 373 if (this->filterMask(&dstM, srcM, SkMatrix::I(), &margin)) { 374 dst->set(dstM.fBounds); 375 } else { 376 dst->set(srcM.fBounds); 377 } 378 } 379 380 /////////////////////////////////////////////////////////////////////////////////////////////////// 381 382 template <typename T> static inline T join(const T& a, const T& b) { 383 T r = a; 384 r.join(b); 385 return r; 386 } 387 template <typename T> static inline T sect(const T& a, const T& b) { 388 T r = a; 389 return r.intersect(b) ? r : T::MakeEmpty(); 390 } 391 392 class SkComposeMF : public SkMaskFilterBase { 393 public: 394 SkComposeMF(sk_sp<SkMaskFilter> outer, sk_sp<SkMaskFilter> inner) 395 : fOuter(std::move(outer)) 396 , fInner(std::move(inner)) 397 { 398 SkASSERT(as_MFB(fOuter)->getFormat() == SkMask::kA8_Format); 399 SkASSERT(as_MFB(fInner)->getFormat() == SkMask::kA8_Format); 400 } 401 402 bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, SkIPoint*) const override; 403 404 void computeFastBounds(const SkRect& src, SkRect* dst) const override { 405 SkRect tmp; 406 as_MFB(fInner)->computeFastBounds(src, &tmp); 407 as_MFB(fOuter)->computeFastBounds(tmp, dst); 408 } 409 410 SkMask::Format getFormat() const override { return SkMask::kA8_Format; } 411 SK_TO_STRING_OVERRIDE() 412 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeMF) 413 414 protected: 415 #if SK_SUPPORT_GPU 416 std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs& args) const override{ 417 std::unique_ptr<GrFragmentProcessor> array[2] = { 418 as_MFB(fInner)->asFragmentProcessor(args), 419 as_MFB(fOuter)->asFragmentProcessor(args), 420 }; 421 if (!array[0] || !array[1]) { 422 return nullptr; 423 } 424 return GrFragmentProcessor::RunInSeries(array, 2); 425 } 426 427 bool onHasFragmentProcessor() const override { 428 return as_MFB(fInner)->hasFragmentProcessor() && as_MFB(fOuter)->hasFragmentProcessor(); 429 } 430 #endif 431 432 private: 433 sk_sp<SkMaskFilter> fOuter; 434 sk_sp<SkMaskFilter> fInner; 435 436 void flatten(SkWriteBuffer&) const override; 437 438 friend class SkMaskFilter; 439 440 typedef SkMaskFilterBase INHERITED; 441 }; 442 443 bool SkComposeMF::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& ctm, 444 SkIPoint* margin) const { 445 SkIPoint innerMargin; 446 SkMask innerMask; 447 448 if (!as_MFB(fInner)->filterMask(&innerMask, src, ctm, &innerMargin)) { 449 return false; 450 } 451 if (!as_MFB(fOuter)->filterMask(dst, innerMask, ctm, margin)) { 452 return false; 453 } 454 if (margin) { 455 margin->fX += innerMargin.fX; 456 margin->fY += innerMargin.fY; 457 } 458 sk_free(innerMask.fImage); 459 return true; 460 } 461 462 void SkComposeMF::flatten(SkWriteBuffer & buffer) const { 463 buffer.writeFlattenable(fOuter.get()); 464 buffer.writeFlattenable(fInner.get()); 465 } 466 467 sk_sp<SkFlattenable> SkComposeMF::CreateProc(SkReadBuffer& buffer) { 468 auto outer = buffer.readMaskFilter(); 469 auto inner = buffer.readMaskFilter(); 470 if (!buffer.validate(outer && inner)) { 471 return nullptr; 472 } 473 return SkMaskFilter::MakeCompose(std::move(outer), std::move(inner)); 474 } 475 476 #ifndef SK_IGNORE_TO_STRING 477 void SkComposeMF::toString(SkString* str) const { 478 str->set("SkComposeMF:"); 479 } 480 #endif 481 482 /////////////////////////////////////////////////////////////////////////////////////////////////// 483 484 class SkCombineMF : public SkMaskFilterBase { 485 public: 486 SkCombineMF(sk_sp<SkMaskFilter> dst, sk_sp<SkMaskFilter> src, SkCoverageMode mode) 487 : fDst(std::move(dst)) 488 , fSrc(std::move(src)) 489 , fMode(mode) 490 { 491 SkASSERT(as_MFB(fSrc)->getFormat() == SkMask::kA8_Format); 492 SkASSERT(as_MFB(fDst)->getFormat() == SkMask::kA8_Format); 493 } 494 495 bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, SkIPoint*) const override; 496 497 void computeFastBounds(const SkRect& src, SkRect* dst) const override { 498 SkRect srcR, dstR; 499 as_MFB(fSrc)->computeFastBounds(src, &srcR); 500 as_MFB(fDst)->computeFastBounds(src, &dstR); 501 *dst = join(srcR, dstR); 502 } 503 504 SkMask::Format getFormat() const override { return SkMask::kA8_Format; } 505 506 SK_TO_STRING_OVERRIDE() 507 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkCombineMF) 508 509 protected: 510 #if SK_SUPPORT_GPU 511 std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs& args) const override{ 512 auto src = as_MFB(fSrc)->asFragmentProcessor(args); 513 auto dst = as_MFB(fDst)->asFragmentProcessor(args); 514 if (!src || !dst) { 515 return nullptr; 516 } 517 return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(src), std::move(dst), 518 SkUncorrelatedCoverageModeToBlendMode(fMode)); 519 } 520 521 bool onHasFragmentProcessor() const override { 522 return as_MFB(fSrc)->hasFragmentProcessor() && as_MFB(fDst)->hasFragmentProcessor(); 523 } 524 #endif 525 526 private: 527 sk_sp<SkMaskFilter> fDst; 528 sk_sp<SkMaskFilter> fSrc; 529 SkCoverageMode fMode; 530 531 void flatten(SkWriteBuffer&) const override; 532 533 friend class SkMaskFilter; 534 535 typedef SkMaskFilterBase INHERITED; 536 }; 537 538 #include "SkSafeMath.h" 539 540 class DrawIntoMask : public SkDraw { 541 public: 542 // we ignore the offset of the mask->fBounds 543 DrawIntoMask(SkMask* mask) { 544 int w = mask->fBounds.width(); 545 int h = mask->fBounds.height(); 546 size_t size = SkSafeMath::Mul(w, h); 547 mask->fFormat = SkMask::kA8_Format; 548 mask->fImage = SkMask::AllocImage(size, SkMask::kZeroInit_Alloc); 549 mask->fRowBytes = w; 550 551 SkAssertResult(fDst.reset(*mask)); 552 553 fMatrixStorage.reset(); 554 fMatrix = &fMatrixStorage; 555 556 fRCStorage.setRect({ 0, 0, w, h }); 557 fRC = &fRCStorage; 558 } 559 560 void drawAsBitmap(const SkMask& m, const SkPaint& p) { 561 SkBitmap b; 562 b.installMaskPixels(m); 563 this->drawSprite(b, m.fBounds.fLeft, m.fBounds.fTop, p); 564 } 565 566 private: 567 SkMatrix fMatrixStorage; 568 SkRasterClip fRCStorage; 569 }; 570 571 static SkIRect join(const SkIRect& src, const SkIRect& dst, SkCoverageMode mode) { 572 switch (mode) { 573 case SkCoverageMode::kUnion: return join(src, dst); 574 case SkCoverageMode::kIntersect: return sect(src, dst); 575 case SkCoverageMode::kDifference: return src; 576 case SkCoverageMode::kReverseDifference: return dst; 577 case SkCoverageMode::kXor: return join(src, dst); 578 } 579 // not reached 580 return { 0, 0, 0, 0 }; 581 } 582 583 bool SkCombineMF::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& ctm, 584 SkIPoint* margin) const { 585 SkIPoint srcP, dstP; 586 SkMask srcM, dstM; 587 588 if (!as_MFB(fSrc)->filterMask(&srcM, src, ctm, &srcP)) { 589 return false; 590 } 591 if (!as_MFB(fDst)->filterMask(&dstM, src, ctm, &dstP)) { 592 return false; 593 } 594 595 dst->fBounds = join(srcM.fBounds, dstM.fBounds, fMode); 596 dst->fFormat = SkMask::kA8_Format; 597 if (src.fImage == nullptr) { 598 dst->fImage = nullptr; 599 return true; 600 } 601 602 DrawIntoMask md(dst); 603 SkPaint p; 604 605 p.setBlendMode(SkBlendMode::kSrc); 606 dstM.fBounds.offset(-dst->fBounds.fLeft, -dst->fBounds.fTop); 607 md.drawAsBitmap(dstM, p); 608 p.setBlendMode(SkUncorrelatedCoverageModeToBlendMode(fMode)); 609 srcM.fBounds.offset(-dst->fBounds.fLeft, -dst->fBounds.fTop); 610 md.drawAsBitmap(srcM, p); 611 612 sk_free(srcM.fImage); 613 sk_free(dstM.fImage); 614 return true; 615 } 616 617 void SkCombineMF::flatten(SkWriteBuffer & buffer) const { 618 buffer.writeFlattenable(fDst.get()); 619 buffer.writeFlattenable(fSrc.get()); 620 buffer.write32(static_cast<uint32_t>(fMode)); 621 } 622 623 sk_sp<SkFlattenable> SkCombineMF::CreateProc(SkReadBuffer& buffer) { 624 auto dst = buffer.readMaskFilter(); 625 auto src = buffer.readMaskFilter(); 626 SkCoverageMode mode = buffer.read32LE(SkCoverageMode::kLast); 627 if (!buffer.validate(dst && src)) { 628 return nullptr; 629 } 630 return SkMaskFilter::MakeCombine(std::move(dst), std::move(src), mode); 631 } 632 633 #ifndef SK_IGNORE_TO_STRING 634 void SkCombineMF::toString(SkString* str) const { 635 str->set("SkCombineMF:"); 636 } 637 #endif 638 639 /////////////////////////////////////////////////////////////////////////////////////////////////// 640 641 class SkLocalMatrixMF : public SkMaskFilterBase { 642 public: 643 SkLocalMatrixMF(sk_sp<SkMaskFilter> filter, const SkMatrix& lm) 644 : fFilter(std::move(filter)) 645 , fLM(lm) 646 {} 647 648 bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix& ctm, 649 SkIPoint* margin) const override { 650 return as_MFB(fFilter)->filterMask(dst, src, SkMatrix::Concat(ctm, fLM), margin); 651 } 652 653 void computeFastBounds(const SkRect& src, SkRect* dst) const override { 654 *dst = src; 655 SkRect tmp; 656 fLM.mapRect(&tmp, src); 657 as_MFB(fFilter)->computeFastBounds(tmp, dst); 658 } 659 660 SkMask::Format getFormat() const override { return as_MFB(fFilter)->getFormat(); } 661 662 #ifndef SK_IGNORE_TO_STRING 663 void toString(SkString* str) const override { 664 str->set("SkLocalMatrixMF:"); 665 } 666 #endif 667 668 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLocalMatrixMF) 669 670 protected: 671 #if SK_SUPPORT_GPU 672 std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs& args) const override{ 673 GrFPArgs newArgs = args; 674 675 SkMatrix storage; 676 if (args.fLocalMatrix) { 677 storage.setConcat(*args.fLocalMatrix, fLM); 678 newArgs.fLocalMatrix = &storage; 679 } else { 680 newArgs.fLocalMatrix = &fLM; 681 } 682 return as_MFB(fFilter)->asFragmentProcessor(newArgs); 683 } 684 685 bool onHasFragmentProcessor() const override { 686 return as_MFB(fFilter)->hasFragmentProcessor(); 687 } 688 #endif 689 690 private: 691 sk_sp<SkMaskFilter> fFilter; 692 const SkMatrix fLM; 693 694 void flatten(SkWriteBuffer& buffer) const override { 695 buffer.writeMatrix(fLM); 696 buffer.writeFlattenable(fFilter.get()); 697 } 698 699 friend class SkMaskFilter; 700 typedef SkMaskFilterBase INHERITED; 701 }; 702 703 sk_sp<SkFlattenable> SkLocalMatrixMF::CreateProc(SkReadBuffer& buffer) { 704 SkMatrix lm; 705 buffer.readMatrix(&lm); 706 auto filter = buffer.readMaskFilter(); 707 return filter ? filter->makeWithLocalMatrix(lm) : nullptr; 708 } 709 710 /////////////////////////////////////////////////////////////////////////////////////////////////// 711 712 sk_sp<SkMaskFilter> SkMaskFilter::MakeCompose(sk_sp<SkMaskFilter> outer, 713 sk_sp<SkMaskFilter> inner) { 714 if (!outer) { 715 return inner; 716 } 717 if (!inner) { 718 return outer; 719 } 720 if (as_MFB(inner)->getFormat() != SkMask::kA8_Format || 721 as_MFB(outer)->getFormat() != SkMask::kA8_Format) { 722 return nullptr; 723 } 724 return sk_sp<SkMaskFilter>(new SkComposeMF(std::move(outer), std::move(inner))); 725 } 726 727 sk_sp<SkMaskFilter> SkMaskFilter::MakeCombine(sk_sp<SkMaskFilter> dst, sk_sp<SkMaskFilter> src, 728 SkCoverageMode mode) { 729 if (!dst) { 730 return src; 731 } 732 if (!src) { 733 return dst; 734 } 735 736 if (as_MFB(dst)->getFormat() != SkMask::kA8_Format || 737 as_MFB(src)->getFormat() != SkMask::kA8_Format) { 738 return nullptr; 739 } 740 return sk_sp<SkMaskFilter>(new SkCombineMF(std::move(dst), std::move(src), mode)); 741 } 742 743 sk_sp<SkMaskFilter> SkMaskFilter::makeWithLocalMatrix(const SkMatrix& lm) const { 744 sk_sp<SkMaskFilter> me = sk_ref_sp(const_cast<SkMaskFilter*>(this)); 745 if (lm.isIdentity()) { 746 return me; 747 } 748 return sk_sp<SkMaskFilter>(new SkLocalMatrixMF(std::move(me), lm)); 749 } 750 751 void SkMaskFilter::InitializeFlattenables() { 752 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLocalMatrixMF) 753 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeMF) 754 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkCombineMF) 755 } 756 757