Kirigami2

shadowedrectanglenode.cpp
1/*
2 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7#include "shadowedrectanglenode.h"
8#include "shadowedborderrectanglematerial.h"
9
10QColor premultiply(const QColor &color)
11{
12 return QColor::fromRgbF(color.redF() * color.alphaF(), //
13 color.greenF() * color.alphaF(),
14 color.blueF() * color.alphaF(),
15 color.alphaF());
16}
17
18ShadowedRectangleNode::ShadowedRectangleNode()
19{
21 setGeometry(m_geometry);
22
24}
25
27{
28 // We can achieve more performant shaders by splitting the two into separate
29 // shaders. This requires separating the materials as well. So when
30 // borderWidth is increased to something where the border should be visible,
31 // switch to the with-border material. Otherwise use the no-border version.
32
33 if (enabled) {
34 if (!m_material || m_material->type() == borderlessMaterialType()) {
35 auto newMaterial = createBorderMaterial();
36 newMaterial->shaderType = m_shaderType;
37 setMaterial(newMaterial);
38 m_material = newMaterial;
39 m_rect = QRectF{};
41 }
42 } else {
43 if (!m_material || m_material->type() == borderMaterialType()) {
44 auto newMaterial = createBorderlessMaterial();
45 newMaterial->shaderType = m_shaderType;
46 setMaterial(newMaterial);
47 m_material = newMaterial;
48 m_rect = QRectF{};
50 }
51 }
52}
53
54void ShadowedRectangleNode::setRect(const QRectF &rect)
55{
56 if (rect == m_rect) {
57 return;
58 }
59
60 m_rect = rect;
61
62 QVector2D newAspect{1.0, 1.0};
63 if (m_rect.width() >= m_rect.height()) {
64 newAspect.setX(m_rect.width() / m_rect.height());
65 } else {
66 newAspect.setY(m_rect.height() / m_rect.width());
67 }
68
69 if (m_material->aspect != newAspect) {
70 m_material->aspect = newAspect;
72 m_aspect = newAspect;
73 }
74}
75
76void ShadowedRectangleNode::setSize(qreal size)
77{
78 auto minDimension = std::min(m_rect.width(), m_rect.height());
79 float uniformSize = (size / minDimension) * 2.0;
80
81 if (!qFuzzyCompare(m_material->size, uniformSize)) {
82 m_material->size = uniformSize;
84 m_size = size;
85 }
86}
87
88void ShadowedRectangleNode::setRadius(const QVector4D &radius)
89{
90 float minDimension = std::min(m_rect.width(), m_rect.height());
91 auto uniformRadius = QVector4D{std::min(radius.x() * 2.0f / minDimension, 1.0f),
92 std::min(radius.y() * 2.0f / minDimension, 1.0f),
93 std::min(radius.z() * 2.0f / minDimension, 1.0f),
94 std::min(radius.w() * 2.0f / minDimension, 1.0f)};
95
96 if (m_material->radius != uniformRadius) {
97 m_material->radius = uniformRadius;
99 m_radius = radius;
100 }
101}
102
103void ShadowedRectangleNode::setColor(const QColor &color)
104{
105 auto premultiplied = premultiply(color);
106 if (m_material->color != premultiplied) {
107 m_material->color = premultiplied;
109 }
110}
111
112void ShadowedRectangleNode::setShadowColor(const QColor &color)
113{
114 auto premultiplied = premultiply(color);
115 if (m_material->shadowColor != premultiplied) {
116 m_material->shadowColor = premultiplied;
118 }
119}
120
121void ShadowedRectangleNode::setOffset(const QVector2D &offset)
122{
123 auto minDimension = std::min(m_rect.width(), m_rect.height());
124 auto uniformOffset = offset / minDimension;
125
126 if (m_material->offset != uniformOffset) {
127 m_material->offset = uniformOffset;
129 m_offset = offset;
130 }
131}
132
133void ShadowedRectangleNode::setBorderWidth(qreal width)
134{
135 if (m_material->type() != borderMaterialType()) {
136 return;
137 }
138
139 auto minDimension = std::min(m_rect.width(), m_rect.height());
140 float uniformBorderWidth = width / minDimension;
141
142 auto borderMaterial = static_cast<ShadowedBorderRectangleMaterial *>(m_material);
143 if (!qFuzzyCompare(borderMaterial->borderWidth, uniformBorderWidth)) {
144 borderMaterial->borderWidth = uniformBorderWidth;
146 m_borderWidth = width;
147 }
148}
149
150void ShadowedRectangleNode::setBorderColor(const QColor &color)
151{
152 if (m_material->type() != borderMaterialType()) {
153 return;
154 }
155
156 auto borderMaterial = static_cast<ShadowedBorderRectangleMaterial *>(m_material);
157 auto premultiplied = premultiply(color);
158 if (borderMaterial->borderColor != premultiplied) {
159 borderMaterial->borderColor = premultiplied;
161 }
162}
163
164void ShadowedRectangleNode::setShaderType(ShadowedRectangleMaterial::ShaderType type)
165{
166 m_shaderType = type;
167}
168
170{
171 auto rect = m_rect;
172 if (m_shaderType == ShadowedRectangleMaterial::ShaderType::Standard) {
173 rect = rect.adjusted(-m_size * m_aspect.x(), //
174 -m_size * m_aspect.y(),
175 m_size * m_aspect.x(),
176 m_size * m_aspect.y());
177
178 auto offsetLength = m_offset.length();
179 rect = rect.adjusted(-offsetLength * m_aspect.x(), //
180 -offsetLength * m_aspect.y(),
181 offsetLength * m_aspect.x(),
182 offsetLength * m_aspect.y());
183 }
184
185 QSGGeometry::updateTexturedRectGeometry(m_geometry, rect, QRectF{0.0, 0.0, 1.0, 1.0});
187}
188
189ShadowedRectangleMaterial *ShadowedRectangleNode::createBorderlessMaterial()
190{
191 return new ShadowedRectangleMaterial{};
192}
193
194ShadowedBorderRectangleMaterial *ShadowedRectangleNode::createBorderMaterial()
195{
197}
198
199QSGMaterialType *ShadowedRectangleNode::borderlessMaterialType()
200{
201 return &ShadowedRectangleMaterial::staticType;
202}
203
204QSGMaterialType *ShadowedRectangleNode::borderMaterialType()
205{
206 return &ShadowedBorderRectangleMaterial::staticType;
207}
A material rendering a rectangle with a shadow and a border.
A material rendering a rectangle with a shadow.
void updateGeometry()
Update the geometry for this node.
void setBorderEnabled(bool enabled)
Set whether to draw a border.
float alphaF() const const
float blueF() const const
QColor fromRgbF(float r, float g, float b, float a)
float greenF() const const
float redF() const const
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const const
qreal height() const const
qreal width() const const
void setGeometry(QSGGeometry *geometry)
const AttributeSet & defaultAttributes_TexturedPoint2D()
void updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &textureRect)
void setMaterial(QSGMaterial *material)
void markDirty(DirtyState bits)
void setFlags(Flags f, bool enabled)
NodeType type() const const
float length() const const
void setX(float x)
float x() const const
float y() const const
float w() const const
float x() const const
float y() const const
float z() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:46 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.