diff options
author | Herb Derby <herb@google.com> | 2017-08-15 15:00:03 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-08-15 15:00:17 +0000 |
commit | f6975ea5fb178c572cf4c1cd255e5fe623418d45 (patch) | |
tree | 0dac43ecceb5cd75350c7a1c1eb131e0b50fb88c /src/core/SkMaskBlurFilter.cpp | |
parent | 72a37bed66c90ff2acb930dc4493dc633f265488 (diff) |
Revert "Revert "Add an average mode for sigma < 2""
We are going to have the google3 auto roller build the CL,
and add the fixes to the failing tests to that CL. Because
these are scuba changes, this should be simpler.
This reverts commit 8e7503195c40492df6a9c072d3303c9df9ec32dc.
Reason for revert: <INSERT REASONING HERE>
Original change's description:
> Revert "Add an average mode for sigma < 2"
>
> This reverts commit ba8275148ab8b10393b053e2586b852796c4afc2.
>
> Reason for revert: layout tests, Google3 equivalent failing.
>
> Original change's description:
> > Add an average mode for sigma < 2
> >
> > The original code had an optimization when sigma < 2 that averaged
> > pixels instead of Gaussian bluring them. This CL adds that
> > behavior back to the new implementat.
> >
> > BUG=chromium:745290
> > Change-Id: I35b7de2138a859d546439cc2053b4b599a94ebe1
> > Reviewed-on: https://skia-review.googlesource.com/34180
> > Commit-Queue: Herb Derby <herb@google.com>
> > Reviewed-by: Mike Klein <mtklein@chromium.org>
>
> TBR=mtklein@chromium.org,mtklein@google.com,herb@google.com
>
> Change-Id: Ie8f38b042acec42260913cb7bed5538a2c957e9b
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: chromium:745290
> Reviewed-on: https://skia-review.googlesource.com/34640
> Reviewed-by: Mike Klein <mtklein@google.com>
> Commit-Queue: Mike Klein <mtklein@google.com>
TBR=mtklein@chromium.org,mtklein@google.com,herb@google.com
Change-Id: I5f7b706a2f8c8d52b3576c638ecddf12a1652031
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:745290
Reviewed-on: https://skia-review.googlesource.com/34641
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Herb Derby <herb@google.com>
Diffstat (limited to 'src/core/SkMaskBlurFilter.cpp')
-rw-r--r-- | src/core/SkMaskBlurFilter.cpp | 103 |
1 files changed, 99 insertions, 4 deletions
diff --git a/src/core/SkMaskBlurFilter.cpp b/src/core/SkMaskBlurFilter.cpp index 42837f79a9..7eba2dab8d 100644 --- a/src/core/SkMaskBlurFilter.cpp +++ b/src/core/SkMaskBlurFilter.cpp @@ -25,22 +25,36 @@ static uint64_t weight_from_diameter(uint32_t d) { } static uint32_t filter_window(double sigma) { - auto possibleWindow = static_cast<uint32_t>(floor(sigma * 3 * sqrt(2*kPi)/4 + 0.5)); + if (sigma < 2) { + uint32_t radius = static_cast<uint32_t>(ceil(1.5 * sigma - 0.5)); + return 2 * radius + 1; + } + auto possibleWindow = static_cast<uint32_t>(floor(sigma * 3 * sqrt(2 * kPi) / 4 + 0.5)); return std::max(1u, possibleWindow); } SkMaskBlurFilter::FilterInfo::FilterInfo(double sigma) - : fFilterWindow{filter_window(sigma)} - , fScaledWeight{(static_cast<uint64_t>(1) << 32) / weight_from_diameter(fFilterWindow)} {} + : fIsSmall{sigma < 2} + , fFilterWindow{filter_window(sigma)} + , fWeight{fIsSmall ? fFilterWindow : weight_from_diameter(fFilterWindow)} + , fScaledWeight{(static_cast<uint64_t>(1) << 32) / fWeight} +{ + SkASSERT(sigma >= 0); +} uint64_t SkMaskBlurFilter::FilterInfo::weight() const { - return weight_from_diameter(fFilterWindow); + return fWeight; } uint32_t SkMaskBlurFilter::FilterInfo::borderSize() const { + if (this->isSmall()) { + return (fFilterWindow - 1) / 2; + } + if ((fFilterWindow&1) == 0) { return 3 * (fFilterWindow / 2) - 1; } + return 3 * (fFilterWindow / 2); } @@ -63,6 +77,10 @@ uint64_t SkMaskBlurFilter::FilterInfo::scaledWeight() const { return fScaledWeight; } +bool SkMaskBlurFilter::FilterInfo::isSmall() const { + return fIsSmall; +} + SkMaskBlurFilter::SkMaskBlurFilter(double sigmaW, double sigmaH) : fInfoW{sigmaW}, fInfoH{sigmaH} , fBuffer0{skstd::make_unique_default<uint32_t[]>(bufferSize(0))} @@ -168,6 +186,83 @@ void SkMaskBlurFilter::blurOneScan( FilterInfo info, const uint8_t* src, size_t srcStride, const uint8_t* srcEnd, uint8_t* dst, size_t dstStride, uint8_t* dstEnd) const { + // We don't think this is good for quality. It is good for compatibility + // with previous expectations... + if (info.isSmall()) { + this->blurOneScanBox(info, src, srcStride, srcEnd, dst, dstStride, dstEnd); + } else { + this->blurOneScanGauss(info, src, srcStride, srcEnd, dst, dstStride, dstEnd); + } + +} + +// Blur one horizontal scan into the dst. +void SkMaskBlurFilter::blurOneScanBox( + FilterInfo info, + const uint8_t* src, size_t srcStride, const uint8_t* srcEnd, + uint8_t* dst, size_t dstStride, uint8_t* dstEnd) const { + + auto buffer0Begin = &fBuffer0[0]; + auto buffer0Cursor = buffer0Begin; + auto buffer0End = &fBuffer0[0] + info.diameter(0) - 1; + std::memset(&fBuffer0[0], 0, (buffer0End - buffer0Begin) * sizeof(fBuffer0[0])); + uint32_t sum0 = 0; + const uint64_t half = static_cast<uint64_t>(1) << 31; + + // Consume the source generating pixels. + for (auto srcCursor = src; srcCursor < srcEnd; dst += dstStride, srcCursor += srcStride) { + uint32_t s = *srcCursor; + sum0 += s; + + *dst = SkTo<uint8_t>((info.scaledWeight() * sum0 + half) >> 32); + + + sum0 -= *buffer0Cursor; + *buffer0Cursor = s; + buffer0Cursor = (buffer0Cursor + 1) < buffer0End ? buffer0Cursor + 1 : &fBuffer0[0]; + } + + // This handles the case when both ends of the box are not between [src, srcEnd), and both + // are zero at that point. + for (auto i = 0; i < static_cast<ptrdiff_t>(2 * info.borderSize()) - (srcEnd - src); i++) { + uint32_t s = 0; + sum0 += s; + + *dst = SkTo<uint8_t>((info.scaledWeight() * sum0 + half) >> 32); + + sum0 -= *buffer0Cursor; + *buffer0Cursor = s; + buffer0Cursor = (buffer0Cursor + 1) < buffer0End ? buffer0Cursor + 1 : &fBuffer0[0]; + dst += dstStride; + } + + // Starting from the right, fill in the rest of the buffer. + std::memset(&fBuffer0[0], 0, (buffer0End - &fBuffer0[0]) * sizeof(fBuffer0[0])); + + sum0 = 0; + + uint8_t* dstCursor = dstEnd; + const uint8_t* srcCursor = srcEnd; + do { + dstCursor -= dstStride; + srcCursor -= srcStride; + uint32_t s = *srcCursor; + sum0 += s; + + *dstCursor = SkTo<uint8_t>((info.scaledWeight() * sum0 + half) >> 32); + + sum0 -= *buffer0Cursor; + *buffer0Cursor = s; + buffer0Cursor = (buffer0Cursor + 1) < buffer0End ? buffer0Cursor + 1 : &fBuffer0[0]; + } while (dstCursor > dst); + +} + +// Blur one horizontal scan into the dst. +void SkMaskBlurFilter::blurOneScanGauss( + FilterInfo info, + const uint8_t* src, size_t srcStride, const uint8_t* srcEnd, + uint8_t* dst, size_t dstStride, uint8_t* dstEnd) const { auto buffer0Begin = &fBuffer0[0]; auto buffer1Begin = &fBuffer1[0]; |