Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | List of all members
SkMaskBlurFilter Class Reference

#include <SkMaskBlurFilter.h>

Public Member Functions

 SkMaskBlurFilter (double sigmaW, double sigmaH)
 
bool hasNoBlur () const
 
SkIPoint blur (const SkMask &src, SkMaskBuilder *dst) const
 

Detailed Description

Definition at line 20 of file SkMaskBlurFilter.h.

Constructor & Destructor Documentation

◆ SkMaskBlurFilter()

SkMaskBlurFilter::SkMaskBlurFilter ( double  sigmaW,
double  sigmaH 
)

Definition at line 254 of file SkMaskBlurFilter.cpp.

255 : fSigmaW{SkTPin(sigmaW, 0.0, 135.0)}
256 , fSigmaH{SkTPin(sigmaH, 0.0, 135.0)}
257{
258 SkASSERT(sigmaW >= 0);
259 SkASSERT(sigmaH >= 0);
260}
#define SkASSERT(cond)
Definition SkAssert.h:116
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition SkTPin.h:19

Member Function Documentation

◆ blur()

SkIPoint SkMaskBlurFilter::blur ( const SkMask src,
SkMaskBuilder dst 
) const

Definition at line 955 of file SkMaskBlurFilter.cpp.

955 {
956
957 if (fSigmaW < 2.0 && fSigmaH < 2.0) {
958 return small_blur(fSigmaW, fSigmaH, src, dst);
959 }
960
961 // 1024 is a place holder guess until more analysis can be done.
963
964 PlanGauss planW(fSigmaW);
965 PlanGauss planH(fSigmaH);
966
967 int borderW = planW.border(),
968 borderH = planH.border();
969 SkASSERT(borderH >= 0 && borderW >= 0);
970
971 *dst = SkMaskBuilder::PrepareDestination(borderW, borderH, src);
972 if (src.fImage == nullptr) {
973 return {SkTo<int32_t>(borderW), SkTo<int32_t>(borderH)};
974 }
975 if (dst->fImage == nullptr) {
976 dst->bounds().setEmpty();
977 return {0, 0};
978 }
979
980 int srcW = src.fBounds.width(),
981 srcH = src.fBounds.height(),
982 dstW = dst->fBounds.width(),
983 dstH = dst->fBounds.height();
984 SkASSERT(srcW >= 0 && srcH >= 0 && dstW >= 0 && dstH >= 0);
985
986 auto bufferSize = std::max(planW.bufferSize(), planH.bufferSize());
987 auto buffer = alloc.makeArrayDefault<uint32_t>(bufferSize);
988
989 // Blur both directions.
990 int tmpW = srcH,
991 tmpH = dstW;
992
993 // Make sure not to overflow the multiply for the tmp buffer size.
994 if (tmpH > std::numeric_limits<int>::max() / tmpW) {
995 return {0, 0};
996 }
997 auto tmp = alloc.makeArrayDefault<uint8_t>(tmpW * tmpH);
998
999 // Blur horizontally, and transpose.
1000 const PlanGauss::Scan& scanW = planW.makeBlurScan(srcW, buffer);
1001 switch (src.fFormat) {
1002 case SkMask::kBW_Format: {
1003 const uint8_t* bwStart = src.fImage;
1005 auto end = SkMask::AlphaIter<SkMask::kBW_Format>(bwStart + (srcW / 8), srcW % 8);
1006 for (int y = 0; y < srcH; ++y, start >>= src.fRowBytes, end >>= src.fRowBytes) {
1007 auto tmpStart = &tmp[y];
1008 scanW.blur(start, end, tmpStart, tmpW, tmpStart + tmpW * tmpH);
1009 }
1010 } break;
1011 case SkMask::kA8_Format: {
1012 const uint8_t* a8Start = src.fImage;
1014 auto end = SkMask::AlphaIter<SkMask::kA8_Format>(a8Start + srcW);
1015 for (int y = 0; y < srcH; ++y, start >>= src.fRowBytes, end >>= src.fRowBytes) {
1016 auto tmpStart = &tmp[y];
1017 scanW.blur(start, end, tmpStart, tmpW, tmpStart + tmpW * tmpH);
1018 }
1019 } break;
1021 const uint32_t* argbStart = reinterpret_cast<const uint32_t*>(src.fImage);
1023 auto end = SkMask::AlphaIter<SkMask::kARGB32_Format>(argbStart + srcW);
1024 for (int y = 0; y < srcH; ++y, start >>= src.fRowBytes, end >>= src.fRowBytes) {
1025 auto tmpStart = &tmp[y];
1026 scanW.blur(start, end, tmpStart, tmpW, tmpStart + tmpW * tmpH);
1027 }
1028 } break;
1029 case SkMask::kLCD16_Format: {
1030 const uint16_t* lcdStart = reinterpret_cast<const uint16_t*>(src.fImage);
1032 auto end = SkMask::AlphaIter<SkMask::kLCD16_Format>(lcdStart + srcW);
1033 for (int y = 0; y < srcH; ++y, start >>= src.fRowBytes, end >>= src.fRowBytes) {
1034 auto tmpStart = &tmp[y];
1035 scanW.blur(start, end, tmpStart, tmpW, tmpStart + tmpW * tmpH);
1036 }
1037 } break;
1038 default:
1039 SK_ABORT("Unhandled format.");
1040 }
1041
1042 // Blur vertically (scan in memory order because of the transposition),
1043 // and transpose back to the original orientation.
1044 const PlanGauss::Scan& scanH = planH.makeBlurScan(tmpW, buffer);
1045 for (int y = 0; y < tmpH; y++) {
1046 auto tmpStart = &tmp[y * tmpW];
1047 auto dstStart = &dst->image()[y];
1048
1049 scanH.blur(tmpStart, tmpStart + tmpW,
1050 dstStart, dst->fRowBytes, dstStart + dst->fRowBytes * dstH);
1051 }
1052
1053 return {SkTo<int32_t>(borderW), SkTo<int32_t>(borderH)};
1054}
#define SK_ABORT(message,...)
Definition SkAssert.h:70
static SkIPoint small_blur(double sigmaX, double sigmaY, const SkMask &src, SkMaskBuilder *dst)
T * makeArrayDefault(size_t count)
glong glong end
static const uint8_t buffer[]
double y
dst
Definition cp.py:12
static SkMaskBuilder PrepareDestination(int radiusX, int radiusY, const SkMask &src)
Definition SkMask.cpp:61
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)
Definition SkMask.h:28
@ kLCD16_Format
565 alpha for r/g/b
Definition SkMask.h:31
@ kARGB32_Format
SkPMColor.
Definition SkMask.h:30
@ kBW_Format
1bit per pixel mask (e.g. monochrome)
Definition SkMask.h:27

◆ hasNoBlur()

bool SkMaskBlurFilter::hasNoBlur ( ) const

Definition at line 262 of file SkMaskBlurFilter.cpp.

262 {
263 return (3 * fSigmaW <= 1) && (3 * fSigmaH <= 1);
264}

The documentation for this class was generated from the following files: