Qt源码解析 索引
Qt图形用户界面
应用程序窗口
Qt GUI 模块中最重要的类是QGuiApplication和QWindow。想要在屏幕上显示内容的 Qt 应用程序需要使用这些。QGuiApplication包含主事件循环,其中处理和调度来自窗口系统和其他来源的所有事件。它还处理应用程序的初始化和结束。
QWindow类表示底层窗口系统中的一个窗口。它提供了许多虚拟函数来处理来自窗口系统的事件 ( QEvent ),例如触摸输入、曝光、焦点、击键和几何变化。
二维图形
Qt GUI 模块包含 2D 图形、图像、字体和高级排版的类。
使用表面类型QSurface::RasterSurface创建的 QWindow可以与QBackingStore和QPainter结合使用,这是 Qt 高度优化的 2D 矢量图形 API。QPainter支持绘制线条、多边形、矢量路径、图像和文本。有关详细信息,请参阅绘画系统和光栅窗口示例。
Qt 可以使用QImage和QPixmap类加载和保存图像。默认情况下,Qt 支持最常见的图像格式,包括 JPEG 和 PNG 等。用户可以通过QImageIOPlugin类添加对其他格式的支持。有关详细信息,请参阅读取和写入图像文件
Qt 中的排版是使用QTextDocument完成的,它使用QPainter API 结合 Qt 的字体类,主要是QFont。比起文本和字体处理更喜欢低级 API 的应用程序,可以使用QRawFont和QGlyphRun等类。
最原始的问题是,文本和线条是如何绘制出来的。研究后发现只分析源码是不够的。
QPainter 源码解读远不止表面的那么简单,需要了解有关 OpenGL 和 QPainter 工作原理的一些背景知识 (Raster paint Engine in Qt )。要想发挥更好的性能,需要进一步深入了解 Qt 的软件光栅器 ( Qt's software rasterizer ), 它是参考实现,也是唯一实现了所QPainter提供的所有可能功能组合的绘画引擎。
OpenGL 和 OpenGL ES 集成(略)
简单示例
尝试分析在 GUI 应用程序中很常见 的 文本绘制
void AnalogClock::paintEvent(QPaintEvent *)
{
QPainter testpainter(this);
QFont font = testpainter.font();
font.setPixelSize(48);
testpainter.setFont(font);
const QRect rectangle = QRect(0, 0, 100, 50);
QRect boundingRect;
testpainter.drawText(rectangle, 0, tr("Hello"), &boundingRect);
QPen pen = painter.pen();
pen.setStyle(Qt::DotLine);
painter.setPen(pen);
testpainter.drawRect(boundingRect.adjusted(0, 0, -pen.width(), -pen.width()));
pen.setStyle(Qt::DashLine);
testpainter.setPen(pen);
testpainter.drawRect(rectangle.adjusted(0, 0, -pen.width(), -pen.width()));
}
要分析QPainter::drawText() 是如何实现的,通过查找资料。它会被分成两个截然不同的部分。
将字符串转换为一组定位字形,通常称为“文本布局”,因为它定位字形、进行文本换行和对齐调整。
将字形传递给绘制引擎进行渲染。当文本始终相同时,第一部分可以完成一次,并且可以重复使用字形/位置。
我们在 Qt 中有一个类,它允许您缓存第一部分并且只为每一帧绘制。班级是QTextLayout。这是一个低级类,会针对最微不足道的错误向您抛出断言。
光栅化引擎
总体架构
引擎的整体架构是将所有绘图分解为具有覆盖值的水平带,称为spans。许多 span 将一起形成形状的“掩码”,掩码内的每个像素都使用span 函数填充。