Graphics 2D docs

This adds an overview of 2D graphics in Qt and how they compare
to each other. There are many tools for this in Qt and they all
have their place. This will hopefully help users navigate the
forest.

Pick-to: 6.10
Fixes: QTBUG-137101
Change-Id: I855c5db8f6f1efe34cfbeecd0d2e05703bc124da
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2025-06-17 12:39:48 +02:00
parent 913aca0b95
commit 9438576ce4
7 changed files with 231 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

View File

@ -56,6 +56,11 @@ deploy on a platform that have a specific graphics API. Visit the
{Rendering via the Qt Rendering Hardware Interface} {Rendering via the Qt Rendering Hardware Interface}
page on how to set the render path in QQuickWindow. page on how to set the render path in QQuickWindow.
\section1 2D Graphics
Qt has multiple different APIs for drawing 2D graphics primitives. See the separate page about
\l{2D Graphics in Qt} for an overview of the possibilities here.
\section1 3D Graphics with Qt Quick 3D \section1 3D Graphics with Qt Quick 3D
\l{Qt Quick 3D} is an add-on that provides a high-level API for creating 3D \l{Qt Quick 3D} is an add-on that provides a high-level API for creating 3D

226
doc/src/graphics2d.qdoc Normal file
View File

@ -0,0 +1,226 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page topics-graphics2d.html
\title 2D Graphics in Qt
\keyword topics-graphics2d
\brief Qt's 2D graphics features
\ingroup explanations-graphicsandmultimedia
Two-dimensional graphics is at the core of Qt's user interface capabilities. This page provides
an overview of the tools and APIs at your disposal for rendering your own 2D graphics. It also aims
to clarify the difference between APIs that perform similar tasks.
This is a high-level overview, focusing on the direct ways to render graphics primitives such as
circles, rectangles, complex shapes and images. For a low-level view of Qt graphics internals, see
the \l{Graphics}{graphics overview documentation}.
Qt also includes high-end \l{Qt Quick 3D}{3D rendering capabilities} with its own set of APIs and
tools. The focus in the following overview will be on two-dimensional graphics, so \l{Qt Quick 3D}
and related components will not be covered here.
\section1 Qt Quick
\l{Qt Quick} has the tools for rendering hardware-accelerated and animated 2D graphics. It serves
as the basis for the rich UI components in \l{Qt Quick Controls}.
The Qt Quick module provides essential primitives such as \l{Rectangle}{rectangles}, \l{Text}{text}
and \l{Image}{images}. These are typically the foundation of a two-dimensional user interface.
User interfaces in Qt Quick can be transformed and animated at a low performance overhead, and this
promise lies at the core of the module. The API is declarative, which allows Qt to optimize how
graphics are stored, rendered and how animation updates are managed.
\section2 Qt Quick Shapes
In addition to the basic primitives, Qt Quick has APIs for rendering more complex shapes. These can
be accessed by importing the \l{Qt Quick Shapes QML Types}{Qt Quick Shapes} module in your code.
Qt Quick Shapes allows you to construct arbitrary \l{ShapePath}{paths} from path operations such as
\l{PathMove}{move-to}, \l{PathLine}{line-to}, \l{PathCubic}{cubic-to} and \l{PathArc}{arc-to}.
Each path can have a stroke defined by a rich set of options. In addition, it can be filled with
either a solid color, a gradient, an image, or even another Qt Quick item.
\image 2dgraphics/tiger.png
The \l{Qt Quick Examples - Shapes}{Qt Quick Shapes example} shows how the classic GhostScript tiger
can be rendered using paths constructed with Qt Quick Shapes.
\section3 Curve renderer
By default, Qt Quick Shapes relies on multi-sampling for antialiasing. In addition, curves are
flattened to short line segments, and this can be visible if you zoom the shape. By setting the
\l{Shape} item's \l{Shape::preferredRendererType}{preferredRendererType} property to
\c{Shape.CurveRenderer}, a different renderer will be used internally. This curve renderer solves
the curves on the GPU itself and applies antialiasing without MSAA.
It comes at some extra cost to performance the first time the shape is rendered. After this,
however, the shape can be smoothly scaled and transformed without extra cost.
\section3 Other operations
In addition to the basic operations for building a path, Qt Quick Shapes also includes some
powerful convenience components.
\list
\li The \l{PathQuad} component can be used to add a quadratic curve to the path.
\li The \l{PathRectangle} component can be used to construct a rectangle, optionally with rounded
corners.
\li The \l{PathSvg} component can be used to construct a path using SVG's path syntax. (Note: this
component only provides a compact way to describe a path, it does not support the entire SVG
syntax.)
\li The \l{PathText} component can be used to add outlines from a font to the path. This comes in
addition to Qt Quick's \l{Text} component. It can be used for advanced effects, for instance
gradient fills and path operations such as subtracting the text from another shape.
\endlist
\section2 Raster images
Raster images (or pixmaps) can be displayed in Qt Quick using the \l{Image} component. A set of
image formats are supported by default through the \l{Qt Gui} module (PNG, JPEG, BMP and GIF). In
addition, the \l{Qt Image Formats} module has plugins for loading other image formats. As long as
your application can access the plugin for a certain format, it can be loaded using the \l{Image}
component.
\section2 Vector images
A limitation of raster images is that they cannot be scaled or otherwise transformed without causing
some reduction of quality. For images that will be displayed at different sizes or with transforms,
it is usually preferable to use a vector image format instead.
The \l{VectorImage} component can be used to include scalable vector graphics directly in your
Qt Quick application. It currently supports the SVG format by default. By deploying a plugin with
your application, it can also be made to support the Lottie format. Note that this support is
currently considered experimental.
The \l{VectorImage} parses the document and creates a Qt Quick scene in memory that represents its
contents, using Qt Quick Shapes and other primitives. Therefore it will behave the same as if the
vector image had been written using Qt Quick.
The vector images can also be converted to QML ahead of time, using the \l{svgtoqml} and
\l{lottietoqml} tools. This creates the same representation of the vector image using Qt Quick
components. However, instead of creating the representation in memory, it is saved to a file.
Pregenerating the QML file means it can be precompiled as part of the application assets, which will
save some time when loading it.
\image 2dgraphics/weatherforecastexample.png
The \l{Weather Forecast Example} shows how \l{svgtoqml} can be used in an application. Weather
symbols, maps and icons are SVG files that have been converted to QML and loaded as items in the
application scene.
Similarly, the \l{lottietoqml} tool can be used to convert Lottie animations into QML.
\section2 Prerasterized vector images
For vector images that are only ever displayed at a single size, it is more efficient to rasterize
them into pixmaps ahead of time and show these using \l{Image}. Often, such images will be stored
as SVGs in the application source assets and then converted to PNGs (for instance) at predefined
sizes. This is typically done as part of the application build and packaging process.
Rendering an image is faster than rendering the complex shapes, so for static images this is the
optimal approach. However, for some applications it is not convenient to do this conversion at
build-time. If the application is targeting many different form factors, for instance, the list
of predefined sizes to cover them all may be very long and hard to predict. Since each prerendered
image consumes extra space in the application deployment, there is also a cost to pay for this
approach.
Qt therefore also supports rasterizing SVG files at a specific size when the image is loaded. This
can be done simply by loading the file through the regular \l{Image} component. The
\l{Image::sourceSize}{sourceSize} property can be used to control the rasterized size of the image.
Loading the SVG through \l{Image} is different from loading it through \l{VectorImage} in the
following ways:
\list
\li With \l{Image}, the image is rasterized on the CPU before it is loaded as a texture. So there
is an extra loading cost involved which depends on the target size of the rasterized image.
Subsequent rendering of the same image, however, will be as fast as if the image was pre-rasterized
and loaded as a pixmap.
\li Additionally, the rasterized image may consume more memory, depending on the complexity of the
vector image and the size of the rasterized data.
\li Scaling/transforming the \l{Image} has the same drawbacks as if it were loaded as a pixmap.
\li If the image has animations, then \l{Image} will only show the first frame.
\endlist
So as a general rule, using prerasterized vector images will be better when the image is not
animated and its size remains the same through-out the life time of the application. Whether the
images are rasterized on build-time by a third party tool, or at run-time when Qt loads the image
is a trade-off between load time and convenience/deployment size.
\image 2dgraphics/vectorimageexample.png
The \l{Vector Image Example} shows an SVG file displayed at different scales using \l{Image},
\l{VectorImage} and a QML file generated with \l{svgtoqml}. When displayed at its source size,
the rendering looks the same across the board, and the \l{Image} will be slightly faster to render.
At higher scales, the \l{Image} becomes blurry and pixelated, whereas the other approaches remain
sharp and true to the source.
\section2 Animated vector graphics
Animations are at the core of Qt Quick's offering. Many vector graphics animations can be run
without changing the geometries of items, and thus benefit well from Qt Quick's hardware-accelerated
renderer.
\l{VectorImage}, \l{svgtoqml} and \l{lottietoqml} support animations for a selected subset of
properties.
\image 2dgraphics/lottietoqmlexample.png
The \l{lottietoqml Example} shows how animated Lottie files can be converted to QML. As seen in
this screenshot, multiple animated images are laid out in a grid. They can each be zoomed without
scaling artifacts or loss of fidelity.
\section2 Effects
The support for post-processing effects is included as a core feature in Qt Quick. Any item can
be turned into a texture and the \l{ShaderEffect} component can be used to apply any effect to it.
In addition to this low-level support for effects, Qt Quick also has a few high-level components
to make the process easier.
The \l{MultiEffect} component allows applying one or more of a pre-defined set of common effects
to an item.
\image 2dgraphics/quickeffectmaker.png
For more complex use cases, the \l{Qt Quick Effect Maker} provides a visual tool where you can
string together pre-defined and custom effects and generate the shader code for use with
\l{ShaderEffect}.
\section1 QPainter
\l{QPainter} is the basis of \l{Qt Widgets}. It provides an imperative API for drawing complex
shapes and images with pixel-perfect antialiasing.
Shapes can be specified using \l{QPainterPath} and the renderer also directly supports primitives
such as text and images.
The \l{QPainter} is primarily a software renderer, and it is optimized for smaller, partial updates
of the screen. Thus it is a good fit for the traditional, desktop-style interfaces of
\l{Qt Widgets}, where most of the UI is static from frame to frame. Therefore, rendering large and
complex 2D scenes with it may be expensive, and it could be worth considering \l{Qt Quick Shapes}
instead.
On the other hand, the rendering quality is higher, so for many use cases it will still be
preferrable. When rendering an SVG image through \l{Image} as outlined previously, \l{QPainter}
will be the underlying renderer.
If pixel perfection is the goal, and updates are rare and/or confined to small regions, then
QPainter is a powerful tool. If it becomes a performance bottle neck, you may consider moving
to using \l{Qt Quick} and \l{Qt Quick Shapes} instead.
\section1 Higher-level components
Building on top of these basic graphics primitives, Qt also provides many specialized, high-level
components.
\l{Qt Quick Controls} is one such module. It provides a rich and stylable set of common user
interface components. Similarly, \l{Qt Widgets} provides the same for \l{QPainter}-based
applications.
In addition, \l{Qt Graphs} is a data visualization module. It provides many different components to
visualize data sets and graphs in a \l{Qt Quick} application. \l{Qt Graphs} supports both 2D and
3D graphs.
*/