还是先看下类的继承关系:
SkNoncopyable
∟ SkRefCnt
∟SkFlattenable
∟SkMaskFilter
∟SkBlurMaskFilterImpl
∟SkEmbossMaskFilter
∟SkTableMaskFilter
∟SkKernel33ProcMaskFilter
SkBlurMaskFilter
SkBlurMask
SkEmbossMask
以上为与MaskFilter相关的类,其他SkBlurMaskFilter/SkBlurMask/SkEmbossMask三个类在effect目录下的文件中定义。
SkBlurMask 只封装了静态成员函数Blur
SkEmbossMask 只封装了静态成员函数Emboss
从参数看 Blur 和Emboss 是改变SkMask对象的作用。
SkEmbossMaskFilter 的成员函数 filterMask 用到了SkBlurMask::Blur和SkEmbossMask::Emboss
SkBlurMaskFilterImpl 的成员函数 filterMask 用到了SkBlurMask::Blur。
--------------------------------------------------------------- -------------------------------使用--
要使用MaskFilter要通过类 SkBlurMaskFilter
SkBlurMaskFilter是个独立的类,没有继承关系。
class SK_API SkBlurMaskFilter
{
public:
enum BlurStyle { //模糊风格
kNormal_BlurStyle, //!< fuzzy inside and outside 模糊内外
kSolid_BlurStyle, //!< solid inside, fuzzy outside 内实体,外模糊
kOuter_BlurStyle, //!< nothing inside, fuzzy outside 内部空,外模糊
kInner_BlurStyle, //!< fuzzy inside, nothing outside 内模糊,外空
kBlurStyleCount //style个数
};
enum BlurFlags {
kNone_BlurFlag = 0x00,
/**模糊半径不被transforms影响 */
kIgnoreTransform_BlurFlag = 0x01,
/** 使用smother 高质量模糊算法 */
kHighQuality_BlurFlag = 0x02,
/** 所有模糊标志的 */
kAll_BlurFlag = 0x03
};
static SkMaskFilter* Create(SkScalar radius, BlurStyle style,
uint32_t flags = kNone_BlurFlag);
static SkMaskFilter* CreateEmboss( const SkScalar direction[3],
SkScalar ambient, SkScalar specular,
SkScalar blurRadius);
private:
SkBlurMaskFilter(); // can't be instantiated
};
SkBlurMaskFilter 定义了 BlurStyle 类型和 BlurFlags 类型
SkBlurMaskFilter的构造函数是私有成员,不能创建SkBlurMaskFilter类型对象。
然后封装了两个静态成员函数Create(...) 和 CreateEmboss(...)。
Create()函数用它的参数 new 了一个 SkBlurMaskFilterImp l对象。
CreateEmboss()用它的参数 new 了一个 SkEmbossMaskFilter 对象。
1.Create(...) 参数
SkScalar radius:要大于0,模糊效果的半径? 从图形边沿开始算(往里、往外)radius经过或者不经过转换的值如果超过128(float),会被赋值为128(float)。
BlurStyle style:BlurStyle
Uint32_t flags: BlurFlags ,flags包含kHighQuality_BlurFlag标志时,为高质量,否则是低质量。
相互关系:当flags是kIgnoreTransform_BlurFlag的时候,radius不被矩阵转换影响,否则会按矩阵转换。
实际效果1:
flags选择默认的kNone_BlurFlag,根据style的不同从左到右分别是:

kNormal_BlurStyle:图形边界内外都有模糊效果
kSolid_BlurStyle:内部是实体(paint指定的颜色),外边模糊
kOuter_BlurStyle:内部不绘制,外边模糊效果
kInner_BlurStyel:内部模糊效果,外部不绘制
实际效果2:
flag选择kIgnoreTransform_BlurFlag的时候,不同style的效果是(顺序同上):

模糊半径忽略了矩阵变换。只有2像素
实际效果3
flag选择kHighQuality_BlurFlag的时候,情况如下:

与kNone_BlurFlag在拐角处略有区别。(看眼花了…)
实际效果4:
flag选择kAll_BlurFlag的时候:

