还是先看下类的继承关系:
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