aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-27 16:14:03 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-27 16:14:03 +0000
commit7ce661d19c5cf4484305a1b20c44bd111f129847 (patch)
treef92424e3d513b3f002481b2c66985113725cf488
parent45891b8e37e131b8298f64ff81b80999ba23b8d6 (diff)
Blur refactoring
-rw-r--r--bench/BlurRectBench.cpp4
-rw-r--r--gm/blurrect.cpp21
-rw-r--r--gm/blurs.cpp22
-rw-r--r--gm/circles.cpp2
-rw-r--r--gm/rects.cpp2
-rw-r--r--gm/shadows.cpp10
-rw-r--r--include/core/SkPicture.h1
-rw-r--r--include/effects/SkBlurDrawLooper.h6
-rw-r--r--include/effects/SkBlurMaskFilter.h24
-rw-r--r--include/effects/SkEmbossMaskFilter.h5
-rw-r--r--samplecode/SampleAll.cpp11
-rw-r--r--samplecode/SampleXfermodesBlur.cpp3
-rw-r--r--src/animator/SkDrawEmboss.cpp17
-rw-r--r--src/animator/SkDrawEmboss.h10
-rw-r--r--src/core/SkPicture.cpp1
-rw-r--r--src/effects/SkBlurDrawLooper.cpp25
-rw-r--r--src/effects/SkBlurMask.cpp98
-rw-r--r--src/effects/SkBlurMask.h36
-rw-r--r--src/effects/SkBlurMaskFilter.cpp135
-rw-r--r--src/effects/SkEmbossMaskFilter.cpp46
20 files changed, 281 insertions, 198 deletions
diff --git a/bench/BlurRectBench.cpp b/bench/BlurRectBench.cpp
index 3d0a896283..1f40780fc2 100644
--- a/bench/BlurRectBench.cpp
+++ b/bench/BlurRectBench.cpp
@@ -141,8 +141,8 @@ protected:
SkMask mask;
mask.fImage = NULL;
SkBlurMask::Blur(&mask, fSrcMask, this->radius(),
- SkBlurMask::kNormal_Style,
- SkBlurMask::kHigh_Quality);
+ SkBlurMask::kNormal_Style,
+ SkBlurMask::kHigh_Quality);
SkMask::FreeImage(mask.fImage);
}
private:
diff --git a/gm/blurrect.cpp b/gm/blurrect.cpp
index 5a18d16fad..2cb962f24c 100644
--- a/gm/blurrect.cpp
+++ b/gm/blurrect.cpp
@@ -71,12 +71,12 @@ class BlurRectGM : public skiagm::GM {
SkAlpha fAlpha;
public:
BlurRectGM(const char name[], PaintProc pproc, U8CPU alpha,
- SkBlurMaskFilter::BlurStyle bs) :
- fMaskFilter(SkBlurMaskFilter::Create(STROKE_WIDTH/2, bs,
- SkBlurMaskFilter::kHighQuality_BlurFlag))
- , fName(name)
- , fPProc(pproc)
- , fAlpha(SkToU8(alpha)) {
+ SkBlurMaskFilter::BlurStyle bs)
+ : fMaskFilter(SkBlurMaskFilter::Create(STROKE_WIDTH/2, bs,
+ SkBlurMaskFilter::kHighQuality_BlurFlag))
+ , fName(name)
+ , fPProc(pproc)
+ , fAlpha(SkToU8(alpha)) {
fName.appendf("_%s", gBlurStyle2Name[bs]);
}
@@ -208,13 +208,12 @@ private:
class BlurRectFastGM: public BlurRectCompareGM {
public:
- BlurRectFastGM(const char name[], unsigned int rect_width,
- unsigned int rect_height, float blur_radius,
+ BlurRectFastGM(const char name[], unsigned int rectWidth,
+ unsigned int rectHeight, float blurRadius,
SkBlurMask::Style style) :
- INHERITED(name, rect_width, rect_height, blur_radius, style)
- {
-
+ INHERITED(name, rectWidth, rectHeight, blurRadius, style) {
}
+
protected:
virtual bool makeMask(SkMask *m, const SkRect& r) SK_OVERRIDE {
return SkBlurMask::BlurRect(m, r, this->radius(), this->style());
diff --git a/gm/blurs.cpp b/gm/blurs.cpp
index 22804c7fa1..988fbe2943 100644
--- a/gm/blurs.cpp
+++ b/gm/blurs.cpp
@@ -60,31 +60,29 @@ protected:
for (size_t i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
if (gRecs[i].fStyle != NONE) {
SkMaskFilter* mf = SkBlurMaskFilter::Create(
- SkIntToScalar(20), gRecs[i].fStyle, flags
- );
+ SkIntToScalar(20), gRecs[i].fStyle, flags);
paint.setMaskFilter(mf)->unref();
} else {
paint.setMaskFilter(NULL);
}
- canvas->drawCircle(SkIntToScalar(200 + gRecs[i].fCx*100)
- , SkIntToScalar(200 + gRecs[i].fCy*100)
- , SkIntToScalar(50)
- , paint);
+ canvas->drawCircle(SkIntToScalar(200 + gRecs[i].fCx*100),
+ SkIntToScalar(200 + gRecs[i].fCy*100),
+ SkIntToScalar(50),
+ paint);
}
// draw text
{
SkMaskFilter* mf = SkBlurMaskFilter::Create(
- SkIntToScalar(4)
- , SkBlurMaskFilter::kNormal_BlurStyle
- , flags
- );
+ SkIntToScalar(4),
+ SkBlurMaskFilter::kNormal_BlurStyle,
+ flags);
paint.setMaskFilter(mf)->unref();
SkScalar x = SkIntToScalar(70);
SkScalar y = SkIntToScalar(400);
paint.setColor(SK_ColorBLACK);
canvas->drawText("Hamburgefons Style", 18, x, y, paint);
- canvas->drawText("Hamburgefons Style", 18
- , x, y + SkIntToScalar(50), paint);
+ canvas->drawText("Hamburgefons Style", 18,
+ x, y + SkIntToScalar(50), paint);
paint.setMaskFilter(NULL);
paint.setColor(SK_ColorWHITE);
x -= SkIntToScalar(2);
diff --git a/gm/circles.cpp b/gm/circles.cpp
index 4513934ab6..1fe114a287 100644
--- a/gm/circles.cpp
+++ b/gm/circles.cpp
@@ -83,7 +83,7 @@ protected:
SkIntToScalar(10), 0xFF0000FF,
SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
SkBlurDrawLooper::kOverrideColor_BlurFlag |
- SkBlurDrawLooper::kHighQuality_BlurFlag );
+ SkBlurDrawLooper::kHighQuality_BlurFlag);
SkAutoUnref aurL0(shadowLooper);
p.setLooper(shadowLooper);
fPaints.push_back(p);
diff --git a/gm/rects.cpp b/gm/rects.cpp
index eee92b35af..f2fa989a4d 100644
--- a/gm/rects.cpp
+++ b/gm/rects.cpp
@@ -88,7 +88,7 @@ protected:
SkIntToScalar(10), SK_ColorWHITE,
SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
SkBlurDrawLooper::kOverrideColor_BlurFlag |
- SkBlurDrawLooper::kHighQuality_BlurFlag );
+ SkBlurDrawLooper::kHighQuality_BlurFlag);
SkAutoUnref aurL0(shadowLooper);
p.setLooper(shadowLooper);
fPaints.push_back(p);
diff --git a/gm/shadows.cpp b/gm/shadows.cpp
index 2fb1615cf9..d7a12548cd 100644
--- a/gm/shadows.cpp
+++ b/gm/shadows.cpp
@@ -50,33 +50,33 @@ protected:
SkIntToScalar(10), 0xFF0000FF,
SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
SkBlurDrawLooper::kOverrideColor_BlurFlag |
- SkBlurDrawLooper::kHighQuality_BlurFlag );
+ SkBlurDrawLooper::kHighQuality_BlurFlag);
SkAutoUnref aurL0(shadowLoopers[0]);
shadowLoopers[1] =
new SkBlurDrawLooper (SkIntToScalar(10), SkIntToScalar(5),
SkIntToScalar(10), 0xFF0000FF,
SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
- SkBlurDrawLooper::kOverrideColor_BlurFlag );
+ SkBlurDrawLooper::kOverrideColor_BlurFlag);
SkAutoUnref aurL1(shadowLoopers[1]);
shadowLoopers[2] =
new SkBlurDrawLooper (SkIntToScalar(5), SkIntToScalar(5),
SkIntToScalar(10), 0xFF000000,
SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
- SkBlurDrawLooper::kHighQuality_BlurFlag );
+ SkBlurDrawLooper::kHighQuality_BlurFlag);
SkAutoUnref aurL2(shadowLoopers[2]);
shadowLoopers[3] =
new SkBlurDrawLooper (SkIntToScalar(5), SkIntToScalar(-5),
SkIntToScalar(-10), 0x7FFF0000,
SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
SkBlurDrawLooper::kOverrideColor_BlurFlag |
- SkBlurDrawLooper::kHighQuality_BlurFlag );
+ SkBlurDrawLooper::kHighQuality_BlurFlag);
SkAutoUnref aurL3(shadowLoopers[3]);
shadowLoopers[4] =
new SkBlurDrawLooper (SkIntToScalar(0), SkIntToScalar(5),
SkIntToScalar(5), 0xFF000000,
SkBlurDrawLooper::kIgnoreTransform_BlurFlag |
SkBlurDrawLooper::kOverrideColor_BlurFlag |
- SkBlurDrawLooper::kHighQuality_BlurFlag );
+ SkBlurDrawLooper::kHighQuality_BlurFlag);
SkAutoUnref aurL4(shadowLoopers[4]);
static const struct {
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index 95034c2a72..39fd7c02b6 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -209,6 +209,7 @@ protected:
// V11: modify how readBitmap and writeBitmap store their info.
// V12: add conics to SkPath, use new SkPathRef flattening
// V13: add flag to drawBitmapRectToRect
+ // parameterize blurs by sigma rather than radius
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V13_AND_ALL_OTHER_INSTANCES_TOO
static const uint32_t PRIOR_PICTURE_VERSION = 12; // TODO: remove when .skps regenerated
#endif
diff --git a/include/effects/SkBlurDrawLooper.h b/include/effects/SkBlurDrawLooper.h
index e968857889..8e0c2dd001 100644
--- a/include/effects/SkBlurDrawLooper.h
+++ b/include/effects/SkBlurDrawLooper.h
@@ -35,6 +35,10 @@ public:
kAll_BlurFlag = 0x07
};
+ SkBlurDrawLooper(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy,
+ uint32_t flags = kNone_BlurFlag);
+
+ // DEPRECATED - radius-based
SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, SkColor color,
uint32_t flags = kNone_BlurFlag);
virtual ~SkBlurDrawLooper();
@@ -64,6 +68,8 @@ private:
};
State fState;
+ void init(SkScalar sigma, SkScalar dx, SkScalar dy, SkColor color, uint32_t flags);
+
typedef SkDrawLooper INHERITED;
};
diff --git a/include/effects/SkBlurMaskFilter.h b/include/effects/SkBlurMaskFilter.h
index 2ab321aa7a..81c0ceb80d 100644
--- a/include/effects/SkBlurMaskFilter.h
+++ b/include/effects/SkBlurMaskFilter.h
@@ -33,27 +33,39 @@ public:
kAll_BlurFlag = 0x03
};
+ /**
+ * DEPRECATED - radius-based
+ */
+ static SkMaskFilter* Create(SkScalar radius, BlurStyle style,
+ uint32_t flags = kNone_BlurFlag);
+
/** Create a blur maskfilter.
- @param radius The radius to extend the blur from the original mask. Must be > 0.
@param style The BlurStyle to use
+ @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.
@param flags Flags to use - defaults to none
@return The new blur maskfilter
*/
- static SkMaskFilter* Create(SkScalar radius, BlurStyle style,
+ static SkMaskFilter* Create(BlurStyle style, SkScalar sigma,
uint32_t flags = kNone_BlurFlag);
/** Create an emboss maskfilter
+ @param blurSigma standard deviation of the Gaussian blur to apply
+ before applying lighting (e.g. 3)
@param direction array of 3 scalars [x, y, z] specifying the direction of the light source
@param ambient 0...1 amount of ambient light
@param specular coefficient for specular highlights (e.g. 8)
- @param blurRadius amount to blur before applying lighting (e.g. 3)
@return the emboss maskfilter
*/
- static SkMaskFilter* CreateEmboss( const SkScalar direction[3],
- SkScalar ambient, SkScalar specular,
- SkScalar blurRadius);
+ static SkMaskFilter* CreateEmboss(SkScalar blurSigma, const SkScalar direction[3],
+ SkScalar ambient, SkScalar specular);
+
+ // DEPRECATED - radius-based
+ static SkMaskFilter* CreateEmboss(const SkScalar direction[3],
+ SkScalar ambient, SkScalar specular,
+ SkScalar blurRadius);
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
+
private:
SkBlurMaskFilter(); // can't be instantiated
};
diff --git a/include/effects/SkEmbossMaskFilter.h b/include/effects/SkEmbossMaskFilter.h
index c6679200b3..4b5bd6f983 100644
--- a/include/effects/SkEmbossMaskFilter.h
+++ b/include/effects/SkEmbossMaskFilter.h
@@ -23,6 +23,9 @@ public:
uint8_t fSpecular; // exponent, 4.4 right now
};
+ SkEmbossMaskFilter(SkScalar blurSigma, const Light& light);
+
+ // DEPRECATED - radius-based
SkEmbossMaskFilter(const Light& light, SkScalar blurRadius);
// overrides from SkMaskFilter
@@ -41,7 +44,7 @@ protected:
private:
Light fLight;
- SkScalar fBlurRadius;
+ SkScalar fBlurSigma;
typedef SkMaskFilter INHERITED;
};
diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp
index 01fbe0f8ec..de99be70cb 100644
--- a/samplecode/SampleAll.cpp
+++ b/samplecode/SampleAll.cpp
@@ -80,7 +80,8 @@ private:
static void r0(SkLayerRasterizer* rast, SkPaint& p) {
p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3),
- SkBlurMaskFilter::kNormal_BlurStyle))->unref();
+ SkBlurMaskFilter::kNormal_BlurStyle,
+ SkBlurMaskFilter::kNone_BlurFlag))->unref();
rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
p.setMaskFilter(NULL);
@@ -254,7 +255,10 @@ static void apply_shader(SkPaint* paint, int index) {
#if 1
SkScalar dir[] = { SK_Scalar1, SK_Scalar1, SK_Scalar1 };
- paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir, SK_Scalar1/4, SkIntToScalar(4), SkIntToScalar(3)))->unref();
+ paint->setMaskFilter(SkBlurMaskFilter::CreateEmboss(dir,
+ SK_Scalar1/4,
+ SkIntToScalar(4),
+ SkIntToScalar(3)))->unref();
paint->setColor(SK_ColorBLUE);
#endif
}
@@ -383,8 +387,7 @@ protected:
light.fAmbient = 0x48;
light.fSpecular = 0x80;
SkScalar radius = SkIntToScalar(12)/5;
- SkEmbossMaskFilter* embossFilter = new SkEmbossMaskFilter(light,
- radius);
+ SkEmbossMaskFilter* embossFilter = new SkEmbossMaskFilter(light, radius);
SkXfermode* xfermode = SkXfermode::Create(SkXfermode::kXor_Mode);
SkColorFilter* lightingFilter = SkColorFilter::CreateLightingFilter(
diff --git a/samplecode/SampleXfermodesBlur.cpp b/samplecode/SampleXfermodesBlur.cpp
index ec5909b06c..a4ca9e7952 100644
--- a/samplecode/SampleXfermodesBlur.cpp
+++ b/samplecode/SampleXfermodesBlur.cpp
@@ -46,7 +46,8 @@ class XfermodesBlurView : public SampleView {
void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
SkScalar x, SkScalar y) {
SkPaint p;
- SkMaskFilter* mf = SkBlurMaskFilter::Create(5, SkBlurMaskFilter::kNormal_BlurStyle, 0);
+ SkMaskFilter* mf = SkBlurMaskFilter::Create(5, SkBlurMaskFilter::kNormal_BlurStyle,
+ SkBlurMaskFilter::kNone_BlurFlag);
p.setMaskFilter(mf)->unref();
SkScalar ww = SkIntToScalar(W);
diff --git a/src/animator/SkDrawEmboss.cpp b/src/animator/SkDrawEmboss.cpp
index 5eed370a5d..a0084eb2fd 100644
--- a/src/animator/SkDrawEmboss.cpp
+++ b/src/animator/SkDrawEmboss.cpp
@@ -12,22 +12,23 @@
#if SK_USE_CONDENSED_INFO == 0
const SkMemberInfo SkDrawEmboss::fInfo[] = {
- SK_MEMBER(ambient, Float),
- SK_MEMBER_ARRAY(direction, Float),
- SK_MEMBER(radius, Float),
- SK_MEMBER(specular, Float)
+ SK_MEMBER(fAmbient, Float),
+ SK_MEMBER_ARRAY(fDirection, Float),
+ SK_MEMBER(fSigma, Float),
+ SK_MEMBER(fSpecular, Float)
};
#endif
DEFINE_GET_MEMBER(SkDrawEmboss);
-SkDrawEmboss::SkDrawEmboss() : radius(-1) {
- direction.setCount(3);
+SkDrawEmboss::SkDrawEmboss() : fSigma(-1) {
+ fDirection.setCount(3);
}
SkMaskFilter* SkDrawEmboss::getMaskFilter() {
- if (radius < 0 || direction.count() !=3)
+ if (fSigma < 0 || fDirection.count() !=3)
return NULL;
- return SkBlurMaskFilter::CreateEmboss(direction.begin(), ambient, specular, radius);
+ return SkBlurMaskFilter::CreateEmboss(fSigma, fDirection.begin(),
+ fAmbient, fSpecular);
}
diff --git a/src/animator/SkDrawEmboss.h b/src/animator/SkDrawEmboss.h
index 6e6199753c..7ffd3ef841 100644
--- a/src/animator/SkDrawEmboss.h
+++ b/src/animator/SkDrawEmboss.h
@@ -15,10 +15,14 @@
class SkDrawEmboss : public SkDrawMaskFilter {
DECLARE_DRAW_MEMBER_INFO(Emboss);
SkDrawEmboss();
- virtual SkMaskFilter* getMaskFilter();
+ virtual SkMaskFilter* getMaskFilter() SK_OVERRIDE;
protected:
- SkTDScalarArray direction;
- SkScalar radius, ambient, specular;
+ SkTDScalarArray fDirection;
+ SkScalar fSigma;
+ SkScalar fAmbient;
+ SkScalar fSpecular;
+
+ typedef SkDrawMaskFilter INHERITED;
};
#endif // SkDrawEmboss_DEFINED
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index 097e0ea0c7..c94641b09b 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -275,6 +275,7 @@ bool SkPicture::StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
}
if (PICTURE_VERSION != info.fVersion
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V13_AND_ALL_OTHER_INSTANCES_TOO
+ // V13 is backwards compatible with V12
&& PRIOR_PICTURE_VERSION != info.fVersion // TODO: remove when .skps regenerated
#endif
) {
diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp
index 9585214b29..fb0153c2e7 100644
--- a/src/effects/SkBlurDrawLooper.cpp
+++ b/src/effects/SkBlurDrawLooper.cpp
@@ -6,6 +6,7 @@
* found in the LICENSE file.
*/
#include "SkBlurDrawLooper.h"
+#include "SkBlurMask.h" // just for SkBlurMask::ConvertRadiusToSigma
#include "SkBlurMaskFilter.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
@@ -16,11 +17,25 @@
#include "SkStringUtils.h"
SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
- SkColor color, uint32_t flags)
- : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags), fState(kDone) {
+ SkColor color, uint32_t flags) {
+ this->init(SkBlurMask::ConvertRadiusToSigma(radius), dx, dy, color, flags);
+}
+
+SkBlurDrawLooper::SkBlurDrawLooper(SkColor color, SkScalar sigma,
+ SkScalar dx, SkScalar dy, uint32_t flags) {
+ this->init(sigma, dx, dy, color, flags);
+}
+
+void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
+ SkColor color, uint32_t flags) {
+ fDx = dx;
+ fDy = dy;
+ fBlurColor = color;
+ fBlurFlags = flags;
+ fState = kDone;
SkASSERT(flags <= kAll_BlurFlag);
- if (radius > 0) {
+ if (sigma > 0) {
uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
SkBlurMaskFilter::kNone_BlurFlag;
@@ -29,8 +44,8 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
SkBlurMaskFilter::kHighQuality_BlurFlag :
SkBlurMaskFilter::kNone_BlurFlag;
- fBlur = SkBlurMaskFilter::Create(radius,
- SkBlurMaskFilter::kNormal_BlurStyle,
+ fBlur = SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle,
+ sigma,
blurFlags);
} else {
fBlur = NULL;
diff --git a/src/effects/SkBlurMask.cpp b/src/effects/SkBlurMask.cpp
index c946c5eb4b..a8ae1d3133 100644
--- a/src/effects/SkBlurMask.cpp
+++ b/src/effects/SkBlurMask.cpp
@@ -12,7 +12,19 @@
#include "SkTemplates.h"
#include "SkEndian.h"
-const SkScalar SkBlurMask::kBlurRadiusFudgeFactor = SkFloatToScalar(.57735f);
+
+SkScalar SkBlurMask::ConvertRadiusToSigma(SkScalar radius) {
+ // This constant approximates the scaling done in the software path's
+ // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
+ // IMHO, it actually should be 1: we blur "less" than we should do
+ // according to the CSS and canvas specs, simply because Safari does the same.
+ // Firefox used to do the same too, until 4.0 where they fixed it. So at some
+ // point we should probably get rid of these scaling constants and rebaseline
+ // all the blur tests.
+ static const SkScalar kBLUR_SIGMA_SCALE = SkFloatToScalar(0.57735f);
+
+ return radius ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f;
+}
#define UNROLL_SEPARABLE_LOOPS
@@ -473,24 +485,40 @@ void SkMask_FreeImage(uint8_t* image) {
bool SkBlurMask::Blur(SkMask* dst, const SkMask& src,
SkScalar radius, Style style, Quality quality,
- SkIPoint* margin)
-{
+ SkIPoint* margin) {
+ return SkBlurMask::BoxBlur(dst, src,
+ SkBlurMask::ConvertRadiusToSigma(radius),
+ style, quality, margin);
+}
+
+bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
+ SkScalar sigma, Style style, Quality quality,
+ SkIPoint* margin) {
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
// Force high quality off for small radii (performance)
- if (radius < SkIntToScalar(3)) {
+ if (sigma <= SkIntToScalar(2)) {
quality = kLow_Quality;
}
+ SkScalar passRadius;
+ if (kHigh_Quality == 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);
+ } 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;
+ }
+
// highQuality: use three box blur passes as a cheap way
// to approximate a Gaussian blur
int passCount = (kHigh_Quality == quality) ? 3 : 1;
- SkScalar passRadius = (kHigh_Quality == quality) ?
- SkScalarMul( radius, kBlurRadiusFudgeFactor):
- radius;
int rx = SkScalarCeil(passRadius);
int outerWeight = 255 - SkScalarRound((SkIntToScalar(rx) - passRadius) * 255);
@@ -510,7 +538,7 @@ bool SkBlurMask::Blur(SkMask* dst, const SkMask& src,
margin->set(padx, pady);
}
dst->fBounds.set(src.fBounds.fLeft - padx, src.fBounds.fTop - pady,
- src.fBounds.fRight + padx, src.fBounds.fBottom + pady);
+ src.fBounds.fRight + padx, src.fBounds.fBottom + pady);
dst->fRowBytes = dst->fBounds.width();
dst->fFormat = SkMask::kA8_Format;
@@ -651,13 +679,6 @@ static float gaussianIntegral(float x) {
return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f * x);
}
-// Compute the size of the array allocated for the profile.
-
-static int compute_profile_size(SkScalar radius) {
- return SkScalarRoundToInt(radius * 3);
-
-}
-
/* compute_profile allocates and fills in an array of floating
point values between 0 and 255 for the profile signature of
a blurred half-plane with the given blur radius. Since we're
@@ -669,13 +690,13 @@ static int compute_profile_size(SkScalar radius) {
memory returned in profile_out.
*/
-static void compute_profile(SkScalar radius, unsigned int **profile_out) {
- int size = compute_profile_size(radius);
+static void compute_profile(SkScalar sigma, unsigned int **profile_out) {
+ int size = SkScalarCeilToInt(6*sigma);
int center = size >> 1;
unsigned int *profile = SkNEW_ARRAY(unsigned int, size);
- float invr = 1.f/radius;
+ float invr = 1.f/(2*sigma);
profile[0] = 255;
for (int x = 1 ; x < size ; ++x) {
@@ -705,16 +726,17 @@ static inline unsigned int profile_lookup( unsigned int *profile, int loc, int b
}
bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src,
- SkScalar provided_radius, Style style,
+ SkScalar radius, Style style,
SkIPoint *margin, SkMask::CreateMode createMode) {
- int profile_size;
-
- float radius = SkScalarToFloat(SkScalarMul(provided_radius, kBlurRadiusFudgeFactor));
-
- // adjust blur radius to match interpretation from boxfilter code
- radius = (radius + .5f) * 2.f;
+ return SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius),
+ dst, src,
+ style, margin, createMode);
+}
- profile_size = compute_profile_size(radius);
+bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
+ const SkRect &src, Style style,
+ SkIPoint *margin, SkMask::CreateMode createMode) {
+ int profile_size = SkScalarCeilToInt(6*sigma);
int pad = profile_size/2;
if (margin) {
@@ -745,7 +767,7 @@ bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src,
}
unsigned int *profile = NULL;
- compute_profile(radius, &profile);
+ compute_profile(sigma, &profile);
SkAutoTDeleteArray<unsigned int> ada(profile);
size_t dstSize = dst->computeImageSize();
@@ -775,8 +797,8 @@ bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src,
if (profile_size <= sw) {
horizontalScanline[x] = profile_lookup(profile, x, dstWidth, w);
} else {
- float span = float(sw)/radius;
- float giX = 1.5f - (x+.5f)/radius;
+ float span = float(sw)/(2*sigma);
+ float giX = 1.5f - (x+.5f)/(2*sigma);
horizontalScanline[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegral(giX + span)));
}
}
@@ -786,8 +808,8 @@ bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src,
if (profile_size <= sh) {
profile_y = profile_lookup(profile, y, dstHeight, h);
} else {
- float span = float(sh)/radius;
- float giY = 1.5f - (y+.5f)/radius;
+ float span = float(sh)/(2*sigma);
+ float giY = 1.5f - (y+.5f)/(2*sigma);
profile_y = (uint8_t) (255 * (gaussianIntegral(giY) - gaussianIntegral(giY + span)));
}
@@ -834,22 +856,24 @@ bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src,
return true;
}
+bool SkBlurMask::BlurGroundTruth(SkMask* dst, const SkMask& src, SkScalar radius,
+ Style style, SkIPoint* margin) {
+ return BlurGroundTruth(ConvertRadiusToSigma(radius), dst, src, style, margin);
+}
// The "simple" blur is a direct implementation of separable convolution with a discrete
// gaussian kernel. It's "ground truth" in a sense; too slow to be used, but very
// useful for correctness comparisons.
-bool SkBlurMask::BlurGroundTruth(SkMask* dst, const SkMask& src, SkScalar provided_radius,
- Style style, SkIPoint* margin) {
+bool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src,
+ Style style, SkIPoint* margin) {
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
- float radius = SkScalarToFloat(SkScalarMul(provided_radius, kBlurRadiusFudgeFactor));
- float stddev = SkScalarToFloat(radius) /2.0f;
- float variance = stddev * stddev;
+ float variance = sigma * sigma;
- int windowSize = SkScalarCeil(stddev*4);
+ int windowSize = SkScalarCeil(sigma*4);
// round window size up to nearest odd number
windowSize |= 1;
diff --git a/src/effects/SkBlurMask.h b/src/effects/SkBlurMask.h
index 36d7800014..f49cd129df 100644
--- a/src/effects/SkBlurMask.h
+++ b/src/effects/SkBlurMask.h
@@ -29,27 +29,37 @@ public:
kHigh_Quality //!< three pass box blur (similar to gaussian)
};
+ static bool BlurRect(SkScalar sigma, SkMask *dst, const SkRect &src,
+ Style style,
+ SkIPoint *margin = NULL,
+ SkMask::CreateMode createMode =
+ SkMask::kComputeBoundsAndRenderImage_CreateMode);
+ static bool BoxBlur(SkMask* dst, const SkMask& src,
+ SkScalar sigma, Style style, Quality quality,
+ SkIPoint* margin = NULL);
+
+ // the "ground truth" blur does a gaussian convolution; it's slow
+ // but useful for comparison purposes.
+ static bool BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src,
+ Style style,
+ SkIPoint* margin = NULL);
+
+ // DEPRECATED - radius-based
static bool BlurRect(SkMask *dst, const SkRect &src,
SkScalar radius, Style style,
SkIPoint *margin = NULL,
- SkMask::CreateMode createMode=SkMask::kComputeBoundsAndRenderImage_CreateMode);
+ SkMask::CreateMode createMode =
+ SkMask::kComputeBoundsAndRenderImage_CreateMode);
+ // DEPRECATED - radius-based
static bool Blur(SkMask* dst, const SkMask& src,
SkScalar radius, Style style, Quality quality,
SkIPoint* margin = NULL);
-
- // the "ground truth" blur does a gaussian convolution; it's slow
- // but useful for comparison purposes.
-
+ // DEPRECATED - radius-based
static bool BlurGroundTruth(SkMask* dst, const SkMask& src,
- SkScalar provided_radius, Style style,
- SkIPoint* margin = NULL);
-
- // scale factor for the blur radius to match the behavior of the all existing blur
- // code (both on the CPU and the GPU). This magic constant is 1/sqrt(3).
- // TODO: get rid of this fudge factor and move any required fudging up into
- // the calling library
- static const SkScalar kBlurRadiusFudgeFactor;
+ SkScalar radius, Style style,
+ SkIPoint* margin = NULL);
+ static SkScalar ConvertRadiusToSigma(SkScalar radius);
};
#endif
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index b54c33004c..88333582a6 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -24,8 +24,7 @@
class SkBlurMaskFilterImpl : public SkMaskFilter {
public:
- SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle,
- uint32_t flags);
+ SkBlurMaskFilterImpl(SkScalar sigma, SkBlurMaskFilter::BlurStyle, uint32_t flags);
// overrides from SkMaskFilter
virtual SkMask::Format getFormat() const SK_OVERRIDE;
@@ -60,37 +59,26 @@ private:
// To avoid unseemly allocation requests (esp. for finite platforms like
// handset) we limit the radius so something manageable. (as opposed to
// a request like 10,000)
- static const SkScalar kMAX_BLUR_RADIUS;
- // This constant approximates the scaling done in the software path's
- // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
- // IMHO, it actually should be 1: we blur "less" than we should do
- // according to the CSS and canvas specs, simply because Safari does the same.
- // Firefox used to do the same too, until 4.0 where they fixed it. So at some
- // point we should probably get rid of these scaling constants and rebaseline
- // all the blur tests.
- static const SkScalar kBLUR_SIGMA_SCALE;
-
- SkScalar fRadius;
+ static const SkScalar kMAX_BLUR_SIGMA;
+
+ SkScalar fSigma;
SkBlurMaskFilter::BlurStyle fBlurStyle;
uint32_t fBlurFlags;
SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
-#if SK_SUPPORT_GPU
- SkScalar computeXformedRadius(const SkMatrix& ctm) const {
+
+ SkScalar computeXformedSigma(const SkMatrix& ctm) const {
bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
- SkScalar xformedRadius = ignoreTransform ? fRadius
- : ctm.mapRadius(fRadius);
- return SkMinScalar(xformedRadius, kMAX_BLUR_RADIUS);
+ SkScalar xformedSigma = ignoreTransform ? fSigma : ctm.mapRadius(fSigma);
+ return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA);
}
-#endif
typedef SkMaskFilter INHERITED;
};
-const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_RADIUS = SkIntToScalar(128);
-const SkScalar SkBlurMaskFilterImpl::kBLUR_SIGMA_SCALE = SkFloatToScalar(0.6f);
+const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128);
SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
SkBlurMaskFilter::BlurStyle style,
@@ -101,15 +89,29 @@ SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
return NULL;
}
- return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
+ SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
+
+ return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags));
+}
+
+SkMaskFilter* SkBlurMaskFilter::Create(SkBlurMaskFilter::BlurStyle style,
+ SkScalar sigma,
+ uint32_t flags) {
+ // use !(sigma > 0) instead of sigma <= 0 to reject NaN values
+ if (!(sigma > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
+ || flags > SkBlurMaskFilter::kAll_BlurFlag) {
+ return NULL;
+ }
+
+ return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags));
}
///////////////////////////////////////////////////////////////////////////////
-SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
+SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma,
SkBlurMaskFilter::BlurStyle style,
uint32_t flags)
- : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) {
+ : fSigma(sigma), fBlurStyle(style), fBlurFlags(flags) {
#if 0
fGamma = NULL;
if (gammaScale) {
@@ -120,7 +122,7 @@ SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
}
#endif
- SkASSERT(radius >= 0);
+ SkASSERT(fSigma >= 0);
SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
}
@@ -132,35 +134,22 @@ SkMask::Format SkBlurMaskFilterImpl::getFormat() const {
bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
const SkMatrix& matrix,
SkIPoint* margin) const{
- SkScalar radius;
- if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
- radius = fRadius;
- } else {
- radius = matrix.mapRadius(fRadius);
- }
+ SkScalar sigma = this->computeXformedSigma(matrix);
- radius = SkMinScalar(radius, kMAX_BLUR_RADIUS);
SkBlurMask::Quality blurQuality =
(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;
- return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
- blurQuality, margin);
+ return SkBlurMask::BoxBlur(dst, src, sigma, (SkBlurMask::Style)fBlurStyle,
+ blurQuality, margin);
}
bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r,
const SkMatrix& matrix,
SkIPoint* margin, SkMask::CreateMode createMode) const{
- SkScalar radius;
- if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
- radius = fRadius;
- } else {
- radius = matrix.mapRadius(fRadius);
- }
+ SkScalar sigma = computeXformedSigma(matrix);
- radius = SkMinScalar(radius, kMAX_BLUR_RADIUS);
-
- return SkBlurMask::BlurRect(dst, r, radius, (SkBlurMask::Style)fBlurStyle,
+ return SkBlurMask::BlurRect(sigma, dst, r, (SkBlurMask::Style)fBlurStyle,
margin, createMode);
}
@@ -334,24 +323,7 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src,
SkRect* dst) const {
- SkScalar gpuPad, rasterPad;
-
- {
- // GPU path
- SkScalar sigma = SkScalarMul(fRadius, kBLUR_SIGMA_SCALE);
- gpuPad = sigma * 3.0f;
- }
-
- {
- // raster path
- SkScalar radius = SkScalarMul(fRadius, SkBlurMask::kBlurRadiusFudgeFactor);
-
- radius = (radius + .5f) * 2.f;
-
- rasterPad = SkIntToScalar(SkScalarRoundToInt(radius * 3)/2);
- }
-
- SkScalar pad = SkMaxScalar(gpuPad, rasterPad);
+ SkScalar pad = 3.0f * fSigma;
dst->set(src.fLeft - pad, src.fTop - pad,
src.fRight + pad, src.fBottom + pad);
@@ -359,16 +331,27 @@ void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src,
SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
: SkMaskFilter(buffer) {
- fRadius = buffer.readScalar();
+ fSigma = buffer.readScalar();
+#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V13_AND_ALL_OTHER_INSTANCES_TOO
+ // Fixing this must be done in two stages. When the skps are recaptured in V13,
+ // remove the ConvertRadiusToSigma but retain the absolute value.
+ // At the same time, switch the code in flatten to write a positive value.
+ // When the skps are captured in V14 the absolute value can be removed.
+ if (fSigma > 0) {
+ fSigma = SkBlurMask::ConvertRadiusToSigma(fSigma);
+ } else {
+ fSigma = -fSigma;
+ }
+#endif
fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt();
fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag;
- SkASSERT(fRadius >= 0);
+ SkASSERT(fSigma >= 0);
SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
}
void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.writeScalar(fRadius);
+ buffer.writeScalar(-fSigma);
buffer.writeInt(fBlurStyle);
buffer.writeUInt(fBlurFlags);
}
@@ -379,17 +362,17 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
const SkIRect& clipBounds,
const SkMatrix& ctm,
SkRect* maskRect) const {
- SkScalar xformedRadius = this->computeXformedRadius(ctm);
- if (xformedRadius <= 0) {
+ SkScalar xformedSigma = this->computeXformedSigma(ctm);
+ if (xformedSigma <= 0) {
return false;
}
- static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64);
- static const SkScalar kMIN_GPU_BLUR_RADIUS = SkIntToScalar(32);
+ static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64);
+ static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32);
if (srcBounds.width() <= kMIN_GPU_BLUR_SIZE &&
srcBounds.height() <= kMIN_GPU_BLUR_SIZE &&
- xformedRadius <= kMIN_GPU_BLUR_RADIUS) {
+ xformedSigma <= kMIN_GPU_BLUR_SIGMA) {
// We prefer to blur small rect with small radius via CPU.
return false;
}
@@ -399,7 +382,7 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
return true;
}
- float sigma3 = 3 * SkScalarToFloat(xformedRadius) * kBLUR_SIGMA_SCALE;
+ float sigma3 = 3 * SkScalarToFloat(xformedSigma);
SkRect clipRect = SkRect::MakeFromIRect(clipBounds);
SkRect srcRect(srcBounds);
@@ -422,16 +405,14 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
- SkScalar xformedRadius = this->computeXformedRadius(context->getMatrix());
- SkASSERT(xformedRadius > 0);
-
- float sigma = SkScalarToFloat(xformedRadius) * kBLUR_SIGMA_SCALE;
+ SkScalar xformedSigma = this->computeXformedSigma(context->getMatrix());
+ SkASSERT(xformedSigma > 0);
// If we're doing a normal blur, we can clobber the pathTexture in the
// gaussianBlur. Otherwise, we need to save it for later compositing.
bool isNormalBlur = (SkBlurMaskFilter::kNormal_BlurStyle == fBlurStyle);
*result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOverwriteSrc,
- clipRect, false, sigma, sigma);
+ clipRect, false, xformedSigma, xformedSigma);
if (NULL == *result) {
return false;
}
@@ -469,8 +450,8 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
void SkBlurMaskFilterImpl::toString(SkString* str) const {
str->append("SkBlurMaskFilterImpl: (");
- str->append("radius: ");
- str->appendScalar(fRadius);
+ str->append("sigma: ");
+ str->appendScalar(fSigma);
str->append(" ");
static const char* gStyleName[SkBlurMaskFilter::kBlurStyleCount] = {
diff --git a/src/effects/SkEmbossMaskFilter.cpp b/src/effects/SkEmbossMaskFilter.cpp
index 391cba55c4..315b8cbab4 100644
--- a/src/effects/SkEmbossMaskFilter.cpp
+++ b/src/effects/SkEmbossMaskFilter.cpp
@@ -26,6 +26,12 @@ static inline int pin2byte(int n) {
SkMaskFilter* SkBlurMaskFilter::CreateEmboss(const SkScalar direction[3],
SkScalar ambient, SkScalar specular,
SkScalar blurRadius) {
+ return SkBlurMaskFilter::CreateEmboss(SkBlurMask::ConvertRadiusToSigma(blurRadius),
+ direction, ambient, specular);
+}
+
+SkMaskFilter* SkBlurMaskFilter::CreateEmboss(SkScalar blurSigma, const SkScalar direction[3],
+ SkScalar ambient, SkScalar specular) {
if (direction == NULL) {
return NULL;
}
@@ -42,7 +48,7 @@ SkMaskFilter* SkBlurMaskFilter::CreateEmboss(const SkScalar direction[3],
light.fAmbient = SkToU8(am);
light.fSpecular = SkToU8(sp);
- return SkNEW_ARGS(SkEmbossMaskFilter, (light, blurRadius));
+ return SkNEW_ARGS(SkEmbossMaskFilter, (blurSigma, light));
}
///////////////////////////////////////////////////////////////////////////////
@@ -56,9 +62,16 @@ static void normalize(SkScalar v[3]) {
}
}
+SkEmbossMaskFilter::SkEmbossMaskFilter(SkScalar blurSigma, const Light& light)
+ : fBlurSigma(blurSigma), fLight(light) {
+ normalize(fLight.fDirection);
+}
+
SkEmbossMaskFilter::SkEmbossMaskFilter(const Light& light, SkScalar blurRadius)
- : fLight(light), fBlurRadius(blurRadius) {
+ : fLight(light) {
normalize(fLight.fDirection);
+
+ fBlurSigma = SkBlurMask::ConvertRadiusToSigma(blurRadius);
}
SkMask::Format SkEmbossMaskFilter::getFormat() const {
@@ -66,17 +79,17 @@ SkMask::Format SkEmbossMaskFilter::getFormat() const {
}
bool SkEmbossMaskFilter::filterMask(SkMask* dst, const SkMask& src,
- const SkMatrix& matrix, SkIPoint* margin) const {
- SkScalar radius = matrix.mapRadius(fBlurRadius);
+ const SkMatrix& matrix, SkIPoint* margin) const {
+ SkScalar sigma = matrix.mapRadius(fBlurSigma);
- if (!SkBlurMask::Blur(dst, src, radius, SkBlurMask::kInner_Style,
- SkBlurMask::kLow_Quality)) {
+ if (!SkBlurMask::BoxBlur(dst, src, sigma, SkBlurMask::kInner_Style,
+ SkBlurMask::kLow_Quality)) {
return false;
}
dst->fFormat = SkMask::k3D_Format;
if (margin) {
- margin->set(SkScalarCeil(radius), SkScalarCeil(radius));
+ margin->set(SkScalarCeil(3*sigma), SkScalarCeil(3*sigma));
}
if (src.fImage == NULL) {
@@ -121,7 +134,18 @@ SkEmbossMaskFilter::SkEmbossMaskFilter(SkFlattenableReadBuffer& buffer)
SkASSERT(buffer.getArrayCount() == sizeof(Light));
buffer.readByteArray(&fLight);
SkASSERT(fLight.fPad == 0); // for the font-cache lookup to be clean
- fBlurRadius = buffer.readScalar();
+ fBlurSigma = buffer.readScalar();
+#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V13_AND_ALL_OTHER_INSTANCES_TOO
+ // Fixing this must be done in two stages. When the skps are recaptured in V13,
+ // remove the ConvertRadiusToSigma but retain the absolute value.
+ // At the same time, switch the code in flatten to write a positive value.
+ // When the skps are captured in V14 the absolute value can be removed.
+ if (fBlurSigma > 0) {
+ fBlurSigma = SkBlurMask::ConvertRadiusToSigma(fBlurSigma);
+ } else {
+ fBlurSigma = -fBlurSigma;
+ }
+#endif
}
void SkEmbossMaskFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
@@ -130,7 +154,7 @@ void SkEmbossMaskFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
Light tmpLight = fLight;
tmpLight.fPad = 0; // for the font-cache lookup to be clean
buffer.writeByteArray(&tmpLight, sizeof(tmpLight));
- buffer.writeScalar(fBlurRadius);
+ buffer.writeScalar(-fBlurSigma);
}
#ifdef SK_DEVELOPER
@@ -148,8 +172,8 @@ void SkEmbossMaskFilter::toString(SkString* str) const {
str->appendf("ambient: %d specular: %d ",
fLight.fAmbient, fLight.fSpecular);
- str->append("blurRadius: ");
- str->appendScalar(fBlurRadius);
+ str->append("blurSigma: ");
+ str->appendScalar(fBlurSigma);
str->append(")");
}
#endif