1// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qpaintedtextureimage.h"
5#include "qpaintedtextureimage_p.h"
6
7#include <QtGui/qpainter.h>
8#include <QtGui/qimage.h>
9
10QT_BEGIN_NAMESPACE
11
12namespace Qt3DRender {
13
14/*!
15 \class Qt3DRender::QPaintedTextureImage
16 \inmodule Qt3DRender
17 \since 5.8
18 \brief A QAbstractTextureImage that can be written through a QPainter.
19
20 A QPaintedTextureImage provides a way to specify a texture image
21 (and thus an OpenGL texture) through a QPainter. The width and height of the
22 texture image can be specified through the width and height or size
23 properties.
24
25 A QPaintedTextureImage must be subclassed and the virtual paint() function
26 implemented. Each time update() is called on the QPaintedTextureImage,
27 the paint() function is invoked and the resulting image is uploaded.
28
29 The QPaintedTextureImage must be attached to some QAbstractTexture.
30 */
31
32
33
34QPaintedTextureImagePrivate::QPaintedTextureImagePrivate()
35 : m_imageSize(256,256)
36 , m_devicePixelRatio(1.0)
37 , m_generation(0)
38{
39}
40
41QPaintedTextureImagePrivate::~QPaintedTextureImagePrivate()
42{
43}
44
45void QPaintedTextureImagePrivate::repaint()
46{
47 // create or re-allocate QImage with current size
48 if (m_image.isNull()
49 || m_image->size() != m_imageSize
50 || m_image->devicePixelRatio() != m_devicePixelRatio)
51 {
52 m_image.reset(other: new QImage(m_imageSize, QImage::Format_RGBA8888));
53 m_image->setDevicePixelRatio(m_devicePixelRatio);
54 m_image->fill(color: Qt::transparent);
55 }
56
57 QPainter painter(m_image.data());
58 q_func()->paint(painter: &painter);
59 painter.end();
60
61 ++m_generation;
62 m_currentGenerator = QSharedPointer<QPaintedTextureImageDataGenerator>::create(arguments&: *m_image.data(), arguments&: m_generation, arguments: q_func()->id());
63 q_func()->notifyDataGeneratorChanged();
64}
65
66QPaintedTextureImage::QPaintedTextureImage(Qt3DCore::QNode *parent)
67 : QAbstractTextureImage(*new QPaintedTextureImagePrivate, parent)
68{
69 Q_D(QPaintedTextureImage);
70
71 d->m_currentGenerator = QSharedPointer<QPaintedTextureImageDataGenerator>::create(arguments: QImage{}, arguments: 0, arguments: id());
72}
73
74QPaintedTextureImage::~QPaintedTextureImage()
75{
76}
77
78/*!
79 \property Qt3DRender::QPaintedTextureImage::width
80
81 This property holds the width of the texture image.
82 The width must be greater than or equal to 1.
83*/
84int QPaintedTextureImage::width() const
85{
86 Q_D(const QPaintedTextureImage);
87 return d->m_imageSize.width();
88}
89
90/*!
91 \property Qt3DRender::QPaintedTextureImage::height
92
93 This property holds the height of the texture image.
94 The height must be greater than or equal to 1.
95*/
96int QPaintedTextureImage::height() const
97{
98 Q_D(const QPaintedTextureImage);
99 return d->m_imageSize.height();
100}
101
102/*!
103 \property Qt3DRender::QPaintedTextureImage::size
104
105 This property holds the size of the texture image.
106
107 \sa height, width
108
109*/
110QSize QPaintedTextureImage::size() const
111{
112 Q_D(const QPaintedTextureImage);
113 return d->m_imageSize;
114}
115
116/*!
117 Sets the width (\a w) of the texture image. Triggers an update, if the size changes.
118 */
119void QPaintedTextureImage::setWidth(int w)
120{
121 if (w < 1) {
122 qWarning() << "QPaintedTextureImage: Attempting to set invalid width" << w << ". Will be ignored";
123 return;
124 }
125 setSize(QSize(w, height()));
126}
127
128/*!
129 Sets the height (\a h) of the texture image. Triggers an update, if the size changes.
130 */
131void QPaintedTextureImage::setHeight(int h)
132{
133 if (h < 1) {
134 qWarning() << "QPaintedTextureImage: Attempting to set invalid height" << h << ". Will be ignored";
135 return;
136 }
137 setSize(QSize(width(), h));
138}
139
140/*!
141 Sets the width and height of the texture image. Triggers an update, if the \a size changes.
142 */
143void QPaintedTextureImage::setSize(QSize size)
144{
145 Q_D(QPaintedTextureImage);
146
147 if (d->m_imageSize != size) {
148 if (size.isEmpty()) {
149 qWarning() << "QPaintedTextureImage: Attempting to set invalid size" << size << ". Will be ignored";
150 return;
151 }
152
153 const bool changeW = d->m_imageSize.width() != size.width();
154 const bool changeH = d->m_imageSize.height() != size.height();
155
156 d->m_imageSize = size;
157
158 if (changeW)
159 Q_EMIT widthChanged(w: d->m_imageSize.height());
160 if (changeH)
161 Q_EMIT heightChanged(w: d->m_imageSize.height());
162
163 Q_EMIT sizeChanged(size: d->m_imageSize);
164
165 d->repaint();
166 }
167}
168
169/*!
170 Immediately triggers the painted texture's paint() function,
171 which in turn uploads the new image to the GPU. If you are
172 making multiple changes to a painted texture, consider waiting
173 until all changes are complete before calling update, in order
174 to minimize the number of repaints required.
175
176 Parameter \a rect is currently unused.
177*/
178void QPaintedTextureImage::update(const QRect &rect)
179{
180 Q_UNUSED(rect);
181 Q_D(QPaintedTextureImage);
182
183 d->repaint();
184}
185
186/*!
187 \fn Qt3DRender::QPaintedTextureImage::paint(QPainter *painter)
188
189 Paints the texture image with the specified QPainter object \a painter.
190
191 QPainter considers the top-left corner of an image as its origin, while OpenGL considers
192 the bottom-left corner of a texture as its origin. An easy way to account for this difference
193 is to set a custom viewport on the painter before doing any other painting:
194
195 \code
196 painter->setViewport(0, height(), width(), -height());
197 ...
198 \endcode
199*/
200QTextureImageDataGeneratorPtr QPaintedTextureImage::dataGenerator() const
201{
202 Q_D(const QPaintedTextureImage);
203 return d->m_currentGenerator;
204}
205
206
207QPaintedTextureImageDataGenerator::QPaintedTextureImageDataGenerator(const QImage &image, int gen, Qt3DCore::QNodeId texId)
208 : m_image(image) // pixels are implicitly shared, no copying
209 , m_generation(gen)
210 , m_paintedTextureImageId(texId)
211{
212}
213
214QPaintedTextureImageDataGenerator::~QPaintedTextureImageDataGenerator()
215{
216}
217
218QTextureImageDataPtr QPaintedTextureImageDataGenerator::operator ()()
219{
220 QTextureImageDataPtr textureData = QTextureImageDataPtr::create();
221 textureData->setImage(m_image);
222 return textureData;
223}
224
225bool QPaintedTextureImageDataGenerator::operator ==(const QTextureImageDataGenerator &other) const
226{
227 const QPaintedTextureImageDataGenerator *otherFunctor = functor_cast<QPaintedTextureImageDataGenerator>(other: &other);
228 return (otherFunctor != nullptr && otherFunctor->m_generation == m_generation && otherFunctor->m_paintedTextureImageId == m_paintedTextureImageId);
229}
230
231} // namespace Qt3DRender
232
233QT_END_NAMESPACE
234
235#include "moc_qpaintedtextureimage.cpp"
236
237

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qt3d/src/render/texture/qpaintedtextureimage.cpp