aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2017-07-13 01:19:16 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-07-13 01:19:23 +0000
commit27b3d272a8fcce24813212f5816b177090111ec6 (patch)
tree0406f2faa23f6652511e428ee1686fc5e922ff8f /src
parentf0366326cc565c9e1535e4ac4baf273d7ea0d816 (diff)
Revert "Experimental blur code with 32 bit fix."
This reverts commit d4b2c537d058ad4cb890ba116d00aa86c3416c08. Reason for revert: speculative fix for android-roll java.lang.AssertionError: expected:<0> but was:<255> at org.junit.Assert.fail(Assert.java:88) at org.junit.Assert.failNotEquals(Assert.java:834) at org.junit.Assert.assertEquals(Assert.java:645) at org.junit.Assert.assertEquals(Assert.java:631) at android.graphics.cts.BlurMaskFilterTest.verifyColor(BlurMaskFilterTest.java:79) at android.graphics.cts.BlurMaskFilterTest.verifyQuadrants(BlurMaskFilterTest.java:72) at android.graphics.cts.BlurMaskFilterTest.testBlurMaskFilter(BlurMaskFilterTest.java:56) Original change's description: > Experimental blur code with 32 bit fix. > > This uses a new method of blurring that runs the three > passes of the box filter in a single pass. This implementation > currently only does 1x1 pixel at a time, but it should be simple > to expand to 4x4 pixels at a time. > > On the blur_10_normal_high_quality benchmark, the new is 7% faster > than the old code. For the blur_100.50_normal_high_quality > benchmark, the new code is 11% slower. > > Bug: skia: > Change-Id: I847270906b0ceac1dfbf43ab5446756689ef660f > Reviewed-on: https://skia-review.googlesource.com/22700 > Reviewed-by: Mike Reed <reed@google.com> > Commit-Queue: Herb Derby <herb@google.com> TBR=herb@google.com,reed@google.com Change-Id: Ie84f6bf8872cae08c06d679f0c2f2e6c3d8a02a2 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: skia: Reviewed-on: https://skia-review.googlesource.com/22880 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkMakeUnique.h5
-rw-r--r--src/core/SkMaskBlurFilter.cpp267
-rw-r--r--src/core/SkMaskBlurFilter.h67
-rw-r--r--src/effects/SkBlurMask.cpp96
4 files changed, 38 insertions, 397 deletions
diff --git a/src/core/SkMakeUnique.h b/src/core/SkMakeUnique.h
index 860ea2e8a7..188eb05ff4 100644
--- a/src/core/SkMakeUnique.h
+++ b/src/core/SkMakeUnique.h
@@ -18,11 +18,6 @@ std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
-template<typename T>
-std::unique_ptr<T> make_unique_default(size_t n) {
- return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]);
-}
-
}
#endif // SkMakeUnique_DEFINED
diff --git a/src/core/SkMaskBlurFilter.cpp b/src/core/SkMaskBlurFilter.cpp
deleted file mode 100644
index 0f0286354c..0000000000
--- a/src/core/SkMaskBlurFilter.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkMaskBlurFilter.h"
-
-#include <cmath>
-
-#include "SkMakeUnique.h"
-
-static const double kPi = 3.14159265358979323846264338327950288;
-
-static uint64_t weight_from_diameter(uint32_t d) {
- uint64_t d2 = d * d;
- uint64_t d3 = d2 * d;
- if ((d&1) == 0) {
- // d * d * (d + 1);
- return d3 + d2;
- }
-
- return d3;
-}
-
-static uint32_t filter_window(double sigma) {
- 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)} {}
-
-uint64_t SkMaskBlurFilter::FilterInfo::weight() const {
- return weight_from_diameter(fFilterWindow);
-
-}
-uint32_t SkMaskBlurFilter::FilterInfo::borderSize() const {
- if ((fFilterWindow&1) == 0) {
- return 3 * (fFilterWindow / 2) - 1;
- }
- return 3 * (fFilterWindow / 2);
-}
-
-size_t SkMaskBlurFilter::FilterInfo::diameter(uint8_t pass) const {
- SkASSERT(pass <= 2);
-
- if ((fFilterWindow&1) == 0) {
- // Handle even case.
- switch (pass) {
- case 0: return fFilterWindow;
- case 1: return fFilterWindow;
- case 2: return fFilterWindow+1;
- }
- }
-
- return fFilterWindow;
-}
-
-uint64_t SkMaskBlurFilter::FilterInfo::scaledWeight() const {
- return fScaledWeight;
-}
-
-SkMaskBlurFilter::SkMaskBlurFilter(double sigmaW, double sigmaH)
- : fInfoW{sigmaW}, fInfoH{sigmaH}
- , fBuffer0{skstd::make_unique_default<uint32_t[]>(bufferSize(0))}
- , fBuffer1{skstd::make_unique_default<uint32_t[]>(bufferSize(1))}
- , fBuffer2{skstd::make_unique_default<uint32_t[]>(bufferSize(2))} {
-}
-
-SkIPoint SkMaskBlurFilter::blur(const SkMask& src, SkMask* dst) const {
-
- uint64_t weightW = fInfoW.weight();
- uint64_t weightH = fInfoH.weight();
-
- size_t borderW = fInfoW.borderSize();
- size_t borderH = fInfoH.borderSize();
-
- size_t srcW = src.fBounds.width();
- size_t srcH = src.fBounds.height();
-
- size_t dstW = srcW + 2 * borderW;
- size_t dstH = srcH + 2 * borderH;
-
- dst->fBounds.set(0, 0, dstW, dstH);
- dst->fBounds.offset(src.fBounds.x(), src.fBounds.y());
- dst->fBounds.offset(-SkTo<int32_t>(borderW), -SkTo<int32_t>(borderH));
-
- dst->fImage = nullptr;
- dst->fRowBytes = dstW;
- dst->fFormat = SkMask::kA8_Format;
-
- if (src.fImage == nullptr) {
- return {SkTo<int32_t>(borderW), SkTo<int32_t>(borderH)};
- }
-
- dst->fImage = SkMask::AllocImage(dstW * dstH);
-
- if (weightW > 1 && weightH > 1) {
- // Blur both directions.
- size_t tmpW = srcH;
- size_t tmpH = dstW;
- auto tmp = skstd::make_unique_default<uint8_t[]>(tmpW * tmpH);
-
- // Blur horizontally, and transpose.
- for (size_t y = 0; y < srcH; y++) {
- auto srcStart = &src.fImage[y * src.fRowBytes];
- auto tmpStart = &tmp[y];
- this->blurOneScan(fInfoW,
- srcStart, 1, srcStart + srcW,
- tmpStart, tmpW, tmpStart + tmpW * tmpH);
- }
-
- // Blur vertically (scan in memory order because of the transposition),
- // and transpose back to the original orientation.
- for (size_t y = 0; y < tmpH; y++) {
- auto tmpStart = &tmp[y * tmpW];
- auto dstStart = &dst->fImage[y];
- this->blurOneScan(fInfoH,
- tmpStart, 1, tmpStart + tmpW,
- dstStart, dst->fRowBytes, dstStart + dst->fRowBytes * dstH);
- }
- } else if (weightW > 1) {
- // Blur only horizontally.
-
- for (size_t y = 0; y < srcH; y++) {
- auto srcStart = &src.fImage[y * src.fRowBytes];
- auto dstStart = &dst->fImage[y * dst->fRowBytes];
- this->blurOneScan(fInfoW,
- srcStart, 1, srcStart + srcW,
- dstStart, 1, dstStart + dstW);
- }
- } else if (weightH > 1) {
- // Blur only vertically.
-
- for (size_t x = 0; x < srcW; x++) {
- auto srcStart = &src.fImage[x];
- auto srcEnd = &src.fImage[src.fRowBytes * srcH];
- auto dstStart = &dst->fImage[x];
- auto dstEnd = &dst->fImage[dst->fRowBytes * dstH];
- this->blurOneScan(fInfoH,
- srcStart, src.fRowBytes, srcEnd,
- dstStart, dst->fRowBytes, dstEnd);
- }
- } else {
- // Copy to dst. No Blur.
-
- for (size_t y = 0; y < srcH; y++) {
- std::memcpy(&dst->fImage[y * dst->fRowBytes], &src.fImage[y * src.fRowBytes], dstW);
- }
- }
-
- return {SkTo<int32_t>(borderW), SkTo<int32_t>(borderH)};
-}
-
-size_t SkMaskBlurFilter::bufferSize(uint8_t bufferPass) const {
- return std::max(fInfoW.diameter(bufferPass), fInfoH.diameter(bufferPass)) - 1;
-}
-
-// Blur one horizontal scan into the dst.
-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 {
-
- auto buffer0Begin = &fBuffer0[0];
- auto buffer1Begin = &fBuffer1[0];
- auto buffer2Begin = &fBuffer2[0];
-
- auto buffer0Cursor = buffer0Begin;
- auto buffer1Cursor = buffer1Begin;
- auto buffer2Cursor = buffer2Begin;
-
- auto buffer0End = &fBuffer0[0] + info.diameter(0) - 1;
- auto buffer1End = &fBuffer1[0] + info.diameter(1) - 1;
- auto buffer2End = &fBuffer2[0] + info.diameter(2) - 1;
-
- std::memset(&fBuffer0[0], 0, (buffer0End - buffer0Begin) * sizeof(fBuffer0[0]));
- std::memset(&fBuffer1[0], 0, (buffer1End - buffer1Begin) * sizeof(fBuffer1[0]));
- std::memset(&fBuffer2[0], 0, (buffer2End - buffer2Begin) * sizeof(fBuffer2[0]));
-
- uint32_t sum0 = 0;
- uint32_t sum1 = 0;
- uint32_t sum2 = 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;
- sum1 += sum0;
- sum2 += sum1;
-
- *dst = SkTo<uint8_t>((info.scaledWeight() * sum2 + half) >> 32);
-
- sum2 -= *buffer2Cursor;
- *buffer2Cursor = sum1;
- buffer2Cursor = (buffer2Cursor + 1) < buffer2End ? buffer2Cursor + 1 : &fBuffer2[0];
-
- sum1 -= *buffer1Cursor;
- *buffer1Cursor = sum0;
- buffer1Cursor = (buffer1Cursor + 1) < buffer1End ? buffer1Cursor + 1 : &fBuffer1[0];
-
- 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;
- sum1 += sum0;
- sum2 += sum1;
-
- *dst = SkTo<uint8_t>((info.scaledWeight() * sum2 + half) >> 32);
-
- sum2 -= *buffer2Cursor;
- *buffer2Cursor = sum1;
- buffer2Cursor = (buffer2Cursor + 1) < buffer2End ? buffer2Cursor + 1 : &fBuffer2[0];
-
- sum1 -= *buffer1Cursor;
- *buffer1Cursor = sum0;
- buffer1Cursor = (buffer1Cursor + 1) < buffer1End ? buffer1Cursor + 1 : &fBuffer1[0];
-
- 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]));
- std::memset(&fBuffer1[0], 0, (buffer1End - &fBuffer1[0]) * sizeof(fBuffer1[0]));
- std::memset(&fBuffer2[0], 0, (buffer2End - &fBuffer2[0]) * sizeof(fBuffer2[0]));
-
- sum0 = sum1 = sum2 = 0;
-
- uint8_t* dstCursor = dstEnd;
- const uint8_t* srcCursor = srcEnd;
- do {
- dstCursor -= dstStride;
- srcCursor -= srcStride;
- uint32_t s = *srcCursor;
- sum0 += s;
- sum1 += sum0;
- sum2 += sum1;
-
- *dstCursor = SkTo<uint8_t>((info.scaledWeight() * sum2 + half) >> 32);
-
- sum2 -= *buffer2Cursor;
- *buffer2Cursor = sum1;
- buffer2Cursor = (buffer2Cursor + 1) < buffer2End ? buffer2Cursor + 1 : &fBuffer2[0];
-
- sum1 -= *buffer1Cursor;
- *buffer1Cursor = sum0;
- buffer1Cursor = (buffer1Cursor + 1) < buffer1End ? buffer1Cursor + 1 : &fBuffer1[0];
-
- sum0 -= *buffer0Cursor;
- *buffer0Cursor = s;
- buffer0Cursor = (buffer0Cursor + 1) < buffer0End ? buffer0Cursor + 1 : &fBuffer0[0];
- } while (dstCursor > dst);
-}
diff --git a/src/core/SkMaskBlurFilter.h b/src/core/SkMaskBlurFilter.h
deleted file mode 100644
index 9becadca39..0000000000
--- a/src/core/SkMaskBlurFilter.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkBlurMaskFilter_DEFINED
-#define SkBlurMaskFilter_DEFINED
-
-#include <algorithm>
-#include <memory>
-
-#include "SkMask.h"
-#include "SkTypes.h"
-
-// Implement a single channel Gaussian blur. The specifics for implementation are taken from:
-// https://drafts.fxtf.org/filters/#feGaussianBlurElement
-class SkMaskBlurFilter {
-public:
- // Given a filter specified by sigma, generate various quantities.
- class FilterInfo {
- public:
- explicit FilterInfo(double sigma);
-
- // The final weight to divide by given a box size calculated from sigma accumulated for
- // all three passes. For example, if the box size is 5, then the final weight for all
- // three passes is 5^3 or 125.
- uint64_t weight() const;
-
- // The distance between the first value of the dst and the first value of the src.
- uint32_t borderSize() const;
-
- // The size of the box filter.
- size_t diameter(uint8_t) const;
-
- // A factor used to simulate division using multiplication and shift.
- uint64_t scaledWeight() const;
-
- private:
- const uint32_t fFilterWindow;
- const uint64_t fScaledWeight;
- };
-
- // Create an object suitable for filtering an SkMask using a filter with width sigmaW and
- // height sigmaH.
- SkMaskBlurFilter(double sigmaW, double sigmaH);
-
- // Given a src SkMask, generate dst SkMask returning the border width and height.
- SkIPoint blur(const SkMask& src, SkMask* dst) const;
-
-private:
- size_t bufferSize(uint8_t bufferPass) const;
-
- void blurOneScan(FilterInfo gen,
- const uint8_t* src, size_t srcStride, const uint8_t* srcEnd,
- uint8_t* dst, size_t dstStride, uint8_t* dstEnd) const;
-
-
- const FilterInfo fInfoW,
- fInfoH;
- std::unique_ptr<uint32_t[]> fBuffer0,
- fBuffer1,
- fBuffer2;
-};
-
-#endif // SkBlurMaskFilter_DEFINED
diff --git a/src/effects/SkBlurMask.cpp b/src/effects/SkBlurMask.cpp
index fe59ab8269..eee16313f6 100644
--- a/src/effects/SkBlurMask.cpp
+++ b/src/effects/SkBlurMask.cpp
@@ -7,7 +7,6 @@
#include "SkBlurMask.h"
-#include "SkMaskBlurFilter.h"
#include "SkMath.h"
#include "SkTemplates.h"
#include "SkEndian.h"
@@ -407,7 +406,13 @@ static int boxBlurInterp(const uint8_t* src, int src_y_stride, uint8_t* dst,
return new_width;
}
-
+static void get_adjusted_radii(SkScalar passRadius, int *loRadius, int *hiRadius)
+{
+ *loRadius = *hiRadius = SkScalarCeilToInt(passRadius);
+ if (SkIntToScalar(*hiRadius) - passRadius > 0.5f) {
+ *loRadius = *hiRadius - 1;
+ }
+}
#include "SkColorPriv.h"
@@ -482,17 +487,6 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
return false;
}
- SkIPoint border;
-
-#ifdef SK_SUPPORT_LEGACY_MASK_BLUR
-
- auto get_adjusted_radii = [](SkScalar passRadius, int *loRadius, int *hiRadius) {
- *loRadius = *hiRadius = SkScalarCeilToInt(passRadius);
- if (SkIntToScalar(*hiRadius) - passRadius > 0.5f) {
- *loRadius = *hiRadius - 1;
- }
- };
-
// Force high quality off for small radii (performance)
if (!force_quality && sigma <= SkIntToScalar(2)) {
quality = kLow_SkBlurQuality;
@@ -502,12 +496,12 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
if (kHigh_SkBlurQuality == quality) {
// For the high quality path the 3 pass box blur kernel width is
// 6*rad+1 while the full Gaussian width is 6*sigma.
- passRadius = sigma - (1 / 6.0f);
+ passRadius = sigma - (1/6.0f);
} else {
// For the low quality path we only attempt to cover 3*sigma of the
// Gaussian blur area (1.5*sigma on each side). The single pass box
// blur's kernel size is 2*rad+1.
- passRadius = 1.5f * sigma - 0.5f;
+ passRadius = 1.5f*sigma - 0.5f;
}
// highQuality: use three box blur passes as a cheap way
@@ -528,8 +522,9 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
int padx = passCount * rx;
int pady = passCount * ry;
- border = {padx, pady};
-
+ if (margin) {
+ margin->set(padx, pady);
+ }
dst->fBounds.set(src.fBounds.fLeft - padx, src.fBounds.fTop - pady,
src.fBounds.fRight + padx, src.fBounds.fBottom + pady);
@@ -543,15 +538,15 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
return false; // too big to allocate, abort
}
- int sw = src.fBounds.width();
- int sh = src.fBounds.height();
- const uint8_t* sp = src.fImage;
- uint8_t* dp = SkMask::AllocImage(dstSize);
+ int sw = src.fBounds.width();
+ int sh = src.fBounds.height();
+ const uint8_t* sp = src.fImage;
+ uint8_t* dp = SkMask::AllocImage(dstSize);
SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp);
// build the blurry destination
- SkAutoTMalloc<uint8_t> tmpBuffer(dstSize);
- uint8_t* tp = tmpBuffer.get();
+ SkAutoTMalloc<uint8_t> tmpBuffer(dstSize);
+ uint8_t* tp = tmpBuffer.get();
int w = sw, h = sh;
if (outerWeight == 255) {
@@ -560,40 +555,33 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
if (kHigh_SkBlurQuality == quality) {
// Do three X blurs, with a transpose on the final one.
w = boxBlur<false>(sp, src.fRowBytes, tp, loRadius, hiRadius, w, h);
- w = boxBlur<false>(tp, w, dp, hiRadius, loRadius, w, h);
- w = boxBlur<true>(dp, w, tp, hiRadius, hiRadius, w, h);
+ w = boxBlur<false>(tp, w, dp, hiRadius, loRadius, w, h);
+ w = boxBlur<true>(dp, w, tp, hiRadius, hiRadius, w, h);
// Do three Y blurs, with a transpose on the final one.
- h = boxBlur<false>(tp, h, dp, loRadius, hiRadius, h, w);
- h = boxBlur<false>(dp, h, tp, hiRadius, loRadius, h, w);
- h = boxBlur<true>(tp, h, dp, hiRadius, hiRadius, h, w);
+ h = boxBlur<false>(tp, h, dp, loRadius, hiRadius, h, w);
+ h = boxBlur<false>(dp, h, tp, hiRadius, loRadius, h, w);
+ h = boxBlur<true>(tp, h, dp, hiRadius, hiRadius, h, w);
} else {
w = boxBlur<true>(sp, src.fRowBytes, tp, rx, rx, w, h);
- h = boxBlur<true>(tp, h, dp, ry, ry, h, w);
+ h = boxBlur<true>(tp, h, dp, ry, ry, h, w);
}
} else {
if (kHigh_SkBlurQuality == quality) {
// Do three X blurs, with a transpose on the final one.
w = boxBlurInterp<false>(sp, src.fRowBytes, tp, rx, w, h, outerWeight);
- w = boxBlurInterp<false>(tp, w, dp, rx, w, h, outerWeight);
- w = boxBlurInterp<true>(dp, w, tp, rx, w, h, outerWeight);
+ w = boxBlurInterp<false>(tp, w, dp, rx, w, h, outerWeight);
+ w = boxBlurInterp<true>(dp, w, tp, rx, w, h, outerWeight);
// Do three Y blurs, with a transpose on the final one.
- h = boxBlurInterp<false>(tp, h, dp, ry, h, w, outerWeight);
- h = boxBlurInterp<false>(dp, h, tp, ry, h, w, outerWeight);
- h = boxBlurInterp<true>(tp, h, dp, ry, h, w, outerWeight);
+ h = boxBlurInterp<false>(tp, h, dp, ry, h, w, outerWeight);
+ h = boxBlurInterp<false>(dp, h, tp, ry, h, w, outerWeight);
+ h = boxBlurInterp<true>(tp, h, dp, ry, h, w, outerWeight);
} else {
w = boxBlurInterp<true>(sp, src.fRowBytes, tp, rx, w, h, outerWeight);
- h = boxBlurInterp<true>(tp, h, dp, ry, h, w, outerWeight);
+ h = boxBlurInterp<true>(tp, h, dp, ry, h, w, outerWeight);
}
}
- dst->fImage = autoCall.release();
- }
-#else
- SkMaskBlurFilter blurFilter{sigma, sigma};
- border = blurFilter.blur(src, dst);
-#endif // SK_SUPPORT_LEGACY_MASK_BLUR
-
- if (src.fImage != nullptr) {
+ dst->fImage = dp;
// if need be, alloc the "real" dst (same size as src) and copy/merge
// the blur into it (applying the src)
if (style == kInner_SkBlurStyle) {
@@ -602,21 +590,17 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
if (0 == srcSize) {
return false; // too big to allocate, abort
}
- auto blur = dst->fImage;
dst->fImage = SkMask::AllocImage(srcSize);
- auto blurStart = &blur[border.x() + border.y() * dst->fRowBytes];
merge_src_with_blur(dst->fImage, src.fRowBytes,
- src.fImage, src.fRowBytes,
- blurStart,
- dst->fRowBytes,
- src.fBounds.width(), src.fBounds.height());
- SkMask::FreeImage(blur);
+ sp, src.fRowBytes,
+ dp + passCount * (rx + ry * dst->fRowBytes),
+ dst->fRowBytes, sw, sh);
+ SkMask::FreeImage(dp);
} else if (style != kNormal_SkBlurStyle) {
- auto dstStart = &dst->fImage[border.x() + border.y() * dst->fRowBytes];
- clamp_with_orig(dstStart,
- dst->fRowBytes, src.fImage, src.fRowBytes,
- src.fBounds.width(), src.fBounds.height(), style);
+ clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes),
+ dst->fRowBytes, sp, src.fRowBytes, sw, sh, style);
}
+ (void)autoCall.release();
}
if (style == kInner_SkBlurStyle) {
@@ -624,10 +608,6 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
dst->fRowBytes = src.fRowBytes;
}
- if (margin != nullptr) {
- *margin = border;
- }
-
return true;
}