相当于:kHighQuality_BlurFlag(高质量)+kIgnoreTransform_BlurFlag(模糊半径忽略矩阵)
2.CreateEmboss(...) 参数
const SkScalar direction[3] 指定光源方向
这里的光应该都是平行光(与所画图形在屏幕上位置无关), Z轴正向是屏幕往外,理解direction为光源位置。direction到(0,0,0)的向量方向就是平行光的光线方向。
如果设置z轴<=0,就相当于没有光源在屏幕后面,也就是在图形后面,无法产生光照效果。
SkScalar ambient 环境光强度 范围0---1的scalar值,小于0效果同0,大于1效果同1。
SkScalar specular 镜面反射光 范围0---15.99的scalar值,小于0效果同0,大于15.99效果同15.99。
SkScalar blurRadius 模糊半径,同Create(...)的参数意义。
效果图:(最后一个箭头)

上图代码:
void BlurMask_path()
{
SkPaint embossPaint;
embossPaint.setAntiAlias(true);
embossPaint.setColor(SK_ColorRED);
SkScalar dir[3] ={-5,5,5};
SkMaskFilter *embossMask = SkBlurMaskFilter::CreateEmboss(dir,
0.5,1,2);
embossPaint.setMaskFilter(embossMask);
embossMask->unref();
SkMaskFilter * blurMask[SkBlurMaskFilter::kBlurStyleCount];
for (size_t i = 0;i<SK_ARRAY_COUNT(blurMask);i++)
{
//下面依次实验flags参数
//maskFilter[i] = SkBlurMaskFilter::Create(2,SkBlurMaskFilter::BlurStyle(i));//默认flags
//maskFilter[i] = SkBlurMaskFilter::Create(2,SkBlurMaskFilter::BlurStyle(i),
//SkBlurMaskFilter::kIgnoreTransform_BlurFlag);//忽略矩阵变换,注意只有模板半径忽略矩阵变换
blurMask[i] = SkBlurMaskFilter::Create(2,SkBlurMaskFilter::BlurStyle(i),
SkBlurMaskFilter::kHighQuality_BlurFlag);
//maskFilter[i] = SkBlurMaskFilter::Create(2,SkBlurMaskFilter::BlurStyle(i),
// SkBlurMaskFilter::kAll_BlurFlag);
}
SkPaint blurPaint[SK_ARRAY_COUNT(blurMask)];
for (size_t i = 0;i<SK_ARRAY_COUNT(blurMask);i++)
{
blurPaint[i].setAntiAlias(true);
blurPaint[i].setColor(SK_ColorRED);
blurPaint[i].setMaskFilter(blurMask[i]);
blurMask[i]->unref();
}
//DrawImage("\\USER\\Skia\\music-n.png",pskCanvas,g_rtImg,&embossPaint); //对画图片没效果
float pts[]=
{
0, 0,
10, 0,
10, 5,
20, -5,
10, -15,
10, -10,
0, -10
}; //将这些坐标连起来是一个箭头形状
SkPath fPath;
fPath.moveTo(pts[0], pts[1]);
for (size_t i = 2; i < SK_ARRAY_COUNT(pts); i += 2)
{
fPath.lineTo(pts[i], pts[i+1]);
}
pskCanvas->scale(5,5); //水平垂直都放大5倍
pskCanvas->translate(10,30); //移动坐标原点
for (size_t i = 0;i<SK_ARRAY_COUNT(blurMask);i++)
{
pskCanvas->drawPath(fPath, blurPaint[i]);
pskCanvas->translate(32, 0); //水平移动32像素(实际效果要经过scale)
}
pskCanvas->drawPath(fPath, embossPaint);
}
(箭头数组来源:http://code.google.com/p/skia/source/browse/trunk/samplecode/SampleEffects.cpp)
分析关于光源的方向:
选定光源指定后,效果与所画图形在屏幕的位置无关,是平行光。
光源在不同x,y坐标情况下,其他参数同上面代码:z坐标5,环境光0.5,反射光1,模糊半径2,效果图如下:

x轴向左?Y轴向上 ,z轴向屏幕外。
以备补充:
ezhong的博客园:http://www.cnblogs.com/ezhong/ 2011-11-30/17:53:47
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ezhong的博客签名-------------------------------------
以上内容来自ezhong的博客园,作者:ezhong
ezhong的博客园: http://www.cnblogs.com/ezhong
感谢您的阅读。感谢您的分享。
浙公网安备 33010602011771号