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 bool before = painter->testRenderHint(hint: QPainter::SmoothPixmapTransform);
141 painter->setRenderHint(hint: QPainter::SmoothPixmapTransform, on: m_linear_filtering);
142 painter->drawPixmap(x: 0, y: 0, w: m_size.width(), h: m_size.height(), pm: m_pixmap);
143 painter->setRenderHint(hint: QPainter::SmoothPixmapTransform, on: before);
144}
145
146void QSGSoftwarePainterNode::paint()
147{
148 QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect;
149
150 QPainter painter;
151
152 painter.begin(&m_pixmap);
153 if (m_smoothPainting) {
154 painter.setRenderHints(hints: QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
155 }
156
157 QRect clipRect;
158
159 if (m_contentsScale == 1) {
160 qreal scaleX = m_textureSize.width() / (qreal) m_size.width();
161 qreal scaleY = m_textureSize.height() / (qreal) m_size.height();
162 painter.scale(sx: scaleX, sy: scaleY);
163 clipRect = dirtyRect;
164 } else {
165 painter.scale(sx: m_contentsScale, sy: m_contentsScale);
166
167 QRect sclip(qFloor(v: dirtyRect.x()/m_contentsScale),
168 qFloor(v: dirtyRect.y()/m_contentsScale),
169 qCeil(v: dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(v: dirtyRect.x()/m_contentsScale)),
170 qCeil(v: dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(v: dirtyRect.y()/m_contentsScale)));
171
172 clipRect = sclip;
173 }
174
175 if (!m_dirtyRect.isNull())
176 painter.setClipRect(clipRect);
177
178 painter.setCompositionMode(QPainter::CompositionMode_Source);
179 painter.fillRect(clipRect, color: m_fillColor);
180 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
181
182 m_item->paint(painter: &painter);
183 painter.end();
184
185 m_dirtyRect = QRect();
186}
187
188
189void QSGSoftwarePainterNode::setTextureSize(const QSize &size)
190{
191 if (size == m_textureSize)
192 return;
193
194 m_textureSize = size;
195 m_dirtyGeometry = true;
196}
197
198QT_END_NAMESPACE
199

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