之前写了一篇文章《Qt使用GDI绘图(仅Windows平台)》
本篇重点介绍Cairo绘图引擎,Qt自带的QPainter的绘图效率和抗锯齿效果都没有cairo的好。cairo 的目标是以跨平台的方式在打印机和屏幕上产生相同的输出,它正在成为 Linux® 图形领域的重要软件。GNOME、GTK+、Pango 等许多软件已经使用了它提供的 2D 功能。另外,cairo 还支持生成 PostScript 或 PDF 输出,从而产生高质量的打印结果。在理想情况下,cairo 的用户可以在打印机和屏幕上获得非常接近的输出效果。
一、Cairo简介
Cairo:C编写的开源绘图引擎(基于LGPL协议),大名鼎鼎的FireFox就是用这个绘图引擎的。Cairo是非常流行的开源2D图形渲染引擎库,它支持包括X-Windos,Win32,图像,pdf在内的各种输出设备。目前,Cairo已被广泛的使用在多个平台上来渲染图形界面,包括Firefox/Webkit-EFL/GTK+/Poppler/Qt等等。Qt的QPainter提供的抗锯齿效果没有cairo的好。cairo是用C编写的,但是为大多数常用的语言提供了绑定。选用 C 语言有助于创建新的绑定,同时在进行C语言调用时可以提供高性能。应该特别注意Python绑定,它支持快速原型开发,而且降低了学习cairo绘图API的门槛。Cairo的绘图效率是接近GDI/GDIPlus的。经过优化算法,可以做到完全忽略绘图效率上的差别。此外,gtk不如qt流行,Qt支持cairo。
cairo 是一个矢量绘图(vector drawing)库,因此绘图需要对图形进行几何描述,而不是描述位图中填充的像素。在采用位图绘图(bitmap drawing)时,按照预先决定的布局用预先决定的颜色填充一系列像素,而且图形的质量与位图的大小成正比。 在放大或修改位图图像时,位图绘图方法的效果就会变差。图像常常会变得模糊,就像是近距离观看背投电视或其他大屏幕电视时的效果。在某一距离上,图像可能看起来很清楚,但是靠近之后就会看到许多离散的点。因为数据无法定义预先定义的像素之间应该是什么,所以放大时会很明显地损失清晰度。计算机绘图系统和体系结构很早就出现了,cairo 的设计借鉴了 PostScript 和 PDF 模型的许多经验。cairo 之所以借鉴 PostScript 和 Portable Document Format(PDF)方法是因为,它们都使用数学语句定义图像。由于用几何方法表示图像,所以可以在任何时候在一定范围内计算几何描述,从而重新创建整个图像(或一部分图像)。图形的几何性质被表示为点、曲线和直线(这些元素构成了矢量)。
www.cairographics.org/samples/ 官方样例
www.cairographics.org/examples/ 官方案例
www.cairographics.org/download/
www.cairographics.org/snapshots/ 抢鲜版源码
www.cairographics.org/releases/ 稳定版源码,提供了C/C++,Python,R语言的支持。pixman是它的依赖库。
github.com/freedesktop… C语言源码
github.com/pygobject/p… Python bindings for cairo
二、Cairo使用示例
原理是:Cairo画图到QImage,再用QPainter把QImae贴图出来。
void MainWindow::paintEvent(QPaintEvent *pEvent)
{
Q_UNUSED(pEvent);
//原生的绘图
QPainter p(this);
p.drawLine(QPoint(0, 0), QPoint(150, 220));
//使用cairo绘图引擎
const char *pVersion = cairo_version_string();
qDebug() << pVersion;
//创建一张图QImage
int iW = this->width();
int iH = this->height();
QImage image(iW, iH, QImage::Format_ARGB32);
unsigned char *pData = image.bits();
int iLineStride = image.bytesPerLine();
//将此图转换为cairo图
cairo_surface_t *pCairoSurface = cairo_image_surface_create_for_data(pData, CAIRO_FORMAT_ARGB32, iW, iH, iLineStride);
cairo_surface_set_device_scale(pCairoSurface, 1, 1);
cairo_t *pCairoContext = cairo_create(pCairoSurface);
cairo_surface_destroy(pCairoSurface);
if (pCairoContext)
{
double x = 100.6, y = 328.0;
double x1 = 102.4 + 100, y1 = 130.4,
x2 = 153.6 + 240, y2 = 405.6,
x3 = 230.4 + 400, y3 = 200;
cairo_move_to(pCairoContext, x, y);
cairo_curve_to(pCairoContext, x1, y1, x2, y2, x3, y3);
cairo_set_line_width(pCairoContext, 1.0); //设置线宽
cairo_set_source_rgb(pCairoContext, 1.0, 0.0, 0.0); //设置线颜色
cairo_stroke(pCairoContext);
cairo_destroy(pCairoContext);
}
//贴图
p.drawImage(this->rect(), image);
}
三、完整的工程源码及库文件
本人使用的编程环境是QtCreator + MSVC2019 32/64位