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 "qsgsoftwarepublicnodes_p.h"
5#include "qsgsoftwarelayer_p.h"
6#include "qsgsoftwarepixmaptexture_p.h"
7#include "qsgsoftwareinternalimagenode_p.h"
8#include <private/qsgplaintexture_p.h>
9
10QT_BEGIN_NAMESPACE
11
12QSGSoftwareRectangleNode::QSGSoftwareRectangleNode()
13 : m_color(QColor(255, 255, 255))
14{
15 setMaterial((QSGMaterial*)1);
16 setGeometry((QSGGeometry*)1);
17}
18
19void QSGSoftwareRectangleNode::paint(QPainter *painter)
20{
21 painter->fillRect(m_rect, color: m_color);
22}
23
24QSGSoftwareImageNode::QSGSoftwareImageNode()
25 : m_texture(nullptr),
26 m_owns(false),
27 m_filtering(QSGTexture::None),
28 m_transformMode(NoTransform),
29 m_cachedMirroredPixmapIsDirty(false)
30{
31 setMaterial((QSGMaterial*)1);
32 setGeometry((QSGGeometry*)1);
33}
34
35QSGSoftwareImageNode::~QSGSoftwareImageNode()
36{
37 if (m_owns)
38 delete m_texture;
39}
40
41void QSGSoftwareImageNode::setTexture(QSGTexture *texture)
42{
43 if (m_owns)
44 delete m_texture;
45
46 m_texture = texture; markDirty(bits: DirtyMaterial);
47 m_cachedMirroredPixmapIsDirty = true;
48}
49
50void QSGSoftwareImageNode::setTextureCoordinatesTransform(QSGImageNode::TextureCoordinatesTransformMode transformNode)
51{
52 if (m_transformMode == transformNode)
53 return;
54
55 m_transformMode = transformNode;
56 m_cachedMirroredPixmapIsDirty = true;
57
58 markDirty(bits: DirtyGeometry);
59}
60
61void QSGSoftwareImageNode::paint(QPainter *painter)
62{
63 if (m_cachedMirroredPixmapIsDirty)
64 updateCachedMirroredPixmap();
65
66 painter->setRenderHint(hint: QPainter::SmoothPixmapTransform, on: (m_filtering == QSGTexture::Linear));
67 // Disable antialiased clipping. It causes transformed tiles to have gaps.
68 painter->setRenderHint(hint: QPainter::Antialiasing, on: false);
69
70 if (!m_cachedPixmap.isNull()) {
71 painter->drawPixmap(targetRect: m_rect, pixmap: m_cachedPixmap, sourceRect: m_sourceRect);
72 } else if (QSGSoftwarePixmapTexture *pt = qobject_cast<QSGSoftwarePixmapTexture *>(object: m_texture)) {
73 const QPixmap &pm = pt->pixmap();
74 painter->drawPixmap(targetRect: m_rect, pixmap: pm, sourceRect: m_sourceRect);
75 } else if (QSGSoftwareLayer *pt = qobject_cast<QSGSoftwareLayer *>(object: m_texture)) {
76 const QPixmap &pm = pt->pixmap();
77 painter->drawPixmap(targetRect: m_rect, pixmap: pm, sourceRect: m_sourceRect);
78 } else if (QSGPlainTexture *pt = qobject_cast<QSGPlainTexture *>(object: m_texture)) {
79 const QImage &im = pt->image();
80 painter->drawImage(targetRect: m_rect, image: im, sourceRect: m_sourceRect);
81 }
82}
83
84void QSGSoftwareImageNode::updateCachedMirroredPixmap()
85{
86 if (m_transformMode == NoTransform) {
87 m_cachedPixmap = QPixmap();
88 } else {
89 if (QSGSoftwarePixmapTexture *pt = qobject_cast<QSGSoftwarePixmapTexture *>(object: m_texture)) {
90 QTransform mirrorTransform;
91 if (m_transformMode.testFlag(flag: MirrorVertically))
92 mirrorTransform = mirrorTransform.scale(sx: 1, sy: -1);
93 if (m_transformMode.testFlag(flag: MirrorHorizontally))
94 mirrorTransform = mirrorTransform.scale(sx: -1, sy: 1);
95 m_cachedPixmap = pt->pixmap().transformed(mirrorTransform);
96 } else if (QSGSoftwareLayer *pt = qobject_cast<QSGSoftwareLayer *>(object: m_texture)) {
97 QTransform mirrorTransform;
98 if (m_transformMode.testFlag(flag: MirrorVertically))
99 mirrorTransform = mirrorTransform.scale(sx: 1, sy: -1);
100 if (m_transformMode.testFlag(flag: MirrorHorizontally))
101 mirrorTransform = mirrorTransform.scale(sx: -1, sy: 1);
102 m_cachedPixmap = pt->pixmap().transformed(mirrorTransform);
103 } else if (QSGPlainTexture *pt = qobject_cast<QSGPlainTexture *>(object: m_texture)) {
104 static constexpr Qt::Orientation none = Qt::Orientation(0);
105 const auto orientation = (m_transformMode.testFlag(flag: MirrorHorizontally) ? Qt::Horizontal : none)
106 | (m_transformMode.testFlag(flag: MirrorVertically) ? Qt::Vertical : none);
107 m_cachedPixmap = QPixmap::fromImage(image: pt->image().flipped(orient: orientation));
108 } else {
109 m_cachedPixmap = QPixmap();
110 }
111 }
112
113 m_cachedMirroredPixmapIsDirty = false;
114}
115
116QSGSoftwareNinePatchNode::QSGSoftwareNinePatchNode()
117{
118 setMaterial((QSGMaterial*)1);
119 setGeometry((QSGGeometry*)1);
120}
121
122void QSGSoftwareNinePatchNode::setTexture(QSGTexture *texture)
123{
124 QSGSoftwarePixmapTexture *pt = qobject_cast<QSGSoftwarePixmapTexture*>(object: texture);
125 if (!pt) {
126 qWarning() << "Image used with invalid texture format.";
127 } else {
128 m_pixmap = pt->pixmap();
129 markDirty(bits: DirtyMaterial);
130 }
131 delete texture;
132}
133
134void QSGSoftwareNinePatchNode::setBounds(const QRectF &bounds)
135{
136 if (m_bounds == bounds)
137 return;
138
139 m_bounds = bounds;
140 markDirty(bits: DirtyGeometry);
141}
142
143void QSGSoftwareNinePatchNode::setDevicePixelRatio(qreal ratio)
144{
145 if (m_pixelRatio == ratio)
146 return;
147
148 m_pixelRatio = ratio;
149 markDirty(bits: DirtyGeometry);
150}
151
152void QSGSoftwareNinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal bottom)
153{
154 QMargins margins(qRound(d: left), qRound(d: top), qRound(d: right), qRound(d: bottom));
155 if (m_margins == margins)
156 return;
157
158 m_margins = QMargins(qRound(d: left), qRound(d: top), qRound(d: right), qRound(d: bottom));
159 markDirty(bits: DirtyGeometry);
160}
161
162void QSGSoftwareNinePatchNode::update()
163{
164}
165
166void QSGSoftwareNinePatchNode::paint(QPainter *painter)
167{
168 // Disable antialiased clipping. It causes transformed tiles to have gaps.
169 painter->setRenderHint(hint: QPainter::Antialiasing, on: false);
170
171 if (m_margins.isNull())
172 painter->drawPixmap(targetRect: m_bounds, pixmap: m_pixmap, sourceRect: QRectF(0, 0, m_pixmap.width(), m_pixmap.height()));
173 else
174 QSGSoftwareHelpers::qDrawBorderPixmap(painter, targetRect: m_bounds.toRect(), targetMargins: m_margins, pixmap: m_pixmap, sourceRect: QRect(0, 0, m_pixmap.width(), m_pixmap.height()),
175 sourceMargins: m_margins, rules: Qt::StretchTile, hints: QSGSoftwareHelpers::QDrawBorderPixmap::DrawingHints{});
176}
177
178QRectF QSGSoftwareNinePatchNode::bounds() const
179{
180 return m_bounds;
181}
182
183QT_END_NAMESPACE
184

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