Windows平台下有两大绘图API,分别是GDI和GDI+
由于没有复杂的抗锯齿处理,绘图效率非常不错,但是同样的绘制质量不好。没有半透明的处理功能,在对界面要求不高而对性能要求比较高的应用程序里面使用比较多,比如股票软件。
GDI的升级版本,Windows独立提供了一个GDIPlus.dll的动态库,具有跨语言特性,C++,C#,VB都可以使用。 API封装性也比较好,支持丰富的半透明处理功能和文字处理特效。 具备抗锯齿绘制的能力。同样的也有其弊端,主要表现在:
所以使用GDI和GDI+在一些复杂的场景下使用非常受限。
有人说可以用OpenGL和DirectX来处理,这两个API库需要实现大量的底层功能,比如文字栅格化等等,另外依赖显卡的驱动,对低配置计算机不是很友好。
除了以上的选择之外Google的Skia的推出确实帮助我们解决了一部分问题,在此基础上我们做对应的扩展即可让我们实现复杂的绘制效果。
接下来我们详细介绍Skia的使用。
Skia一个开源的2D图形库,后面被Google收购调之后做了改进,然后在大量的设备和软件上使用,比如他们家的Chrome,Android。
官方网站:https://skia.org/
Windows下Skia的绘制流程:
以下示例如何绘制一张32位的内存位图
HBITMAP CreateGDIBitmap(int nWid, int nHei, void ** ppBits)
{
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = nWid;
bmi.bmiHeader.biHeight = -nHei;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
HDC hdc = GetDC(NULL);
LPVOID pBits = NULL;
HBITMAP hBmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, ppBits, 0, 0);
ReleaseDC(NULL, hdc);
return hBmp;
}
...
_hBmp = CreateGDIBitmap(_w, _h, &_pBmpBits);
这张位图我们会后面会传递给Skia,让他在上面绘制,替代之前的GDI/GDI+绘制过程。
if (_skBitmap == UIGNull)
{
_skBitmap = new SkBitmap();
}
_skBitmap->setConfig(SkImageInfo::Make(_w, _h, kN32_SkColorType, kPremul_SkAlphaType));
_skBitmap->setPixels(_pBmpBits);
_pBmpBits 是我们创建内存位图拿到的位图数据地址
if (_canvas == UIGNull)
{
_canvas = new SkCanvas(*_skBitmap);
}
else
{
delete ((SkCanvas*)_canvas);
_canvas = new SkCanvas(*_skBitmap);
}
通过传入skbimap给skcanvas可以可以利用skcanvas的api来进行绘图了
if (_canvas)
{
SkColor color = SkColorSetARGBInline(0, 0, 0, 0);
SkRect skRect = SkRect::MakeXYWH((SkScalar)rect._x, (SkScalar)rect._y, (SkScalar)rect._w, (SkScalar)rect._h);
SkPaint paint;
paint.setARGB(0, 0, 0, 0);
paint.setXfermodeMode(SkXfermode::kClear_Mode);
_canvas->drawRect(skRect, paint);
}
设置绘图模式为 ClearMode就可以清空位图
以上是基本的位图处理过程,后面我们会逐步介绍Skia绘图API和特效处理方法。