зеркало из https://github.com/mozilla/moz-skia.git
Blur refactoring
https://codereview.chromium.org/21835004/ git-svn-id: http://skia.googlecode.com/svn/trunk@10936 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
45891b8e37
Коммит
7ce661d19c
|
@ -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:
|
||||
|
|
|
@ -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());
|
||||
|
|
22
gm/blurs.cpp
22
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -33,27 +33,39 @@ public:
|
|||
kAll_BlurFlag = 0x03
|
||||
};
|
||||
|
||||
/** 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 flags Flags to use - defaults to none
|
||||
@return The new blur maskfilter
|
||||
*/
|
||||
/**
|
||||
* DEPRECATED - radius-based
|
||||
*/
|
||||
static SkMaskFilter* Create(SkScalar radius, BlurStyle style,
|
||||
uint32_t flags = kNone_BlurFlag);
|
||||
|
||||
/** Create a blur maskfilter.
|
||||
@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(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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
return SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius),
|
||||
dst, src,
|
||||
style, margin, createMode);
|
||||
}
|
||||
|
||||
float radius = SkScalarToFloat(SkScalarMul(provided_radius, kBlurRadiusFudgeFactor));
|
||||
|
||||
// adjust blur radius to match interpretation from boxfilter code
|
||||
radius = (radius + .5f) * 2.f;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -29,27 +29,37 @@ public:
|
|||
kHigh_Quality //!< three pass box blur (similar to gaussian)
|
||||
};
|
||||
|
||||
static bool BlurRect(SkMask *dst, const SkRect &src,
|
||||
SkScalar radius, Style style,
|
||||
static bool BlurRect(SkScalar sigma, SkMask *dst, const SkRect &src,
|
||||
Style style,
|
||||
SkIPoint *margin = NULL,
|
||||
SkMask::CreateMode createMode=SkMask::kComputeBoundsAndRenderImage_CreateMode);
|
||||
static bool Blur(SkMask* dst, const SkMask& src,
|
||||
SkScalar radius, Style style, Quality quality,
|
||||
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);
|
||||
// DEPRECATED - radius-based
|
||||
static bool Blur(SkMask* dst, const SkMask& src,
|
||||
SkScalar radius, Style style, Quality quality,
|
||||
SkIPoint* margin = NULL);
|
||||
// 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
|
||||
|
|
|
@ -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;
|
||||
static const SkScalar kMAX_BLUR_SIGMA;
|
||||
|
||||
SkScalar fRadius;
|
||||
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] = {
|
||||
|
|
|
@ -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,27 +62,34 @@ static void normalize(SkScalar v[3]) {
|
|||
}
|
||||
}
|
||||
|
||||
SkEmbossMaskFilter::SkEmbossMaskFilter(const Light& light, SkScalar blurRadius)
|
||||
: fLight(light), fBlurRadius(blurRadius) {
|
||||
SkEmbossMaskFilter::SkEmbossMaskFilter(SkScalar blurSigma, const Light& light)
|
||||
: fBlurSigma(blurSigma), fLight(light) {
|
||||
normalize(fLight.fDirection);
|
||||
}
|
||||
|
||||
SkEmbossMaskFilter::SkEmbossMaskFilter(const Light& light, SkScalar blurRadius)
|
||||
: fLight(light) {
|
||||
normalize(fLight.fDirection);
|
||||
|
||||
fBlurSigma = SkBlurMask::ConvertRadiusToSigma(blurRadius);
|
||||
}
|
||||
|
||||
SkMask::Format SkEmbossMaskFilter::getFormat() const {
|
||||
return SkMask::k3D_Format;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
Загрузка…
Ссылка в новой задаче