Development/Architecture/KDE3/Low-level Graphics
Qt's low level imaging model is based on the capabilities provided by X11 and other windowing systems for which Qt ports exist. But it also extends these by implementing additional features such as arbitrary affine transformations for text and pixmaps.
Rendering with QPainter
The central graphics class for 2D painting with Qt is QPainter. It can draw on a QPaintDevice. There are three possible paint devices implemented: One is QWidget which represents a widget on the screen. The second is QPrinter which represents a printer and produces Postscript output. The third it the class QPicture which records paint commands and can save them on disk and play them back later. A possible storage format for paint commands is the W3C standard SVG.
So, it is possible to reuse the rendering code you use for displaying a widget for printing, with the same features supported. Of course, in practice, the code is used in a slightly different context. Drawing on a widget is almost exlusively done in the paintEvent() method of a widget class.
void FooWidget::paintEvent()
{
QPainter p(this);
// Setup painter
// Use painter
}
When drawing on a printer, you have to make sure to use QPrinter::newPage() to finish with a page and begin a new one - something that naturally is not relevant for painting widgets. Also, when printing, you may want to use the device metrics in order to compute coordinates.
Transformations
By default, when using the QPainter, it draws in the natural coordinate system of the device used. This means, if you draw a line along the horizontal axis with a length of 10 units, it will be painted as a horizontal line on the screen with a length of 10 pixels. However, QPainter can apply arbitrary affine transformations before actually rendering shapes and curves. An affine transformation maps the x and y coordinates linearly into x' and y' according to
The 3x3 matrix in this equation can be set with QPainter::setWorldMatrix() and is of type QWMatrix. Normally, this is the identity matrix, i.e. m11 and m22 are one, and the other parameters are zero. There are basically three different groups of transformations:
- Translations: These move all points of an object by a fixed amount in some direction. A translation matrix can be obtained by calling method m.translate(dx, dy) for a QWMatrix. This corresponds to the matrix
- Scaling: These stretch or shrink the coordinates of an object, making it bigger or smaller without distorting it. A scaling transformation can be applied to a QWMatrix by calling m.scale(sx, sy). By setting one of the parameters to a negative value, one can achieve a mirroring of the coordinate system. The corresponding matrix looks like this
- Shearing: A distortion of the coordinate system with two parameters. A shearing transformation can be applied by calling m.shear(sh, sv), corresponding to the matrix
- Rotating: This rotates an object. A rotation transformation can be applied by calling m.rotate(alpha). Note that the angle has to be given in degrees, not as mathematical angle! Notate that a rotation is equivalent with a combination of scaling and shearing. The corresponding matrix is
Here are some pictures that show the effect of the elementary transformation to our masquot: