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

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