Windows平台下Skia使用技巧一

Windows平台下Skia使用技巧一

www.visual-gear.com 原创技术文章

Windows平台下有两大绘图API,分别是GDI和GDI+

GDI

由于没有复杂的抗锯齿处理,绘图效率非常不错,但是同样的绘制质量不好。没有半透明的处理功能,在对界面要求不高而对性能要求比较高的应用程序里面使用比较多,比如股票软件。

GDI+

GDI的升级版本,Windows独立提供了一个GDIPlus.dll的动态库,具有跨语言特性,C++,C#,VB都可以使用。 API封装性也比较好,支持丰富的半透明处理功能和文字处理特效。 具备抗锯齿绘制的能力。同样的也有其弊端,主要表现在:

  1. 绘制性能低下,连续绘制1000张大图片CPU基本就扛不住了
  2. 部分API存在bug,最典型的就是文字大小计算,计算不准确,在文字处理场景下存在一定的弊端。
  3. 没有特效的处理能力,比如模糊处理,发光处理,三维旋转效果,只提供了2D的选择和矩阵透视变形特效。

所以使用GDI和GDI+在一些复杂的场景下使用非常受限。

有人说可以用OpenGL和DirectX来处理,这两个API库需要实现大量的底层功能,比如文字栅格化等等,另外依赖显卡的驱动,对低配置计算机不是很友好。

除了以上的选择之外Google的Skia的推出确实帮助我们解决了一部分问题,在此基础上我们做对应的扩展即可让我们实现复杂的绘制效果。

接下来我们详细介绍Skia的使用。

Skia

Skia一个开源的2D图形库,后面被Google收购调之后做了改进,然后在大量的设备和软件上使用,比如他们家的Chrome,Android。

官方网站:https://skia.org/

开发示例

Windows下Skia的绘制流程:

以下示例如何绘制一张32位的内存位图

新建一张内存位图和内存DC

  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+绘制过程。

新建一个位图对象 SkBitmap

        if (_skBitmap == UIGNull)
            {
                _skBitmap = new SkBitmap();
            }

            _skBitmap->setConfig(SkImageInfo::Make(_w, _h, kN32_SkColorType, kPremul_SkAlphaType));
            _skBitmap->setPixels(_pBmpBits);

_pBmpBits 是我们创建内存位图拿到的位图数据地址

新建一个画布对象 SkCanvas

       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和特效处理方法。

猜你喜欢

转载自www.cnblogs.com/Visual-Gear/p/9721974.html