aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkMaskBlurFilter.cpp
diff options
context:
space:
mode:
authorGravatar Herb Derby <herb@google.com>2017-08-15 15:00:03 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-08-15 15:00:17 +0000
commitf6975ea5fb178c572cf4c1cd255e5fe623418d45 (patch)
tree0dac43ecceb5cd75350c7a1c1eb131e0b50fb88c /src/core/SkMaskBlurFilter.cpp
parent72a37bed66c90ff2acb930dc4493dc633f265488 (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.cpp103
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];