1// Copyright (C) 2016 The Qt Company Ltd.
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 "qsgsoftwarepainternode_p.h"
5#include "qsgsoftwarepixmaptexture_p.h"
6#include <qmath.h>
7
8QT_BEGIN_NAMESPACE
9
10QSGSoftwarePainterNode::QSGSoftwarePainterNode(QQuickPaintedItem *item)
11 : QSGPainterNode()
12 , m_preferredRenderTarget(QQuickPaintedItem::Image)
13 , m_item(item)
14 , m_texture(nullptr)
15 , m_dirtyContents(false)
16 , m_opaquePainting(false)
17 , m_linear_filtering(false)
18 , m_mipmapping(false)
19 , m_smoothPainting(false)
20 , m_fastFBOResizing(false)
21 , m_fillColor(Qt::transparent)
22 , m_contentsScale(1.0)
23 , m_dirtyGeometry(false)
24{
25 setMaterial((QSGMaterial*)1);
26 setGeometry((QSGGeometry*)1);
27}
28
29QSGSoftwarePainterNode::~QSGSoftwarePainterNode()
30{
31 delete m_texture;
32}
33
34void QSGSoftwarePainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target)
35{
36 if (m_preferredRenderTarget == target)
37 return;
38
39 m_preferredRenderTarget = target;
40}
41
42void QSGSoftwarePainterNode::setSize(const QSize &size)
43{
44 if (size == m_size)
45 return;
46
47 m_size = size;
48
49 m_dirtyGeometry = true;
50}
51
52void QSGSoftwarePainterNode::setDirty(const QRect &dirtyRect)
53{
54 m_dirtyContents = true;
55 m_dirtyRect = dirtyRect;
56 markDirty(bits: DirtyMaterial);
57}
58
59void QSGSoftwarePainterNode::setOpaquePainting(bool opaque)
60{
61 if (opaque == m_opaquePainting)
62 return;
63
64 m_opaquePainting = opaque;
65}
66
67void QSGSoftwarePainterNode::setLinearFiltering(bool linearFiltering)
68{
69 if (linearFiltering == m_linear_filtering)
70 return;
71
72 m_linear_filtering = linearFiltering;
73}
74
75void QSGSoftwarePainterNode::setMipmapping(bool mipmapping)
76{
77 if (mipmapping == m_mipmapping)
78 return;
79
80 m_mipmapping = mipmapping;
81}
82
83void QSGSoftwarePainterNode::setSmoothPainting(bool s)
84{
85 if (s == m_smoothPainting)
86 return;
87
88 m_smoothPainting = s;
89}
90
91void QSGSoftwarePainterNode::setFillColor(const QColor &c)
92{
93 if (c == m_fillColor)
94 return;
95
96 m_fillColor = c;
97 markDirty(bits: DirtyMaterial);
98}
99
100void QSGSoftwarePainterNode::setContentsScale(qreal s)
101{
102 if (s == m_contentsScale)
103 return;
104
105 m_contentsScale = s;
106 markDirty(bits: DirtyMaterial);
107}
108
109void QSGSoftwarePainterNode::setFastFBOResizing(bool dynamic)
110{
111 m_fastFBOResizing = dynamic;
112}
113
114QImage QSGSoftwarePainterNode::toImage() const
115{
116 return m_pixmap.toImage();
117}
118
119void QSGSoftwarePainterNode::update()
120{
121 if (m_dirtyGeometry) {
122 m_pixmap = QPixmap(m_textureSize);
123 if (!m_opaquePainting)
124 m_pixmap.fill(fillColor: Qt::transparent);
125
126 if (m_texture)
127 delete m_texture;
128 m_texture = new QSGSoftwarePixmapTexture(m_pixmap);
129 }
130
131 if (m_dirtyContents)
132 paint();
133
134 m_dirtyGeometry = false;
135 m_dirtyContents = false;
136}
137
138void QSGSoftwarePainterNode::paint(QPainter *painter)
139{
140 painter->drawPixmap(x: 0, y: 0, w: m_size.width(), h: m_size.height(), pm: m_pixmap);
141}
142
143void QSGSoftwarePainterNode::paint()
144{
145 QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect;
146
147 QPainter painter;
148
149 painter.begin(&m_pixmap);
150 if (m_smoothPainting) {
151 painter.setRenderHints(hints: QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
152 }
153
154 QRect clipRect;
155
156 if (m_contentsScale == 1) {
157 qreal scaleX = m_textureSize.width() / (qreal) m_size.width();
158 qreal scaleY = m_textureSize.height() / (qreal) m_size.height();
159 painter.scale(sx: scaleX, sy: scaleY);
160 clipRect = dirtyRect;
161 } else {
162 painter.scale(sx: m_contentsScale, sy: m_contentsScale);
163
164 QRect sclip(qFloor(v: dirtyRect.x()/m_contentsScale),
165 qFloor(v: dirtyRect.y()/m_contentsScale),
166 qCeil(v: dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(v: dirtyRect.x()/m_contentsScale)),
167 qCeil(v: dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(v: dirtyRect.y()/m_contentsScale)));
168
169 clipRect = sclip;
170 }
171
172 if (!m_dirtyRect.isNull())
173 painter.setClipRect(clipRect);
174
175 painter.setCompositionMode(QPainter::CompositionMode_Source);
176 painter.fillRect(clipRect, color: m_fillColor);
177 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
178
179 m_item->paint(painter: &painter);
180 painter.end();
181
182 m_dirtyRect = QRect();
183}
184
185
186void QSGSoftwarePainterNode::setTextureSize(const QSize &size)
187{
188 if (size == m_textureSize)
189 return;
190
191 m_textureSize = size;
192 m_dirtyGeometry = true;
193}
194
195QT_END_NAMESPACE
196

source code of qtdeclarative/src/quick/scenegraph/adaptations/software/qsgsoftwarepainternode.cpp