skia android 教程,Android下Skia遮罩特效的实现

大体需求是,有一个文字点阵,叫glyph,为单色点阵,有笔画的地方为黑色,1;无笔画的地方为白色,0;

现在要把这个字画到屏幕,还有一个要求,要用当前颜色画;

分析来分析去,这就是一个简单的rop3操作,或者简单一点,就是一个遮罩特效:使用glyph当遮罩,使用当前颜色画矩形,仅此而以。

但是,目前没有在Skia中找到类似的操作,只找到SkXformode里有这样的定义:

enum Mode {

kClear_Mode, //!< [0, 0]

kSrc_Mode, //!< [Sa, Sc]

kDst_Mode, //!< [Da, Dc]

kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 -

Sa)*Dc]

kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 -

Da)*Sc]

kSrcIn_Mode, //!< [Sa * Da, Sc * Da]

kDstIn_Mode, //!< [Sa * Da, Sa * Dc]

kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]

kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]

kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]

kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]

kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1-Sa)* Dc]

......

基本上看不懂,光看公式,没法知道到底是个什么效果;看来只有使用这些东西来模拟遮罩效果了。

试验来试验去,下面的代码可以实现:

1 首先,把单色位图转换成32位

static void depth1to32(const uint16 * data, uint8 * out,

uint8

*

end)

{

uint16 pixel;

uint32 value;

......

// glyph : src SkBitmap

// bitmap : dst SkBitmap

int width;

int height;

width = glyph->width();

height = glyph->height();

uint8 *sbits;

sbits = (uint8 *)data;

int sstride;

sstride = (width + 7) / 8;

uint8 *sline;

sline = sbits;

// check format

uint8 *dbits;

dbits = (uint8 *)out;

int dstride;

dstride = bitmap->rowBytes();

int dbpp; // bytes per pixel

dbpp = bitmap->bytesPerPixel();

uint8 *dline;

dline = dbits;

while (height--)

{

int w = width;

uint8 *dline1 = dline;

uint8 *sline1 = sline;

while(w > 0)

{

uint8 pixel8;

pixel8 = *(sline1++);

for(int i = 0; i < (w < 8 ? w : 8); i++)

{

uint8 c = 1 < < (7 - i);

if(pixel8 & c)

{

*(dline1++) = 0;

*(dline1++) = 0;

*(dline1++) = 0;

// 这个地方,如果最高两个字节是0,则表示透明

*(dline1++) = 0xFF;

}

else

{

*(dline1++) = 0xff;

*(dline1++) = 0xff;

*(dline1++) = 0xff;

// 这个地方,如果最高两个字节是0,则表示透明

*(dline1++) = 0;

}

}

w -= 8;

}

dline += dstride;

sline += sstride;

}

}

......

2 使用当前颜色转换遮罩

SkBitmap *srcbmp = (SkBitmap*)(bitmap);

SkPaint paint;

SkCanvas canvas(*srcbmp);

paint.setXfermodeMode(SkXfermode::kSrcIn_Mode);

paint.setColor(display->foreColor);

SkRect rect = { 0, 0, srcbmp->width(),

srcbmp->height()};

canvas.drawRect(rect, paint);

自此,srcbmp已经变成了当前颜色表示的字符点阵

3 把字符画到屏幕

SkShader* s = SkShader::CreateBitmapShader(*srcbmp,

SkShader::kClamp_TileMode,

SkShader::kClamp_TileMode);

SkMatrix matrix;

matrix.reset();

matrix.postTranslate(x, y);

SkShader *shader = (SkShader *)s;

shader->setLocalMatrix(matrix); // 设置原点

SkPaint *paint = (SkPaint *)paint;

paint->setShader(shader)->unref();

paint->setXfermodeMode(SkXfermode::kSrcOver_Mode);

paint->setColor(display->foreColor);

SkRect rect = { x, y, x + w, y + h};

canvas->drawRect(rect, *paint);

这段代码,相当于把一个部分区域透明的pattern画到屏幕上

这样,我们就实现了字符遮罩的功能,使用当前颜色把字符画到屏幕上了。

当然,我们只是画了一个单色字符,其实也可以画很复杂的图案,类似于PS和Flash里的遮罩层的效果。

以上代码是示意代码,因此有些地方明显无法编译,有些地方明显多此一举,请注意。

另,Skia有类似Mask的概念,但看来看去,好像没有我们这里说的遮罩功能。

如果大家有更好的实现方法,也请告诉我一下。0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值